import { sha256Hex } from "./crypto";
import { accountDb } from "./scoped-db";
import { forgetLocator, locate, registerLocator } from "./scoped-db/locators";
/** Tokens issued before anyone is signed in (a passkey sign-in challenge) live in this pseudo-account. */
export const ANONYMOUS_AUTH_SCOPE = "_anonymous";
async function tokenScope(tokenHash: string) {
const scopeId = await locate("auth_token", tokenHash);
return scopeId ? accountDb(scopeId) : null;
}
export type AuthTokenKind =
| "email-verify"
| "email-verify-spent"
| "password-reset"
| "webauthn"
| "pending-login"
| "editor-session"
| "editor-preview"
| "mcp-authz";
type Row = { user_id: string | null; payload: string; created_at: number };
export type ConsumedToken = { userId: string | null; payload: string; createdAt: number };
/** Stores single-use state keyed by the hash of a secret token. */
export async function storeAuthToken(
kind: AuthTokenKind,
token: string,
userId: string | null,
payload: string,
ttlSeconds: number,
): Promise<void> {
const now = Date.now();
const tokenHash = await sha256Hex(token);
const scopeId = userId ?? ANONYMOUS_AUTH_SCOPE;
await accountDb(scopeId).run(
"INSERT INTO auth_tokens (token_hash, kind, user_id, payload, created_at, expires_at) VALUES (?, ?, ?, ?, ?, ?)",
tokenHash,
kind,