Basis: Certvia dev@a48c5fb als Fundament für Craftvia
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>
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
# Kickoff-Prompt — Framework-Dimension: ISO 27001 neben TISAX
|
||||
|
||||
Du übernimmst den **Anwendungsumbau** für die Mehr-Framework-Fähigkeit. Die **Inhaltsseite ist fertig**: `seed/isms-vorlagenpaket-v2` trägt seit Branch `feature/iso27001-framework-mapping` **zwei Framework-Mappings auf einem Dokumentensatz** — `mapping.json` (VDA ISA, 321 Anforderungen) und `mapping-iso.json` (ISO/IEC 27001:2022, 120 Anforderungen). Die Anwendung kennt das zweite Mapping nicht: `parsePackageFiles` liest `mapping.json` fest verdrahtet.
|
||||
|
||||
**Pflichtlektüre vor der ersten Zeile Code:** `docs/UEBERGABE-framework-iso27001.md` — insbesondere **§1 „Die vier Fallen"**. Hintergrund und Begründung der Entscheidung: `docs/FRAMEWORK-MAPPING-ISO27001.md`. Gesamtarchitektur: `docs/KONZEPT-framework-iso27001.md` (D4 und Lane 2 sind dort per Nachtrag korrigiert).
|
||||
|
||||
## Repo & Branch
|
||||
- **origin:** `git.certvia.de/msolarczek/certvia`; zweiter Remote `local-gitea`.
|
||||
- **Basis ist `feature/iso27001-framework-mapping`**, nicht `dev` — dort liegt die Vorarbeit (Commits `492d315`, `bbde804`, `7769908`, `b28d0f0`).
|
||||
- AP1 auf `feature/framework-core`, PR gegen den Basis-Branch. AP2–AP5 danach je eigener Branch, parallelisierbar.
|
||||
|
||||
## Nicht anfassen
|
||||
- **`seed/isms-vorlagenpaket-v2/**`** — generiert. Inhaltliche Änderungen laufen ausschließlich über `_iso_crosswalk.json` / `_iso_sections.json` + `python3 _generate_iso.py`, nie direkt in den Markdown-Dateien (der Generator überschreibt sentinel-begrenzte Blöcke).
|
||||
- **Die TISAX-Logik verhaltensgleich lassen:** `src/lib/maturity.ts`, `src/lib/scope-filter.ts`, `src/server/assessment-level.ts`, `src/lib/control-titles.ts`, `src/lib/export/vda-isa*.ts`. Wenn du sie hinter eine `FrameworkStrategy` ziehst, muss das Verhalten identisch bleiben.
|
||||
|
||||
## Vier Invarianten — hier geht es sonst schief
|
||||
|
||||
1. **`reconcilePackage` archiviert fremde Anforderungen.** `prisma/import-policies.ts:368-371` setzt `archivedAt` auf jede `PolicyRequirement`, deren `reqId` nicht im importierten Paket steht. Ein ISO-Import in einen TISAX-Mandanten legt damit **alle 321 VDA-ISA-Anforderungen still** — und umgekehrt. Lösung: `PolicyRequirement.framework` ergänzen (Backfill `TISAX`) und den Archivierungslauf auf `where: { tenantId, framework }` einschränken. Für Dokumente, Variablen, Baseline und Nachweisregister gilt das **nicht** — die sind geteilt und identisch, sie dürfen genau einmal je Mandant abgeglichen werden.
|
||||
2. **Zwei Unique-Constraints brechen.** `PolicyTemplateVersion.version @unique` (`prisma/schema.prisma:1639`) → `@@unique([framework, version])`, sonst kollidieren ISO 2.1 und TISAX 2.1. `PolicyPackageState.tenantId @unique` (`:1614`) → `@@unique([tenantId, framework])`, sonst merkt sich ein Mandant nur eine Paketversion.
|
||||
3. **TISAX darf sich nicht verändern.** Messlatte ist `python3 seed/isms-vorlagenpaket-v2/_render_diff.py HEAD` → 0 Abweichungen.
|
||||
4. **Den Fail-Safe in `src/lib/policy-render.ts` nicht entfernen.** `buildContext` belegt fehlende Framework-Flags vor (`FLAG_FW_TISAX = true`, `FLAG_FW_ISO27001 = false`), damit Bestandsmandanten vor dem Paket-Re-Import keine leeren Anforderungsblöcke sehen.
|
||||
|
||||
## AP1 — Framework-Dimension *(Fundament, blockiert alles)*
|
||||
|
||||
**Schema, additiv:**
|
||||
```prisma
|
||||
enum Framework { ISO_27001 TISAX }
|
||||
|
||||
model TenantFramework {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
framework Framework
|
||||
isPrimary Boolean @default(false) @map("is_primary")
|
||||
config Json? // z. B. { tisaxLevel: "AL3" } bzw. { certScope }
|
||||
createdAt DateTime @default(now()) @map("created_at")
|
||||
@@unique([tenantId, framework])
|
||||
@@index([tenantId])
|
||||
@@map("tenant_frameworks")
|
||||
}
|
||||
```
|
||||
Dazu `PolicyRequirement.framework`, `PolicyTemplateVersion.framework`, `PolicyPackageState.framework`. Backfill aller Bestandsdaten auf `TISAX`. `TenantFramework` gehört in **`TENANT_MODELS`** (`src/server/db.ts:81`) und braucht eine **RLS-Policy in der Migration**.
|
||||
|
||||
**Code:**
|
||||
| Datei | Änderung |
|
||||
|---|---|
|
||||
| `prisma/import-policies.ts` | `parsePackageFiles(seedDir, mappingFile = "mapping.json")`; Requirements framework-scoped reconcilen |
|
||||
| `prisma/template-store.ts:147` | `resolvePackageForTenant(prisma, tenantId, seedDir, framework)`; `loadPublishedPackage(prisma, locale, framework)`; `getAvailableVersion` ebenso |
|
||||
| `scripts/sync-policy-templates.ts:23` | über **Frameworks × Sprachen** iterieren |
|
||||
|
||||
Die vier Aufrufer bekommen den Parameter durchgereicht: `src/server/provision.ts:139`, `src/server/actions/policy-package.ts:28`, `src/server/actions/admin.ts`, `src/app/(app)/policies/updates/page.tsx:44`. **Das Seed-Verzeichnis bleibt für beide Frameworks dasselbe** — die fünf `SEED_DIR`-Konstanten ändern sich nicht, nur der Mapping-Dateiname.
|
||||
|
||||
**DoD:** Bestandsmandanten laufen unverändert als TISAX; ein Mandant lässt sich mit `["ISO_27001"]`, `["TISAX"]` oder beiden provisionieren; bei Doppel-Framework koexistieren 321 + 120 Anforderungen und **keine** ist fälschlich archiviert.
|
||||
|
||||
## AP2 — Provisionierung und Flags *(klein, direkt nach AP1)*
|
||||
|
||||
`ProvisionOpts` (`src/server/provision.ts:37`) um `frameworks: Framework[]`. `provisionTenant` schreibt die `TenantFramework`-Zeilen, importiert je Framework das passende Mapping und setzt die Sichtbarkeits-Flags als `PolicyVariable`: nur TISAX → `true/false`, nur ISO → `false/true`, beides → `true/true`.
|
||||
|
||||
**Reihenfolge beachten:** `reconcilePackage` erhält nutzergepflegte Variablenwerte und überschreibt sie nicht — die Flags also **nach** dem Import setzen, sonst bleibt der Schema-Default stehen und ein ISO-Mandant sieht die VDA-ISA-Sicht. `tisaxLevel` bleibt auf `TenantSettings`, ist aber TISAX-scoped; bei einem reinen ISO-Mandanten keine AL-Flags setzen.
|
||||
|
||||
**DoD:** Frisch provisionierter ISO-Mandant öffnet `/policies` und sieht je Abschnitt `*Anforderungsbezug:* ISO/IEC 27001 …` plus die 19 ISO-only-Abschnitte; keine VDA-ISA-Anforderungen.
|
||||
|
||||
## AP3 — SoA-Modul *(das fehlende ISO-Kernartefakt)*
|
||||
|
||||
Der Modul-Key `soa` (`src/lib/modules.ts:19`) zeigt auf `/soa`, **die Route existiert nicht**; die heutige Logik liegt als Wizard-Schritt in `src/server/actions/soa.ts` und ist ein VDA-ISA-Reifegrad-Assessment (0–3), nicht die ISO-Anwendbarkeitserklärung.
|
||||
|
||||
```prisma
|
||||
model SoaEntry {
|
||||
id String @id @default(cuid())
|
||||
tenantId String @map("tenant_id")
|
||||
framework Framework
|
||||
control String // "A.5.15"
|
||||
applicable Boolean @default(true)
|
||||
justification String // Begründung Einbeziehung ODER Ausschluss
|
||||
source String? // Risiko-ID / gesetzliche / vertragliche Anforderung
|
||||
implementationStatus String @default("geplant") // umgesetzt | teilweise | geplant
|
||||
ownerId String? @map("owner_id")
|
||||
policyCode String? @map("policy_code")
|
||||
evidenceId String? @map("evidence_id")
|
||||
@@unique([tenantId, framework, control])
|
||||
@@index([tenantId])
|
||||
@@map("soa_entries")
|
||||
}
|
||||
```
|
||||
|
||||
`applicable`, `justification`, `implementationStatus` und die Ausschlussbegründung sind **normative Pflichtangaben** (ISO/IEC 27001:2022, 6.1.3 d) — ohne sie ist die SoA im Zertifizierungsaudit angreifbar. Vorbefüllung aus `mapping-iso.json` (93 Controls); das Feld `condition` steuert die Default-Anwendbarkeit. Fachliche Vorlage für Aufbau und Spalten: `seed/isms-vorlagenpaket-v2/Statement-of-Applicability-ISO.md`.
|
||||
|
||||
**DoD:** SoA vollständig pflegbar und als PDF/XLSX exportierbar; ein Control ohne Begründung wird als unvollständig markiert.
|
||||
|
||||
## AP4 — Kennzahlen, Managementbewertung, Korrekturmaßnahmen
|
||||
|
||||
| Klausel | Modell | Inhalt |
|
||||
|---|---|---|
|
||||
| 9.1 | `Kpi` / `KpiValue` | Kennzahl, Datenquelle, Zielwert, Turnus, Verantwortlicher, Messwerte je Periode |
|
||||
| 9.3 | `ManagementReview` | Datum, Eingaben nach 9.3.2, Ergebnisse nach 9.3.3, Beschlüsse mit Verantwortlichem und Termin |
|
||||
| 10.2 | `Nonconformity` + `CorrectiveAction` | Herkunft, Sofortkorrektur, Ursachenanalyse, Maßnahme, Wirksamkeitsbewertung |
|
||||
|
||||
Aufsetzen auf Vorhandenes: `Task.recurrence` (RRULE), `Task.remindAt`, `Task.effectiveUntil` (Wirksamkeitsintervall, gekoppelt an `Evidence.validUntil`), `TaskParticipant` (RACI), `AuditLog`. Datenquellen für Kennzahlen liegen bereits im Tool: Aufgabenfristen und Überfälligkeit, Incident-SLA und Meldefristen (`src/lib/incident-deadlines.ts`), Reifegrade je Control, Maßnahmenstatus. Die Feldinhalte stehen fachlich in R03 der Bibliothek (`ISO-MS-MESSUNG`, `ISO-MS-MGMTREVIEW`, `ISO-MS-CAPA`).
|
||||
|
||||
**DoD:** Kennzahlenblatt mit Zielwerten über zwei Perioden auswertbar; Management-Review entlang der 9.3.2-Agenda protokollierbar; ein Maßnahmenfall inklusive dokumentierter Wirksamkeitsprüfung abschließbar.
|
||||
|
||||
## AP5 — Dokumentenlenkung *(klein, hohe Auditwirkung)*
|
||||
|
||||
- `PolicyDocument.reviewCycle` + `nextReviewAt` — heute führt nur `ManagedRegister` einen `reviewCycle`; A.5.1 verlangt die Überprüfung „in geplanten Abständen".
|
||||
- `PolicyAcknowledgement { tenantId, policyDocumentId, version, userId, acknowledgedAt }` — Lesebestätigung, in `SPEC.md` §4.6 vorgesehen und bis heute nicht gebaut. Zugleich der einfachste Nachweis für Klausel 7.3 und Control A.6.3.
|
||||
- Änderungshistorie je Dokumentversion — aus `AuditLog` (Vorher/Nachher) ableitbar oder eigene Tabelle.
|
||||
|
||||
**DoD:** Übersicht „Prüfung fällig"; Auswertung der Lesebestätigungen je Richtlinienversion; Dokumenthistorie über mindestens zwei Versionen sichtbar.
|
||||
|
||||
## Validierungs-Gate vor jedem PR
|
||||
|
||||
```bash
|
||||
npx tsc --noEmit && npm run lint && npm run build
|
||||
cd seed/isms-vorlagenpaket-v2
|
||||
python3 _verify.py # TISAX-Sicht → OK
|
||||
python3 _verify_iso.py # ISO-Sicht → OK (0 Befunde)
|
||||
python3 _render_diff.py HEAD # TISAX-Regression → 0 Abweichungen
|
||||
```
|
||||
|
||||
Zusätzlich beachten:
|
||||
- **Migrationsflow Prisma 7** (`docs/HANDOVER-DEV.md:100`): `migrate diff --from-config-datasource … --to-schema … --script`, danach den **RLS-DO-Block manuell** an die `migration.sql` anhängen, dann `migrate deploy`.
|
||||
- **`scripts/check-module-guards.ts`** läuft als `prebuild`-Gate: jede neue Datei unter `src/server/actions/` dort eintragen (Modul-Key oder `EXEMPT`), sonst schlägt der Build fehl.
|
||||
- Bei paralleler Lane-Entwicklung teilen sich die Worktrees dieselbe lokale Postgres-DB: beim Erzeugen einer Migration nur die **eigenen** DDL-Blöcke übernehmen, Fremd-Drops von Hand entfernen.
|
||||
|
||||
## Definition of Done (gesamt)
|
||||
|
||||
| Prüfung | Erwartung |
|
||||
|---|---|
|
||||
| Bestandsmandant (TISAX) nach Deploy | Readiness und Exporte identisch zum Snapshot vor dem Umbau |
|
||||
| Import ISO in Mandant mit TISAX | 120 neue Anforderungen, **0 archivierte** ISA-Anforderungen |
|
||||
| Import ISO, Umsetzungstexte | 120 von 120 gefüllt |
|
||||
| Dokumente bei Doppel-Framework | 39 Dokumente, **nicht** doppelt |
|
||||
| Parallelbetrieb im Dokument | beide Anforderungssichten unter einem gemeinsamen Umsetzungstext |
|
||||
| Gate | tsc, lint, build, beide `_verify*`, `_render_diff` grün |
|
||||
|
||||
`parsePackageFiles` ist reine Dateiarbeit und ohne Datenbank testbar; für den Mandanten-Import gibt es `reconcilePackage(..., { dryRun: true })` — Änderungsreport ohne Schreibzugriff, geeignet als Freigabebedingung.
|
||||
|
||||
## Reihenfolge und Aufwand
|
||||
|
||||
```
|
||||
AP1 Framework-Dimension 4–6 PT ← blockiert alles
|
||||
├─ AP2 Provisionierung 1–2 PT
|
||||
├─ AP3 SoA-Modul 5–8 PT
|
||||
├─ AP4 Managementkl. 5–8 PT
|
||||
└─ AP5 Dok.-Lenkung 2–3 PT
|
||||
```
|
||||
|
||||
AP3–AP5 sind nach AP1 parallelisierbar. **Feature-Flag:** ISO bleibt laut Entscheidung D7 hinter einem Plattform-Schalter, bis AP3 abgenommen ist.
|
||||
|
||||
## Nicht dein Scope
|
||||
|
||||
Diese Punkte gehören dem ISB bzw. der Redaktion: Nachweisregister um Zeilen für Kennzahlenblatt, Management-Review-Protokoll und Maßnahmenregister ergänzen; VA-15 trennen und ein Verfahren für Korrekturmaßnahmen ergänzen (**Nummer ab VA-21**, VA-20 ist belegt); `REVIEW_CYCLE` an den 33 Bestandsstellen auf die getrennten Zyklus-Variablen umstellen; ISB-Freigabe der 19 neuen Abschnittstexte.
|
||||
Reference in New Issue
Block a user