# FDN-02 – Prüfprotokoll: Datenmodell & Migrationen Welle 2. Voraussetzung: FDN-01 (Status "Fertig"). ## Datenmodell `migrations/tenant/0001_documents.up.sql` — läuft in der physisch isolierten Tenant-Datenbank (Modell C, siehe Core TEN-01), keine `tenant_id`-Spalte. | Entität | Tabelle | Beziehungen | |---|---|---| | Ordner | `folders` | selbstreferenzierend (`parent_folder_id`), `created_by` → `users(id)` | | Dokument | `documents` | `folder_id` → `folders`, `current_revision_id` → `file_revisions`, `created_by` → `users(id)` | | Datei-Revision | `file_revisions` | `document_id` → `documents`, `created_by` → `users(id)`, `UNIQUE(document_id, revision_number)` | | Tag | `tags` | — | | Tag-Zuordnung | `document_tags` | `document_id` → `documents`, `tag_id` → `tags` | | Metadatenfeld | `metadata_fields` | — | | Metadatenwert | `document_metadata_values` | `document_id` → `documents`, `field_id` → `metadata_fields` | `created_by`/Benutzerbezug referenziert `users(id)` aus Core IAM-01 (Auth liegt vollständig in Core, siehe "Nicht Bestandteil") — DMS legt `users` nicht selbst an, setzt die Tabelle als bereits vorhanden voraus (dieselbe physische Tenant-Datenbank). **Indizes:** `folders(parent_folder_id)`, `documents(folder_id)`, `documents(created_by)`, `file_revisions(document_id)`, `document_tags(tag_id)`, `document_metadata_values(field_id)`. ## Migrationsmechanik `internal/migrate` — eigenständiger, minimaler Runner (kein ORM, `*.up.sql`/`*.down.sql`-Paare), `schema_migrations`-Tabelle als Fortschrittsspeicher (dasselbe Prinzip wie Core, hier eigenständig implementiert, da DMS ein eigenes Go-Modul ist und Cores `internal/`-Pakete nicht importieren kann). ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Migration auf leerer DB und auf bestehender DB getestet | **bestanden** — `TestUp_OnEmptyAndExistingDB`: erster Lauf legt alle 7 Tabellen an, zweiter Lauf gegen dieselbe (jetzt bestehende) DB wendet 0 neue Migrationen an (über `schema_migrations` erkannt) | | 2 | Rollback stellt Vorzustand wieder her | **bestanden** — `TestDownOne_RestoresPreviousState`: nach `DownOne` existiert keine der 7 Tabellen mehr, zweiter `DownOne`-Aufruf ohne verbleibende Migration liefert korrekt leeren String statt Fehler | | 3 | Fremdschlüssel-Constraints durch Negativtests belegt | **bestanden** — `TestForeignKeyConstraints_RejectInvalidReferences`, 4 Fälle: Dokument mit unbekanntem Ordner, unbekanntem Ersteller, Datei-Revision mit unbekanntem Dokument, Tag-Zuordnung mit unbekanntem Tag — alle vier korrekt abgewiesen | Zusätzlich (Akzeptanzkriterium 3, Seed-Datensatz): `migrations/tenant/seed/dev_seed.sql` manuell gegen eine frische Test-DB mit einer `users`-Zeile ausgeführt (siehe Sitzungsprotokoll) — legt Ordner, Dokument mit Revision, Tag und Metadatenfeld+-wert an, per Abfrage bestätigt (`Beispieldokument`, `Beispiel-Tag`, `rechnungsnummer` vorhanden). Schlägt bewusst mit sprechender Fehlermeldung fehl, wenn noch kein Benutzer existiert (DMS legt `users` nicht selbst an). ## Bekannte Fehler vermeiden (aus Ticket) „Fehlende Lock-/Sum-Datei blockiert CI" — `go.sum` ist committet (siehe `git status`/Commit-Diff), `go mod tidy` auf 192.168.1.131 ausgeführt und Ergebnis übernommen. ## Build/Test-Ergebnis (192.168.1.131) ``` go build ./... -> clean go vet ./... -> clean make lint -> clean (golangci-lint) go test ./... -v -count=1 -> 3/3 Pakete mit Tests ok (cmd/app, internal/migrate), 0 Fehlschläge ``` ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen erfüllt und belegt.