80f2e2f619
Medical before Payment: the harder scientific test (safety AND security coupled, full lifecycle, deep risk/evidence demands). ISO 13485 runs through the SAME engine as ISO 27001 -> CRA, only new data, 0 runtime. The key result: IEC 81001-5-1 (health-software security) pulls in the SAME security MCAPs as the CRA, so Medical REUSES cyber capabilities (the safety/security coupling appears as capability reuse) while adding 7 genuinely new medical caps (clinical evaluation, software safety classification, ISO 14971 risk file, benefit-risk). rejected_assumptions intact. Effect on the convergence core: secure_signed_update_distribution 18 -> 24 and technical_vulnerability_management 17 -> 23, now spanning 3 domains (cyber + industrial + medical) — the core visibly GROWS, exactly the convergence signal. New 5th report: MISSING CONVERGENCE — deterministic (no ML) token-cluster detector for potential structural duplications: a name token shared by >=3 MCAPs across >=2 distinct sources is flagged for EXPERT REVIEW (never auto-merged). Surfaces e.g. the `risk` cluster (6 risk MCAPs across 6 sources) and `security`/`software`; single-source decompositions are filtered out. Complements Suspicious by looking at cross-source duplication, not single MCAPs. Also records the durable modelling rule extracted from the frequency fix: evidence is attributed to its ORIGIN; its value against a target is computed later (relevance(evidence,target)). Ledger now 8 sources, Architecture Stability 8/8 = 100%. Non-runtime -> no deploy. 29 tests pass, check-loc 0.
84 lines
5.0 KiB
Python
84 lines
5.0 KiB
Python
# ruff: noqa
|
|
# mypy: ignore-errors
|
|
"""Medical stress test — the harder scientific test: safety + security coupled (Phase Ω #3).
|
|
|
|
Medical jointly tests properties not yet tested together: safety and security TIGHTLY COUPLED, a full
|
|
product lifecycle, very strong risk-management/evidence demands, high regulatory depth. ISO 13485 (a
|
|
medical QMS) is run as a Company Profile through the SAME engine as before — only new DATA, 0 runtime.
|
|
|
|
The interesting result: IEC 81001-5-1 (health-software security) requires the SAME security capabilities
|
|
as the CRA, so Medical REUSES cyber MCAPs (the coupling shows up as capability reuse, growing the core),
|
|
while ALSO adding genuinely new medical caps (clinical evaluation, software safety classification, the
|
|
ISO 14971 risk file, benefit-risk). Synthetic, no real names. Non-runtime -> no deploy.
|
|
Run: cd backend-compliance && PYTHONPATH=. python3 reference_scenarios/medical_stress_test.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)
|
|
|
|
|
|
_TP = os.path.join(os.path.dirname(__file__), "..", "knowledge", "transition_patterns")
|
|
MED = yaml.safe_load(open(os.path.join(_TP, "transition_pattern_iso13485_to_medical_v1.yaml"), encoding="utf-8"))
|
|
|
|
# existing capability universe (everything modelled before Medical) — to detect reuse vs new
|
|
known = set()
|
|
for f in os.listdir(_TP):
|
|
if f.endswith(".yaml") and "iso13485" not in f:
|
|
p = yaml.safe_load(open(os.path.join(_TP, f), encoding="utf-8"))
|
|
known |= {a["capability"] for a in p.get("likely_covered", [])}
|
|
known |= {d["capability"] for d in p.get("delta_requirements", [])}
|
|
|
|
mgmt = [a["capability"] for a in MED["likely_covered"]]
|
|
delta_caps = [d["capability"] for d in MED["delta_requirements"]]
|
|
profile = build_company_profile(
|
|
CompanyContext(company_id="med", certifications=[Certification(certification_id="ISO13485")]),
|
|
{"ISO13485": CapabilityMappingEntry(capability_ids=mgmt, confidence=Confidence.MEDIUM)})
|
|
assess = assess_transition(TransitionContext(company_id="med", target=TransitionGoal(target_id="Medical")),
|
|
[TargetRequirement(capability_id=c) for c in mgmt + delta_caps], profile)
|
|
delta = sorted({c.capability_id for c in assess.coverage if c.status == CoverageStatus.MISSING})
|
|
|
|
reused = sorted(c for c in delta if c in known) # safety/security coupling: cyber caps reused
|
|
fresh = sorted(c for c in delta if c not in known) # genuinely new medical caps
|
|
|
|
w("# Medical Stress Test — Safety + Security gekoppelt, der härtere Test (Phase Ω #3)")
|
|
w("")
|
|
w('_Medical prüft erstmals gemeinsam: Safety UND Security gekoppelt, voller Produktlebenszyklus, sehr starke Risikomanagement-/Nachweispflichten, hohe regulatorische Tiefe. ISO 13485 als Company Profile durch DIESELBE Engine — nur neue Daten, 0 Runtime. Synthetisch, keine echten Namen._')
|
|
w("")
|
|
w("## 1. ISO 13485 als Profil → Delta über dieselbe Engine")
|
|
w("- ISO 13485 liefert medizinische QMS-Disziplin (Welt-1): %s." % ", ".join("`%s`" % c for c in mgmt[:4]) + " …")
|
|
w("- Delta (fehlt): **%d** Capabilities — über dieselbe `assess_transition`, **0 neue Runtime-Klassen**." % len(delta))
|
|
w("")
|
|
w("## 2. Safety/Security-KOPPLUNG — Medical REUSED Cyber-MCAPs (IEC 81001-5-1 = CRA-Security)")
|
|
w("- **Wiederverwendete Cyber-Capabilities (%d):** %s." % (len(reused), ", ".join("`%s`" % c for c in reused)))
|
|
w("- → Genau das ist die Kopplung: die Gesundheitssoftware-Security (IEC 81001-5-1) fordert **dieselben** Fähigkeiten wie die CRA. Diese MCAPs wandern damit in eine **dritte Domäne** und werden im Convergence-Core noch zentraler.")
|
|
w("")
|
|
w("## 3. Genuin neue, medizin-spezifische Capabilities")
|
|
w("- **Neu (%d):** %s." % (len(fresh), ", ".join("`%s`" % c for c in fresh)))
|
|
w("- Capabilities als Verben: `conduct_clinical_evaluation`, `classify_software_safety_iec62304`, `maintain_risk_management_file_iso14971`, `perform_benefit_risk_analysis`.")
|
|
w("")
|
|
w("## 4. Was ISO 13485 typischerweise NICHT erzeugt _(rejected_assumptions, Welt-1/Welt-2)_")
|
|
for r in MED["rejected_assumptions"]:
|
|
w("- %s" % r)
|
|
w("")
|
|
w("## Befund")
|
|
w("")
|
|
w('> **Die härteste Domäne bisher (Safety+Security gekoppelt, voller Lebenszyklus, tiefe Risiko-/Nachweispflicht) lief durch die unveränderte Pipeline — 0 neue Runtime-Klassen, nur ein Pattern-YAML.** Das stärkste Einzelsignal: **%d Security-Capabilities werden aus dem Cyber-Bestand WIEDERVERWENDET** (IEC 81001-5-1 = CRA), während **%d medizin-spezifische** neu hinzukommen. Genau so wächst ein Kern: gemeinsame Fähigkeiten verbinden Cyber, Maschinenbau, Automotive UND Medizin; das Domänenspezifische bleibt am Rand. Architecture Stability bleibt stabil; der Engpass ist jetzt die Qualität der Wissensmodellierung, nicht die Architektur.' % (len(reused), len(fresh)))
|
|
w("")
|
|
|
|
print("\n".join(OUT))
|