From 9b6e9d8383653f68c81ed535a006d9bc8227ab07 Mon Sep 17 00:00:00 2001 From: Joachim Hummel Date: Fri, 17 Apr 2026 17:36:25 +0000 Subject: [PATCH] migration: subscribers-Tabelle mit DOI-Feldern und Consent-Tracking (Finding 3) Co-Authored-By: Claude Sonnet 4.6 --- migrations/pg/2026-04-17_subscribers-doi.sql | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 migrations/pg/2026-04-17_subscribers-doi.sql diff --git a/migrations/pg/2026-04-17_subscribers-doi.sql b/migrations/pg/2026-04-17_subscribers-doi.sql new file mode 100644 index 0000000..e3d1bd0 --- /dev/null +++ b/migrations/pg/2026-04-17_subscribers-doi.sql @@ -0,0 +1,31 @@ +-- Subscribers-Tabelle mit Double-Opt-In und DSGVO-Consent-Tracking +-- Wird pro Tenant-Schema ausgeführt (SET search_path = tenant_, public vorher) + +CREATE TABLE IF NOT EXISTS subscribers ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + email TEXT NOT NULL, + email_hash TEXT NOT NULL UNIQUE, + status TEXT NOT NULL DEFAULT 'pending' + CHECK (status IN ('pending', 'active', 'unsubscribed', 'bounced')), + list_id UUID, + + -- Double-Opt-In (DSGVO-Pflicht) + doi_token TEXT UNIQUE, + doi_requested_at TIMESTAMPTZ, + doi_confirmed_at TIMESTAMPTZ, + + -- Consent-Nachweis + consent_ip INET, + consent_user_agent TEXT, + + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE INDEX IF NOT EXISTS idx_subscribers_email_hash ON subscribers(email_hash); +CREATE INDEX IF NOT EXISTS idx_subscribers_doi_token ON subscribers(doi_token); +CREATE INDEX IF NOT EXISTS idx_subscribers_status ON subscribers(status); + +CREATE OR REPLACE TRIGGER subscribers_updated_at + BEFORE UPDATE ON subscribers + FOR EACH ROW EXECUTE FUNCTION update_updated_at();