Files
multica/server/migrations/091_daemon_token_revoked_at.up.sql
Jiayuan Zhang f52db9e96c feat(server): install_token mint+exchange + daemon_token revoke (MUL-2305)
Phase 1 of RFC MUL-2297 — DB and credential contract for the new runtime
install flow. CLI/daemon/UI plumbing lands in later phases.

Schema (migration 091):
- daemon_token.revoked_at — explicit revoke replaces TTL-based expiry; the
  exchange path now mints daemon_token rows with a ~100y expires_at so the
  cleanup query stays intact while the credential is effectively long-lived
  until revoked.
- install_token — short-lived (15m) single-use credential. used_at IS NULL
  is the atomic gate enforced inside the UPDATE so a concurrent second
  exchange returns zero rows.

API:
- POST /api/workspaces/{id}/install-tokens — admin-only mint, returns mit_
  once; only the hash is stored.
- POST /api/install-tokens/exchange — public (the mit_ is the credential);
  atomically consumes the install_token and returns a fresh mdt_.

Error contract for Phase 2 daemon installer:
- 401 invalid_install_token — unknown hash OR expired
- 401 install_token_already_used — hash exists but used_at IS NOT NULL

Co-authored-by: multica-agent <github@multica.ai>
2026-05-17 00:09:48 +08:00

11 lines
639 B
SQL

-- daemon_token.revoked_at flips the credential from "short-lived auto-expiry"
-- to "long-lived until explicitly revoked". Phase 1 of the runtime UX
-- refactor (RFC MUL-2297): once the install_token / mdt_ flow is wired up
-- (Phase 2+), an issued daemon token sticks until the workspace owner
-- revokes its runtime — so users no longer need to re-paste a token on a
-- schedule. expires_at stays NOT NULL and is set to ~now()+100y at mint
-- time, which is functionally equivalent to "no expiry" while keeping the
-- DeleteExpiredDaemonTokens cleanup path intact.
ALTER TABLE daemon_token
ADD COLUMN revoked_at TIMESTAMPTZ NULL;