Files
breakpilot-compliance/docs-src/development/obligation_registry_v1.md
T
Benjamin Admin 2a8abb6235 docs(citability): Weg-1 Datenbereitschaft dokumentiert (Obligation->Norm), UI deferred
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>
2026-07-01 14:31:32 +02:00

182 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Obligation Registry v1 — Schema, Zitierfähigkeit, Zwei-Graphen-Architektur
Status: **Spec festgeschrieben (2026-06-24)**. Baut auf
[legal_obligation_layer_v1.md](legal_obligation_layer_v1.md) +
[obligation_aggregation_validation.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
```yaml
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 3001000 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). Aus `obligation_join_keys.json` gefiltert. Präzedenz CSIRT/ENISA.
- `derived_obligation` — Norm adressiert primär eine andere Rolle, erzeugt aber MITTELBAR eine
Hersteller-Handlungspflicht → **bleibt im Set** (`scope_split_candidate` markiert 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** (setzt `scope`), läuft NUR nach explizitem Review-Go
(ändert `join_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-v2 `article_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:**
1. **Data-Prep** (nicht-UI, Domäne 2): `norm_ids` in `export_join_keys.py``obligation_join_keys.json` exportieren.
2. **Build** (ai-sdk, koordiniert): `NormIDs` in `ObligationKey`; `AssessObligationStatus` füllt `CitationSpans` aus `norm_ids` statt `"pending"`.
3. **UI** (später): „Diese Pflicht beruht auf **CRA Anhang I / Art. 13**".