feat: Customer Mission #5 — a non-security target, evidence relevance flips both ways

Closes the Evidence-Relevance(Target) claim by testing it on a deliberately NON-security target
(a hand-authored environmental / material-evidence Required set — no corpus, no ISO-14001 norm
model, no new module). One company profile, three targets through the same engine:

  - ISO 14001: keine (CRA) / keine (TISAX) / HOCH (environmental)   <- flips
  - ISO 27001: hoch (CRA) / hoch (TISAX) / keine (environmental)    <- flips the other way
  - PSIRT:     hoch (CRA) / keine (TISAX) / keine (environmental)

Proves relevance(evidence, target) is two-sided: no evidence is relevant "in itself"; relevance
only arises against a target -> it must be computed, never stored as an attribute of the evidence.

With this, the target-type diversity for the later selector is complete (Regulation · Certification
· Contract/Tender · OEM-Spec · Environmental/Material) — five target types through one engine, so a
Scope→Journey selector finally makes sense. Synthetic, no real names. Non-runtime -> no deploy. 5 tests.
This commit is contained in:
Benjamin Admin
2026-06-28 10:18:28 +02:00
parent 5cba0504df
commit dbf7b9b587
3 changed files with 211 additions and 0 deletions
@@ -0,0 +1,129 @@
# ruff: noqa
# mypy: ignore-errors
"""Customer Mission #5 — a NON-security target: does evidence relevance really flip?
The whole „Evidence-Relevance(Target)" claim is only convincing if it holds in BOTH directions. Missions
#2#4 showed security evidence (ISO 27001, PSIRT) ranking differently across security targets, and ISO
14001 being worthless against the CRA/TISAX. This mission closes the loop with a deliberately NON-security
target — an environmental / material-evidence requirement set — and asks the one question:
is `relevance(evidence, target)` genuinely a function of the TARGET, or an attribute of the evidence?
Expected and shown: ISO 14001 is keine/niedrig against CRA and TISAX but HOCH against the environmental
target — while the security certificates (ISO 27001, PSIRT) flip the other way (relevant for security,
keine for the environmental target). The same evidence is worthless or decisive depending on the target.
DELIBERATELY NOT here (per scope): no environmental corpus, no ISO-14001 norm model, no new runtime
module, no deploy, no real names. The environmental target is a hand-authored Required set (injected like
any TargetRequirement) purely to point the existing engine at a non-security goal.
Run: cd backend-compliance && PYTHONPATH=. python3 reference_scenarios/mission_non_security_target.py
"""
from __future__ import annotations
import os
import yaml
from compliance.company import (
CompanyContext, Certification, CapabilityMappingEntry, build_company_profile,
)
from compliance.reasoning.enums import Confidence
from compliance.transition_reasoning import (
TransitionContext, TransitionGoal, TargetRequirement, assess_transition, CoverageStatus,
)
OUT = []
def w(s=""):
OUT.append(s)
_K = os.path.join(os.path.dirname(__file__), "..", "knowledge", "transition_patterns")
def _caps(pattern_file):
p = yaml.safe_load(open(os.path.join(_K, pattern_file), encoding="utf-8"))
return [a["capability"] for a in p["likely_covered"]] + [d["capability"] for d in p["delta_requirements"]]
# ── Three targets — two security, one NON-security (the new axis) ───────────────────────────
CRA = _caps("transition_pattern_iso27001_to_cra_maschinenvo_v1.yaml") # security regulation
TISAX = _caps("transition_pattern_isms_to_tisax_v1.yaml") # security certification
# NON-security target: an environmental / material-evidence requirement set. Hand-authored Required
# capabilities (NOT a corpus, NOT an ISO-14001 norm model) — just a goal to point the engine at.
ENVIRONMENTAL = [
"environmental_management_documentation", "energy_efficiency_documentation",
"supply_chain_environmental_due_diligence", "material_declaration_scip_reach",
"hazardous_substance_restriction_rohs", "carbon_footprint_accounting",
"recycling_and_take_back", "battery_passport_material_data",
]
TARGETS = [("CRA", "Security/Regulation", CRA), ("TISAX", "Security/Certification", TISAX),
("Umwelt-/Materialnachweis", "NICHT-Security", ENVIRONMENTAL)]
# ── ONE company profile (the same multi-certified archetype; it HAS ISO 14001) ──────────────
CERT_OBS = {
"ISO27001": ["information_security_management", "incident_management", "access_control_and_authentication",
"technical_vulnerability_management", "security_logging_and_monitoring", "secure_development_lifecycle"],
"TISAX": ["information_security_management", "access_control_and_authentication", "incident_management",
"supplier_security", "physical_security", "prototype_protection"],
"PSIRT": ["coordinated_vulnerability_disclosure", "exploited_vuln_and_incident_reporting",
"public_security_advisories"],
# an EMS (ISO 14001) touches several environmental process areas — relevant ONLY to an env target:
"ISO14001": ["environmental_management_documentation", "energy_efficiency_documentation",
"supply_chain_environmental_due_diligence"],
"ISO9001": ["ce_conformity_assessment_and_technical_documentation"],
}
cmap = {k: CapabilityMappingEntry(capability_ids=v, confidence=Confidence.MEDIUM) for k, v in CERT_OBS.items()}
profile = build_company_profile(
CompanyContext(company_id="mc5", certifications=[Certification(certification_id=k) for k in CERT_OBS]), cmap)
def _delta(caps):
reqs = [TargetRequirement(capability_id=c) for c in caps]
a = assess_transition(TransitionContext(company_id="mc5", target=TransitionGoal(target_id="t")), reqs, profile)
return sorted({c.capability_id for c in a.coverage if c.status == CoverageStatus.MISSING})
def _rel(cert_caps, target_caps):
n = len(set(cert_caps) & set(target_caps))
return n, ("hoch" if n >= 3 else "niedrig" if n >= 1 else "keine")
w('# Customer Mission #5 — ein Nicht-Security-Ziel: kippt die Evidence-Relevanz?')
w("")
w('_Enger Scope: KEIN Umweltrecht, KEINE ISO-14001-Normmodellierung, KEIN neues Modul, KEIN Deploy. Nur die EINE Frage: ist `relevance(evidence, target)` wirklich eine Funktion des Ziels — oder ein Attribut der Evidence? Das Umwelt-/Materialnachweis-Ziel ist ein hand-authored `Required`-Satz (synthetisch), nur um die bestehende Engine auf ein Nicht-Security-Ziel zu richten. Synthetischer Kunde, keine echten Namen._')
w("")
w("## Der Kunde (synthetisch) — EIN Profil (hat u. a. ISO 14001)")
w("> **ISO 9001 · ISO 27001 · ISO 14001 · TISAX · PSIRT** · vernetzte Maschinen · Export EU")
w("")
# ── 1. Die Relevanz-Matrix (zwei Security-Ziele + ein Umwelt-Ziel) ─────────
w("## 1. Evidence-Relevanz über drei Ziele — zwei Security, eines NICHT")
w("| Zertifizierung (Evidence) | → CRA | → TISAX | → Umwelt-/Material |")
w("|---|---|---|---|")
for cert, caps in CERT_OBS.items():
cells = [_rel(caps, t)[1] + " (%d)" % _rel(caps, t)[0] for _, _, t in TARGETS]
mark = " ⟵ kippt" if cert == "ISO14001" else ""
w("| **%s** | %s | %s | %s |%s" % (cert, cells[0], cells[1], cells[2], mark))
w("")
# ── 2. Der Beweis: dieselbe Evidence, gegensätzlicher Wert je Ziel ─────────
iso14_env = _rel(CERT_OBS["ISO14001"], ENVIRONMENTAL)
iso27_env = _rel(CERT_OBS["ISO27001"], ENVIRONMENTAL)
psirt_env = _rel(CERT_OBS["PSIRT"], ENVIRONMENTAL)
w("## 2. Beweis — Relevanz ist eine Funktion des ZIELS (in BEIDE Richtungen)")
w("- **ISO 14001:** gegen CRA/TISAX **keine**, gegen das Umwelt-/Materialziel **%s (%d)**. Dieselbe Zertifizierung — von wertlos zu entscheidend, nur weil das Ziel wechselt." % (iso14_env[1], iso14_env[0]))
w("- **Symmetrisch:** **ISO 27001** (hoch gegen CRA/TISAX) ist gegen das Umwelt-/Materialziel **%s (%d)**; **PSIRT** ebenso **%s (%d)**. Security-Evidence ist hier wertlos." % (iso27_env[1], iso27_env[0], psirt_env[1], psirt_env[0]))
w("- Delta des Umwelt-/Materialziels: **%d** fehlende Fähigkeiten (das Profil deckt nur die ISO-14001-nahen ab) — über dieselbe `assess_transition`-Engine, kein Sonderpfad." % len(_delta(ENVIRONMENTAL)))
w("")
w('→ **Damit ist `relevance(evidence, target)` zweiseitig bewiesen:** keine Evidence ist „an sich" relevant; Relevanz entsteht erst gegen ein Ziel. Eine Capability/Zertifizierung ohne Ziel hat keinen Relevanzwert.')
w("")
# ── Befund ────────────────────────────────────────────────────────────────
w("## Befund")
w("")
w('> **Ein und dieselbe Evidence kann je Ziel wertlos oder hoch relevant sein** — hier erstmals an einem NICHT-Security-Ziel gezeigt, in beide Richtungen (ISO 14001 kippt von keine→hoch, Security-Certs von hoch→keine). Folgerung für das spätere Modell: Relevanz darf NICHT als Attribut der Evidence gespeichert werden, sondern nur als `relevance(evidence, target)` berechnet (computed-not-stored). **Damit ist die Ziel-Diversität für den späteren Selektor beisammen: Regulation · Certification · Contract/Tender · OEM-Spec · Umwelt-/Material-Ziel — fünf Zielarten durch dieselbe Engine. Erst jetzt wird ein Scope→Journey-Selektor sinnvoll** (er optimiert nicht mehr auf einer einzigen Zielart).')
w("")
print("\n".join(OUT))