Skip to content

Build direct-onchain admin dashboard - #37

Merged
snissn merged 11 commits into
mainfrom
codex/issue-32-admin-dashboard
Jul 2, 2026
Merged

Build direct-onchain admin dashboard#37
snissn merged 11 commits into
mainfrom
codex/issue-32-admin-dashboard

Conversation

@snissn

@snissn snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member

Linked Issues

Closes #32.
Refs #27, #29, #30, #31, #33, #5.

Dependency Position

This is D3 in the direct-onchain dashboard stack:

#29 contract pagination -> #30 docs -> #31 Token Host wrapper -> #32 Worker dashboard -> #33 Calibration evidence

#29, #30, and #31 are merged on main. #33 remains responsible for publishing updated Calibration/demo evidence against a registry that supports the new pagination ABI.

Start-Phase UI/Data Contract

The Worker dashboard is public/read-only and treats FocPlatformRegistry direct views as the current-state source when the configured registry runtime hash matches the current pagination-capable artifact hash:

  • /api/admin/overview: bounded count reads for objects, accounts, datasets, coordinators, and relayers.
  • /api/admin/files: cursor-paginated object list/detail reads.
  • /api/admin/accounts: offset-paginated account usage reads.
  • /api/admin/datasets: offset-paginated dataset record reads.
  • /api/admin/coordinators: offset-paginated coordinator/relayer reads.
  • /api/admin/reconciliation: cursor-paginated, page-scoped object reconciliation checks. Account-usage, dataset-record, and coordinator-policy check families are declared as omitted instead of scanning the whole registry from one Worker request.

The first screen at /, /demo, and /admin is now the FOC Platform admin console rather than a static evidence page. Existing evidence endpoints remain available. For the committed pre-pagination Calibration registry, dashboard APIs default to skipped read-only payloads instead of live-reading missing count/list methods; ?live=true remains available for an upgraded registry. Skipped dashboard responses render as an unavailable state instead of an empty table.

Data Source Mapping

  • Counts come from objectCount, accountCount, datasetRecordCount, coordinatorCount, and relayerCount.
  • File rows come from listObjects, getStorageObject, getCopyReceipts, and receiptPayer.
  • Account rows come from listAccountIds, listAccountObjects, and getAccountUsage.
  • Dataset rows come from listDatasetKeys and getDatasetRecord.
  • Coordinator/relayer rows come from listCoordinators, coordinatorPolicies, listRelayers, and isRelayer.
  • Reconciliation uses the current object cursor page from the Wire Token Host wrapper to FOC Platform onchain list reads #31 direct-read wrapper and keeps FOC/payment evidence as optional public evidence, not implied truth.

The file table intentionally exposes raw object/copy receipt fields only. Reconciliation-derived warnings stay in /api/admin/reconciliation so page-local file reads do not claim false dependency errors from partial data.

The coordinator dashboard renders coordinator policies and relayer rows as separate sections, so relayer-only pages do not collapse into the generic empty state. The coordinator tab pager combines coordinator and relayer pagination so relayer-only next pages remain reachable.

Current Test Evidence

Post-filter-pagination local validation on 96e1dc1:

  • node --test test/calibration-worker.test.mjs -> 13 tests passed.
  • pnpm lint -> workspace scaffold checks passed.
  • git diff --check -> clean.
  • pnpm test -> 118 Node tests and 29 Foundry tests passed.
  • pnpm ops:validate -> secret scan findings: 0.
  • pnpm ops:smoke -- --iterations 3 -> 3 mocked API/coordinator iterations passed.
  • pnpm worker:dry-run -> Wrangler 4.106.0, upload 834.13 KiB / gzip 167.30 KiB.

Earlier local evidence on this PR also included pnpm build:artifacts, clean artifact diff checks, direct regression coverage for mixed-case coordinator filtering, relayer global search filtering, shared-filter pagination reset, default skipped dashboard read gate, bare-hex runtime hash matching, relayer-only rendering, relayer pagination, page-scoped reconciliation, skipped warning metrics rendering as n/a, and stale dashboard response suppression.

