User-Auftrag: Datenbereitschaft für Weg 1 bestätigen + dokumentieren, KEIN UI bauen.
Neuer Spec-Abschnitt "Weg 1 — Obligation->Norm-Zitierfähigkeit":
- Zwei Zitierebenen getrennt: RAG-Evidence-Zitat (Advisor heute, /retrieve) ⊥
Obligation->Norm-Zitat (norm_id-Join, diese Registry) — beide langfristig nötig.
- Datenbereitschaft: obligation norm_ids READY (62/64 joinbar) + KB-v2-Ziele bestätigt;
GAP = Runtime-Vertrag obligation_join_keys.json trägt norm_ids NICHT (nur citation_units),
Go ObligationKey ohne NormIDs, AssessObligationStatus setzt CitationSpans:"pending" hart.
- Deferred-Sequenz (nicht gebaut): 1 Data-Prep norm_ids->join_keys (Domäne 2) ->
2 Go-Build (CitationSpans aus norm_ids, koordiniert) -> 3 UI ("Diese Pflicht beruht auf ...").
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
9.4 KiB
Obligation Registry v1 — Schema, Zitierfähigkeit, Zwei-Graphen-Architektur
Status: Spec festgeschrieben (2026-06-24). Baut auf legal_obligation_layer_v1.md + obligation_aggregation_validation.md. Die Obligation Discovery Pipeline v1 ist gegen Ground Truth validiert (SBOM 12 vs 10, Vuln 8 vs 7, out_of_scope + conditional Applicability korrekt).
Leitsatz
Die Legal Obligation ist das fachliche Wissensobjekt der Plattform — nicht der Master Control. Controls sind Prüfstrategien / Erkennungsmuster / Evidenzsammler FÜR eine Obligation. Ohne Zitierfähigkeit ist die Registry fachlich nicht belastbar: die erste Kundenfrage ist immer „Wo steht das?".
Zwei Assets, zwei Graphen, EIN Join (nicht verschmelzen, verbinden)
- Asset 1 — Compliance Knowledge (bereits gebaut): 313k atomare Controls, 33k Master Controls, ~14k use-case-gemappt, Dedup, Obligation Layer, Applicability, Tiering, G/C/E.
- Asset 2 — Zitierfähige Wissensbasis (entsteht in anderer Session): Dokument → Chunk → Paragraph → Span → Zitat.
Die beiden werden NICHT verschmolzen (das wäre wie eine normalisierte DB nach CSV zu exportieren und neu zu importieren). Sie werden über die Obligation gekoppelt:
GRAPH 1 — Legal Knowledge Graph (Chat/Advisor) GRAPH 2 — Compliance Execution Graph (Engine)
Regulation → Annex/Artikel → Paragraph → Span Obligation → Control → Criterion → Evidence → Finding
\ /
\____ LEGAL OBLIGATION ______/ ← gemeinsame Sprache (der Join)
Chat: „diese Aussage stammt aus Absatz X." · Engine: „diese Obligation ist nicht erfüllt." →
beide meinen DIESELBE obligation_id.
Registry-Schema v1
id: # snake_case, regulierungs-agnostisch (z.B. sbom_complete)
name: # kurz
description: # 1 Satz
tier: # LEGAL_MINIMUM | BEST_PRACTICE | IMPLEMENTATION_GUIDANCE | EVIDENCE
family: # Organisationshilfe (z.B. sbom, vulnerability_handling)
applicability: # universal | conditional:<pred> | domain:<x>
facets: # welche Evidenz-Facetten die Pflicht belegt
governance: bool
capability: bool
evidence: bool
legal_basis: # PRIMÄRRECHT — Pflicht zwingend (mind. 1 Anker für LEGAL_MINIMUM)
- source: CRA
regulation_code: eu_2024_2847
article: "" # falls zutreffend
annex: "Annex I, Part II"
section: ""
paragraph: ""
span_id: "" # harter Anker in die zitierfähige Wissensbasis (Asset 2)
document_version: ""
citation: "" # menschenlesbar
guidance_basis: # SEKUNDÄR — Umsetzung/Best Practice, NICHT Pflicht
- source: NIST SSDF
anchor: ""
role: best_practice # implementation_guidance | best_practice
member_controls: # control_uuids (Prüflogik aus Asset 1)
citation_anchor_ids: # span/paragraph-Anker (Asset 2) — auf der OBLIGATION, NICHT auf Controls
relationships: # siehe Beziehungsgraph
decision_method: # CONTENT/LLM | CONTENT/EMBEDDING | FIELD/REGEX | BEHAVIOR/PLAYWRIGHT ...
out_of_scope: [] # ausgeschlossene Cluster + Begründung
Zitierfähigkeit hängt an der OBLIGATION (nicht an Controls)
258 SBOM-Controls → 11 Obligations: nur die Obligation speichert
CRA / Annex I / Paragraph X / chunk_id / span_id / document_version. Die 258 Controls zeigen
nur auf die obligation_id. Folge: Regulierungsänderung (CRA v1→v2) = citation_anchor
tauschen, Controls bleiben identisch. Massive Pflegeersparnis + Versionsstabilität.
legal_basis vs guidance_basis + source_role
Damit beim Verschmelzen von CRA + NIST + OWASP zu einer Obligation NICHT verloren geht, was
Pflicht / Best Practice / Evidenz / Umsetzung ist, klassifiziert die Discovery-Pipeline jeden
Member/Cluster mit einer source_role:
LEGAL_BASIS → Primärrecht (begründet die Pflicht)
GUIDANCE → NIST/OWASP/ENISA/BSI/ISO (Umsetzung/Best Practice)
EVIDENCE → Nachweis/Bericht/Audit
IMPLEMENTATION → technische Umsetzungsanweisung
OUT_OF_SCOPE → gehört nicht zur Obligation (andere Regulierung/Domäne)
HARTE Tier-Regel
Eine Obligation wird LEGAL_MINIMUM nur mit mindestens einem Primärrechts-Anker
(legal_basis nicht leer). Ohne Primärrechts-Anker:
BEST_PRACTICE | IMPLEMENTATION_GUIDANCE | EVIDENCE — aber niemals Pflicht.
Beziehungsgraph (Ontologie)
Strukturell (bereits in der Pipeline): same_obligation, sub_obligation,
applicability_variant, evidence_for, governance_for, out_of_scope.
Semantisch (NEU, P2-Ergänzung): requires, implements, supports,
produces_evidence_for, depends_on, derived_from. Beispiele:
sbom_established --supports--> vulnerability_handling --supports--> incident_reporting
authentication --requires--> credential_management
→ für den Compliance Advisor extrem wertvoll (er kann Pflicht-Ketten erklären).
Citation-Anchor-Pipeline (Document → Obligation, NICHT Document → Control)
Der neue Ingest erzeugt zusätzlich zu Chunk/Embedding: paragraph_uuid, span_uuid,
document_version, legal_citation, referenced_articles, referenced_regulations.
Erst danach läuft Obligation Discovery, sodass jede neu entdeckte Obligation sofort ihre
Primärquelle bekommt:
Neue Dokumente → Chunking → Span IDs → LLM („welche Obligation(en)?") → Confidence
→ Review → obligation.citation_anchor_ids[]
Die alten Controls werden wiederverwendet; die Pipeline erzeugt zusätzlich Obligation→Evidence und Obligation→Citation-Anchors. Kein Re-Ingest zum Neubau von Controls.
Sequenz (geändert — Registry vor weiteren Cuts)
SBOM ✓ → Vuln ✓ → Registry v1 (DIESE Spec) → Ontologie/Beziehungsgraph ergänzen
→ Authentication → Remote Access → Logging → Updates
Begründung: Schema jetzt billig änderbar; bei 300–1000 Obligations wird jede Schemaänderung teuer. Fortschritt wird daran gemessen, ob jede neue Obligation die Registry besser macht — nicht an neuen Controls.
Scope-Audit (Review-Step, PFLICHT je Cut)
Die Registry modelliert Hersteller-Pflichten. Bestimmungen, die an Behörden / notifizierte
Stellen / Mitgliedstaaten adressiert sind (Sanktionen, Marktüberwachung, Anforderungen an
Konformitätsbewertungsstellen), sind Enforcement-/Institutions-Recht. Prinzip: Adressat der Norm
⊥ Handlungspflicht des Herstellers. scope-Attribut-Achse (Enum, KEINE neue Objektklasse):
in_scope— Norm adressiert direkt den Hersteller (Default).out_of_scope— reines Staats-/Durchsetzungs-/Institutions-Recht (Adressat ≠ Hersteller, KEINE mittelbare Herstellerpflicht). Ausobligation_join_keys.jsongefiltert. Präzedenz CSIRT/ENISA.derived_obligation— Norm adressiert primär eine andere Rolle, erzeugt aber MITTELBAR eine Hersteller-Handlungspflicht → bleibt im Set (scope_split_candidatemarkiert spätere Aufspaltung Normadressat ↔ abgeleitete Pflicht; nicht vorzeitig festziehen).
Gate-Regel:
Jeder neue Obligation-Cut muss durch Scope-Audit laufen.
Findings mit authority-/institution-addressed obligations werden dokumentiert.
Automatische Reclassification ist verboten, solange kein explizites Review-Go vorliegt.
Werkzeug-Trennung (FLAG ⊥ MUTATE):
scope_audit.py— flaggt nur (scannt alle Registries →scope_audit_findings.json; mutiert nie).validate_registry.py— surfaced pro Cut unklassifizierte authority-/institution-Obligations als non-fatal Warnung (blockt nicht, mutiert nicht).apply_scope_classification.py— mutiert (setztscope), läuft NUR nach explizitem Review-Go (ändertjoin_keys+ Compliance-Execution-Sync → menschlich/koordiniert).
Weg 1 — Obligation→Norm-Zitierfähigkeit (Datenbereitschaft; UI deferred)
Zwei Zitierebenen — NICHT verwechseln (beide langfristig nötig):
- RAG-Evidence-Zitat (heute im Advisor sichtbar):
Frage/Antwort → Evidence-Chunk(KB-v2article_label/source_url,[n]-Citations). Quelle = Compliance/KB-Session/retrieve. - Obligation→Norm-Zitat (der
norm_id-Join):Pflicht → konkrete Rechtsgrundlage(KB-v2-Unit). Quelle = diese Registry. Weg 1 = dieses Zitat sichtbar machen.
Datenbereitschaft (Stand 2026-07-01):
| Baustein | Status |
|---|---|
obligations/*.json → legal_basis.norm_ids |
✅ 62/64 joinbar (53 annex + 16 article, KB-v2-verifiziert) |
| KB-v2-Join-Ziele (CRA Art1-71 · MaschVO Art1-54 · Annexe) | ✅ bestätigt |
obligation-status-Endpoint + Traversal (obligation_id→citation_unit→Controls→Evidence) |
✅ vorhanden; exponiert LegalBasis = citation_units |
Runtime-Vertrag obligation_join_keys.json trägt norm_ids |
❌ nur citation_units (Anker-Strings), KEINE norm_ids |
Go ObligationKey-Struct / CitationSpans |
❌ kein NormIDs-Feld; AssessObligationStatus setzt CitationSpans:"pending" hart (compliance_status.go) |
Deferred-Sequenz (UI zuletzt) — bewusst NICHT gebaut:
- Data-Prep (nicht-UI, Domäne 2):
norm_idsinexport_join_keys.py→obligation_join_keys.jsonexportieren. - Build (ai-sdk, koordiniert):
NormIDsinObligationKey;AssessObligationStatusfülltCitationSpansausnorm_idsstatt"pending". - UI (später): „Diese Pflicht beruht auf CRA Anhang I / Art. 13".