SET search_path TO atlas, public; -- A link request exists before it belongs to a workspace, so it cannot use the -- normal workspace RLS policy. Its UUID is high entropy and the final token -- exchange additionally requires the PKCE verifier stored with the request. CREATE TABLE extension_link_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), client_id TEXT NOT NULL, code_challenge TEXT NOT NULL, workspace_id UUID REFERENCES workspaces(id) ON DELETE RESTRICT, user_id UUID REFERENCES users(id) ON DELETE RESTRICT, approved_at TIMESTAMPTZ, consumed_at TIMESTAMPTZ, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), CHECK (expires_at > created_at), CHECK ((workspace_id IS NULL AND user_id IS NULL AND approved_at IS NULL) OR (workspace_id IS NOT NULL AND user_id IS NOT NULL AND approved_at IS NOT NULL)) ); CREATE INDEX ix_extension_link_requests_pending ON extension_link_requests (expires_at) WHERE approved_at IS NULL AND consumed_at IS NULL; COMMENT ON TABLE extension_link_requests IS 'Short-lived browser-to-extension pairing requests. Access is protected by unguessable IDs and PKCE, not workspace RLS, because the request is created before Web-session approval.';