Screenshot / Browser Verification

Fresh local Worker checks after the relayer pagination fix:

  • pnpm worker:dev -- --port 8795 served at http://localhost:8787.
  • Playwright temp spec mocked /api/admin/coordinators with empty coordinator pagination and relayer hasNextPage: true; verified the Next button was enabled, advanced to offset=20, and rendered the second relayer.
  • Screenshot: /tmp/foc-platform-admin-issue32-relayer-pagination.png.

Fresh local Worker checks after the relayer render fix:

  • pnpm worker:dev -- --port 8794 served at http://localhost:8787.
  • Playwright temp spec mocked a relayer-only /api/admin/coordinators payload and verified the coordinator tab renders a Relayers section plus 0x0000000000000000000000000000000000004000, without the No rows on this page empty state.
  • Screenshot: /tmp/foc-platform-admin-issue32-relayer-only.png.

Earlier local Worker checks after the default-live gate:

  • pnpm worker:dev -- --port 8793 served at http://localhost:8787.
  • Desktop screenshot: /tmp/foc-platform-admin-issue32-default-gated-desktop.png.
  • Mobile screenshot: /tmp/foc-platform-admin-issue32-default-gated-mobile.png.
  • Playwright DOM checks on /: title and H1 are FOC Platform Admin, 5 nav buttons, body-level horizontal overflow 0 on desktop and mobile.
  • Default /api/admin/overview returned source: "skipped", dashboardLiveDefault: false, expected runtime hash 0x2c49443e7a9ebf3337453240e706df249d29f4f217ec948d6c10e9502a199d1f, and current configured registry runtime hash 0xed478a27e255a1b27989ffa4f2fcbf38f1a9ec61a84c8d3e20aceb4e26f72040.

Pre-gate screenshots from the direct dashboard fixture path remain available at /tmp/foc-platform-admin-issue32-rebased-*.png.

Worker / Wrangler Evidence

The dashboard dry-run bundles through Wrangler and exposes only public read env vars from the existing demo configuration. The current deployed demo registry predates the pagination ABI; live public evidence for the new direct-list dashboard is intentionally deferred to #33. The dashboard now avoids opening the deployed pre-pagination config in a live-read error state and renders skipped responses explicitly as unavailable.

Secret-Surface Assessment

  • No private keys, session keys, coordinator secrets, payment credentials, admin tokens, or write paths were added.
  • pnpm ops:validate reported secretScan.findings: 0 across tracked files.
  • Dashboard APIs are GET only and read-only.
  • The default pre-pagination config returns explicit skipped/read-only dashboard payloads; ?live=true is explicit and should be used only with an upgraded pagination-capable registry.

AI Review Status

Copilot reviewed c92d9ad and raised two issues; both were fixed in 222e303:

  • unused buildAdminSurfaces import;
  • case-sensitive coordinator filtering.

Codex reviewed 222e303 and raised a P2 default-live-read issue for the committed pre-pagination registry. Fixed in ce5beaf by gating default dashboard live reads on runtime hash match and documenting the #33 boundary.

Codex reviewed ce5beaf and raised a P2 relayer-only rendering issue. Fixed in 4588fcf by rendering coordinator policies and relayers as separate dashboard sections.

Codex reviewed 4588fcf and raised a P2 relayer-pagination issue. Fixed in 9d0d677 by combining coordinator and relayer pagination for the coordinator tab pager.

Codex reviewed 9d0d677 and raised a P2 reconciliation fanout issue. Fixed in ce1221f by making /api/admin/reconciliation page-scoped and cursor-paginated; the thread was replied to and resolved.

Codex reviewed ce1221f and raised a P2 skipped-response rendering issue. Fixed in c8e6838 by rendering source: "skipped" dashboard payloads as unavailable before table rendering; the thread was replied to and resolved.

Codex reviewed c8e6838 and raised a P2 runtime-hash normalization issue. Fixed in da4ac1c by stripping an optional 0x prefix before comparing runtime hashes; the thread was replied to and resolved.

