Repository navigation
Description
Gap
Drew's ruling (2026-11-03): a quota ask must terminate at the OpenCode server — not at a standalone proxy, and not at a credential store the server never sees. The Meta leg now complies: the quota gatherer (pm-stack/aggregator/scripts/gather-quota.ts) asks the standing fork server's GET /api/credential (127.0.0.1:13420) for the credential, with the direct opencode.db read kept only as a transport-failure fallback (the quota CLI's combined-source shape, #2490).
The OpenDesign leg cannot comply today, and this issue names why precisely:
- The OpenChamber quota module's OpenDesign provider (
server/lib/quota/providers/opendesign.jsin the OpenChamber fork) does not read the OpenCode credential machinery at all. It reads a managed session credential from OpenChamber's own quota credential store (~/.config/openchamber/quota/opendesign.json): a Better Auth session cookie plus a workspace id. - The usage API it answers from (
https://amr-api.open-design.ai/api/auth/get-session,.../v1/workspaces/:id/billing/coding-plan-usage) accepts only that session cookie (Cookie: better-auth.session_token=…+x-vela-workspace-idheader). Verified live 2026-11-03: the managed cookie returns 200. - The credential the OpenCode server holds for integration
opendesignis the AMR inference API key (type: key,sk-a…). Verified live 2026-11-03: that key is refused by the billing/session API — 403 as a Bearer token and 403 presented as the session cookie. It cannot answer the quota read. - The OpenCode fork server exposes no quota/usage surface to terminate the ask at: its live route table (
/openapi.json, v2.0.30) has credential, session, integration, provider, etc. groups, but no quota group, and no credential shape that holds a (session cookie, workspace id) pair for a billing API.
So the OpenDesign read currently terminates at OpenDesign's own API with a locally-stored session cookie that the OpenCode server has no access to. The gatherer keeps that read working (fail-soft contract: never zero a pool over a routing principle), but the hop is named here rather than silently left in place.
What closing this takes (any one)
- The OpenCode fork server gains a quota surface for OpenDesign: e.g. a credential shape that can hold the AMR session cookie + workspace id, plus a server-side usage read (or a credential projection the quota module can consume via
GET /api/credentialin place of the managed store) — thenopendesign.jsswitches its credential source to the wired OpenCode source like the other providers; or - AMR's billing API starts accepting the inference API key the server already holds (then the provider can read the key from the server like Meta does); or
- A documented decision that OpenDesign is a permanent token-exception provider (cf. audit(quota-plane): name the two token-exception providers definitively #1155), recorded on the board/quota docs so the exception is explicit rather than ambient.
Note the session cookie is short-lived (the current one expires 2026-11-10), so any server-side home for it also needs the re-import/refresh story the OpenChamber Settings import provides today.
Acceptance criteria
- The OpenDesign quota leg terminates at the OpenCode server like the Meta leg does: the credential the server needs is held/usable by the server, not only in OpenChamber's standalone managed-cookie store — or a recorded decision names this leg as an explicit exception with its reasoning.
- gather-quota's OpenDesign leg returns current coding-plan usage without depending on ~/.config/openchamber/quota/opendesign.json as its sole source.
- The direct-store read, if retained at all, is demoted to the same transport-failure-fallback status the Meta leg's opencode.db read has (unify(quota-plane): one quota read path — server endpoint, CLI, and aggregator gatherer must share the direct credential-store read #2490 shape).
Activity
developing-today commentedon Nov 3, 2026
Premise update (2026-11-03, quota pass-through — PR #5080, merged
f508cfb5): the dashboard is now a straight display of the OpenCode quota read. The layers that could drop or override the OpenDesign read are gone (the #1114 disabled-door filter and its exemption hack, the extractor note promotion, the overlay's silent drop of unmatched entries), and the live side-by-side after deploy shows the board rendering the read'sopendesignentry exactly as reported (5h 100%, 7d 34.43% at the 19:08Z tick, freshness stamped from the read).So the OpenDesign READ is not, and after #5080 cannot again become, a dashboard problem. What remains of this issue is accurately a fork-surface gap, and it stays open for exactly this:
opendesignprovider is the AMR inference API key, which that billing API refuses (verified 403 as Bearer and as cookie when this issue was filed).Closure paths are unchanged from the issue body: (1) the fork grows a quota surface (or a credential shape the AMR billing API accepts), (2) OpenChamber exposes its managed session credential through a sanctioned read, or (3) AMR accepts the inference key for the billing read. Until one lands, this issue tracks a fork/credential-surface gap — not a read gap and not a dashboard gap.
dezren39 commentedon Nov 3, 2026
Intake review
— fleet monitor intake pass (repo-fleet-monitor, 2026-11-03 12:12 CST run)
dezren39 commentedon Nov 3, 2026
agent-note:v1
state: queued (task 8926)
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
1a180ae5-384f-4e71-8d77-08f7b1652c75(OpenChamber scheduled lane)handed_offcheckpoint for OpenCode execution. I am verifying current GitHub and queue ownership before relying on that state; no credential-path implementation will be attempted without a design decision.dezren39 commentedon Nov 4, 2026
🤖 Agent note · escalated
1a180ae5-384f-4e71-8d77-08f7b1652c75(OpenChamber scheduled lane)Verified current state
developing-today/codemain48cb3fe:pm-stack/aggregator/scripts/gather-quota.ts:34-43documents OpenDesign as the remaining server-first exception: the OpenCode integration holds the AMR inference key, which the billing API rejects, and the server has no quota/usage surface. PR feat(quota-gatherer): quota ask terminates at the OpenCode server (server-first credential source) #5062 (server-first for supported credentials) and quota: straight pass-through of the OpenCode quota read (Drew, 2026-11-03) #5080 (quota read pass-through) are both MERGED; the dashboard is not the remaining gap.developing-today/openchambermain5962e8856:packages/web/server/lib/quota/providers/opendesign.js:117-151,185-209sends the Better Auth cookie andx-vela-workspace-iddirectly to the AMR billing endpoints.packages/web/server/lib/quota/DOCUMENTATION.md:83-87says the credential is explicitly imported from the browser, is not auto-scanned, and must be re-imported when expired. The managed store writes atomically with directory/file mode0700/0600(packages/web/server/lib/quota/credentials/store.js:29-43); the docs say its API never returns secrets.developing-today/opencodemainc5f234f48f: credential types are OAuth, key, and external (packages/schema/src/credential.ts:33-56). The existingGET /api/credentiallists every stored credential including secret values (packages/protocol/src/groups/credential.ts:8-14); I found no quota/usage server route. A session cookie must therefore not be inserted as an ordinary key and exposed through this generic listing.Drew decision required before implementation
{session cookie, workspace id}with provider-only use, no secret disclosure through generic credential APIs, and an explicit manual renewal path (Turnstile sign-in is not automated); then route implementation across OpenCode/OpenChamber.Recommendation: do not store the cookie as a normal OpenCode
keycredential. If the server-first policy is retained, choose option 1 with a separately scoped secret boundary; otherwise record option 2 as an explicit exception. No credential values were read, and no implementation was attempted.