Consumes the cross-session contract obligations/obligation_join_keys.json (47
obligation_ids). Interim bridge = citation_unit (our source_norm <-> registry
citation_units), to be hardened to the stable obligation_id (field now optional
on ControlMapping).
ComputeObligationCoverage joins the 47 registry obligations to our accepted
control mappings: covered=2 (user_authentication_required, firmware_software_
authentication), mapped_rejected=3 ((2)(e) -> our OWASP mappings rejected,
route via NIST/BSI), uncovered=42. This coverage signal is the feedback to the
Obligation session for what to cut/refine next.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- DROP confidence from the persisted mapping: a curated mapping is a
professional statement, not an AI guess (retriever score -> rationale only).
- ADD mapping_status (candidate|accepted|rejected|superseded) — the review state.
- ADD audit trail (reviewed_by/review_date/review_reason); accepted/rejected
fail-closed without it.
- EXTEND mapping_type: + implements, + contradicts.
- Advisor truth = mapping_status=accepted (acceptedOnly filter).
- migrate the 18 CRA->OWASP rows to mapping_status=candidate.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Versioned JSONL store + Go model for Regulation->Control mappings, per the
A-decision: the retriever only PROPOSES candidates; the curated mapping is the
audited truth the Advisor uses at runtime, never re-invented per query.
- ControlMapping struct (source_norm/source_role/target_framework/target_control/
mapping_type/confidence/provenance/rationale/version)
- enum validation (rule layer), fail-closed loader, forward+reverse index,
curated-only filter (IsCurated)
- seed: 2 retriever_candidate rows CRA Annex I -> OWASP ASVS (not yet curated)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>