Skip to content

Replace /admin/usage with a per-user usage drill-down on /admin/users - #724

Merged
kody-bot merged 2 commits into
mainfrom
cursor/usage-on-admin-users-94de
Jul 11, 2026
Merged

kody-bot merged 2 commits into
mainfrom
cursor/usage-on-admin-users-94de

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 11, 2026 •

Copy link
Copy Markdown
Owner

Why

/admin/usage loaded usage rollups, daily quota counters, and live resource counts for every user on the page (up to 100 accounts × ~7 counter reads each per load). That read model scales linearly with the user base and was already the slowest admin page.

What changed

  • /admin/usage and /admin/usage.json are gone — page, handler, client route, nav item, and the paged multi-user read model.
  • Usage now lives on /admin/users: selecting an account lazily loads a "Usage & quotas" panel from a new admin-only endpoint GET /admin/users/usage.json?userId=N. Cost is O(1) per view — one KV-cached rollup query plus a fixed set of entitlement counter reads for exactly one user.
  • The panel shows a Monthly activity stacked bar chart (reusing the insights chart components, same metric colors via the new shared usage-metric-series.ts), a metric legend with current-month counts, a quota-watch notice, and an Entitlements table with plan limits and % used (amber above 80%).
  • New data module admin-user-usage-data.ts replaces admin-usage-data.ts; keeps the 5-minute KV cache on the per-user rollup read model.
  • MCP capability admin_usage_overview (paged, whole-user-base) is replaced by admin_user_usage (by id or email), matching admin_user_get and keeping the same scalability fix on the MCP surface.
  • Plan changes on the users page invalidate the drill-down so limits refresh immediately after "Save plan".
  • The /admin/insights graphs are untouched.

Demo

admin_users_usage_drilldown_demo.mp4

Usage panel with chart and legend for a pro-plan user
Entitlements table with pro plan limits

Testing

  • npm run validate fully green locally (format, lint, typecheck, 819 unit tests, 13 Playwright E2E, MCP E2E).
  • Unit tests moved/adapted to the per-user loader (admin-user-usage-data.node.test.ts): null for unknown users, zeroed rollups, >80% warnings, plan-less email fallback limits, KV caching, UTC month boundaries.
  • admin-rbac.spec.ts updated: non-admins get 403 from the usage endpoint; admins see the Usage & quotas panel on /admin/users; the JSON payload leaks no secrets or emails.
  • Manual: verified 400 without userId, 404 for unknown users, 404 on the old /admin/usage, and the full GUI flow in the demo video.
System recap — extends existing primitives (medium risk)

Mode: recap · Base: main @ ff425827 · Head: dbee844b

Classification: extends — the admin usage surface (routes, JSON contract, MCP capability) changes shape; no new primitives, no schema changes.

Primitives touched

Primitive Group Impact
app-ui surfaces extends — /admin/usage removed; per-user drill-down + /admin/users/usage.json added
capability-registry assistant extends — admin_usage_overview replaced by per-user admin_user_usage
usage-metering storage composes — same rollups/counters read through a new single-user read model
entitlements auth composes — plan limits compared against live counters, unchanged APIs
rbac auth composes — endpoint guarded by existing read:user:any permission
bundle-artifacts-kv storage composes — same 5-minute cachified cache, now keyed per user + month

System map

The admin users page fetches one selected account's usage through a new JSON endpoint into the existing metering and entitlement reads.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
	appUi["app-ui<br/>Browser app (Remix 3)"]:::extended
	rbac["rbac<br/>Role-based access control"]:::touched
	usageMetering["usage-metering<br/>Usage metering"]:::touched
	entitlements["entitlements<br/>Plans & entitlements"]:::touched
	kv["bundle-artifacts-kv<br/>Bundle artifacts KV"]:::touched
	capabilityRegistry["capability-registry<br/>Capability registry"]:::extended
	appUi -->|"GET /admin/users/usage.json?userId=N"| rbac
	rbac -->|"read:user:any guard"| usageMetering
	usageMetering -->|"usage_rollups per-user query"| kv
	usageMetering -->|"entitlement counters vs plan limits"| entitlements
	capabilityRegistry -->|"admin_user_usage(id|email)"| usageMetering
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading

