Skip to content

spike(L2): thin per-session gateway over OpenRouter — Contract #1 [DO NOT MERGE]#486

Draft
ZIJ wants to merge 1 commit into
flue-slicefrom
spike/oc-gateway
Draft

spike(L2): thin per-session gateway over OpenRouter — Contract #1 [DO NOT MERGE]#486
ZIJ wants to merge 1 commit into
flue-slicefrom
spike/oc-gateway

Conversation

@ZIJ

@ZIJ ZIJ commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Slice-0 de-risk spike for the Flue-native agent type (oc-bg-agents work/flue-native-buildout.md, design 013 §4), Lane L2. Proves a thin CF Worker over OpenRouter and delivers frozen inter-lane Contract #1 (the gateway HTTP contract). Draft — opencomputer is PR-only, Igor merges.

The full contract + live-verification steps are in cloudflare-workers/oc-gateway/README.md.

The proof

npx vitest run14 green. test/integration.test.ts runs the real worker handler + real SessionBudget DO against a mock OpenRouter and asserts the whole on-path flow: 401 (missing/expired token), forward with org-key injection (the session token never reaches OR) + usage.include, body passthrough, on-path budget enforcement with a bounded one-call overshoot ($0.03 cap, $0.02/call → 2 pass, 3rd → 402), uncapped sessions never refuse.

One real anthropic/* turn isn't run here (no OpenRouter key / dev env in this sandbox — the buildout explicitly allows documenting it); the README has the exact wrangler dev + registerProvider(baseUrl=gateway) steps. The OR wire format (cost echo) is already validated by the §9.7 managed-path spike.

Extends, doesn't replace

Org-level spend keeps flowing through the org's single OpenRouter inference key → the existing model_meter cron → Autumn (one cost-source-of-truth). The gateway builds no billing path; it only adds the injection point a CF Worker needs (it can't use the box secrets-proxy) + per-session sub-metering + enforcement.

Explicit answer: per-session OR keys vs on-path counter → on-path counter

Per-session OR keys would fragment the per-org truth the cron reconciles and add a per-session key lifecycle at session scale; the gateway is already on-path, so it reads OR's echoed cost and enforces before/after each call (authoritative, not best-effort observe()). A SessionBudget DO (not KV) gives read-then-write consistency so concurrent subagent/tool calls can't double-spend past the cap.

Flagged for the frozen contract / prod

  • Token: HS256 (shared secret) for the spike → EdDSA + lease-epoch fence in prod (minter holds private key; gateway holds public; superseded token stops verifying).
  • Org-key resolution: spike uses a SPIKE_OR_KEY/ORG_KEYS KV stand-in → prod fetches the sealed OR key from the credential store (Infisical), cached per-org.
  • Budget-refusal shape: 402 budget_exceeded — the exact shape Flue/pi-ai surfaces cleanly as a turn-terminating error (→ outcome budget_exceeded) is a live-verify item.
  • Cost extraction: primary = OR's echoed usage.cost; GET /generation?id= exact-cost fallback documented, unwired.

🤖 Generated with Claude Code

Slice-0 de-risk spike for the Flue-native agent type (oc-bg-agents
work/flue-native-buildout.md, design 013 §4). Proves a THIN CF Worker over
OpenRouter and freezes inter-lane Contract #1 (the gateway HTTP contract).

EXTENDS the shipped managed-model path, does not replace it: org-level spend keeps
flowing through the org's single OpenRouter inference key → the existing
model_meter cron → Autumn (one cost-source-of-truth). The gateway only adds the
injection point a CF Worker needs (can't use the box secrets-proxy) plus
per-session sub-metering + on-path budget enforcement.

Worker (cloudflare-workers/oc-gateway/):
- index.ts — verify per-session token → (org,agent,session); budget gate on-path;
  inject the ORG's OR key (never exposed to the tenant); forward to
  openrouter.ai/api; tee-meter the response cost; passthrough (JSON + SSE).
- token.ts — HS256 session token (Web Crypto). PROD: EdDSA + lease-epoch fence.
- budget.ts — SessionBudget DO: strongly-consistent per-session µ$ counter + gate
  (a DO, not KV, so concurrent calls can't double-spend past the cap).
- cost.ts — per-response cost from OR's echoed usage.cost (JSON + SSE).
- scripts/mint.ts — mint a session token for live verification.

Explicit answer (per-session OR keys vs on-path counter): ON-PATH COUNTER.
Per-session OR keys would fragment the per-org cost-source-of-truth the cron
reconciles + add per-session key lifecycle; the gateway is already on-path so it
reads OR's echoed cost and enforces before/after each call (authoritative, not
best-effort observe()). Cost = a bounded one-call overshoot, proven in tests.

Verification: 14 vitest green — logic (token/cost) + integration (real handler +
real DO vs mock OpenRouter): 401s, org-key injection, usage.include, on-path
budget refusal with bounded overshoot, uncapped sessions. One REAL anthropic/*
turn is documented (no OR key/dev env here; the buildout allows documenting it) —
README has the exact wrangler-dev + registerProvider steps.

opencomputer = PR-only; do NOT merge (Igor merges). Draft for review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant