Serious Incident Autopilot
The Serious Incident Autopilot detects events that qualify as serious incidents under EU AI Act Article 73, runs them through a 2-of-N human review, and produces a signed regulator declaration bundle — all inside the 15-day statutory deadline.
- Continuous detection — a rule-based classifier watches fresh
events, DNA alerts, and Guardian decisions. The moment a qualifying
pattern fires, a
suspectedincident row is opened with the fact-occurrence timestamp already pinned. - Four canonical categories — health & safety, critical infrastructure, fundamental rights, property & environment.
- Reproducible classification — every incident carries a list of
explicit triggers and a SHA-256
classificationHasha regulator can recompute offline. - 2-of-N quorum review — two reviewers (Admin or
Compliance-Officer) must agree before an incident is
confirmedordismissed. No single-person declarations. - 15-day countdown — every incident shows a live countdown to the
Art. 73 deadline measured from
factOccurredAt, not detection time. - Signed bundle — confirmed incidents produce an Ed25519-signed ZIP
(FR or EN) ready to hand to the competent market-surveillance
authority, verifiable offline with
@kaplaix/cli-verify.
Detection — what fires an incident
Four pure detectors run on every fresh event:
| Detector | Fires when | Primary category |
|---|---|---|
| Failure cascade | ≥5 agent.failed / tool.failed events in 3 minutes on the same session | property_environment (escalates to critical_infra if target system matches) |
| Critical target | A single event whose target system matches a per-category regex (e.g. ehr, scada, payment-gateway) | Category of the regex that matched |
| DNA cascade | DNA score ≥ 3.5 with anomalous severity in a session that already shows failures | fundamental_rights |
| Guardian cascade | ≥3 Guardian denies in 30 minutes against the same tool family | critical_infra |
Confidence is high when at least two triggers agree on the primary
category or when a critical-target match fires. Everything else is
medium.
Deduplication
Identical (tenant, agent, classificationHash) within 24 hours is
treated as a duplicate — the detector may fire on the same facts many
times, but only one incident row is opened. The classification hash is
stable: triggers, category, confidence, and factOccurredAt feed a
SHA-256 over canonical JSON.
The review workflow
Open Compliance → Serious Incidents in the console.
suspected— the incident was just opened by the classifier. The tenant’s compliance contacts receive an email.under_review— the first review vote has landed. The incident is now waiting on a second vote.confirmed— two reviewers have votedconfirm. The declaration panel unlocks.dismissed— two reviewers have voteddismiss. The incident is closed; declarations are not available.
Every vote requires a rationale of ≥10 characters. request_info
votes leave the incident in under_review and do not count toward the
quorum.
Writing a declaration
Once confirmed, use the Declarations panel on the incident detail page:
| Action | Who | Notes |
|---|---|---|
| Generate revision | Compliance-Officer, Admin | Pick locale (en or fr). Each click produces a new revision snapshot. |
| Sign | Admin | Enters signer name; the revision is signed with Ed25519 over canonical JSON. |
| Revoke | Compliance-Officer, Admin | Reason ≥10 chars. Revoked signatures stay in the audit trail. |
| Download ZIP | Anyone with serious_incident:read | The signed bundle. |
Only the latest draft revision is signable. Older revisions remain queryable for the audit trail but cannot be re-signed.
The signed bundle
serious-incident-{incidentId}-rev{N}.zip
├── declaration.pdf — regulator-facing PDF (FR or EN)
├── declaration.json — full revision body
├── signed_payload.json — canonical JSON fed into Ed25519
├── signatures.json — active signatures with Ed25519 bytes
├── witness_keys.json — public keys (JWKS)
├── README.txt — offline-verify recipe
└── manifest.json — per-file SHA-256, version sincident-bundle-1.0The bundle is self-contained — no Kaplaix endpoint is required to verify it. Use the standalone binary:
npx @kaplaix/cli-verify verify serious-incident-*.zipThe 15-day clock
Art. 73 measures the deadline from the fact date, not the detection
date. Kaplaix computes factOccurredAt as the earliest trigger
timestamp in the classification — which is generally the source
timestamp of the offending event, not when it was received.
The console shows:
- Emerald when more than 3 days remain.
- Amber when 24 h to 3 days remain.
- Red when less than 24 h remain, or the deadline has passed.
Dismissed incidents freeze the countdown.
Permissions (RBAC)
The epic introduced a new compliance-officer role and four
permissions:
| Permission | Scope | Roles |
|---|---|---|
serious_incident:read | List and read incidents, download bundles | Admin, Viewer, Auditor, Approver, Compliance-Officer |
serious_incident:review | Vote confirm / dismiss / request_info | Admin, Compliance-Officer |
serious_incident:declare | Generate and revoke declaration revisions | Admin, Compliance-Officer |
serious_incident:sign | Ed25519-sign a draft revision | Admin |
Notifications
When an incident transitions to suspected, the tenant’s configured
compliance contacts receive an email. Contacts are edited on the
tenant settings record — this is an always-on legal-notification
channel and does not flow through the tenant’s configurable
webhook system.
REST API
All routes are tenant-scoped via Authorization: Bearer <api_key>.
| Method | Path |
|---|---|
| GET | /v1/serious-incidents |
| GET | /v1/serious-incidents/:id |
| POST | /v1/serious-incidents/:id/reviews |
| POST | /v1/serious-incidents/:id/declarations |
| POST | /v1/serious-incidents/:id/declarations/:rev/sign |
| POST | /v1/serious-incidents/:id/declarations/:rev/revoke |
| GET | /v1/serious-incidents/:id/declarations/:rev/bundle?locale=fr |