Most writing about AI Act record-keeping explains the regulation. This page shows the artifact. Below is a real evidence pack from a production Prompt Tornado run — unedited except for identifiers — including the parts where it refuses to claim more than it can prove.
Three provisions do most of the work. The technical implication of each is the part worth arguing about.
| Provision | In substance | What that means for a system |
|---|---|---|
| Art. 12 Record-keeping |
High-risk systems automatically record events across their lifetime, at a level that makes operation traceable. | Logging the final output is not enough. If a model was swapped mid-run, that substitution is part of how the result was produced. |
| Art. 14 Human oversight |
Systems are designed so people can effectively oversee them. | Whether a human actually reviewed a given run is a fact about that run, and belongs in its record — including when the answer is "nobody did". |
| Art. 26(6) Retention |
Deployers keep the logs for at least six months. | Retention is a property to be checked and stated, not a setting to be assumed. |
Summarised for engineers, not lawyers. Whether a particular deployment is a high-risk AI system in scope of these provisions is a legal determination.
One prompt, two steps: generate a memo, then generate an image. Everything below is copied from the export. Only identifiers are replaced.
{
"steps_total": 2,
"steps_with_policy_record": 2,
"policy_coverage_complete": true,
"models_used": [
"openai/gpt-5.6-sol",
"openai/gpt-image-1.5"
],
"rejected_alternatives": 0,
"denied_steps": 0
}
Every step carries a policy record. When one doesn't, this reads false — see below.
{
"event_count": 11,
"decision_count": 2,
"algorithm": "hmac-sha256",
"tamper_evident": true,
"key_id": "55aa7db0",
"digest": "fa703f856fc3d29d…"
}
The digest covers the counts too, so the record of how much evidence exists is itself authenticated.
{
"task_type": "image_generation",
"chosen_model": "openai/gpt-image-1.5",
"candidates": [
"openai/gpt-image-1.5",
"fal_ai/fal-ai/flux-pro/v1.1",
"openai/dall-e-3",
"stability/sd3.5-large",
"fal_ai/fal-ai/flux/schnell"
],
"rejected": [],
"rejected_count": 0,
"denied": false,
"decided_at": "2026-08-08T21:16:19Z",
"policy": {
"operator": { /* the policy the operator had in force */ },
"effective": { /* operator ∩ user, after narrowing */ },
"user_scoped": false
}
}
This is the answer to "why this model?" — what was considered, what ran, what was excluded and by which policy layer, and the policy snapshot as it stood at that instant. A policy edited next week does not rewrite what last week's run was governed by.
{
"redacted_text": "…Sign it off with the contact line {{EMAIL_1}}. Then create…",
"sensitive_findings": { "EMAIL": 1 },
"content_id_basis": "hmac-sha256:original"
}
"data_protection": {
"redaction_applied": true,
"findings_by_category": { "EMAIL": 1 },
"note": "Counts only. Detected values are never included in an evidence pack."
}
The content handle is an HMAC of the original, not a plain hash. Sensitive strings are low-entropy — an unkeyed hash of an email address is brute-forceable, and publishing one inside a "redacted" document would quietly undo the redaction.
This is the part that matters. A compliance artifact that always reports success is not evidence — it is decoration.
policy_coverage_complete: false is a real state and it ships. An earlier run of ours reported steps_with_policy_record: 0 of 2 — because the media path wasn't recording decisions yet. We found that by reading the export, not from a test suite that was entirely green at the time. The number was right; the system was wrong.
Every evidence source is listed with a read status, and complete goes false with the failing sources named. A pack that quietly reported "no human review occurred" when the query had simply failed would be a false attestation — worse than producing no pack at all.
human_review_occurred: false. Most runs are unsupervised, and the record says so rather than leaving an absence to be read as approval.
With a signing key, the digest is an HMAC verifiable only by the key-holder. Without one, the pack falls back to an unkeyed checksum and says exactly that in its own words: "detects accidental corruption, NOT deliberate tampering." Anyone can recompute an unkeyed hash after editing a document; only a key you hold can establish authorship.
Every pack carries this line, verbatim:
Per run, or across a date range for a period an auditor asks about.
Records are produced by execution, not by a separate logging step you have to remember to switch on. Every routed model decision passes one chokepoint, so a new call site cannot bypass it.
Export one run's pack, or a date range as a single document with per-run coverage rolled up — capped, and honest in the pack when the range held more than was returned.
Verification distinguishes verified, checksum_only, cannot_verify and tampered. Retired keys are tried before anything is called tampered — a false accusation is its own failure mode.
Run a workflow, export the pack, read it before anyone else has to.