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>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```sql
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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)
|
||||
|
||||
```bash
|
||||
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`.
|
||||
Reference in New Issue
Block a user