W3 — Flue gateway (productionize) to the resolved token seam - #491
Merged
Conversation
Productionizes the 1a spike (spike/oc-gateway, #486) into the flue-native gateway per buildout contract #1 / design 013 §4. Thin OC Worker over OpenRouter: verify a per-session token → epoch-fence + on-path budget gate → inject the org's OR key → cache-safe + usage-accounted forward → sub-meter. Org spend stays on the org's single OR key → the existing OpenRouter→Autumn cron (nothing pushed to Autumn); the gateway only adds per-session sub-metering + enforcement. What changed vs the spike: - Token: HS256 → EdDSA (Ed25519). The minter holds the private key; the gateway holds only GATEWAY_TOKEN_PUBLIC_KEY (base64url raw). Alg pinned to EdDSA (rejects none/HS256 swaps). - Lease-epoch fence (close the freeze-flags): the SessionBudget DO tracks a monotonic max_epoch; a token with a stale `ep` → 401 token_superseded; a newer epoch supersedes older in-flight tokens. DO-serialized. - Org OR key from the credential store, not the KV/SPIKE stand-in: a dedicated internal sessions-api seam (mirrors the edge's dedicated-secret key hand-off), cached per-org in-isolate (60s). TEST_OR_KEY override for the acceptance run. The L3 route (resolveManagedSecret) is flagged for sessions-api. - Prompt-caching safety: strip cache_control for caching-unsafe models (claude-3-haiku → Bedrock 400s) via an env-extensible denylist. - Kept: usage:{include:true}, 402 budget_exceeded, metering by token.sub, the µ$ counter + /add idempotency on the OR generation id. Tests: 23 green (vitest) — EdDSA/alg-pin/tamper/expired, SessionBudget fence + budget + idempotency, cache_control strip, cost extraction, and the full on-path flow through the real handler. Live acceptance (2026-07-05, real OpenRouter via wrangler dev --local, throwaway $1-capped OR key minted from the provisioning key and deleted after): a real claude-haiku-4.5 turn completed gateway → OpenRouter (200, no key in the response, token != key); per-session budget refused on-path (402); cache_control stripped so claude-3-haiku succeeds via the gateway where a direct OR call 400s; epoch fence returns 401 token_superseded. Seam to confirm with the orchestrator (W1): EdDSA claim set + the mint side (default: per-turn token via getApiKey). L3 seam to build: the internal org-OR-key route. Not merged — Igor merges opencomputer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oken, org+agt enforcement) Reshapes the productionized gateway to the RESOLVED token seam (2026-07-05, option b) and the co-location refinement, and lands a consistent, compiling tree. The prior commit (0b5f580) captured a mid-reshape snapshot (new token.ts + old index.ts) that does not compile; this commit completes the reshape. buildout contract #1 / design 013 §4. Token seam (was per-session {sub,bud}; now per-DEPLOY): - token.ts: claims are {org, agt, iat, exp, ep?} — no sub:session, no bud. EdDSA (Ed25519), alg-pinned; the minter (W7) holds the private key, the gateway only the public key. verifyDeployToken/mintDeployToken/DeployClaims. - Session identity rides the X-OC-Session request header (Flue's static apiKey can't carry per-session data). It is BEST-EFFORT: Flue's provider registry is isolate-global and CF co-locates many session-DOs of one script per isolate, so per-session data injected via registerProvider races. Therefore hard enforcement is at the race-free org+agt grain. Enforcement (co-location refinement): - SpendCounter DO (renamed from SessionBudget; generic keyed µ$ counter + gate). HARD 402 at the org+agt grain (keyed agt:${org}:${agt}, from the token). Best-effort per-session tracking keyed sess:${X-OC-Session} — recorded for visibility, NEVER gated (a race must not wrongly 402 a legit session). Budget looked up server-side (provisioned or the gateway default), never carried in the token. Exact per-session enforcement is deferred to an upstream Flue per-request resolver (tracked ask, off the critical path). - DeployLease DO (new): per-(org,agt) lease-epoch floor. A token below the floor is fenced (401 token_superseded); the floor auto-rises on a higher-epoch token (rotation) and via POST /admin/lease/bump (revoke without redeploy). - Admin routes (guarded by GATEWAY_ADMIN_SECRET): /admin/agent/budget (provision org+agt cap), /admin/lease/bump (revoke). Unchanged from the spike: org OR key from the dedicated sessions-api seam (orgkey.ts; TEST_OR_KEY override), usage:{include:true}, cache_control strip for caching-unsafe models, cost extraction (JSON+SSE), org spend stays on the existing OpenRouter→Autumn cron (gateway pushes NOTHING to Autumn). Tests: 31 green (vitest) — EdDSA/alg-pin/tamper/expired/missing-claims, SpendCounter gate+provision+idempotency, DeployLease fence+bump, org+agt hard enforcement, co-location (two sessions share the org+agt cap), per-session tracked-but-never-gated, cache_control strip, admin provision. Live acceptance (2026-07-06, real OpenRouter via wrangler dev, throwaway $1-capped OR key minted from the provisioning key and DELETEd after): a real claude-haiku-4.5 turn completed gateway → OpenRouter (200, model claude-4.5-haiku, cost echoed; no OR key / deploy token in the response); org+agt budget refused on-path (402 budget_exceeded, spent 0.000088 > budget 0.00001); a stale lease epoch was fenced (401 token_superseded); no-token and bad-admin-secret → 401. opencomputer = PR-only; do NOT merge (Igor merges). Base = flue-native, into #489. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
2027 auto-runs evals against preview deployments of your docs. To enable this, install one of:
Once a preview is deployed, open a new PR and we'll run the eval automatically. Evaluating agent experience using 2027.dev · View dashboard |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
W3 — Gateway (productionize) of the Flue-native buildout. Base =
flue-native(feeds the evergreen #489). Buildout contract #1 / design 013 §4.cloudflare-workers/oc-gateway/.A thin OC Worker over OpenRouter: verify a per-deploy token → lease-epoch fence → org+agt budget gate → inject the org's OR key → cache-safe + usage-accounted forward → sub-meter. Org-level spend stays on the org's single OR key → the existing
model_meter→ Autumn cron (nothing pushed to Autumn); the gateway only adds enforcement + per-session sub-metering.Built to the RESOLVED token seam (option b + co-location refinement)
{org, agt, iat, exp, ep?}— nosub:session, nobud. HS256 → EdDSA (Ed25519), alg-pinned; the minter (W7) holds the private key, the gateway only the public key.X-OC-Sessionheader (Flue's staticapiKeycan't carry per-session data). Because Flue's provider registry is isolate-global and CF co-locates many session-DOs of one script per isolate, the header is best-effort: hard enforcement is at the race-free org+agt grain (from the token); the header is tracked-only, never gated (a co-location race must not wrongly 402 a legit session). Exact per-session enforcement is deferred to an upstream Flue per-request resolver (tracked ask, off the critical path).SpendCounterDO (renamed fromSessionBudget): generic µ$ counter + gate. HARD 402 atagt:${org}:${agt}; best-effort tracking atsess:${session}. Budget looked up server-side (provisioned or a gateway default) — never in the token.DeployLeaseDO (new): per-(org,agt) lease-epoch floor. A token below the floor is fenced (401 token_superseded); the floor auto-rises on a higher-epoch (rotation) or viaPOST /admin/lease/bump(revoke without redeploy).sessions-apiseam (orgkey.ts; mirrors the edge's dedicated-secret key hand-off;TEST_OR_KEYoverride for the acceptance run).usage:{include:true};cache_controlstripped for caching-unsafe models (claude-3-haiku→ OR→Bedrock 400s;claude-haiku-4.5works); cost extraction (JSON + SSE).Verification
SpendCountergate+provision+idempotency,DeployLeasefence+bump, org+agt hard enforcement, co-location (two sessions share the org+agt cap), per-session tracked-but-never-gated,cache_controlstrip, admin provision.wrangler dev, throwaway $1-capped OR key minted from the provisioning key and DELETEd after): a realclaude-haiku-4.5turn completed gateway → OpenRouter (200; modelclaude-4.5-haiku, cost echoed; no OR key / deploy token in the response); org+agt budget refused on-path (402 budget_exceeded, spent0.000088> budget0.00001); a stale lease epoch was fenced (401 token_superseded); no-token + bad-admin-secret → 401.Seam questions for the control plane (W1/W7)
TEST_OR_KEY):sessions-apiexposesPOST {GATEWAY_ORKEY_URL}(dedicated bearer) →{key}=resolveManagedSecretfor the org's active managed credential.AGENT_BUDGET_USD_DEFAULTviaPOST /admin/agent/budget.ep) minting: W7 mints a monotonic per-(org,agt)epinto the deploy token so rotation auto-fences; a leaked token is revoked viaPOST /admin/lease/bump.opencomputer = PR-only; do NOT merge (Igor merges).
🤖 Generated with Claude Code