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);