Skip to content

Add observer declaration scope audit - #378

Merged
dborup merged 4 commits into
masterfrom
codex/scope-audit
Oct 14, 2026
Merged

dborup merged 4 commits into
masterfrom
codex/scope-audit

Conversation

@dborup

@dborup dborup commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Adds Scope Audit under Analytics → Scopes. A repeater's confirmed observer declaration is compared with flood forwarding observed over 1h, 24h or 7d. For example, unscoped forwarding without a declared * is shown as a finding; a declared scope with no traffic is shown as unobserved rather than a proven configuration fault.

The whole-network audit marks stale declarations, unknown transported scopes, ambiguous hop attribution and legacy observations as incomplete evidence. It uses observed paths, counts each transmission once per repeater/scope state, respects hidden identities, and preserves window, search and pagination in shareable links. CoreDrive declarations and HMAC verification are outside this first version.

Performance

One node snapshot and one streaming observation query replace per-node queries. Aggregation is linear in nodes and observed path hops, with bounded token memoization, per-transmission deduplication, a three-window/30-second cache and singleflight. The browser diffs at most 50 visible rows and searches the bulk response locally.

Parent-run benchmark on Apple M5: 30,000 transmissions, 90,000 observations, 2,000 nodes and four hops per observation averaged 138.6 ms/op across three runs (67.9 MB/op). This measures uncached aggregation, not an end-to-end production request.

Validation

  • Full Go server and ingestor suites passed; Scope Audit race tests passed.
  • npm test: 235 test files passed, zero failures.
  • Full local Playwright suite passed, including both new Scope Audit tests. Existing fixture-dependent checks retain their explicit skips.
  • Browser checks cover lazy fetching, window changes, local search, stable row refresh, long labels, URL restoration, stale/unknown evidence, empty/error states and manual retry.
  • ESLint: zero errors (existing warnings in analytics.js); XSS preflight passed.

Initial thresholds and limits are documented for a later customizer milestone. No server database writes or new dependencies are introduced.

@dborup

dborup commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

Report — CS-Minimax PR#378 overtagelse — head 66bce8b

