Skip to content

analytics: deep-link inner views (Scopes sub-tabs + window, audit other tabs' local view state) #205

Description

@dborup

Summary

Inner views of analytics tabs cannot be deep-linked. The clearest case is the Scopes tab:

  • its sub-tabs Overview / Hop Depth / Regions / Hygiene and its window picker 1h / 24h / 7d are kept only in sessionStorage (public/analytics.js around lines 4959–5074);
  • they are never written to the URL;
  • so #/analytics?tab=scopes always opens the last-used or default sub-tab, and a link to "Hop Depth" cannot be shared.

This breaks the AGENTS.md deep-link rule: tabs, filters, selected items and view modes must be reflected in the URL hash. It is not a regression; current production behaves the same.

Existing patterns to follow

  • #/analytics?tab=…&window=… via _updateAnalyticsUrl() / URLState.updateHashParams in analytics.js.
  • Hash Stats writes bytes and section into the hash (around line 1713).
  • Node page ?section= scrolls to a section (public/nodes.js around line 945).
  • fix(analytics): escape-safe ?tab= lookup and withQuery contract (#193) #194: URL values are looked up by exact comparison (dataset.x === value), never by building a selector from the URL, and unknown values fall back to the default.

Scope

  1. Scopes tab:

    • add sub=<overview|hopdepth|regions|hygiene> and use the existing window=, or a tab-specific key if window already means something else for Scopes, and document the choice;
    • read them on mount and write them on click;
    • a URL value wins over sessionStorage;
    • unknown values fall back to the defaults;
    • back and forward restore the state.
  2. Audit of the other analytics tabs for inner view state that lives only in memory or sessionStorage/localStorage:

    • e.g. the second window picker around line 6380 (another tab's selectedWindow);
    • Foreign Traffic, Wardriving, Areas and Roles;
    • the repeater-metrics scatter axes and the neighbor-graph min score (around lines 2980 and 3261).

    For each item, either bring it into the URL with the same pattern, or record why it should stay local (e.g. a pure display preference).

  3. No change to the URLs that are produced today for the default state (tab omitted for Overview, etc.).

Acceptance criteria

  • #/analytics?tab=scopes&sub=hopdepth opens Scopes on Hop Depth, both on a cold load and when navigating there from another page. Clicking a sub-tab updates the URL. Reload and back/forward keep the state.
  • Hostile or unknown sub/window values never throw and fall back to the defaults (tests, as in fix(analytics): escape-safe ?tab= lookup and withQuery contract (#193) #194).
  • Each audited tab is either deep-linked with a test, or listed with a reason in the PR description.
  • Unit tests (vm harness, as in test-analytics-tab-state-and-query.js) and at least one E2E in the Playwright step. Fork guards are unchanged.

Activity

  1. added a commit that references this issue on Oct 4, 2026
  2. dborup commented on Oct 4, 2026

    @dborup
    OwnerAuthor

    Fixed by #206 (merged as 066fbf54): the Scopes sub-tab and window are now in the URL (#/analytics?tab=scopes&sub=…). The URL wins over sessionStorage, and hostile values fall back safely. The PR contains the audit table of the other tabs.

    Review follow-ups, tracked in #208:

    • back/forward to entries in the default state;
    • the Hash Stats mb-filter and sort are missing from the audit;
    • the Hash Issues keys are not cleared on a tab switch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions