# 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 300–1000 Obligations wird jede Schemaänderung
teuer. Fortschritt wird daran gemessen, ob jede neue Obligation die Registry besser macht —
nicht an neuen Controls.
