dbf7b9b587
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.
130 lines
8.1 KiB
Python
130 lines
8.1 KiB
Python
# 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))
|