Skip to content

Analytics configuration, schema viewer, and the Report Builder: what to review โ€‹

FieldValue
Branchfeat/admin-and-merchant-portals, draft PR #976: feat(admin): portal navigation, financials and monitoring, plus the agent-process work behind them, not merged
ProjectREADME.md
Issue#987: feat(admin/analytics): a configurations page, a BigQuery-sourced schema viewer, and the BigQuery page becomes the Report Builder
Servers you needAdmin portal on http://localhost:3001 (npm run admin:dev). Admin Storybook on http://localhost:6008 (npm run storybook:admin)
Local originsRequired for the Configurations page to show real retention data. See the warning below

Why does the Configurations row say "needs the local origins"? โ€‹

The retention panel reads GET /analytics/admin/bq-schema, and this branch is what taught that endpoint to return partitioning, clustering and expiration. โ€‹

What changed here? โ€‹

Analytics got a Configurations page, and it is LIVE rather than a move. โ€‹

  • It is a new sidebar entry under Analytics: Configurations, at /admin/analytics/config. The old bigquery/retention path redirects to it.
  • It was rebuilt live rather than moved, because the panel it replaces rendered a hand-written RETENTION_POLICIES constant that checked wrong against BigQuery in three ways: it omitted user_id from analytics.events clustering, claimed event_counts_daily has no clustering when it is clustered on event_name, and left ad_delivery_daily out of the table entirely. It also never showed that analytics.events requires a partition filter, which is the difference between a slow query and a failed one.
  • The page states its own scope, so a future addition has a test to pass rather than a gap to fill.

A BigQuery schema viewer exists as a component, built against a real warehouse capture. It is NOT wired. โ€‹

  • Storybook only, no route, deliberately. The endpoint that would feed it was still returning the old payload when it was built, so wiring it would have shown the not-wired state and nothing else.
  • Its fixture came out of the real schema service running against lantern-app-dev. Nothing in it was typed by hand.

A Report Builder exists as a component. It is NOT wired either. โ€‹

  • Storybook only, no route, deliberately. Its whole value is in what its metric list refuses, and the refusals are kept as data in the component so the next person adding a metric reads them.

The three Analytics > Dashboards placeholders now declare their real age. โ€‹

  • They render through the new Scaffold component and say 123 days out loud in warning amber. The dates are read from git, not stamped.

Where do I look, and what am I looking for? โ€‹

Configurations http://localhost:3001/admin/analytics/config โ€‹

  • Needs the local origins to show the real retention table.
  • The sidebar should carry Configurations as a fifth Analytics sub-item, after Query Console.
  • /admin/analytics/bigquery/retention should redirect here.
  • Four states that must never look alike: loading, the service did not answer, the endpoint does not carry the fields, and genuinely no base tables. Against the deployed origin you should get the third of those, worded plainly, not an empty table.
  • The scope statement at the top should say what belongs on this page. Nothing speculative should be on it.

Configurations in Storybook http://localhost:6008 โ€‹

The schema viewer, Storybook only http://localhost:6008 โ€‹

  • Default, Embedded.
  • A view is not undocumented: BigQuery views do not inherit column descriptions, and both analytics views read from events, whose twelve columns are complete. Reporting them as a documentation gap would be wrong, and the viewer says so in the result rather than in a tooltip.
  • A genuine gap: what a real missing description looks like. It never invents a definition, never falls back to a prettified column name, and never renders a missing description as an empty cell.
  • Endpoint does not carry descriptions yet, Service did not answer, Loading.
  • Keyboard check: the column tables scroll, and a scrolling region has to be reachable by keyboard. Tab into one and confirm you can scroll it without a mouse.

The Report Builder, Storybook only http://localhost:6008 โ€‹

The three Dashboards placeholders http://localhost:3001/admin/analytics/dashboards/engagement โ€‹

What is deliberately NOT done? โ€‹

The schema viewer and the Report Builder have no route and no nav entry. Both are Storybook-only on purpose. โ€‹

The BigQuery page has NOT become the Report Builder yet. โ€‹

The merchant-facing report creator is downstream and out of scope. โ€‹

The bounded metric set has not been agreed with you. โ€‹

  • The builder is only as good as the metrics it offers. The list in the component is the builder's proposal, not a decision.

What open findings touch this project? โ€‹

Cross-referenced from ../merchant-and-venue-dashboards/branch-review-0828.md.

A non-JSON 200 is returned as the payload. shared/lib/analyticsApi.js:50 โ€‹

  • An HTML shell becomes {detail, raw:true}, and the retention panel reports "BigQuery returned no base tables" as a finding when what actually happened is that the request did not reach the service.
  • merchantsApi.js was hardened for exactly this in the same PR. analyticsApi.js was not. Open, not fixed.
  • If the Configurations page tells you the warehouse is empty, check this before believing it.

Finding 8 was DOWNGRADED by the reviewer, and the correction is worth reading. analytics/config/retentionModel.js:61 โ€‹

  • The ?? mechanism is real: it only falls through on null, while the function's own comment says it must read both places.
  • Its trigger is unevidenced. Against the branch's own real-warehouse fixture, BigQuery echoes the top-level flag and it agrees with the nested one in all eight tables captured.
  • A fourth reviewer called it moot because the server normalizes the field first. It does not: bqSchema.service.js:130 uses the same ??. The honest statement is that the flaw exists in two layers and its trigger is unevidenced.
  • Nothing to look at on screen. It is here so you know the row was considered and downgraded rather than dropped.

What issue does each piece close? โ€‹

PieceIssueState
The Configurations page, the schema viewer, the Report Builder#987: feat(admin/analytics): a configurations page, a BigQuery-sourced schema viewer, and the BigQuery page becomes the Report BuilderOne of three routed, two Storybook-only
The three Dashboards placeholders declaring their age#999: feat(admin/analytics): the three Dashboards routes have been placeholders for 123 days, and one of them has no data sourceOpen, filed as the finding
The Scaffold component they render through#991: feat(admin): a shared Scaffold component whose required props make a placeholder declare its age and its wiring issueBuilt on branch
The k-anonymity policy behind any merchant-facing cut#874: design(privacy): one data-classification and egress policy, before search, the assistant, and the apps platform each invent their ownOpen, must not be answered ad hoc
The local origin flip#1002: fix(dev-env): local dev proxies venues and analytics to Cloud Run, so branch backend changes are invisible locallyOpen, another lane

Built with VitePress