You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
setkernel-live: Usage Durable Object with /ingest/usage and Access-gated /usage/data #66
Part of the v1 tracker setkernel/hq#721 (daily tokens per seat, path B).
The table needs durable storage longer than Prometheus/Loki's 30 days, and a private read path on the site Raghav named. A separate SQLite DO class keeps usage away from the Hub, so no public route can return it. The ingest reuses INGEST_AUD, and the read checks a new USAGE_AUD and fails closed. setkernel-live deploys on every merge, so the route must be safe while the Access app does not exist yet.
The Access app for /usage is a separate issue. With USAGE_AUD empty, the read route answers 503, so this can merge and deploy first.
Acceptance criteria
Usage DO (migration tag v2, new_sqlite_classes ["Usage"]) with table buckets(hour, seat, model, surface, input, output, cache_read, cache_write, usd_micros, requests, PRIMARY KEY(hour, seat, model, surface)); upsert; rows older than 400 days deleted.
POST /ingest/usage: Access JWT checked against INGEST_AUD, body ≤ 256 KiB, seat in allowlist [vega, rigel, lyra, orion, polaris, codex, other], surface in [vm, desktop, cli, cloud, codex], integers ≥ 0, hour YYYY-MM-DDTHH; else 400. Response echoes per-Halifax-day per-seat totals for the hours pushed.
GET /usage/data?month=YYYY-MM: Access JWT checked against USAGE_AUD (var "" → 503); returns per-day (Halifax, via homeDay) per-seat sums plus month totals; Cache-Control: no-store.
Tests (vitest worker pool): fixture push of 48 hourly buckets → /usage/data sums match; a bucket at 03:00Z on a DST day lands on the previous Halifax day; missing or wrong JWT → 403; bad seat → 400; privacy test: after a usage push, /api/state, /api/replay?h=24 and the /ws first frame contain none of the pushed numbers or seat-usage keys.
scripts/smoke.mjs also checks GET /usage/data is refused (401/403/503, never 200) and README documents the routes; npm run validate passes.
The PR body says Closes setkernel/setkernel-live#<this issue> and Refs setkernel/hq#721
Files likely touched
src/usage.js
src/worker.js
wrangler.jsonc
scripts/smoke.mjs
test/worker/usage.test.js
test/usage.test.mjs
README.md
Risk class
R3: a new private data route on a site that deploys on every merge; it must fail closed
Split on 2026-11-01: this ships as #68, then #69; #69 closes this issue. PR #67 is closed unmerged (401 lines). agent-ready comes off here, so the slices are the only work items. — Claude Lead
Activity
orion-setkernel commentedon Nov 1, 2026
Picked up. Working on branch
agent/66-setkernel-live-usage-durable-object-with. Automated: @orion-setkernel's agent onorion-dev.realRaghavGupta commentedon Nov 1, 2026
Split on 2026-11-01: this ships as #68, then #69; #69 closes this issue. PR #67 is closed unmerged (401 lines). agent-ready comes off here, so the slices are the only work items. — Claude Lead
Merge pull request #70 from setkernel/agent/68-usage-store-and-write-…
Merge pull request #72 from setkernel/agent/69-usage-read-path-and-sm…