feat(dashboard): consume recent_events + chain_meta from authoritative endpoint#35
Conversation
…e endpoint
Wires the dashboard sub-widgets to the new fields on
/v1/users/{handle}/dashboard (api PR #14):
composeSnapshot in app/(tenant)/dashboard/page.tsx
- overrides recentEvents with owner-scoped fleet.recent_events
when present; falls back to the public-feed-derived value on
older api deploys (back-compat via optional types).
- overrides chainHeight with fleet.chain_meta.owner_chain_height,
else global_chain_height, else fromFeed.chainHeight.
app/(tenant)/audit/page.tsx
- SSR-fetches /v1/users/{handle}/dashboard.chain_meta and passes
initialChainHeight + initialLatestAt to AuditPageClient so the
chips render on first paint (not "—" until client poll fires).
AuditPageClient
- accepts initialChainHeight + initialLatestAt props (back-compat
defaulted to null).
- seeds useState from those props so the SSR value persists until
the client poll backfills.
Net effect: the three sub-widgets that were rendering empty post-D3
(Recent activity widget, bottom Audit chain mini-widget, /audit page
metric chips) all populate from one authoritative round-trip. The
public-feed scrape is now a fallback path, not the source of truth.
Resolves the "one viewport = one truth" violation flagged in the
deep-audit doc Part 5.2 + Principle 1.
Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is ON, but it could not run because the branch was deleted or merged before autofix could start.
Reviewed by Cursor Bugbot for commit 57f701c. Configure here.
| initialChainHeight = | ||
| data.chain_meta.owner_chain_height || | ||
| data.chain_meta.global_chain_height || | ||
| null; |
There was a problem hiding this comment.
SSR seeds owner-scoped height, client poll overwrites with global
Medium Severity
The SSR seeds initialChainHeight preferring owner_chain_height (the owner's event count), and initialLatestAt from the owner's latest_event_at. However, the client poll in AuditPageClient unconditionally overwrites both with global values from /v1/audit/public — d.chain_height is the global chain height, and first.created_at is the global latest event timestamp. This causes the chips to flash from owner-scoped values to global values on first poll, changing semantic meaning mid-render.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 57f701c. Configure here.
| recentEventsAuthoritative.length > 0 | ||
| ? recentEventsAuthoritative | ||
| : fromFeed.recentEvents, | ||
| chainHeight: chainHeightForChip, |
There was a problem hiding this comment.
Client poll overwrites authoritative recentEvents with public-feed data
High Severity
The SSR now computes authoritative, owner-scoped recentEvents and chainHeight via the authenticated endpoint, but the client poll in OverviewView.tsx spreads ...next from reduceOverview (public-feed data) and only preserves agentCount, inferencesInRange, receiptsInRange, and agents. Within ~5 seconds the authoritative recentEvents and chainHeight are silently replaced by public-feed-derived values. When the public feed is drowned by other tenants' high-volume test runs, the Recent Activity widget re-empties — the exact P0 scenario this PR intends to fix, but only for the first paint.
Triggered by learned rule: Use proxyGet with /v1/users/{handle}/dashboard for fleet/stats — not /v1/audit/public
Reviewed by Cursor Bugbot for commit 57f701c. Configure here.


Summary
Wires the dashboard sub-widgets to the new fields on
`/v1/users/{handle}/dashboard` (api PR #14 — required to land first).
After this lands + api deploys, the three sub-widgets that render empty
post-D3 (Recent activity widget, bottom Audit chain mini-widget,
`/audit` page metric chips) all populate from one authoritative
round-trip. The public-feed scrape becomes a fallback path, not the
source of truth.
Files
Dependency
Requires api PR #14 to merge + Railway-deploy first.
Until then, this PR is back-compat safe — the new fields are optional
and the frontend falls back to the existing public-feed reduce when
they're absent. So merging this before api PR #14 is non-breaking.
Reference
Note
Low Risk
Low risk UI/data-wiring change that only affects dashboard/audit rendering; main risk is incorrect empty-state or stale display if the new optional API fields are missing or shaped unexpectedly.
Overview
Improves first-paint correctness for audit/overview widgets by consuming the authenticated
/v1/users/{handle}/dashboardresponse as the authoritative source for recent activity and chain height.The
/auditpage now SSR-fetcheschain_metaviaproxyGetand seedsAuditPageClientstate withinitialChainHeight/initialLatestAtso the metric chips don’t render as "—" while the client poll catches up. The overview snapshot composition prefersrecent_eventsandchain_meta(owner → global → public-feed fallback) when present, andapps/dashboard/lib/ainfera/types.tsadds the corresponding optional response types for back-compat with older API deploys.Reviewed by Cursor Bugbot for commit 57f701c. Bugbot is set up for automated code reviews on this repo. Configure here.