EU AI Act Compliance Tooling (D1)¶
Next-Gen 40 · feature D1 · ADR 0012 · spec
design/vision/specs/D1-eu-ai-act-compliance.mdDISCLAIMER: This feature assembles compliance evidence from platform metadata. It is not legal advice, a conformity assessment, or CE certification. Consult a qualified authority before making any EU AI Act declaration. Every generated document and CLI surface repeats this disclaimer.
D1 maps ExaMLOps metadata to EU AI Act obligations: per-system risk classification, an auto-generated Annex-IV technical file assembled from live artifacts, Art. 12 logging conformance, and a conformity state machine — all built on a reusable control → article → evidence framework (shared with D2 / NIST AI RMF).
Risk classification¶
exa compliance classify JPCP --risk-tier high \
--purpose "HPC job triage" --context "internal operations"
Risk tiers: prohibited | high | limited | minimal. Classifying a model marks it
in-scope and records its intended purpose + deployment context.
Promotion gate (R2): an in-scope model with no risk classification is blocked from promotion until it is classified:
exa pipeline promote jpcp --if-rmse-lt 5.0
# → error: Promotion blocked: in-scope system has no EU AI Act risk classification. Use --force to override (audited).
Annex-IV technical file¶
The document is assembled from live evidence — never hand-maintained (R5) — and pulls from the other Next-Gen tracks:
| Section | Annex IV | Evidence source |
|---|---|---|
| System description | §1 | model card (A6) |
| Development process | §2(b) | lineage (A2) |
| Data governance | §2(d) | data versioning + quality (A1/A5) |
| Performance | §3 | evaluation (C2) |
| Fairness | §3 | subgroup report (C8) |
| Risk management | §5 | guardrails + drift (D8/C5) |
| Integrity | §2(e) | AI-BOM + signature (D3) |
| Monitoring | §8 | drift + SLO (C5/C6) |
| Record-keeping | Art. 12 | audit trail (D4) |
| Changes | §6 | change log |
Missing evidence is flagged in the document (⚠️ MISSING EVIDENCE), never silently
omitted (R4). Each generation is stored as a new version in technical_files.
Existing evidence is also checked for integrity (ADR 0110 decision 6). A section whose
records come from a broken audit chain or a broken telemetry anchor is flagged
⚠️ INSUFFICIENT EVIDENCE and counted as a gap, alongside missing sections. A section resting on
records outside the chain and its anchors is marked not tamper-evident, which names it without
counting it as a gap. The file opens with an Insufficient evidence section listing both, with
reasons, and an Evidence integrity summary. --json reports missing, insufficient,
unverified, and a status and reasons per section. The statuses are explained in
Evidence chain.
Art. 12 record-keeping¶
Verifies that the required operational event types (retrains, promotions, approvals, overrides) are present in the immutable audit trail (D4) and reports coverage + uncovered event types.
Conformity state machine¶
exa compliance declare JPCP --state documented
exa compliance declare JPCP --state assessed
exa compliance declare JPCP --state declared
Valid states: draft → documented → assessed → declared (with limited back-transitions).
Skipping a step (e.g. documented → declared) is rejected (R8).
Declaration of Conformity (Annex V)¶
declared is a state; the document is what the state exists to reach.
exa compliance declaration JPCP \
--issued-at "Julich, 2026-09-02" \
--provider "Example GmbH" --provider-address "Example Str. 1, 52425 Example, DE" \
--signatory "A. Person" --signatory-function "Head of AI Governance" \
--standard "EN ISO/IEC 42001:2023" \
--out declaration.md
Annex V requires eight items. The platform fills the ones it can know — system identity, risk tier, conformity state, the Annex-IV technical file version it rests on and that file's gap count, and the audit-chain head that makes the claim traceable.
It will not fill the other five. Provider legal name and address, signatory name and
function, notified body, and harmonised standards are statements only you can make: the platform
holds no legal entity and no signatory. Anything you do not supply renders as
⚠️ TO BE COMPLETED BY THE PROVIDER.
When a declaration is FINAL¶
Only when all three hold:
- the conformity state is
declared, - every provider-supplied field is present, and
- the referenced Annex-IV technical file has no evidence gaps.
Otherwise the document is stamped DRAFT — NOT A DECLARATION and lists, on its own face, every
reason it is not final. There is no --force. An override that produces a final-looking
regulatory artifact over a listed objection is precisely the thing this generator must not
offer — if a blocker is wrong, fix the underlying fact, not the document.
Two Annex-V items are conditional and are treated as such rather than as blanks: a system that processes no personal data gets a recorded statement that it does not, never a GDPR conformity claim nobody made (V(5)); and an absent notified body reads "Not applicable", because most systems genuinely have none and that is an answer (V(7)).
--issued-at is required. The issue date is a fact about when a person signed, not about when
the generator ran.
Each generated declaration is versioned and retained alongside the technical files, in its own version sequence. Art. 47's ten-year retention is not enforced by the platform — the documents are stored and every generation is audited, but nothing prevents their removal.
The Compliance page (dashboard)¶
Govern → Compliance (/govern/compliance) is the same tooling as a page:
- System register. Every system's risk tier and conformity state. Admins classify and
advance state through the same audited code path as
exa compliance classify/declare. - Technical file, live. Pick a system and the page generates its Annex-IV file from current evidence: nothing is stored until you save. It opens with What this file cannot vouch for, every section that is insufficient (its integrity check failed), missing, or not tamper-evident, each with its reason. Below that come the gap counts, the audit-chain and telemetry-anchor state, and each section with its status.
- Art. 12 record-keeping. Which required event types the audit trail holds.
- Saved versions. Admins save a version (audited as
technical_file_saved) into the storeexa compliance declarereads. A declaration resting on a version with gaps stays a draft.
API (for automation): GET /api/compliance/technical-file/{model} (preview),
GET /api/compliance/technical-files/{model} (saved versions), GET /api/compliance/art12/{model},
POST /api/compliance/technical-file/{model} (admin, compliance.classify).
The shared framework¶
This data-driven mapping is reused by D2 (NIST AI RMF) with a different article vocabulary — one framework, two regulatory lenses (R9).
Programmatic use¶
from examlops.compliance import (
classify_system, generate_technical_file, check_art12_logging, set_conformity_state,
)
classify_system("JPCP", "high", "HPC triage", "internal", actor="alice")
doc = generate_technical_file("JPCP") # Document; doc.gaps flags missing evidence
print(doc.to_markdown())
coverage = check_art12_logging("JPCP") # {'coverage': {...}, 'uncovered': [...]}
set_conformity_state("JPCP", "documented", actor="alice")
Governance¶
- Audited (D4):
compliance_classified,compliance_conformity,promotion_blocked_by_compliance,compliance_gate_override. - Tenant-scoped (D6): every record carries a
tenant.
See also¶
- Fairness (C8), SLOs (C6), Advanced drift (C5) — evidence sources.
- Supply-chain security (D3) — AI-BOM + signatures.
- Lineage (A2) — development-process evidence.