package web // S2 offsite connectivity: the read-only /offsite registry page (doc 06 §8 S2 "hub UI shows the // peer registry"). Read-only by design — add/remove stay on the admin API; UI mutations arrive // with tunnel health (S3/S6). Peers render neutral (no health state exists yet — nothing to // except on, so no status colors). import ( "database/sql" "net/http" ) // truncateMiddle shortens a long opaque value (pubkeys) for table display, keeping both ends — // the full value always rides the title attribute. func truncateMiddle(s string, keep int) string { if len(s) <= 2*keep+1 { return s } return s[:keep] + "…" + s[len(s)-keep:] } // offsitePeerRow is the per-peer view model. type offsitePeerRow struct { Pubkey string PubkeyShort string AssignedIP string // with /32 HostID string // "" = unbound Note string CreatedAt string } // handleOffsite renders the offsite registry: the endpoint card + the peer table. func (s *Server) handleOffsite(w http.ResponseWriter, r *http.Request) { data := map[string]interface{}{ "HasEndpoint": false, } ep, err := s.store.GetWGEndpoint() if err != nil && err != sql.ErrNoRows { s.logger.Printf("[ERROR] offsite: endpoint read: %v", err) http.Error(w, "Internal error", http.StatusInternalServerError) return } if ep != nil { data["HasEndpoint"] = true data["Endpoint"] = map[string]interface{}{ "DNSName": ep.DNSName, "WGPort": ep.WGPort, "ServerPubkey": ep.ServerPubkey, "ServerPubkeyShort": truncateMiddle(ep.ServerPubkey, 10), "TunnelSubnet": ep.TunnelSubnet, "PBSTunnelIP": ep.PBSTunnelIP, } } peers, err := s.store.ListWGPeers() if err != nil { s.logger.Printf("[ERROR] offsite: peer list: %v", err) http.Error(w, "Internal error", http.StatusInternalServerError) return } rows := make([]offsitePeerRow, 0, len(peers)) for _, p := range peers { rows = append(rows, offsitePeerRow{ Pubkey: p.Pubkey, PubkeyShort: truncateMiddle(p.Pubkey, 10), AssignedIP: p.AssignedIP + "/32", HostID: p.HostID, Note: p.Note, CreatedAt: p.CreatedAt, }) } data["Peers"] = rows if err := s.templates.ExecuteTemplate(w, "offsite.html", data); err != nil { s.logger.Printf("[ERROR] offsite.html template: %v", err) } }