Skip to content

Provider accounts P10: arb usage --by account / --account, arb quota --account, JSON + LiveView surfaces - #2000

Merged
ryanrborn merged 3 commits into
mainfrom
feature/1856-provider-accounts-p10-arb-usage-by
Sep 23, 2026
Merged

ryanrborn merged 3 commits into
mainfrom
feature/1856-provider-accounts-p10-arb-usage-by

Conversation

@ryanrborn

Copy link
Copy Markdown
Owner

Summary

Provider accounts P10 (docs/provider-account-design.md §8): arb usage --by account / --account, arb quota --account, and the account dimension on the JSON + LiveView surfaces.

The real fix here is underneath the new flags. P7 had already added Usage.summarize(by: :provider_account) and a :provider_account_id filter, but since usage_events had no account column yet, both worked by joining through workspace_id — an approximation that silently dropped probe/pre-flight rows, which carry no workspace_id but always an account (they're issued as a credential). That's exactly the under-reporting bias bd-adyhvn measured. Quota.provider_spend/1 had the same gap, since it summed workspace_spend/1 per workspace.

Now that P9 has landed usage_events.provider_account_id (a real column, backfilled and written on every insert), both are rewired to read/filter that column directly — so probe/pre-flight spend is included, and a chunk of now-dead approximation code (account_index/1, provider_codes/1, default_provider_codes/2, exact_account_groups/3) comes out with it.

On top of that:

  • arb usage --by provider_account / --account <id|provider:slug|slug> (mirrors --workspace), same on arb usage events.
  • arb quota --account <ref> goes straight to an account (no workspace lookup), reusing the account-total + per-workspace-breakdown machinery P5/P6 already built.
  • GET /api/usage and GET /api/usage/events gain account; GET /api/quota gains ?account=.
  • /usage LiveView gains a "By account" tab (account slug, not raw id).
  • The workspace detail page's "Worker agent pool" now names which account each selected provider is metered under.

Test plan

  • New Arbiter.Usage.ProviderAccountRollupTest — probe/pre-flight rows (no workspace_id) are included in by: :provider_account and the provider_account_id filter, across-account isolation, (none) sentinel.
  • New Arbiter.Quota.ProviderSpendTest — provider_spend/1 includes probe rows, cross-account isolation, nil account spends nothing.
  • Updated Arbiter.Quota.AccountWideHoldTest fixtures to stamp provider_account_id the way the real Arbiter.Worker write path does (they previously relied on the read-time workspace-join fallback this PR removes); added a probe-row case.
  • Fixed Arbiter.Workflows.DispatchQueueTest's overage-alert test, which had the same gap (seed_usage/2 wrote no provider_account_id, so Overage.windowed_spend/2 — which already read the account column via P7 — silently stopped seeing the seeded spend once the filter became exact).
  • ArbiterWeb.Api.UsageControllerTest / QuotaControllerTest — new ?account= / by=provider_account coverage, including unknown/ambiguous account refs (400/404/422).
  • ArbiterCli.Cmd.UsageTest / QuotaTest — --account forwarded as a query param, --account takes priority over --workspace for arb quota.
  • ArbiterWeb.UsageLiveTest — "By account" tab renders bars with the account slug.
  • ArbiterWeb.WorkspaceLiveTest — provider account label shown/not-shown on the agent pool.
  • Full suite: apps/arbiter (7262 tests), apps/arbiter_web (1687 tests), apps/arbiter_cli (883 tests) — all green.
  • mix precommit (compile --warnings-as-errors, format, test) clean.

References

bd-icwk2k. Depends on P9 (bd-al9qqe) and P5 (bd-3yokey), both already merged. Part of bd-7df8nh / #1593.

Closes #1856

…--account, JSON + LiveView surfaces (bd-icwk2k)

Usage.summarize(by: :provider_account) and its provider_account_id filter now
read usage_events.provider_account_id directly instead of the pre-P9
workspace-join approximation, so probe/pre-flight rows (no workspace_id, but
always an account) are included — closing the exact under-reporting bias
bd-adyhvn measured. Quota.provider_spend/1 gets the same fix. arb usage and
arb quota gain --account (CLI + REST), and the usage/quota web surfaces and
workspace detail page expose the account dimension.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ryanrborn and others added 2 commits September 23, 2026 09:11
- Quota.decorate_view/2's headline cost_usd now reads Quota.provider_spend/1
  (account_id, direct usage_events.provider_account_id read) instead of
  summing the per-workspace breakdown, which excluded probe/preflight rows
  (workspace_id: nil) and reintroduced the bd-adyhvn under-reporting bias.
  provider_spend/1 now has a real caller.
- Usage.summarize/1 accepts `--by account` / `by=account` as an alias for
  `provider_account` (docs/provider-account-design.md §8's spelling),
  alongside the existing `campaign` -> `epic` alias.
- Updated moduledocs (Usage, UsageController, arb usage CLI help) and the
  provider_spend_test.exs claim that was false before this fix.
- Tests: controller test asserting the account total includes a
  workspace-less preflight row; CLI test asserting the printed total isn't
  recomputed from the breakdown; CLI/controller tests for --by account /
  by=account; fixed quota_test.exs fixtures that predated P9's
  provider_account_id column.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ryanrborn
ryanrborn merged commit 41d81de into main Sep 23, 2026
3 checks passed
@ryanrborn
ryanrborn deleted the feature/1856-provider-accounts-p10-arb-usage-by branch September 23, 2026 13:45
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.

Provider accounts P10: arb usage --by account / --account, arb quota --account, JSON + LiveView surfaces

1 participant