Files
craftvia/docs/craftvia/MIGRATIONS.md
T
msolarczekandClaude Opus 5 6f3f5a5947 Fundament: Baseline-Migration mit RLS-Funktion
- 67 Certvia-Migrationen zu prisma/migrations/0001_baseline gesquasht
  (prisma migrate diff --from-empty --to-schema)
- RLS-Block: Rolle craftvia_app (NOLOGIN NOBYPASSRLS, idempotent), GRANTs +
  ALTER DEFAULT PRIVILEGES, wiederverwendbare Funktion enable_tenant_rls(tbl)
  (ENABLE + Policy tenant_isolation USING/WITH CHECK + FORCE + GRANT),
  angewendet auf alle Tenant-Tabellen (inkl. nullable tenant_id wie bisher)
- docs/craftvia/MIGRATIONS.md: Pflichten für neue Tenant-Tabellen
  (enable_tenant_rls + beide TENANT_MODELS-Listen + PII-Felder)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:40:34 +02:00

2.7 KiB

Craftvia — Migrationen & Row Level Security

Ausgangslage

Die Certvia-Historie (67 Migrationen) wurde beim Rückbau zu einer Baseline gesquasht:

  • prisma/migrations/0001_baseline/migration.sql
    • DDL aus npx prisma migrate diff --from-empty --to-schema prisma/schema.prisma --script
    • angehängter RLS-Block (Rolle craftvia_app, GRANTs, Funktion enable_tenant_rls)

Bestehende Datenbanken aus der Certvia-Zeit sind nicht migrierbar — lokal neu aufsetzen:

docker compose exec postgres psql -U craftvia -d postgres -c 'DROP DATABASE IF EXISTS craftvia WITH (FORCE);' -c 'CREATE DATABASE craftvia;'
npx prisma migrate deploy
npx prisma db seed

Mandantentrennung — drei Stellen, die immer zusammen gepflegt werden

Jede neue Tabelle mit tenant_id (z. B. customers, work_orders) braucht:

  1. Migration: nach dem CREATE TABLE im selben Migrationsfile

    SELECT enable_tenant_rls('customers');
    

    Die Funktion ist idempotent und setzt ENABLE ROW LEVEL SECURITY, die Policy tenant_isolation (USING und WITH CHECK auf tenant_id = current_setting('app.tenant_id', true)), FORCE ROW LEVEL SECURITY und die GRANTs für craftvia_app.

  2. TENANT_MODELS in src/server/db.ts — aktiviert den Tenant-Guard (dbForTenant filtert/injiziert tenantId, prüft Ownership bei Mutationen).

  3. TENANT_MODELS in src/server/backup/topology.ts — Backup/Restore/DSGVO-Export. Die Liste ist bewusst dupliziert; scripts/test-backup-isolation.ts bzw. scripts/test-rls-enforcement.ts prüfen Synchronität und RLS-Abdeckung gegen die DB.

Zusätzlich: Felder, die eine User.id referenzieren (Zuweisung, Freigabe, Ersteller), in src/server/dsgvo/pii-fields.ts eintragen.

Globale Tabellen (Kataloge ohne tenant_id, z. B. künftige Materialstammdaten des Plattformbetreibers) bekommen keine Policy und stehen in keiner TENANT_MODELS-Liste.

Nullable tenant_id

audit_logs, mail_logs und auth_tokens tragen eine nullable tenant_id (Plattform-Ereignisse). Die Policy ist identisch; Zeilen mit NULL sind für craftvia_app unsichtbar und werden ausschließlich über den Owner-Client geschrieben.

Neue Migration anlegen

# Schema ändern, dann:
npx prisma migrate dev --name <kurzname> --create-only
# migration.sql prüfen und ggf. `SELECT enable_tenant_rls('<tabelle>');` anhängen
npx prisma migrate dev

RLS scharf testen (lokal)

docker compose exec postgres psql -U craftvia -d craftvia \
  -c "ALTER ROLE craftvia_app WITH LOGIN PASSWORD 'craftvia_app_local';"
npx tsx scripts/test-rls-enforcement.ts

Für den Betrieb mit scharfer RLS: RLS_ENFORCED=true und RLS_DATABASE_URL=postgresql://craftvia_app:<pw>@<host>:5432/craftvia?schema=public.