Skip to content

console: [SAS-128] Add per-account/per-cluster cost breakdown to the billing page#37286

Draft
rjimeno-mz wants to merge 3 commits into
mainfrom
rjimeno/sas-128-phase-1-minimal-console-change
Draft

console: [SAS-128] Add per-account/per-cluster cost breakdown to the billing page#37286
rjimeno-mz wants to merge 3 commits into
mainfrom
rjimeno/sas-128-phase-1-minimal-console-change

Conversation

@rjimeno-mz

@rjimeno-mz rjimeno-mz commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Motivation

Phase 1 of Orb account-hierarchy support in the console (Linear: SAS-128). Today the billing page shows only an org-wide spend total. With sub-accounts, a parent org needs to see how spend breaks down across its own and its child accounts, per cluster — driven by the new GET /api/costs/breakdown endpoint.

Description

  • Adds a "Spend by account & cluster" section to Usage → Overview, fed by GET /api/costs/breakdown (new getCostsBreakdown in cloudGlobalApi.ts + useCostsBreakdown in queries.ts). A parent org sees itself plus each child account; a child or standalone org sees a single account. This augments the existing daily chart and SpendBreakdown sparklines rather than replacing them — the hybrid two-call approach (/costs/daily for the chart, /costs/breakdown for the new section). Legacy chart removal is tracked in SAS-138.
  • Each account renders as a collapsible group reusing SpendBreakdown's ResourceGroup / SafariSafeCollapse / caret disclosure pattern; shared baseCellStyles and resourceTypePaddingLeft were moved to constants.ts so both tables share them (no duplication of the Safari subgrid workaround). Cluster rows are indented children.
  • Cluster rows are region-qualifiedaws/us-east-1 / quickstart.r1, aws/us-east-1 / Storage — matching the daily "Spend between …" table and giving storage/egress rows a readable label instead of a raw environment id. This consumes the new CostBreakdownCluster.region field from cloud SAS-136.
  • Each account currently renders its Orb external-customer UUID; friendly org names are a deliberate follow-up (frontend SAS-142, backend SAS-141).
  • Type generation: the breakdown path/schemas — and the one region field — are spliced into the committed global-api types rather than a full yarn gen:api re-sync, because the console's committed spec has drifted from cloud (regions / self-managed-subscription). On a clean rebase once the cloud spec lands, yarn gen:api reproduces these.

Verification

  • Component tests: yarn test run src/platform/billing/UsagePage.test.tsx — covers parent / child / standalone rendering, the region-qualified cluster rows (aws/us-east-1 / quickstart.r1), and the storage row (aws/us-east-1 / Storage). Typecheck + lint clean.
  • Manual, end-to-end: ran this console locally against a personal stack (rjimeno.dev) wired to the cloud SAS-136 backend, logged in to a root/leaf Orb hierarchy (+mock-root@ / +mock-leaf@). Confirmed parent + child account groups and region-qualified cluster/storage rows from live Orb data.

Linear: SAS-128

@rjimeno-mz rjimeno-mz requested a review from a team as a code owner June 24, 2026 22:18
@rjimeno-mz rjimeno-mz requested review from SangJunBak and removed request for a team June 24, 2026 22:18
@SangJunBak SangJunBak requested review from leedqin and removed request for SangJunBak June 25, 2026 14:13
@SangJunBak

Copy link
Copy Markdown
Contributor

Reassigning to @leedqin

@rjimeno-mz rjimeno-mz self-assigned this Jun 26, 2026
…billing page

Add a "Spend by account & cluster" section to Usage → Overview, driven by
GET /api/costs/breakdown. A parent org sees itself plus each child account;
a child or standalone org sees a single account.

- Render each account as a collapsible group, reusing SpendBreakdown's
  ResourceGroup / SafariSafeCollapse / caret disclosure pattern (shared
  baseCellStyles and resourceTypePaddingLeft moved to constants.ts), with
  indented cluster child rows.
- Region-qualify each cluster row ("aws/us-east-1 / quickstart.r1",
  "aws/us-east-1 / Storage") to match the daily "Spend between …" table and
  give storage rows a readable label instead of the raw environment id.
  Consumes the new CostBreakdownCluster.region field from the backend
  (cloud SAS-136).
- Tests cover parent / child / standalone rendering and the region-qualified
  cluster and storage rows.
@rjimeno-mz rjimeno-mz force-pushed the rjimeno/sas-128-phase-1-minimal-console-change branch from c9ca34f to 03947e4 Compare June 29, 2026 23:35
* surfaced as "Storage".
*/
function clusterLabel(cluster: CostBreakdownCluster): string {
return `${cluster.region} / ${cluster.cluster_grouping_key || "Storage"}`;

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.

This seems wrong. We should check price-storage and price-egress and separate them

@rjimeno-mz

Copy link
Copy Markdown
Contributor Author

I'm reverting this PR to draft while I implement some requested changes.

@rjimeno-mz rjimeno-mz marked this pull request as draft June 30, 2026 14:37
Consume the new CostBreakdownCluster.category field: non-compute rows
(empty cluster_grouping_key) now label from `category`, so storage and
egress render as distinct "<region> / Storage" and "<region> / Egress"
rows instead of both falling back to "Storage" (addresses def-'s review).
Fall back to "Other" only when neither key nor category is set — e.g. a
backend that predates the field. Splice the `category` field into the
generated global-api types; add egress and "Other"-fallback test coverage.
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