Before / after

Before: GET /admin/usage.json?page=&pageSize=&userId=
        → N users × (2 daily counters + 5 resource counts) + paged rollups
        MCP: admin_usage_overview { page, pageSize, userId }

After:  GET /admin/users/usage.json?userId=N   (400 without userId, 404 unknown)
        → 1 user × (10 entitlement counters + 1 KV-cached rollup query)
        MCP: admin_user_usage { id | email }

Invariants

Per-user isolation unchanged: the endpoint returns aggregate metadata for one account, is admin-gated via read:user:any, and never returns user content (asserted in admin-rbac.spec.ts).

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Added per-account “Usage & quotas” drill-down on the admin users page, including monthly activity, entitlement consumption/limits, and over-limit warnings.
    • Introduced a per-user admin usage API and corresponding admin capability to retrieve usage by account id/email.
    • Standardized admin usage chart labeling, colors, and month formatting.
  • Changes

    • Removed the standalone admin usage page and its navigation entry, switching to the drill-down experience.
    • Updated admin insigths chart configuration to reuse shared formatting.
  • Tests

    • Updated RBAC/e2e coverage to validate the new drill-down flow and per-user API behavior.
  • Documentation

    • Refreshed the usage metering documentation for the admin drill-down and caching behavior.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c4f9c0ca-4c03-4b06-ba5a-af37a11878a2

📥 Commits

Reviewing files that changed from the base of the PR and between dbee844 and dce32f0.

📒 Files selected for processing (1)
  • packages/worker/client/routes/admin-users.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/worker/client/routes/admin-users.tsx

📝 Walkthrough

Walkthrough

The PR replaces the admin usage overview with per-user usage loading through /admin/users/usage.json, integrates usage and entitlement details into the users page, adds shared chart formatting, and replaces the MCP overview capability with admin_user_usage.

Changes

Admin user usage

Layer / File(s) Summary
Per-user usage loader and data contract
packages/worker/src/app/admin-user-usage-data.ts, packages/worker/src/app/loader-data.ts, packages/worker/src/app/admin-user-usage-data.node.test.ts, docs/contributing/architecture/usage-metering.md
Per-user rollups, entitlement consumption, warnings, month handling, KV caching, and associated loader types are implemented and tested.
Per-user API and route wiring
packages/worker/src/app/handlers/admin-users.ts, packages/worker/src/app/router.ts, packages/worker/src/app/routes.ts, e2e/admin-rbac.spec.ts
A permission-protected per-user usage endpoint is added, the previous usage routes are removed, and RBAC/API behavior is covered by end-to-end tests.
Users-page usage drill-down and chart reuse
packages/worker/client/routes/admin-users.tsx, packages/worker/client/charts/usage-metric-series.ts, packages/worker/client/routes/admin-insights.tsx, packages/worker/client/routes/account-management-components.tsx, packages/worker/client/routes/index.tsx
The users page fetches selected-account usage and renders activity charts, warnings, and entitlement consumption using shared chart configuration; standalone usage navigation and routing are removed.
Admin MCP user usage capability
packages/worker/src/mcp/capabilities/admin/admin-user-usage.ts, packages/worker/src/mcp/capabilities/admin/domain.ts, packages/worker/src/mcp/capabilities/admin/admin-capabilities.node.test.ts
The admin MCP domain now exposes audited, schema-validated usage details for a user identified by ID or email, with updated capability tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Admin
  participant AdminUsersRoute
  participant UsageAPI
  participant UsageLoader
  participant APP_DB
  Admin->>AdminUsersRoute: Select user account
  AdminUsersRoute->>UsageAPI: GET /admin/users/usage.json?userId
  UsageAPI->>UsageLoader: Load selected user usage
  UsageLoader->>APP_DB: Read user, rollups, and entitlements
  UsageLoader-->>UsageAPI: Usage payload
  UsageAPI-->>AdminUsersRoute: JSON response
  AdminUsersRoute-->>Admin: Render charts and quotas
