- MAJOR: config.example.json was missing geoFilterExemptNodeList
entirely — every other Config field in this repo gets a sibling
_comment_<field> entry (established, actively-used convention
throughout the file, ~20 existing examples), documented here to
match. Also corrected the adjacent geo_filter _comment, which
predates this PR and claimed it "restricts ingestion" — it doesn't;
that's foreignAdverts.mode=drop's job, unrelated to this flag.
- MINOR: ?geoFilter=<v> only recognized the literal string "1" to
enable and treated anything else (including "true") as disabling —
a real footgun since "true" reads as an obviously valid boolean
value. Now accepts 1/true and 0/false as explicit overrides; any
other value (including absent) falls through to the deployment
default instead of silently flipping it off.
- Tightened the Foreign Traffic tab's stop-hook test: it previously
only asserted stop() doesn't throw, which a no-op stub would also
pass. Sandbox's setInterval/clearInterval are now real spies
tracking live/cleared ids, so the test verifies render() registers
exactly one interval and stop() actually clears that exact id
(idempotently on a second call).
- NIT: relays.sort now wraps unscoped_relay_count_24h in Number(...)
defensively (AGENTS.md § Type Safety — cast at the boundary).
- NIT: foreignNodes.sort now parses last_seen once per node
(decorate-sort-undecorate) instead of twice per comparator call.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reordered so the node list (what's actually accumulating right now,
worth checking back on) comes first, with the unscoped-relay-volume
table — the part that needs more data to be interesting — below it.
Added a heading to the relay table for symmetry with the new
sub-heading above it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a second table to the tab: every node currently foreign_advert
-tagged (name, role, lat/lon, first/last seen), newest-heard first —
so there's something to look at while more foreign_advert data
accumulates, instead of only the one-sentence summary count.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Per bot review on PR #1852 (comment 5012304813): renderForeignTrafficTab
shipped without a test, repeating the same TDD-policy finding flagged
on the prior round, and the tab lacked the 60s auto-refresh + stop-hook
convention its Roles/Scopes siblings use (data would go stale until the
user re-navigated away and back).
- Added _stopForeignTrafficRefresh + a 60s setInterval loop, wired into
the tab-switch handler and destroy(), matching _stopRolesRefresh/
_stopScopesRefresh exactly.
- New test-analytics-foreign-traffic-tab.js: loads analytics.js in a vm
sandbox (same pattern as test-frontend-helpers.js's
makeAnalyticsSandbox), stubs fetchAllNodes with a fixed node mix, and
asserts row sort order, role/zero-count exclusion, the empty state,
both foreignCount note variants, and that the new stop-hook is
exported and idempotent.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>