jevstrudel.git / worker / migrations / 0007_site_address.sql
1-- The site's move from jevstrudel.deizel.workers.dev to strudel.lmjtfy.fun
2-- (2026-10-05). Owner: src/accounts-store.ts, for src/auth.ts and
3-- src/moved.ts.
4--
5-- A passkey belongs to the host it was made on (its WebAuthn relying party
6-- ID): the browser offers it there and nowhere else. So each credential
7-- records its host, and the site can tell a signed-in listener whether they
8-- have a passkey for the address they are on. Every row older than this
9-- migration was made on the workers.dev host in production. A local dev
10-- database's older rows were made on localhost and are tagged with the
11-- wrong host by this default: its owner is asked once to add a passkey for
12-- localhost, which is allowed, since only passkeys of the same host are
13-- excluded from a new one.
14ALTER TABLE credentials ADD COLUMN rp_id TEXT NOT NULL DEFAULT 'jevstrudel.deizel.workers.dev'
15  CHECK (length(rp_id) BETWEEN 1 AND 253);
16
17-- A session carried from the old address to the new one (src/moved.ts): the
18-- SHA-256 (hex) of a random token the old host put in its redirect, the
19-- account, and the old host's session, which ends when the token is taken.
20-- Taken with DELETE … RETURNING, so once, and within a minute.
21--
22-- What is identifying here (migrations/CLAUDE.md): the account's id, for a
23-- minute. Never the token, so a read of this table carries no session
24-- anywhere.
25CREATE TABLE session_handoffs (
26  token_hash TEXT PRIMARY KEY CHECK (length(token_hash) = 64 AND token_hash NOT GLOB '*[^0-9a-f]*'),
27  user_id TEXT NOT NULL REFERENCES users (id) ON DELETE CASCADE,
28  from_session_hash TEXT NOT NULL CHECK (length(from_session_hash) = 64 AND from_session_hash NOT GLOB '*[^0-9a-f]*'),
29  created_at INTEGER NOT NULL CHECK (created_at > 0),
30  expires_at INTEGER NOT NULL CHECK (expires_at > created_at)
31) STRICT;
32CREATE INDEX session_handoffs_by_expiry ON session_handoffs (expires_at);