Compliance map¶
Maps the project's controls (the nine invariants and the STPA security constraints
SEC-1..SEC-10) to regulatory frameworks, and onward to the enforcing code. Citations
use the original-language convention (Art. for EU law). This is a working mapping,
not legal advice. The authoritative control derivation is
docs/stpa/07-security-constraints.md. Application and transition dates for these
frameworks are tracked in docs/governance/regulatory-deadlines.md (BL-036).
Path-citation convention (BL-060): an enforcement path in the Enforcement column is
repo-relative when it begins with a top-level directory (scripts/, deploy/,
.github/) or a root file (pyproject.toml); every other module path is relative to
src/praxis/ (so execution/audit.py means src/praxis/execution/audit.py). The
machine-checked projection in docs/governance/compliance-controls.json always uses the full
repo-relative form, which scripts/validate_compliance.py verifies exists.
Honesty note (ADR-0015, 2026-06-08): some rows name a control that is specified or
partly built but not yet fully wired in v0. Those rows are annotated inline with the
v0 gap and the tracking BL-NNN; treat them as in-progress, not delivered, until
the item closes.
Machine-checkable since 2026-06-13 (ADR-0021, BL-031): this prose map has a
machine-checked projection in docs/governance/compliance-controls.json, validated
in CI by scripts/validate_compliance.py (make validate-compliance). The
validator enforces that every control's cited enforcement module exists and carries
its SEC-N back-citation, that every in-scope framework is mapped, that every
proving test exists, and that this map cites no control the catalog does not define.
An implemented control with no proving test is therefore a build break, not just a
visible gap (partial or planned controls are exempt; their gap is tracked by a BL id).
EU AI Act (Regulation (EU) 2024/1689)¶
| Reference | Project control | SEC / invariant | Enforcement |
|---|---|---|---|
| Art. 9 (risk management) | Conservative pre-execution tier classification | SEC-3 / inv 2 | execution/patterns.py, execution/policy.py::classify |
| Art. 12 (logging and traceability) | Tamper-evident, append-only audit trail; runtime Merkle checkpoints and optional anchor; opt-in RFC 3161 TSA stamper | SEC-2, SEC-9 / inv 1, 3 | execution/audit.py, audit/evidence.py (runtime checkpoints produced since ADR-0019/BL-076; RFC 3161 TSA opt-in, ADR-0030/BL-095; OS append-only the control for the default LocalStamper) |
| Art. 14 (human oversight) | Tiered HITL at T2+; server-minted, single-use, TTL-bound approval nonce surfaced out-of-band (human-binding since ADR-0016, BL-072) | SEC-2, SEC-6 / inv 6 | execution/runner.py, execution/contract.py::ApprovalRegistry, drift/converge.py |
| Art. 15 (accuracy, robustness, cybersecurity) | Bitemporal source of truth; drift detection; SSRF filter | SEC-7, SEC-10 / inv 4, 7 | store/sqlite.py, drift/, _ssrf.py |
NIS2 (Directive (EU) 2022/2555) and NISG 2026 (Austria)¶
| Reference | Project control | SEC / invariant | Enforcement |
|---|---|---|---|
| Art. 21 (risk-management measures) | Least privilege; scoped, revocable credentials (broker wired, opt-in via the first grant, ADR-0016 BL-049); kill switch with an audited operator actuator and a durable sentinel (ADR-0016 BL-075) | SEC-8 / inv 9 | actuation/credentials.py, execution/runner.py::KillSwitch, tools/emergency.py |
| Art. 21 (asset and configuration management) | Drift detection against desired state | SEC-6 / inv 6 | drift/engine.py, drift/sources.py |
| Art. 23 (reporting) | Complete, verifiable audit evidence for incident reconstruction; documented audit/evidence retention tiers bound in config | SEC-2, SEC-9 / inv 3 | audit/verify_evidence, scripts/verify_audit.py, runtime Merkle checkpoints and anchor (ADR-0019, BL-076); retention tiers in config.py (PRAXIS_AUDIT_RETENTION_DAYS/PRAXIS_EVIDENCE_RETENTION_DAYS, BL-035) bound into the session record, enforced by storage-layer archival (SECURITY.md, docs/runbooks/operate.md); a non-forgeable RFC 3161 TSA stamper is available opt-in (audit/rfc3161.py::Rfc3161Stamper, BL-095, ADR-0030), with OS append-only the control for the default LocalStamper |
Cyber Resilience Act (Regulation (EU) 2024/2847)¶
| Reference | Project control | SEC / invariant | Enforcement |
|---|---|---|---|
| Annex I 1 (secure by design / default) | Default-deny posture; stdio default; fail-closed HTTP | SEC-7 / inv 7 | config.py::validate_transport, the Helm default-deny NetworkPolicy with a scoped from: ingress selector (BL-051, ADR-0018) |
| Annex I 1 (no known exploitable vulns; supply chain) | Digest-pinned image; SBOM; dependency review; SHA-pinned CI; signed release with SLSA provenance and image SBOM attestations | inv (supply chain) | deploy/, .github/workflows/{sbom,dependency-review,release}.yml (BL-033 ADR-0032/0035, BL-088 ADR-0018; the all-zero image digest is the fail-closed default until the operator's first tagged release) |
| Annex I 2 (vulnerability handling) | CodeQL, nightly fuzz, the STPA revisit triggers | SEC-1..SEC-10 | .github/workflows/{codeql,fuzz}.yml |
GDPR (Regulation (EU) 2016/679) and Austrian DSG¶
| Reference | Project control | SEC / invariant | Enforcement |
|---|---|---|---|
| Art. 25 (data protection by design and default) | No output bodies stored; classification filtering | SEC-9, SEC-4 | execution/audit.py, context.py::filter_restricted |
| Art. 32 (security of processing) | Redaction of secrets; tamper-evident integrity | SEC-9 / inv 3 | execution/redaction.py, audit/merkle.py |
ISO/IEC 27001:2022 (Annex A)¶
| Reference | Project control | SEC / invariant | Enforcement |
|---|---|---|---|
| A.5.15 (access control) | Tiered authority; per-role scoped credentials | SEC-3, SEC-8 / inv 2, 9 | execution/policy.py, actuation/credentials.py |
| A.8.15 (logging) | Append-only, hash-chained audit; redacted params; documented log retention tiers bound in config | SEC-2, SEC-9 / inv 1, 3 | execution/audit.py; retention tiers in config.py (BL-035), enforced by storage-layer archival (SECURITY.md, docs/runbooks/operate.md) |
| A.8.16 (monitoring activities) | Drift findings as bitemporal facts | SEC-6 / inv 4 | drift/, store/ |
| A.8.28 (secure coding) | mypy strict, ruff (incl. bandit S-rules), CodeQL, fuzz | n/a | pyproject.toml, CI |
Every row traces through a SEC constraint to a proving test in
docs/stpa/07-security-constraints.md; a control without a test is a visible gap.