-- AlterTable ALTER TABLE "platform_admins" ADD COLUMN "sessions_valid_after" TIMESTAMP(3); -- AlterTable ALTER TABLE "users" ADD COLUMN "sessions_valid_after" TIMESTAMP(3); -- CreateTable CREATE TABLE "auth_tokens" ( "id" TEXT NOT NULL, "principal_type" TEXT NOT NULL, "principal_id" TEXT NOT NULL, "tenant_id" TEXT, "type" TEXT NOT NULL, "token_hash" TEXT NOT NULL, "new_email" TEXT, "expires_at" TIMESTAMP(3) NOT NULL, "used_at" TIMESTAMP(3), "request_ip" TEXT, "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "auth_tokens_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE UNIQUE INDEX "auth_tokens_token_hash_key" ON "auth_tokens"("token_hash"); -- CreateIndex CREATE INDEX "auth_tokens_principal_type_principal_id_type_idx" ON "auth_tokens"("principal_type", "principal_id", "type"); -- CreateIndex CREATE INDEX "auth_tokens_expires_at_idx" ON "auth_tokens"("expires_at"); -- ============================================================================ -- Row Level Security (SEC2) -- -- Muster wie seit F-04: ENABLE + FORCE + Policy mit USING *und* WITH CHECK. -- -- auth_tokens.tenant_id ist NULLABLE (Plattform-Admin-Tokens ohne -- Mandantenbezug) — dieselbe Situation wie bei audit_logs und mail_logs. Zeilen -- mit tenant_id = NULL sind fuer `isms_app` weder les- noch schreibbar. -- -- WICHTIG: Der Token-Lookup beim Einloesen laeuft ohne Session (der Nutzer ist -- gerade nicht angemeldet) und damit ohne Mandantenkontext. Er erfolgt deshalb -- bewusst ueber den rohen `prisma`-Client (Owner-Rolle, BYPASSRLS) — siehe -- src/server/auth-token.ts. Die Policy bleibt als zweite Verteidigungslinie -- gegen versehentliche Zugriffe ueber den Mandanten-Guard bestehen. -- ============================================================================ GRANT SELECT, INSERT, UPDATE, DELETE ON "auth_tokens" TO isms_app; ALTER TABLE "auth_tokens" ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS tenant_isolation ON "auth_tokens"; CREATE POLICY tenant_isolation ON "auth_tokens" USING ("tenant_id" = current_setting('app.tenant_id', true)) WITH CHECK ("tenant_id" = current_setting('app.tenant_id', true)); ALTER TABLE "auth_tokens" FORCE ROW LEVEL SECURITY;