Unveränderter Stand von certvia/dev (a48c5fb) plus Craftvia-Spezifikation und Brandbook unter docs/craftvia/. ISMS-Module werden im Folgecommit entfernt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
85 lines
3.4 KiB
SQL
85 lines
3.4 KiB
SQL
-- CreateTable
|
|
CREATE TABLE "mail_logs" (
|
|
"id" TEXT NOT NULL,
|
|
"tenant_id" TEXT,
|
|
"scope" TEXT NOT NULL DEFAULT 'tenant',
|
|
"to" TEXT NOT NULL,
|
|
"template" TEXT NOT NULL,
|
|
"locale" TEXT NOT NULL DEFAULT 'de',
|
|
"status" TEXT NOT NULL DEFAULT 'pending',
|
|
"provider_message_id" TEXT,
|
|
"error" TEXT,
|
|
"attempts" INTEGER NOT NULL DEFAULT 0,
|
|
"dedupe_key" TEXT,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"sent_at" TIMESTAMP(3),
|
|
|
|
CONSTRAINT "mail_logs_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "notification_preferences" (
|
|
"id" TEXT NOT NULL,
|
|
"tenant_id" TEXT NOT NULL,
|
|
"user_id" TEXT NOT NULL,
|
|
"event_type" TEXT NOT NULL,
|
|
"email" BOOLEAN NOT NULL DEFAULT true,
|
|
"locale" TEXT,
|
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "notification_preferences_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "mail_logs_dedupe_key_key" ON "mail_logs"("dedupe_key");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "mail_logs_tenant_id_created_at_idx" ON "mail_logs"("tenant_id", "created_at");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "mail_logs_status_idx" ON "mail_logs"("status");
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "notification_preferences_tenant_id_idx" ON "notification_preferences"("tenant_id");
|
|
|
|
-- CreateIndex
|
|
CREATE UNIQUE INDEX "notification_preferences_user_id_event_type_key" ON "notification_preferences"("user_id", "event_type");
|
|
|
|
|
|
-- ============================================================================
|
|
-- Row Level Security (SEC1)
|
|
--
|
|
-- Muster wie seit F-04 (20260730160000_rls_enforce): ENABLE + FORCE + Policy mit
|
|
-- USING *und* WITH CHECK. Ohne WITH CHECK koennte die eingeschraenkte App-Rolle
|
|
-- `isms_app` unter FORCE keine Zeilen mehr anlegen.
|
|
--
|
|
-- mail_logs.tenant_id ist NULLABLE (Plattform-Mails ohne Mandantenbezug). Die
|
|
-- Policy ist trotzdem identisch zu audit_logs, das dieselbe Situation hat:
|
|
-- Zeilen mit tenant_id = NULL erfuellen die Bedingung nie und sind fuer `isms_app`
|
|
-- weder les- noch schreibbar. Das ist beabsichtigt — Plattform-Zeilen werden
|
|
-- ausschliesslich ueber den rohen `prisma`-Client (Owner-Rolle, BYPASSRLS)
|
|
-- geschrieben, genau wie writePlatformAudit().
|
|
--
|
|
-- GRANT ist noetig, weil die pauschalen Rechte aus 20260702095816 nur fuer die
|
|
-- damals existierenden Tabellen galten; ALTER DEFAULT PRIVILEGES greift nur fuer
|
|
-- Objekte, die von der dort gesetzten Rolle erzeugt werden.
|
|
-- ============================================================================
|
|
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON "mail_logs" TO isms_app;
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON "notification_preferences" TO isms_app;
|
|
|
|
ALTER TABLE "mail_logs" ENABLE ROW LEVEL SECURITY;
|
|
DROP POLICY IF EXISTS tenant_isolation ON "mail_logs";
|
|
CREATE POLICY tenant_isolation ON "mail_logs"
|
|
USING ("tenant_id" = current_setting('app.tenant_id', true))
|
|
WITH CHECK ("tenant_id" = current_setting('app.tenant_id', true));
|
|
ALTER TABLE "mail_logs" FORCE ROW LEVEL SECURITY;
|
|
|
|
ALTER TABLE "notification_preferences" ENABLE ROW LEVEL SECURITY;
|
|
DROP POLICY IF EXISTS tenant_isolation ON "notification_preferences";
|
|
CREATE POLICY tenant_isolation ON "notification_preferences"
|
|
USING ("tenant_id" = current_setting('app.tenant_id', true))
|
|
WITH CHECK ("tenant_id" = current_setting('app.tenant_id', true));
|
|
ALTER TABLE "notification_preferences" FORCE ROW LEVEL SECURITY;
|