Loading

Possibly related PRs

  • kentcdodds/kody#627: Directly overlaps the replacement of the former admin usage overview with the per-user drill-down.
  • kentcdodds/kody#669: Relates to the KV-backed usage rollup caching replaced by this per-user cache.
  • kentcdodds/kody#682: Overlaps the admin users route and handler surfaces used by the new usage API.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing the old /admin/usage flow with a per-user drill-down under /admin/users.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/usage-on-admin-users-94de

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kody-bot
kody-bot marked this pull request as ready for review July 11, 2026 07:14
@github-actions

github-actions Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-724.kody-a99.workers.dev

Worker: kody-pr-724
D1: kody-pr-724-db
KV: kody-pr-724-oauth-kv

Mocks:

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/worker/client/routes/admin-users.tsx`:
- Around line 170-175: Update invalidateUsage() to also clear usageData (set it
to null or the appropriate empty state) alongside usageLoadedForUserId and
usageFailedForUserId, ensuring selectedUsage cannot display stale entitlements
while the refetch is in progress.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e9a28b1a-8717-46bc-aa09-b6f4b729689f

📥 Commits

Reviewing files that changed from the base of the PR and between ff42582 and dbee844.

📒 Files selected for processing (21)
  • docs/contributing/architecture/usage-metering.md
  • e2e/admin-rbac.spec.ts
  • packages/worker/client/charts/usage-metric-series.ts
  • packages/worker/client/routes/account-management-components.tsx
  • packages/worker/client/routes/admin-insights.tsx
  • packages/worker/client/routes/admin-usage.tsx
  • packages/worker/client/routes/admin-users.tsx
  • packages/worker/client/routes/index.tsx
  • packages/worker/src/app/admin-insights-data.ts
  • packages/worker/src/app/admin-usage-data.ts
  • packages/worker/src/app/admin-user-usage-data.node.test.ts
  • packages/worker/src/app/admin-user-usage-data.ts
  • packages/worker/src/app/handlers/admin-usage.ts
  • packages/worker/src/app/handlers/admin-users.ts
  • packages/worker/src/app/loader-data.ts
  • packages/worker/src/app/router.ts
  • packages/worker/src/app/routes.ts
  • packages/worker/src/mcp/capabilities/admin/admin-capabilities.node.test.ts
  • packages/worker/src/mcp/capabilities/admin/admin-usage-overview.ts
  • packages/worker/src/mcp/capabilities/admin/admin-user-usage.ts
  • packages/worker/src/mcp/capabilities/admin/domain.ts
💤 Files with no reviewable changes (6)
  • packages/worker/src/app/admin-usage-data.ts
  • packages/worker/src/app/handlers/admin-usage.ts
  • packages/worker/src/mcp/capabilities/admin/admin-usage-overview.ts
  • packages/worker/client/routes/account-management-components.tsx
  • packages/worker/client/routes/admin-usage.tsx
  • packages/worker/client/routes/index.tsx

Comment thread packages/worker/client/routes/admin-users.tsx

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit dce32f0. Configure here.

typeof document !== 'undefined' &&
usageLoadedForUserId !== selectedUser.id &&
usageLoadingForUserId !== selectedUser.id &&
usageFailedForUserId !== selectedUser.id

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Usage load never retries

Medium Severity

After a failed loadUserUsage fetch, usageFailedForUserId stops the render path from queueing another load for that account. Reselecting the same user or switching away and back does not clear that flag, so the Usage & quotas panel can stay on the error state until a full page reload (or a plan save that calls invalidateUsage).

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dce32f0. Configure here.

@kody-bot
kody-bot merged commit dcd021e into main Jul 11, 2026
5 checks passed
@kody-bot
kody-bot deleted the cursor/usage-on-admin-users-94de branch July 11, 2026 07:32
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.

3 participants