Skip to content

feat(users): add recent_events + chain_meta to /v1/users/{handle}/dashboard#14

Merged
hizrianraz merged 1 commit into
mainfrom
feat/dashboard-recent-events-chain-meta
May 16, 2026
Merged

feat(users): add recent_events + chain_meta to /v1/users/{handle}/dashboard#14
hizrianraz merged 1 commit into
mainfrom
feat/dashboard-recent-events-chain-meta

Conversation

@hizrianraz
Copy link
Copy Markdown
Contributor

@hizrianraz hizrianraz commented May 16, 2026

Summary

Adds two fields to `UserDashboardResponse` so the web tier has an
authoritative, owner-scoped source for the dashboard sub-widgets
that currently render empty when the global public feed gets drowned
by another tenant's high-volume test run.

```
recent_events: list[RecentAuditEvent] # top 12 by created_at desc
chain_meta: ChainMeta # owner_chain_height,
# global_chain_height,
# latest_event_at
```

Both additive (Pydantic defaults to empty / zero) → backward-compatible.

Implementation

  • Single owner-scoped query joining `AuditEventORM + AgentORM`, filter
    `agent_id IN (owner's agent ids)`, order by `created_at desc`, limit 12.
  • Returns a slim PublicAuditEvent-style projection — no payload body,
    just identity + hash + provenance fields (model, provider, agent name).
  • `owner_chain_height` = `max(seq)` over the owner's agent_ids; 0 if none.
  • `global_chain_height` = `max(seq)` globally — surfaces total platform
    throughput in the audit chip.
  • `latest_event_at` = `recent_events[0].created_at` if present.

Why

Today the dashboard "Recent activity" widget and `/audit` chain chips
on the web tier scrape `/v1/audit/public` client-side and filter by
owner_handle. With 305 ainfera-ai E2E test events in the top 500 today,
hizrianraz's events are drowned out — the widget renders "No events
yet" while the metric tile above reads "INFERENCES · 24h: 82" on the
same viewport. Audit Principle 1 violation: one viewport = one truth.

After this lands + the web tier consumes the new fields (separate PR),
the three sub-widgets all populate from one authoritative round-trip
instead of two unreliable fetches.

Pre-commit gates

ruff + ruff-format + mypy --strict + pytest -x — all passed.

Reference

  • Audit doc Part 5.2 (/dashboard rewrite spec)
  • [[feedback-curl-vs-browser-verification]]
  • Three-bug-decomposition receipts in ainfera-ai/.launch-snapshots/ (D2 + D3)

Note

Medium Risk
Adds new database queries and response fields to the /v1/users/{handle}/dashboard endpoint; while additive/backward-compatible, it changes dashboard payload shape and increases query load, which could affect performance on large tenants.

Overview
Extends GET /v1/users/{handle}/dashboard to return owner-scoped recent audit activity and chain-height metadata for dashboard widgets.

Adds recent_events (top 12 audit events across the user’s agents, returning a slim/public-safe projection) and chain_meta (owner max(seq), global max(seq), and latest owner event timestamp), computed via new SQLAlchemy queries filtered by the owner’s agent_ids with safe defaults when no agents/events exist.

Reviewed by Cursor Bugbot for commit aa10772. Bugbot is set up for automated code reviews on this repo. Configure here.

…hboard

The dashboard "Recent activity" widget and the audit chain chips on the
web tier currently scrape /v1/audit/public client-side and filter by
owner_handle. That fails when another tenant's high-volume test run
(305 ainfera-ai E2E events in the last 500 today) drowns the owner's
signal — the widget renders "No events yet" while the metric tile
above it reads "INFERENCES · 24h: 82" on the same viewport. Memory
[[feedback-curl-vs-browser-verification]] · audit Principle 1
("one viewport = one truth").

Adds two fields to UserDashboardResponse (additive, backward-compat):

  recent_events: list[RecentAuditEvent]   # top 12 by created_at desc
  chain_meta: ChainMeta                    # owner_chain_height,
                                           # global_chain_height,
                                           # latest_event_at

Single owner-scoped query joining AuditEventORM + AgentORM, filter
agent_id IN (owner's agent ids), order by created_at desc, limit 12.
Returns a slim PublicAuditEvent-style projection (no payload body —
just identity + hash + provenance). owner_chain_height = max(seq) over
the same agent_ids; 0 if none. global_chain_height = max(seq) globally.

Replaces the public-feed scrape pattern in the web tier (separate PR)
for the three sub-widgets that were rendering empty post-D3.

Co-Authored-By: Claude <noreply@anthropic.com>
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.

1 participant