- Added `listDisabledCredentials` and `refreshSnapshot` methods to credential stores along with API endpoints and wire schemas.
- Added `authorizedAt` timestamps and Anthropic OAuth grant TTL constants to track credential lifecycles.
- Updated the usage CLI to render auto-disabled credential tombstones and grant expiration warnings.
- Added comprehensive unit and broker integration tests covering the new credential management features.
Codex review round 7 on e90a72bdd flagged that broker usage-report
matching, header-overlay keying, and omp-usage coverage all treated a
matching organization as a sufficient match. Two Team members share the
org id while drawing on per-user pools, so the first same-org report
(or a lone sibling report) was handed to the wrong member. The org is
now a gate: within the same-org subset the member's own base identity
(account/email/project) must still match, with org-only entities (no
base identifiers) matching on the org alone when unambiguous. The
overlay merger (findMatchingReportIndex) had the identical same-org
flaw and receives the symmetric fix. Org-presence-mismatch semantics
are unchanged: org-scoped vs org-less stays fall-through/unreported,
and both-org-less keeps the legacy base-identity fallback.
Addresses the fourth review round (Codex no-email finding on d37e3992c,
confirmed and scoped by internal review):
- resolveProviderCredentialIdentityKey: the anthropic org qualifier now
rides on whichever base identity exists (email > account > project),
not only email. The account UUID is identical across the orgs of one
login account, so the bare account fallback let a second subscription
replace the first whenever the email could not be recovered (token
response omits it AND bootstrap fails). Org-only credentials key on
the org alone instead of losing identity entirely.
- matchesReplacementCredential: the one-way legacy claim strips a
trailing |org: from ANY anthropic base key (account/project included);
only anthropic keys carry the qualifier, so other providers are
unaffected.
- Usage-report dedupe falls back to the org-qualified account for
no-email anthropic reports instead of returning no identifiers.
- Broker report/overlay routing (matchUsageReport/findMatchingReportIndex)
is org-decisive on EITHER side: an org-less legacy credential no longer
receives an org-attributed sibling's pool via the lone-candidate or
email/account fallback, and an org-less overlay only merges into
org-less reports.
- omp usage unreported-account attribution follows the same either-side
rule, so a legacy row whose fetch failed surfaces as 'no usage data'
instead of being hidden by a sibling's report.
- Regression tests: no-email identity coexistence/replace/claim, no-email
report dedupe, org-less broker routing, either-side unreported
attribution.
- Added test case to verify that missing provider limits in sibling accounts are correctly marked as not reported.
- Verified that the usage breakdown correctly distinguishes between reported and unreported sibling provider limits.
Provider-wide disclaimers (e.g. OpenCode Go's "OMP-observed spend
only") were duplicated onto every UsageLimit, then repeated N times
in the TUI aggregate renderer (once per account × window). With
2 accounts × 3 windows, the same disclaimer appeared 6 times
bullet-joined.
Structural fix:
- Add notes?: string[] to UsageReport (interface + both schema
copies: usage.ts and auth-broker/wire-schemas.ts) so the field
survives the broker client's "+": "reject" deserialization gate.
- Move opencode-go's disclaimer from per-limit notes to
provider-level notes.
Defensive fix:
- Dedup identical per-limit notes in the TUI aggregate renderer
(command-controller.ts) via [...new Set(...)].
- Render provider-level notes once above per-account sections in
all three rendering paths: TUI (command-controller), CLI
(usage-cli), and ACP (usage-report helper).
Regression tests:
- usage-cli.test.ts: provider-level notes render once, not
duplicated per account or limit; positioned above per-account rows.
- usage-report-notes-schema.test.ts: wire-schema round-trip proving
notes survives usageResponseSchema validation.
Fixes#3268
- Added usage snapshot persistence in sqlite with hour-bucket upsert behavior.
- Added listUsageHistory query support with optional provider and sinceMs filters.
- Added usage CLI history mode with `--history` and `--days` and trend rendering.
- Added changelog documentation for usage trend inspection and no-history exit behavior.
- Added catalog-level host/model predicates and compat resolvers.
- Extended compatibility types and model schema with timeout and replay flags.
- Replaced provider-specific heuristics with shared resolver-based checks.
- Updated host/identity and resolver tests to validate the new behavior.
- Added per-account usage reporting in the `omp usage` command.
- Added `provider`, `json`, and `redact` options to customize usage output.
- Updated CLI wiring to route usage commands to the new per-account behavior.