Skip to content

dashboard: consume /billing/usage + /team/summary (§10.20)#33

Merged
mastermanas805 merged 2 commits into
mainfrom
cache-aggregates-2026-05-12
May 12, 2026
Merged

dashboard: consume /billing/usage + /team/summary (§10.20)#33
mastermanas805 merged 2 commits into
mainfrom
cache-aggregates-2026-05-12

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Summary

Pairs with the api §10.20 PR (https://github.com/InstaNode-dev/api/pull/22). Retires the client-side Usage-panel aggregation in BillingPage (resources → useMemo) and wires the new cached server aggregates. Sidebar gains live resource/member counts that previously didn't render because there was no live source.

  • api/index.tsfetchBillingUsage() + fetchTeamSummary() typed wrappers, with BillingUsage / TeamSummary / UsageMetric types.
  • BillingPage.tsx — Usage panel reads from fetchBillingUsage() instead of summing listResources() storage bytes client-side. Renders an "as of Ns ago · cached 30s" footnote so users can see the eventual-consistency window (per §13).
  • AppShell.tsxSidebarUpgradeCard fetches /team/summary once per session-load (5m Redis cache + browser Cache-Control: max-age=300 keeps the cost low) and renders "N resources · M members" on paid-tier cards.

Test plan

  • npx tsc --noEmit — clean.
  • npm test -- --run — 164 pass, 3 skipped (matches main).
  • New tests assert: listResources() is NOT called for usage; fetchBillingUsage() is called once; the as_of footnote renders.
  • Live verification post-merge: confirm Usage panel reflects real data + footnote, sidebar shows counts on paid teams. (Manas to verify.)

§14 caching-review checklist (consumer side)

This PR is a pure read consumer — the cache lives on the agent API. The dashboard relies on the API's Cache-Control: private, max-age=30, stale-while-revalidate=60 for browser caching. No client-side stash, no localStorage usage state.

🤖 Generated with Claude Code

mastermanas805 and others added 2 commits May 12, 2026 08:31
Retires the client-side Usage-panel aggregation (resources → useMemo) in
favour of the new server-side cached aggregates. The dashboard no longer
pulls the full resource list just to compute six numbers; the agent API
caches the rollup per team in Redis (30s for billing/usage, 5min for
team/summary) and shares it across surfaces.

Per the §13 freshness rule, the eventual-consistency tradeoff is now
visible to users — the Usage panel renders an "as of Ns ago · cached
30s" footnote so they can tell whether a freshly-provisioned resource
should already appear in the figures.

api/index.ts — adds fetchBillingUsage() + fetchTeamSummary() typed
wrappers, including BillingUsage / TeamSummary / UsageMetric /
TeamSummaryCounts types.

BillingPage.tsx — replaces the resources useMemo aggregate with the
server payload. The Usage panel still renders the same six rows; values
now come from `billingUsage.usage.<service>.bytes` (or `.count`) and
the seats row finally reads a real member count (closes the §10.7 gap
for the Usage panel). Adds formatAsOf() helper + data-testid
`billing-usage-as-of` for the eventual-consistency footnote.

AppShell.tsx — extends SidebarUpgradeCard to fetch /team/summary once
per session-load (5m Redis cache + browser Cache-Control makes this
cheap) and render a "N resources · M members" line on paid-tier cards.
Skipped for anonymous/free where the card is the upgrade CTA only.

Tests: 164 pass, 3 skipped (matches main). New §10.20 coverage in
BillingPage.test.tsx asserts:
  - listResources() is NOT called for usage data (regression guard)
  - fetchBillingUsage() is called exactly once
  - the `as_of` footnote renders when the cached payload arrives
  - zero-usage server response renders zeroes in every row
  - server bytes → MB conversion (100 MB Postgres → "100 / 1 GB")

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…re removal

PR #33 (caching layer §10.20) and PR #32 (fixture removal §10.21) both
edited BillingPage.tsx in different places. Merge resolution keeps:
- fetchBillingUsage() from #33 for the Usage panel (server-side cached
  30s with singleflight)
- billingErr + billingLoading state from #32 for honest error rendering
  when fetchBilling rejects (no more fixture-fallback lie)

Drop the now-unused listResources() call in the useEffect — usage data
comes from fetchBillingUsage now, not client-side aggregation.

Update BillingPage.test.tsx — the two §10.21 error-state tests need to
mock fetchBillingUsage too (was previously mocking listResources, which
is no longer called by the page).

Test gate: 172 passed, 3 skipped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mastermanas805 mastermanas805 merged commit 855f7f4 into main May 12, 2026
1 of 2 checks passed
@mastermanas805 mastermanas805 deleted the cache-aggregates-2026-05-12 branch May 12, 2026 03:10
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