Review feedback addressed (commit 66bce8b3)

  1. Merge origin/master (bcf263e): merged with an ordinary merge commit (66bce8b3, parents 319b3d3e + bcf263e1), no force-push, no rebase. Git auto-resolved every file (analytics.js, routes.go, openapi.go, test-all.sh, test-e2e-playwright.js) with zero manual conflict resolution needed — the two branches touched disjoint regions. [A] git log --oneline -3 on the branch; git show --stat 66bce8b3.

  2. security(api): bound public analytics response caches #430 cache-bound pattern for the scope-audit cache: no code change — verified the existing cache already satisfies the pattern. scopeAuditCache is keyed only by window, which handleScopeAudit rejects with 400 before any DB/cache work unless it is exactly 1h/24h/7d — so the key space is hard-capped at 3 entries by construction, with rejection-before-work already in place. search (saq) never reaches the server at all; it is a client-side array filter over the already-fetched rows (public/scope-audit.js searchRows()), so it cannot be a cache key. This is the same shape as the sibling scopeStatsCache (routes.go:4429-4441, 4605-4611) — identical enum-validated window-only key — which security(api): bound public analytics response caches #430's own security pass (PR security(api): bound public analytics response caches #430, "security(api): bound public analytics response caches") deliberately left untouched; security(api): bound public analytics response caches #430 only added evictCachedResultLocked/evictStatsCacheLocked to caches whose keys embed caller-controlled free text or unbounded ranges (e.g. wardrivingStatsCache's window|channel key, region/area filters, absolute from/to). Adding an eviction function here would be dead code bounding a map that structurally cannot exceed 3 entries. [A] read of cmd/server/analytics_cache_bounds.go, cmd/server/scope_audit.go:65-110, cmd/server/routes.go:4429-4611; git show dd712bc9 --stat (security(api): bound public analytics response caches #430 file list) confirms scopeStatsCache was not among the files it touched.

  3. Escaping of scope names, node names and labels: no code change — already compliant. public/scope-audit.js builds every row exclusively through createElement + .textContent (the shared element()/add() helpers), never innerHTML or string-built HTML, so node names / scope names / labels can't execute as markup regardless of content. scripts/check-xss-sinks.sh --file public/scope-audit.js and --file public/analytics.js both exit 0 (no flagged sinks). The PR's own tools/scope-audit-e2e.js injects a node name of <img src=x onerror="window.auditXss=1"> through the mocked /api/scope-audit response and asserts zero <img> elements render and window.auditXss stays unset — reran it against a real local server (not mocked Playwright route only) and it passes. [T] scripts/check-xss-sinks.sh --file public/scope-audit.js → exit 0; scripts/check-xss-sinks.sh --file public/analytics.js → exit 0; tools/scope-audit-e2e.js run against http://localhost:13712: "✅ Scope Audit: lazy tab, window, local search, stable refresh and deep link" (XSS assertions included).

  4. Leak fixes (fix(ui): stop observers.js leaking delegated handlers on #app (#405) #419/fix(ui): stop compare/channels/live leaking handlers on #app (#428) #437 pattern): no code change — already compliant. Every addEventListener in scope-audit.js (window-tab buttons, search input, pager buttons, Refresh) is attached to elements the component itself creates inside its own mounted container, not document/window/#app, so they die with the container. analytics.js wires _stopScopeAudit() (→ auditView.destroy()) into the same teardown points as the pre-existing _stopScopesRefresh(): on leaving the "scopes" sub-tab and in the shared destroy(). [A] read of public/scope-audit.js (all 5 addEventListener call sites scoped to locally-created nodes) and public/analytics.js diff (_stopScopeAudit, destroy() wiring).

  5. E2E sharding (ci: measure and shard Playwright E2E suites (#434) #436): no scripts/e2e-shards.json edit needed. The three test files this PR adds are not standalone browser-driven top-level suites: test-scope-audit.js and test-analytics-subtab-deeplinks-205.js are jsdom/vm-style unit tests already registered in test-all.sh; tools/scope-audit-e2e.js is a helper module require()'d from inside the already-sharded test-e2e-playwright.js (test-e2e-playwright.js:3893). scripts/ci/e2e-manifest.js's auto-discovery only onboards root-level test-*.js files that literally require('playwright'); none of the three match that shape. [T] node scripts/run-e2e-shard.js --validate → "E2E assignments: 158 suites across three non-empty shards" (exit 0) on the merged branch; node test-ci-shards.js → 9/9 pass (includes "unit registry cannot hide newly added browser imports or E2E filenames").

  6. fix(hops): avoid unproven receiver-region narrowing #427 (no receiver-region narrowing of hops): not applicable to this PR — verified, no code change. fix(hops): avoid unproven receiver-region narrowing #427 touched only public/hop-resolver.js, public/map.js, public/packets.js (a frontend heuristic for attributing a received hop to a region). scope_audit.go does no region-based hop attribution of its own; it reuses the pre-existing, fix(hops): avoid unproven receiver-region narrowing #427-unrelated buildPrefixMap/newRelayTokenResolver (cmd/server/node_activity.go, cmd/server/store.go), and grep -n region cmd/server/scope_audit.go returns nothing. [A] git show --stat on the fix(hops): avoid unproven receiver-region narrowing #427 merge commit; grep of scope_audit.go.

  7. PR description: no change needed. The body contains no closing keyword (Fixes/Closes/Resolves) and no issue-number reference at all (grep -iE "fixes|closes|resolves|#[0-9]+" on the body → no match). [A] gh pr view 378 --json body.

  8. No new map[string]interface{}; server stays read-only: confirmed, no violations. grep -n "map\[string\]interface{}" cmd/server/scope_audit.go → no matches (all response/accumulator types are concrete structs). buildScopeAuditContext issues only SELECT statements against nodes/transmissions/observations; no INSERT/UPDATE/DELETE. [A] grep + read of cmd/server/scope_audit.go.

  9. -race: green, both scoped and full-package. go test -run TestScopeAudit -race -v ./... (cmd/server): 8/8 pass (TestScopeAuditFindings, TestScopeAuditCollisionAndWindow, TestScopeAuditHTTPAndCache, TestScopeAuditObservationRouteAndScope, TestScopeAuditMissingDeclarationAndSevenDayWindow, TestScopeAuditCacheSingleflightExpiryAndErrors, TestScopeAuditCachedHiddenNameAndUnsupportedSchema, TestScopeAuditNoDeclarationsSkipsObservationScan), 0 data races. Full cmd/server package under -race -timeout 25m: ok github.com/corescope/server 595.542s, 0 --- FAIL, 0 DATA RACE. go vet ./... (cmd/server): clean. [T] local runs on the merged worktree.

Performance (benchmark rerun on Linux)

BenchmarkScopeAudit30KPackets2KNodes (30,000 transmissions / 90,000 observations / 2,000 nodes, 4 hops/observation — same corpus as the PR body's M5 number) was rerun on Linux, since the PR description's 138.6 ms/op figure was measured on Apple M5 (macOS/arm64). No Linux box was available locally, so it ran inside golang:1.27.1-bookworm (Docker) on the shared demo QA host (ssh demo, Ubuntu, Intel Xeon Skylake, CGO sqlite3 build, GOMAXPROCS=2 — a 2-vCPU cloud VM, not a dedicated core), under its own task prefix (pr378-20261014t065651z), touching no other prefix:

  • -benchtime=3x: 739.2 ms/op, 67,849,458 B/op, 2,040,076 allocs/op
  • -benchtime=6x: 770.9 ms/op, 67,847,205 B/op, 2,040,073 allocs/op

The allocation profile (≈67.85 MB/op, ≈2.04M allocs/op) matches the PR body's claimed 67.9 MB/op almost exactly — expected, since Go's allocator count is architecture-independent for the same code path. The ≈5.4–5.6× slower wall-clock vs. the Apple M5's 138.6 ms/op tracks a 2-vCPU shared cloud VM vs. a dedicated modern laptop core and is not a regression signal; no algorithmic change was made. [A][T] go test -run NONE -bench BenchmarkScopeAudit30KPackets2KNodes -benchmem -benchtime=3x|6x ./cmd/server inside golang:1.27.1-bookworm on ssh demo.

Tests

  • sh test-all.sh: 246 passed, 0 failed (includes test-scope-audit.js and test-analytics-subtab-deeplinks-205.js; the file-registry self-checks in test-test-all.js — "every registered file exists", "no registered file needs a browser or a server" — also pass). [T]
  • go vet ./... (cmd/server): clean. [T]
  • cmd/server full suite, -race: ok github.com/corescope/server 595.542s, 0 failures, 0 data races (see item 9). [T]
  • node run-e2e-shard.js --validate / node test-ci-shards.js: pass (see item 5). [T]
  • test-e2e-playwright.js against a local Go server built from this branch, with test-fixtures/e2e-fixture.db prepared exactly as CI does (tools/freshen-fixture.sh, the Packets page collapse button in the left column of the table opens the dialog. Kpa-clawbot/CoreScope#1486/"Group Data" message type missing from packet view window's "message type" filter Kpa-clawbot/CoreScope#1791 seed SQL, corescope-migrate, seed-2073/-199/-245*.sql): 153/156 passed, 3 skipped. The 3 skips are pre-existing, fixture-size-dependent skip guards already documented in the file ("no packet with ≥2 observations found in first 10 rows", "no multi-hop packet with byte breakdown", "no multi-observation packet in first 10 group rows") — unrelated to scope-audit. Both Scope Audit cases pass: "Scope Audit: lazy tab, window, local search, stable refresh and deep link" and "Scope Audit: empty and failed responses remain actionable". An initial run against an under-seeded fixture (missing the deploy.yml seed-SQL steps) spuriously failed an unrelated "Group Data" message type missing from packet view window's "message type" filter Kpa-clawbot/CoreScope#1791 test; rebuilding the fixture to match CI's exact recipe fixed that — not a scope-audit issue. [T]
  • Browser check of Analytics → Scopes → Scope Audit: opened against the local server, switched sub-tab, confirmed the empty state ("No confirmed observer declarations available…") with zero console errors, then set one fixture node's configured_scope and confirmed the populated table renders correctly (declared/observed chips, assessment, ambiguous-hop count) with zero console errors — screenshot captured locally. [T]

Mutants

No fix-worthy findings survived investigation (items 2–6, 8 above were already compliant on the branch as pulled), so there is nothing to mutate — one mutant is produced per finding that required a code change, and none did. Where I disagreed that a listed risk area required a change, the reasoning and evidence are in items 2, 3, 4, 5, 6 above rather than silently skipped.

CI (per job, on 66bce8b3)

All checks green on https://github.com/dborup/CoreScope/actions/runs/38526649946 as of the 3rd attempt. PR left as-is (not draft already; not marked ready, no merge, no issue closed).

[T] = local test/benchmark run, [A] = code/diff reading & reasoning, [K] = GitHub Actions CI evidence.

@dborup-agent

Copy link
Copy Markdown
Collaborator

Review — CS-MacBook PR#378 — head 66bce8b

Dom: APPROVE med nits

Read-only review. Head was 66bce8b3 before and after (git ls-remote). Evidence: [T] I ran it, [A] I read code or diff, [K] CI evidence.

Premise check

PR #378 is the original Scope Audit feature PR (2 commits: the feature and a merge of bcf263e1), not a nit follow-up. I found no separate issue and no earlier review comment. The only checklist available was the author's 9-item report, so I checked those items one by one against the code. If a different issue or review text is the reference, it was not available to me.

Findings

# Sev Finding
1 Process The head is behind origin/master (89adc5be). Merging it conflicts in public/style.css. Both sides append at the end of the file; keeping both blocks resolves it, and I did that in my scratch merge. The PR needs a master merge before it can land. [T]
2 Nit handleScopeAudit builds inside singleflight with context.WithTimeout(r.Context(), …) (scope_audit.go, handler). The first caller's context drives the shared build. If that client disconnects mid-build, every coalesced waiter gets a 500 context canceled, and nothing is cached. context.WithoutCancel(r.Context()) plus the existing 20s timeout avoids this. Not run, [A].
3 Nit (test gap) Four mutants survive; see Mutants. The ambiguous-hop expansion to per-row AmbiguousHops, the listener-only exclusion (markNonRelay), and the singleflight re-check have no test. Two of these are behaviours the PR text claims ("respects hidden identities"/listener identities, shared cache fill).
4 Nit (test gap) declarationAge hours branch is untested (only 1d and Unknown are asserted). Mutant F10 survives.
5 Cosmetic scopeAudit scopeAuditCache was inserted in Server under the "Cached /api/scope-stats response" comment. It belongs in its own group. [A]
6 Info The response-level ambiguousHops is not recomputed after hidden-identity filtering, unlike summary. It is a count only and leaks no identity. Design choice, no change requested. [A]

Answers to the author's 9 items

  1. Master merge — ordinary merge commit, no force-push, authors correct. Confirmed [A]. Superseded by finding 1.
  2. security(api): bound public analytics response caches #430 cache bound — agreed, no change needed. The handler rejects any window outside 1h/24h/7d with 400 before any cache or DB work, so the map has at most 3 keys; search is client-side only. [A][T] (?window=bad → 400 on my local server)
  3. Escaping — agreed. scope-audit.js uses only createElement + textContent; the unit test fails on any innerHTML write and checks an <img onerror> name. scripts/check-xss-sinks.sh --diff 89adc5be exits 0. [T]
  4. Leaks — agreed. Listeners are on nodes the view creates, and destroy() is wired into the sub-tab switch and the analytics destroy(). Mutant F8 (inactive-input guard) is caught; F7 is equivalent because the timer callback also checks active. [A][T]
  5. Sharding — agreed; the new E2E is a helper required from the already-sharded test-e2e-playwright.js, and the other two are registered unit tests. test-ci-shards-style checks are green in CI. [A][K]
  6. fix(hops): avoid unproven receiver-region narrowing #427 — agreed, not applicable. [A]
  7. PR body — no closing keyword and no issue reference; commit messages have none either. [A]
  8. No map[string]interface{}, server read-only — confirmed. No map[string]interface{} or map[string]any in the added lines (all types are structs), and only SELECTs are issued. [T][A]
  9. -race — not re-run by me (I ran the plain suites below). CI Go job is green. [K]

Hard checks

  • Commit authors and committers are dborup <kontakt@meshview.dk> on both commits. [T]
  • Fork guards: deploy.yml 9 and release-fast-path.yml 1, in the merged tree; the PR does not touch .github. [T]
  • No hardcoded colors in added public/ lines (CSS uses var(--…)). [T]
  • cmd/server stays read-only. [A][T]
  • No behaviour changes outside the feature. The analytics.js changes are the lazy audit panel, teardown, and a _refreshScopes re-entry. Config-like values (7d staleness, 50 rows, 150 ms debounce, 30 s TTL, 20 s deadline) are listed in the docs as a later customizer milestone, not exposed silently. [A]

Tests

On the merged tree (origin/master 89adc5be + head, style.css resolved by keeping both blocks):

  • cmd/server go test ./...: ok (59.5 s). [T]
  • cmd/ingestor go test ./...: ok (109 s). [T]
  • sh test-all.sh: 248 passed, 0 failed (248 files). [T]
  • node test-frontend-helpers.js: 713 passed, 0 failed. [T]
  • test-e2e-playwright.js against a local Go server (fixture prepared as in CI: freshen, Packets page collapse button in the left column of the table opens the dialog. Kpa-clawbot/CoreScope#1486/"Group Data" message type missing from packet view window's "message type" filter Kpa-clawbot/CoreScope#1791 seed SQL, corescope-migrate, seeds 2073, 199, 245): 154/157 passed, 0 failed, 3 skipped (pre-existing fixture guards). Both Scope Audit cases passed. [T]
  • test-issue-205-analytics-subtab-deeplinks-e2e.js: 15 passed. test-analytics-tab-state-and-query.js: 39 passed. [T]
  • API sanity on the fixture with all repeaters given a declaration: 172 rows, status no-evidence, 410 ambiguous hop observations (fixture hop prefixes are short). I reverted that edit afterwards. [T]
  • CI on 66bce8b3, per job: Go Build & Test, Playwright 1/3, 2/3, 3/3, Validate Docker Image, Build & Publish Docker Image, and Verify E2E Shards are all pass; Deploy/Release/Badges skipped as expected. Shard 3 needed a rerun after two different failures (test-channels-client-state-152-e2e.js, test-issue-1640-compare-discovery-e2e.js). Neither file is touched by this PR. I did not read those job logs, so unrelated-flake is the author's claim plus my diff check, not my own reproduction. [K]

Mutants (my own; scratch copies, go test -run ScopeAudit and node test-scope-audit.js)

Mutant Result
M1 drop per-transmission dedup (Forwarded++ always) killed
M2 wildcard contradiction ignores declared * killed
M3 flood-route filter >2 instead of 0/1 killed
M4 stale threshold 7d → 30d killed
M6 cache TTL always valid killed
M7 hidden-identity filter replaced killed
M10 observation window upper bound removed killed
M11 transport-code cross-check disabled killed
M5 drop singleflight re-check survives
M8 per-row ambiguous-hop expansion zeroed survives
M9 listener-only exclusion removed survives
F1 stale-response guard removed killed
F3 page size 50 → 5000 killed
F4 stale ignored in assessment killed
F5 row signature diff disabled killed
F8 inactive-input guard removed killed
F9 saq not parsed from hash killed
F10 hours formatting wrong survives
F7 destroy() skips clearTimeout equivalent (callback checks active)

(Two first attempts at M7/M8 failed to build and were redone as compiling mutants.)

Not verified

  • The author's -race full-package run and the Linux benchmark (138.6 ms/op on the author's machine; a slower figure on another host). I did not run the benchmark.
  • Staging or prod behaviour with real declarations; the fixture has none, so populated rendering rests on the PR's mocked E2E plus my API sanity run.
  • Visual check in a real browser by me; I relied on the Playwright cases.
  • CI flake logs (see above).

… close mutant gaps

Review — CS-MacBook PR#378: handleScopeAudit derived the shared
singleflight build's context from the first caller's r.Context(), so
that caller disconnecting canceled the build for every coalesced
waiter. Detach with context.WithoutCancel, keeping only the absolute
deadline.

Also: move the scopeAuditCache field out of the scope-stats struct
comment group (cosmetic), and add tests for the four surviving
mutants (singleflight recheck, per-row AmbiguousHops expansion,
listener-only exclusion, declarationAge hours formatting).
@dborup

dborup commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

Rapport — CS-Minimax PR#378 master-sync — head 25569b1

Review feedback addressed (commit 25569b16).

Findings

  1. [Process] Head behind origin/master, conflicts in public/style.css. Merged origin/master (89adc5be) into codex/scope-audit with an ordinary merge commit (5206ad86, author/committer dborup <kontakt@meshview.dk>, no force-push). The only conflict was the predicted append-conflict in public/style.css (Scope Audit block vs. Regions-map block); resolved by keeping both blocks, matching the reviewer's own scratch resolution. [T]
  2. [Nit, fixed] handleScopeAudit tied the shared singleflight build's context to the first caller's r.Context(). If that client disconnected mid-build, every coalesced waiter got a 500 and nothing was cached. Fixed exactly as proposed: context.WithTimeout(context.WithoutCancel(r.Context()), scopeAuditQueryTimeout) — detaches from the caller's cancellation, keeps the existing 20s absolute deadline. Added TestScopeAuditHandlerSingleflightShareSurvivesFirstCallerDisconnect, which forces caller A to become the singleflight leader with a ~14 ms build (6000 observations), cancels A's context 2 ms after B joins, and asserts B still gets 200. Confirmed red against the un-fixed line (reliably reproduced over 3 runs), green with the fix, and clean under -race. [T]
  3. [Nit test gap, fixed] Mutants M5 (drop singleflight recheck), M8 (zero per-row AmbiguousHops expansion), M9 (drop listener-only exclusion) survived. All three now have dedicated coverage:
    • M5 — added a recheckHook test seam on scopeAuditCache (same pattern as the existing distanceBuildHook seam in store.go; nil/zero-cost in production), and TestScopeAuditCacheRecheckInsideSingleflightReusesConcurrentFill, which lands a fresh cache entry in the hook and asserts build is never called.
    • M8 — extended TestScopeAuditCollisionAndWindow's existing 1h-window assertion to also check r.Rows[0].AmbiguousHops == 1 (per-row), not just the response-level total.
    • M9 — added TestScopeAuditListenerOnlyNodeExcludedFromForwardedCount: a declared repeater marked can_relay=0 in observers (feat(disambiguator): use new firmware repeat: on|off hint to exclude listening-only observers from path-hop candidates Kpa-clawbot/CoreScope#1290) must not have its own hop token counted as a confirmed relay (Forwarded stays 0, status no-evidence).
  4. [Nit test gap, fixed] F10 (declarationAge hours formatting) survived. Added assert.strictEqual(audit.declarationAge('7200'), '2h') to test-scope-audit.js.
  5. [Cosmetic, fixed] scopeAudit scopeAuditCache field was grouped under the /api/scope-stats comment. Moved it into its own // Cached /api/scope-audit response group in routes.go, after the scope-stats fields.
  6. [Info, no change] ambiguousHops not recomputed after hidden-identity filtering. Agree with the reviewer's own conclusion — it's a count only, leaks no identity, and is a documented design choice. Left as-is.

Mutants

One mutant per fixed finding, each confirmed caught before restoring the fix:

Mutant What it did Result
Context-cancellation revert context.WithTimeout(r.Context(), …) (pre-fix) caught — TestScopeAuditHandlerSingleflightShareSurvivesFirstCallerDisconnect fails, 3/3 runs [T]
M5 removed the recheck inside sf.Do caught — TestScopeAuditCacheRecheckInsideSingleflightReusesConcurrentFill fails [T]
M8 target.row.AmbiguousHops += count → no-op caught — TestScopeAuditCollisionAndWindow fails (AmbiguousHops:0) [T]
M9 pm.markNonRelay(listeners) → no-op caught — TestScopeAuditListenerOnlyNodeExcludedFromForwardedCount fails (Forwarded:1) [T]
F10 hours divisor /3600 → /60 caught — test-scope-audit.js fails ('120h' !== '2h') [T]

Tests

On the merged tree (origin/master 89adc5be + head 25569b16):

  • cd cmd/server && go test ./...: ok, 52.7s. [T]
  • cd cmd/server && go test ./... -run ScopeAudit -race: ok, 8.8s, no races, 5 consecutive runs of the non-race suite all green (no flake observed). [T]
  • cd cmd/ingestor && go test ./...: ok, 129.8s. [T]
  • sh test-all.sh: 248 passed, 0 failed (248 files). [T]
  • node test-frontend-helpers.js: 713 passed, 0 failed. [T]
  • node test-test-all.js (registry self-test, confirms every new root test-*.js from both this PR and the master merge — test-scope-audit.js, test-regions-map.js, test-analytics-subtab-deeplinks-205.js, test-issue-441-disable-mosquitto.js — is already correctly registered in test-all.sh or scripts/e2e-shards.json; test-regions-map-e2e.js was already present there): 10 passed, 0 failed. [T]
  • test-e2e-playwright.js against a local Go server (fixture prepared as in CI: freshen, Packets page collapse button in the left column of the table opens the dialog. Kpa-clawbot/CoreScope#1486/"Group Data" message type missing from packet view window's "message type" filter Kpa-clawbot/CoreScope#1791 seed SQL, corescope-migrate, seeds 2073/199/245, .git-commit written for the Version perf card): 154/157 passed, 0 failed, 3 skipped (pre-existing fixture guards). Both Scope Audit cases and the new Regions-map deep-link case passed. [T]
  • test-issue-205-analytics-subtab-deeplinks-e2e.js: 15 passed, 0 failed. [T]
  • test-nav-priority-1391-e2e.js: 36/36 passed (confirms the Priority+ nav merges from master survived intact). [T]
  • test-regions-map-e2e.js: passed (confirms the Regions-map feature from Add observed relay Regions map #376 survived the merge). [T]
  • npm install --no-save eslint@8 && npx eslint public/*.js (matches deploy.yml's pinned eslint@8/legacy-config invocation): 0 errors, 91 pre-existing warnings (same files/lines the reviewer already noted, e.g. analytics.js). [T]
  • bash scripts/check-xss-sinks.sh --diff 89adc5be: exit 0. [T]
  • API sanity: GET /api/scope-audit?window=bad → 400; GET /api/scope-audit?window=24h on the clean fixture (no declarations) → rows:0; /api/health reports commit: 5206ad86... confirming the merge landed. [T]

CI (run 38550922015, head 25569b16)

Job Result
Go Build & Test success [K]
Playwright E2E Tests 1/3 success [K]
Playwright E2E Tests 2/3 success [K]
Playwright E2E Tests 3/3 success [K]
Validate Docker Image success [K]
Verify E2E Shards & Coverage success [K]
Build & Publish Docker Image success [K]
Release Artifacts skipped (expected, draft/non-release) [K]
Deploy Staging skipped (expected) [K]
Publish Badges & Summary skipped (expected) [K]

No reruns were needed — none of the known-flaky tests (#271, #301) triggered a failure on this run.

Rester

  • Finding 6 (ambiguousHops not recomputed after hidden-identity filtering): left unchanged, per agreement with the reviewer's own "design choice, no change requested" — it's a count only and leaks no identity.

@dborup
dborup merged commit 94dedd7 into master Oct 14, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants