Skip to content

Incidents, reports & documentation

One incident, several clocks. A model misbehaving in a credit decision can be an EU AI Act Art 73 serious incident, a DORA major ICT-related incident and a GDPR personal-data breach at once. The register (Compliance → Incidents) keeps one row and computes every framework’s deadline from that framework’s deadline_rules and the incident’s classification.

Framework Rules (from became_aware_at) Shape
EU AI Act (Art 73) standard 15 days · death 10 days · widespread 2 days alternatives
GDPR (Art 33) standard 72 hours alternatives
HIPAA (Breach Rule §164.404) standard 60 days alternatives
Colorado standard 90 days alternatives
DORA (Art 19) initial 4 h → intermediate 72 h → final 1 month stages
NIS2 (Art 23) early_warning 24 h → notification 72 h → final 1 month stages
SOC 2 none — declare an SLA, else the statement is not_evaluable —

Alternatives: the classification picks a rule when it names one (e.g. death), else standard applies. Stages: every stage applies; the earliest is the report, satisfied by reported_at; later stages are follow-ups shown on the incident and satisfied by closing it.

Per framework and rule, the deadline status is open, due_soon (within 24 hours), overdue, reported_on_time, reported_late or closed.

Create, update, report, close and notes each append a compliance_incident_events row and seal an ai.brutor.incident record (context.state = the event, context.incident_id). The description and every free-text field enter only as the payload digest. Each record references the previous one (ai.brutor.incident, purpose previous_state), so the history is a chain an auditor can walk. A seal failure never loses the change: the event is saved with record_id = NULL and the response says sealed: false.

Incidents link to runs and inbox items, and feed incidents.register_exists and incidents.reported_within_deadline for every framework that cites them.

Terminal window
curl -X POST http://localhost:5050/v1/admin/compliance/incidents \
-H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
-d '{
"title": "Claims agent approved payouts outside grant",
"description": "…",
"classification": "standard",
"severity": "high",
"became_aware_at": "2026-09-18T08:30:00Z",
"frameworks": ["eu-ai-act", "gdpr"],
"ai_system_id": "rg-claims-agent",
"linked_run_ids": ["run_01K5…"]
}'
{
"incident": {
"id": "inc-01k5…", "status": "open", "classification": "standard", "severity": "high",
"frameworks": ["eu-ai-act", "gdpr"], "deadlines_enforced": false,
"deadline_status": [
{ "framework_id": "gdpr", "rule": "standard", "stage": "report", "due_at": "2026-09-21T08:30:00+00:00", "status": "open", "hours_remaining": 71.5 },
{ "framework_id": "eu-ai-act", "rule": "standard", "stage": "report", "due_at": "2026-10-03T08:30:00+00:00", "status": "open", "hours_remaining": 359.5 }
],
"last_record_id": "9b1e…"
},
"event": { "id": "ince-01k5…", "event": "created", "record_id": "9b1e…" },
"seal": { "sealed": true, "record_id": "9b1e…", "seal_error": null, "seal_detail": null }
}

Report it with POST /v1/admin/compliance/incidents/{id}/report {"authority": "…", "reported_at"?, "external_reference"?} and close it with POST …/{id}/close. See the API reference.

An Evidence Report evaluates one framework’s obligations in force for a period, per AI System or estate-wide, against the shared resolvers. Because resolvers are shared, the same month rendered under the EU AI Act, ISO/IEC 42001 and SOC 2 shows the same row wherever the frameworks cite the same resolver and parameters — one evidence log, many audits.

Cadence Generated Contains
daily yesterday, per enabled framework obligations in scope, recomputed rows n of m, judged rows with agreement, records sealed, head grades
weekly last week the same, plus the week’s blind grades
monthly last month identity and roles, every obligation in force with every statement, recomputed vs judged never merged, human agreement, witness plurality, declared prunes, not_covered, and a human-signed scope census placeholder

The scheduler generates them hourly (idempotent on tenant, framework, system-or-estate, cadence and period start, so a period is generated once). You can also generate on demand:

Terminal window
curl -X POST http://localhost:5050/v1/admin/compliance/reports \
-H "Authorization: Bearer $ADMIN_TOKEN" -H "Content-Type: application/json" \
-d '{"framework_id": "eu-ai-act", "cadence": "monthly", "ai_system_id": "rg-claims-agent", "period_start": "2026-08-01"}'

Each report row carries the statement’s basis, status, n of m, detail, limit and citations. The summary keeps the bases apart — recomputed and judged counts are never summed — and records the catalog_version it was computed under.

Every report is persisted (compliance_reports) and sealed as an ai.brutor.report record whose payload digest covers the rows. A monthly report is also emitted as an evidence bundle rooted at the report record, with the rows in extensions["ai.brutor/evidence-report/v1"] (framework_id inside) and up to 5 000 cited records. Fetch it with GET /v1/admin/compliance/reports/{id}/bundle and check it with any verifier. Countersignatures (a witness’s or an auditor’s) are listed with their status and do not change the bundle digest.

The Assurance Report keeps its behavioural role (health, drift, liveness); obligation evidence lives here.

GET /v1/admin/ai-systems/{id}/documentation?framework=eu-ai-act&format=json|html renders a framework’s documentation template for one AI System from what the platform actually holds: the register entry, the active contract (version, hash, approver, composition), the compliance profile, bindings, evidence pointers on file, the latest Assurance Report and the latest Evidence Report.

Framework Template
EU AI Act eu-annex-iv — Annex IV technical documentation (Art 11)
ISO/IEC 42001 iso-a6-2-7 — A.6.2.7 technical documentation / A.8.2 information for users
SOC 2 soc2-system-description — system description headings
any other generic

Each section separates what the platform filled (with its source) from what the operator must still complete. The document says, in its own text:

This document is a skeleton generated from the platform’s configuration and records. It is not a statement that any requirement is met, and it is not legal advice. Sections marked ‘to complete’ need the operator’s own content before the document can be used.

Content is deterministic for the same inputs, so its digest (SHA-256 of the canonical JSON) is stable: re-requesting an unchanged document returns the existing export; a changed input produces a new export and a new ai.brutor.documentation record referencing it. That is what docs.technical_documentation checks. List exports with GET /v1/admin/ai-systems/{id}/documentation/exports.