Codex reviewed da4ac1c and raised two P2 dashboard state issues. Fixed in ee6d632 by rendering skipped warning/mismatch counts as unavailable and by discarding stale dashboard fetch responses after view/filter changes; both threads were replied to and resolved.

Codex reviewed ee6d632 and raised a P3 relayer-search issue. Fixed in 8cb17e9 by filtering relayer rows through the same global q path as coordinator rows; the thread was replied to and resolved.

Codex reviewed 8cb17e9 and raised a P2 shared-filter pagination reset issue. Fixed in 96e1dc1 by resetting every view cursor/offset when shared filters change; the thread was replied to and resolved. Copilot reviewed 96e1dc1 cleanly, Codex reported no major issues on 96e1dc1, latest-head CI passed, and all review threads are resolved.

Copilot AI review requested due to automatic review settings July 2, 2026 00:05
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review @copilot review @coderabbitai review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Calibration Worker to serve a public, read-only “FOC Platform Admin” dashboard as the default HTML surface, backed by direct FocPlatformRegistry count/list/detail reads and new /api/admin/* endpoints, while preserving the existing evidence endpoints and clarifying the demo’s source-of-truth boundaries in docs.

Changes:

  • Switch the Worker’s primary HTML route (/, /demo, /admin) to the admin dashboard UI and add dashboard JSON endpoints under /api/admin/*.
  • Add Node tests that exercise the new dashboard endpoints via an injected adapter/fixture model.
  • Update docs/README to describe the new dashboard routes, pagination model, and the “pre-pagination ABI” caveat for the currently deployed Calibration registry.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/calibration-worker.test.mjs Adds dashboard route/API tests and a fixture adapter to validate injected direct-read pages.
src/worker/calibration-demo.mjs Implements /api/admin/* routes and replaces the demo HTML with the admin dashboard UI + client-side fetch/paging.
src/registry/read-model.mjs Switches registry artifact loading to an ESM JSON import for runtime/bundle compatibility.
README.md Documents the dashboard-first Worker behavior and the new admin API endpoints.
docs/calibration-worker-demo.md Updates demo docs with dashboard endpoints, pagination semantics, and evidence caveats.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/worker/calibration-demo.mjs
Comment thread src/worker/calibration-demo.mjs Outdated
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review @copilot review @coderabbitai review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review @copilot review @coderabbitai review

Code Review

Overall the dashboard implementation is clean and well-structured. One bug was identified and already fixed in commit 222e303:

Bug fixed — filterCoordinatorRows case-insensitive comparison (line 783)
The coordinator query param was lowercased (.toLowerCase()) before comparison, but row.coordinator was compared as-is (row.coordinator === coordinator). Since EVM addresses from the contract come back checksummed (mixed case), this filter would silently return no results for any ?coordinator= query. Fixed to match the pattern in filterObjectRows:

- rows.filter((row) => !coordinator || row.coordinator === coordinator),
+ rows.filter((row) => !coordinator || String(row.coordinator ?? "").toLowerCase() === coordinator),

A test covering the case-insensitive coordinator filter was added alongside the fix.


Other observations (no changes needed):

  • src/registry/read-model.mjs: Switching from readFileSync to import … with { type: "json" } is the correct approach for Cloudflare Workers compatibility — Node FS APIs are not available in that runtime.

  • HTML escaping: All server-side template values go through escapeHtml. The only JS literal injected directly is JSON.stringify(DASHBOARD_API_ENDPOINTS) (hardcoded paths) and the boolean live, both of which are safe.

  • Client-side XSS: The inline esc() helper in the browser script escapes &, <, >, ", ' before any untrusted contract data is set as innerHTML. The data-copy clipboard path is also escaped through esc.

  • Input validation: parseBigIntString guards cursor/offset params with /^\d+$/; dashboardPageLimit clamps to the configured max page size; isAddress guards the registry address before creating a public client.

  • hasNextPage heuristic: rowCount >= pageLimit is a standard "could-have-more" heuristic. It may show a disabled empty last page, but doesn't leak data or cause errors.

  • Two pre-existing test failures (spawn anvil ENOENT for dev-upload-spine and platform-api) are environment-specific (Foundry's anvil binary not installed locally) and unrelated to this PR. CI passes.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review @copilot review @coderabbitai review

Code Review — current HEAD (222e303)

CI passes and all 13 calibration-worker tests pass locally. The two issues from the previous review are both resolved:

  • Unused buildAdminSurfaces import — removed from src/worker/calibration-demo.mjs (line 3 deleted).
  • Case-insensitive coordinator filterfilterCoordinatorRows now normalises row.coordinator with .toLowerCase() before comparing, matching the pattern already used in filterObjectRows. A regression test with a checksummed address (0x000000000000000000000000000000000000ABCD → fixture 0x000000000000000000000000000000000000abcd) covers the fix.

No new issues identified. The implementation is clean:

  • All server-side template values go through escapeHtml; the only JS literals injected directly (DASHBOARD_API_ENDPOINTS, live) are hardcoded/boolean and safe.
  • Client-side esc() escapes &, <, >, ", ' before any contract data touches innerHTML.
  • Cursor/offset params are guarded by /^\d+$/; registry address is validated with isAddress before a public client is created.
  • Dashboard APIs are GET-only and read-only — no write paths added.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 00:16

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 222e303791

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/worker/calibration-demo.mjs Outdated
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review @copilot review @coderabbitai review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review @copilot review @coderabbitai review

Code Review — current HEAD (ce5beaf)

CI passes and all 13 calibration-worker tests pass locally.

New in ce5beaf — ABI gate for default live reads

dashboardLiveReadsEnabled now checks the committed registry runtime SHA-256 against registryArtifact.deployedBytecodeSha256 to decide whether the default (no ?live= param) should attempt live contract reads. For the pre-pagination Calibration registry the hashes differ, so the default is skipped; ?live=true forces live reads; ?live=false forces skip. The gate is correctly applied to both the HTML render path and the /api/admin/* JSON paths.

normalizeHash lower-cases before comparing — consistent with the coordinator-filter fix.

dashboardMetadata now includes expectedRuntimeSha256 and dashboardLiveDefault, which let callers understand why reads were skipped without inspecting env vars.

The client-side fetchJson now always passes an explicit live=true/false param so the browser UI and the Worker route are always in sync (no ambiguous "no param" state from the client).

No issues identified.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 00:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce5beaff72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/worker/calibration-demo.mjs Outdated
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review @copilot review @coderabbitai review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review @copilot review @coderabbitai review

Code Review — current HEAD (4588fcf)

CI passes and all 13 calibration-worker tests pass locally.

New in 4588fcf — separate relayer rendering

renderCoordinatorView replaces the previous single-table coordinator render. It builds coordinator policies and relayers as independent <div class="subtable-title"> + <table> sections, so a relayer-only response correctly renders a "Relayers" section rather than collapsing into the "No rows on this page" empty state. The shared tableMarkup helper is correctly extracted and reused by both the new function and the existing table() utility.

All section titles (Coordinator policies, Relayers) are hardcoded strings, not contract data, so they don't require escaping. Cell data continues to route through copy() / pill() / esc() as appropriate.

The empty-state guard (sections.length === 0) is correct — it only fires when both coordinators and relayers arrays are empty.

No issues identified.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 00:40
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review
@copilot review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review
@copilot review

Code Review — current HEAD (da4ac1c)

All 13 calibration-worker tests pass.

New in da4ac1c — runtime hash normalization

normalizeHash now strips an optional 0x prefix (replace(/^0x/, "")) before the lowercase comparison in dashboardDirectReadAbiMatches. This means FOC_PLATFORM_REGISTRY_RUNTIME_SHA256 accepts both 0x2c49443e... and 2c49443e... without a false mismatch. The artifact's deployedBytecodeSha256 (0x2c49443e...) and the env-supplied value are both normalized before comparison, so neither format is privileged.

The regression test passes a bare-hex env value (.replace(/^0x/i, "")) and confirms the overview response returns dashboardLiveDefault: true and objectCount: 2 — matching the fully-prefixed path already covered in the prior upgradedOverview assertion.

No issues identified.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 01:30

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: da4ac1cff8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/worker/calibration-demo.mjs Outdated
Comment thread src/worker/calibration-demo.mjs Outdated
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review
@copilot review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review
@copilot review

Code Review — current HEAD (ee6d632)

All 13 calibration-worker tests pass.

New in ee6d632 — stale response suppression and warnings unavailable guard

Stale response suppression: state.requestSeq is incremented at the start of every loadView call. After await fetchJson(...) resolves, the guard requestId !== state.requestSeq || view !== state.view silently drops the response if either a newer request has started or the view changed while the fetch was in-flight. The explicit const view = state.view capture ensures the fetch, URL construction, rendering, and footer all operate on the view that was active at call time — not whatever state.view is at render time. fetchJson, renderView, renderFooter, and currentPage all accept a view parameter for this.

Warnings unavailable guard: The previous check (warningCount === null || mismatchCount === null) would pass undefined values through to Number(undefined) = NaN. The new warningsUnavailable flag covers both null and undefined, so the "Warnings" metric correctly shows n/a for skipped or partial overview payloads.

Both the requestId pattern and the warningsUnavailable check are covered by the HTML-bundle assertions in the updated test.

No issues identified.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 01:44

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ee6d632a28

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/worker/calibration-demo.mjs Outdated
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review
@copilot review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review
@copilot review

Code Review — current HEAD (8cb17e9)

All 13 calibration-worker tests pass and CI is green.

New in 8cb17e9 — relayer global search filtering

filterRelayerRows delegates to textFilter with ["relayer", "allowed"] fields, matching the pattern already used by filterCoordinatorRows, filterAccountRows, and filterDatasetRows. The ?q= needle is applied to both the relayer address and its boolean allowed value (coerced via String(...).toLowerCase()), which is consistent with how the coordinator tab handles address and session-status text search.

The fix is correctly applied at the readDashboardApi return site — filterRelayerRows(relayerPage.relayers, query) replaces the bare relayerPage.relayers pass-through that previously ignored the q parameter for relayers.

The regression test sends ?q=<RELAYER> and asserts coordinators: [] (no false positives) and relayers: [RELAYER] (correct match), giving both sides of the cross-tab isolation.

No issues identified. Implementation is ready for merge.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 01:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8cb17e96ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/worker/calibration-demo.mjs Outdated
@snissn

snissn commented Jul 2, 2026

Copy link
Copy Markdown
Member Author

@codex review
@copilot review

Copilot AI commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

@codex review
@copilot review

Code Review — current HEAD (96e1dc1)

All 13 calibration-worker tests pass and CI is green.

New in 96e1dc1 — reset all views on shared filter changes

resetPage now accepts an optional view parameter (defaulting to state.view) so it can be called for any view, not just the active one. resetAllPages iterates Object.keys(state.pages) and delegates to resetPage(view) for each, resetting cursors/offsets across all five views atomically.

Previously, changing status, provider, limit, or q only reset the active view's cursor/offset. Any non-active view with a stale page position would still serve old results after a filter change. resetAllPages at both call sites (the change handler for status/provider/limit, and the debounced input handler for q) ensures all views are reset together whenever a shared filter changes.

applyPageAction still calls the no-arg resetPage() (active view only), which is correct — the First button should only reset the current tab, not all tabs.

The regression test asserts both function resetAllPages() and Object.keys(state.pages).forEach((view) => resetPage(view)) appear in the served HTML bundle, plus that both filter event handlers call resetAllPages().

No issues identified. Implementation is ready for merge.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

Copilot finished work on behalf of snissn July 2, 2026 02:07
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 96e1dc1bc6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@snissn
snissn merged commit ff85d8e into main Jul 2, 2026
2 checks passed
@snissn
snissn deleted the codex/issue-32-admin-dashboard branch July 2, 2026 02:15
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.

Build direct-onchain admin dashboard for platform usage

3 participants