diff --git a/cmd/server/db.go b/cmd/server/db.go index 85b07f85..2862722c 100644 --- a/cmd/server/db.go +++ b/cmd/server/db.go @@ -1540,13 +1540,6 @@ type PacketPathPoint struct { // those neighbors -- 0 (and omitted) with a single contributor; // larger means the neighbors disagree more about where "nearby" is. ApproxSpreadKm *float64 `json:"approxSpreadKm,omitempty"` - // IsBridge is true when this node has been confirmed relaying - // traffic for 2+ distinct region scopes -- the same "Bridge" badge - // definition as the Foreign Traffic tab (ScopeStatsResponse. - // bridgeRepeaters). Set by the handler (routes.go), not GetPacketPath - // itself, since the underlying data lives in the in-memory store, not - // SQL. Absent/false when the store isn't available. - IsBridge bool `json:"isBridge,omitempty"` } // PacketPathObserver is the station that produced a given branch's @@ -1558,9 +1551,8 @@ type PacketPathPoint struct { type PacketPathObserver struct { // PublicKey is the observer's mesh pubkey (observers.id for v3, // observer_id for legacy), when it has one -- lets callers link out - // to the node detail page or cross-reference other per-node data - // (e.g. IsBridge, filled in by the handler). Empty for an observer - // whose id never resembled a pubkey. + // to the node detail page. Empty for an observer whose id never + // resembled a pubkey. PublicKey string `json:"publicKey,omitempty"` Name string `json:"name"` IATA string `json:"iata,omitempty"` @@ -1573,8 +1565,6 @@ type PacketPathObserver struct { Approx bool `json:"approx,omitempty"` ApproxNeighborCount int `json:"approxNeighborCount,omitempty"` ApproxSpreadKm *float64 `json:"approxSpreadKm,omitempty"` - // IsBridge -- see PacketPathPoint.IsBridge. - IsBridge bool `json:"isBridge,omitempty"` } // PacketPathBranch is one station's route to a packet: how far it diff --git a/cmd/server/openapi.go b/cmd/server/openapi.go index 37642972..44dfab65 100644 --- a/cmd/server/openapi.go +++ b/cmd/server/openapi.go @@ -345,7 +345,6 @@ func componentSchemas() map[string]interface{} { "approx": map[string]interface{}{"type": "boolean", "description": "True when lat/lon are not this node's own position but a count-weighted centroid of its positioned neighbor_edges neighbors instead -- a last-resort stand-in, not a real fix."}, "approxNeighborCount": map[string]interface{}{"type": "integer", "description": "Present only when approx=true. How many positioned neighbors fed the centroid -- a rough confidence signal, higher is more confident."}, "approxSpreadKm": map[string]interface{}{"type": "number", "nullable": true, "description": "Present only when approx=true and approxNeighborCount>1. Widest distance (km) between any two contributing neighbors -- larger means they disagree more about where 'nearby' is."}, - "isBridge": map[string]interface{}{"type": "boolean", "description": "True when this node has been confirmed relaying traffic for 2+ distinct region scopes -- same definition/data source as the Foreign Traffic tab's Bridge badge. Set by the handler from the in-memory store; always false when that store isn't available."}, }, }, "PacketPathObserver": map[string]interface{}{ @@ -361,7 +360,6 @@ func componentSchemas() map[string]interface{} { "approx": map[string]interface{}{"type": "boolean", "description": "True when lat/lon are not this station's own position but a count-weighted centroid of its positioned neighbors instead -- a last-resort stand-in, not a real fix."}, "approxNeighborCount": map[string]interface{}{"type": "integer", "description": "Present only when approx=true. See PacketPathPoint.approxNeighborCount."}, "approxSpreadKm": map[string]interface{}{"type": "number", "nullable": true, "description": "Present only when approx=true and approxNeighborCount>1. See PacketPathPoint.approxSpreadKm."}, - "isBridge": map[string]interface{}{"type": "boolean", "description": "See PacketPathPoint.isBridge."}, }, }, "PacketPathBranch": map[string]interface{}{ diff --git a/cmd/server/packet_path_bridge_test.go b/cmd/server/packet_path_bridge_test.go deleted file mode 100644 index 05a128c8..00000000 --- a/cmd/server/packet_path_bridge_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "testing" - "time" -) - -// TestMarkBridgeRepeaters_NilStore covers the graceful no-op when the -// in-memory store isn't available (s.store can legitimately be nil -- -// see handlePacketPath). Must not panic and must leave every IsBridge -// at its zero value (false). -func TestMarkBridgeRepeaters_NilStore(t *testing.T) { - resp := &PacketPathResponse{ - Hash: "deadbeef", - Branches: []PacketPathBranch{ - {Points: []PacketPathPoint{{PublicKey: "pk1"}}, Observer: &PacketPathObserver{PublicKey: "obs1"}}, - }, - } - markBridgeRepeaters(resp, nil, &Config{}) - if resp.Branches[0].Points[0].IsBridge { - t.Errorf("Points[0].IsBridge = true, want false -- store is nil, nothing should be marked") - } - if resp.Branches[0].Observer.IsBridge { - t.Errorf("Observer.IsBridge = true, want false -- store is nil, nothing should be marked") - } -} - -// TestMarkBridgeRepeaters_TwoScopesIsBridge covers the actual -// determination: a pubkey relaying 2+ distinct region scopes (the same -// definition/data source as the Foreign Traffic tab's "Bridge" badge, -// ScopeStatsResponse.bridgeRepeaters) gets IsBridge=true on every point -// and observer entry referencing it; a pubkey with 0 or 1 scope, or one -// missing from the relay map entirely, stays false. -func TestMarkBridgeRepeaters_TwoScopesIsBridge(t *testing.T) { - store := &PacketStore{ - repeaterRelayCache: map[string]RepeaterRelayInfo{ - "bridgepk": {TransportedScopes: []string{"#dk", "#se"}}, - "regionalpk": {TransportedScopes: []string{"#dk"}}, - "unknownscopepk": {TransportedScopes: nil}, - }, - repeaterRelayCacheWin: 24, - repeaterRelayAt: time.Now(), - } - resp := &PacketPathResponse{ - Hash: "deadbeef", - Branches: []PacketPathBranch{ - { - Points: []PacketPathPoint{ - {PublicKey: "bridgepk"}, - {PublicKey: "regionalpk"}, - {PublicKey: "unknownscopepk"}, - {PublicKey: "notinrelaymap"}, - }, - Observer: &PacketPathObserver{PublicKey: "BridgePK"}, // case-insensitive match - }, - }, - } - markBridgeRepeaters(resp, store, &Config{}) - - pts := resp.Branches[0].Points - if !pts[0].IsBridge { - t.Errorf("Points[0] (bridgepk, 2 scopes) IsBridge = false, want true") - } - if pts[1].IsBridge { - t.Errorf("Points[1] (regionalpk, 1 scope) IsBridge = true, want false") - } - if pts[2].IsBridge { - t.Errorf("Points[2] (unknownscopepk, 0 scopes) IsBridge = true, want false") - } - if pts[3].IsBridge { - t.Errorf("Points[3] (notinrelaymap, absent from relay map) IsBridge = true, want false") - } - if !resp.Branches[0].Observer.IsBridge { - t.Errorf("Observer (BridgePK, case-insensitive match on bridgepk) IsBridge = false, want true") - } -} diff --git a/cmd/server/routes.go b/cmd/server/routes.go index 2e42da72..d88fca6c 100644 --- a/cmd/server/routes.go +++ b/cmd/server/routes.go @@ -3164,46 +3164,9 @@ func (s *Server) handlePacketPath(w http.ResponseWriter, r *http.Request) { writeError(w, 500, err.Error()) return } - markBridgeRepeaters(resp, s.store, s.cfg) writeJSON(w, resp) } -// markBridgeRepeaters sets IsBridge on every point/observer in resp whose -// pubkey has been confirmed relaying traffic for 2+ distinct region -// scopes -- the same "Bridge" definition/data source as the Foreign -// Traffic tab's badge (ScopeStatsResponse.bridgeRepeaters), just applied -// to whichever handful of pubkeys this one packet's path touches instead -// of scanning the whole mesh. No-op when the in-memory store isn't -// available (IsBridge stays false/omitted on every entry). -func markBridgeRepeaters(resp *PacketPathResponse, store *PacketStore, cfg *Config) { - if resp == nil || store == nil || cfg == nil { - return - } - relayMap := store.GetRepeaterRelayInfoMap(cfg.GetHealthThresholds().RelayActiveHours) - isBridge := func(pubkey string) bool { - if pubkey == "" { - return false - } - info, ok := relayMap[strings.ToLower(pubkey)] - return ok && len(info.TransportedScopes) >= 2 - } - mark := func(b *PacketPathBranch) { - if b == nil { - return - } - for i := range b.Points { - b.Points[i].IsBridge = isBridge(b.Points[i].PublicKey) - } - if b.Observer != nil { - b.Observer.IsBridge = isBridge(b.Observer.PublicKey) - } - } - for i := range resp.Branches { - mark(&resp.Branches[i]) - } - mark(resp.First) -} - var iataCoords = map[string]IataCoord{ "SJC": {Lat: 37.3626, Lon: -121.929}, "SFO": {Lat: 37.6213, Lon: -122.379}, diff --git a/public/packet-path-map.js b/public/packet-path-map.js index b73e0923..a6fca65f 100644 --- a/public/packet-path-map.js +++ b/public/packet-path-map.js @@ -100,7 +100,7 @@ var chain = located.map(function (p, hi) { return { lat: p.lat, lon: p.lon, name: p.name, label: 'hop ' + (hi + 1) + ' of ' + b.hops, approx: !!p.approx, - approxNeighborCount: p.approxNeighborCount, approxSpreadKm: p.approxSpreadKm, role: p.role, isBridge: !!p.isBridge, + approxNeighborCount: p.approxNeighborCount, approxSpreadKm: p.approxSpreadKm, role: p.role, publicKey: p.publicKey, }; }); @@ -112,7 +112,7 @@ lat: b.observer.lat, lon: b.observer.lon, name: b.observer.name, label: observerLabel, isObserver: true, approx: !!b.observer.approx, approxNeighborCount: b.observer.approxNeighborCount, approxSpreadKm: b.observer.approxSpreadKm, - role: b.observer.role, isBridge: !!b.observer.isBridge, publicKey: b.observer.publicKey, + role: b.observer.role, publicKey: b.observer.publicKey, }); } return { chain: chain, missing: (b.points || []).length - located.length }; @@ -129,7 +129,7 @@ '' + '
How far and how wide this packet spread. The highlighted route is the farthest-traveled branch; every other station that heard it is shown too. The green ring marks whoever heard it first. Dashed markers are approximate -- estimated from nearby positioned neighbors, not the station\'s own position. A bold purple outline marks a confirmed bridge repeater. Click a marker to open that node\'s detail page.
' + + 'How far and how wide this packet spread. The highlighted route is the farthest-traveled branch; every other station that heard it is shown too. The green ring marks whoever heard it first. Dashed markers are approximate -- estimated from nearby positioned neighbors, not the station\'s own position. Click a marker to open that node\'s detail page.
' + '' + '