-- CreateTable CREATE TABLE "login_pairings" ( "id" TEXT NOT NULL, "secret_hash" TEXT NOT NULL, "desktop_token_hash" TEXT NOT NULL, "status" TEXT NOT NULL, "user_id" TEXT, "desktop_ua" VARCHAR(255), "desktop_ip" VARCHAR(45), "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, "expires_at" TIMESTAMP(3) NOT NULL, "approved_at" TIMESTAMP(3), "consumed_at" TIMESTAMP(3), CONSTRAINT "login_pairings_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE INDEX "login_pairings_expires_at_idx" ON "login_pairings"("expires_at"); -- CreateIndex CREATE INDEX "login_pairings_status_expires_at_idx" ON "login_pairings"("status", "expires_at"); -- AddForeignKey ALTER TABLE "login_pairings" ADD CONSTRAINT "login_pairings_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE; -- ST-1001: Postgres LISTEN/NOTIFY voor QR-pairing flow. -- -- AFTER INSERT/UPDATE-trigger op login_pairings emit een JSON-payload op het -- `scrum4me_pairing`-kanaal. De SSE-route /api/auth/pair/stream/[pairingId] -- (ST-1004) abonneert op dit kanaal en filtert per pairing_id. -- -- DELETE wordt niet ondersteund — pairings gaan naar status='consumed' of -- 'cancelled', niet weg. Een eventuele cleanup-job die rijen wel deleten zou -- kan dat zonder dit kanaal te bereiken. -- -- Payload shape: -- { op: 'I' | 'U', -- pairing_id: text, -- status: text } -- -- Channel-name is hardcoded analoog aan `scrum4me_changes` uit ST-801. Bij -- wijziging deze migratie én app/api/auth/pair/stream/[pairingId]/route.ts -- bijwerken. CREATE OR REPLACE FUNCTION notify_pairing_change() RETURNS trigger AS $$ DECLARE payload jsonb; BEGIN payload := jsonb_build_object( 'op', CASE TG_OP WHEN 'INSERT' THEN 'I' WHEN 'UPDATE' THEN 'U' END, 'pairing_id', NEW.id, 'status', NEW.status ); PERFORM pg_notify('scrum4me_pairing', payload::text); RETURN NEW; END; $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS login_pairings_notify ON login_pairings; CREATE TRIGGER login_pairings_notify AFTER INSERT OR UPDATE ON login_pairings FOR EACH ROW EXECUTE FUNCTION notify_pairing_change();