Files
craftvia/docs/PROMPT-lane-framework-iso27001.md
msolarczekandClaude Opus 5 c8e6f30a27
CI / build-and-check (push) Canceled after 0s
CI / audit (push) Canceled after 0s
CI / sbom (push) Canceled after 0s
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>
2026-09-14 11:05:39 +02:00

12 KiB
Raw Permalink Blame History

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:

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.

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

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.