Public: anyone can read this; the crew can change it.

App identity, the core: the `app` table, `src/apps.ts` and the four actions — no doors #44

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Pushed. This lands the core of #7's design (from pull #22, which no longer merges) resized to just what nothing else can start without.

shipped production is serving it deploy 460b31c

opened this

Pushed. This lands the core of #7's design (from pull #22, which no longer merges) resized to just what nothing else can start without.

What changed

  • app table appended to migrations in src/db.ts (id, name, created_at, created_by, generation, revoked_at).
  • src/apps.ts: appSecret(id, generation, key = identityKey) derives a posting key as base64url(HMAC-SHA256(key, "relay-app:<id>:<generation>")), throwing on an empty key; appById(db, id) looks up a row or returns undefined.
  • src/actions.ts grows registerApp, rotateAppKey, revokeApp, listApps — admin-only (anon → signin_required, user → forbidden); id reuses SOURCE_RE; a duplicate id is invalid, never a silent rotate; a revoked app refuses to rotate. registerApp/rotateAppKey take an optional key (defaulting to the real identityKey) so a test can hand in a fixed key instead of the empty local default — an empty key surfaces as the new unavailable failure rather than throwing. The key is returned exactly once; listApps returns { id, name, generation, revoked } only.
  • Tests: src/apps.test.ts pins the derivation against a hand-computed vector, checks generation/id sensitivity and the empty-key refusal, and covers appById. src/actions.test.ts covers every refusal by name, the duplicate id, the revoked-app-can't-rotate case, and asserts no key ever appears in listApps.
  • README: a module-table row for src/apps.ts and a paragraph on how keys are derived, shown once, rotated by generation, revoked by a column.

Left out, on purpose: no route, page section, MCP tool or terminal key — those are #36 and #30, both waiting on this issue.

Try it: bun test, or FORGE_APP_DATA=./data bun run src/db.ts --check to see the new schema version against a fresh or pre-existing database.

🤖 Generated with Claude Code

Closes #35

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs