DORA incident reporting (Articles 17-19)
How Aira models the DORA incident lifecycle — detection, classification, resolution, and Article 19 ESA-submission PDFs signed with Ed25519.
DORA Articles 17–19 govern the full ICT-incident lifecycle:
- Article 17 — internal incident management process
- Article 18 — classification by severity, category, and impact
- Article 19 — mandatory reporting of major incidents to the relevant European Supervisory Authority within tight initial, intermediate, and final deadlines
Aira models this as a four-state lifecycle with an auditable transition per step.
Incident states
detected → classified → resolved → reported| State | Transition |
|---|---|
detected | POST /dora/incidents — opens the record with title, description, timestamp, and operational impact |
classified | PUT /dora/incidents/{uuid}/classify — sets severity, category, optional root-cause details |
resolved | PUT /dora/incidents/{uuid}/resolve — post-mortem summary + lessons learned |
reported | GET /dora/incidents/{uuid}/report — generates the signed PDF (auto-promotes the state) |
Classification
Severity is one of critical, high, medium, low. Category is one
of:
| Value | Meaning |
|---|---|
cyber_attack | External malicious activity (ransomware, DDoS, intrusion) |
system_failure | Internal failure (DB, infra, dependency) |
third_party_failure | An ICT third party caused the incident — third_party_uuid is required |
data_breach | Confidentiality-impacting incident |
operational_error | Human or procedural error |
other | None of the above |
An incident is automatically promoted to is_major=True when severity
is critical or high. You can also override this explicitly via the
is_major field on the classify request.
Root cause
Optional on classify, typically populated at resolve-time:
root_cause_summary— free-text narrativeroot_cause_classification— one ofsoftware_bug,configuration_error,human_error,malicious_attack,third_party_issue,infrastructure_failure,unknown
Article 19 — the ESA submission
Only major incidents produce a PDF. The report contains seven sections:
- Summary — title, timestamps, clients affected
- Classification — severity, category, major flag
- Timeline — detected / classified / resolved / reported
- Impact — affected services, geographic scope, client count
- Root cause analysis — classification + narrative
- Resolution — summary + lessons learned
- Linked Aira receipts —
related_action_uuidswith their cryptographic hashes
The PDF is signed with the same Ed25519 key used for action receipts
and EU AI Act reports. Auditors can verify the signature offline
against the public JWKS at /.well-known/jwks.json.
Aira does not submit the report to the ESA for you — that transmission goes through your regulator's portal (e.g. the BaFin MVP reporting system). The signed PDF is the evidence you upload.
Example
from aira import Aira
client = Aira(api_key="aira_live_...")
# Step 1: detect
incident = client.create_dora_incident(
title="Core banking DB unavailable",
description="Primary Postgres cluster rejected connections for 23 min.",
detected_at="2026-04-15T10:00:00Z",
clients_affected_count=42000,
affected_services=["core-banking", "mobile-app"],
)
# Step 2: classify (auto-promotes to major at severity=critical)
client.classify_dora_incident(
incident.uuid,
severity="critical",
category="system_failure",
root_cause_classification="infrastructure_failure",
root_cause_summary=(
"Synchronous replication to standby broke during a disk-"
"pressure event on the primary; standby refused writes."
),
)
# Step 3: resolve
client.resolve_dora_incident(
incident.uuid,
resolution_summary="Failover to standby completed at 10:23. Primary rebuilt by 11:14.",
lessons_learned="Add disk-pressure monitor that triggers failover preemptively.",
)
# Step 4: download signed PDF for ESA submission
pdf = client.download_dora_incident_report(incident.uuid)
open(f"dora-{incident.uuid}.pdf", "wb").write(pdf)import { Aira } from "aira-sdk";
const aira = new Aira({ apiKey: "aira_live_..." });
const incident = await aira.createDoraIncident({
title: "Core banking DB unavailable",
description: "Primary Postgres cluster rejected connections for 23 min.",
detectedAt: "2026-04-15T10:00:00Z",
clientsAffectedCount: 42000,
affectedServices: ["core-banking", "mobile-app"],
});
await aira.classifyDoraIncident(incident.uuid, {
severity: "critical",
category: "system_failure",
rootCauseClassification: "infrastructure_failure",
rootCauseSummary:
"Synchronous replication to standby broke during a disk-pressure event.",
});
await aira.resolveDoraIncident(incident.uuid, {
resolutionSummary: "Failover to standby completed at 10:23.",
lessonsLearned: "Add disk-pressure monitor that triggers failover preemptively.",
});
const pdf = await aira.downloadDoraIncidentReport(incident.uuid);Verification
The PDF carries three pieces of evidence:
report_content_hash— SHA-256 of the canonical PDF bytesreport_signature— Ed25519 signature over the content hashreport_signing_key_id— the JWKS key ID used
An external auditor can verify without any Aira client by downloading
the public key from /.well-known/jwks.json and running a standard
Ed25519 check.
DORA compliance
Overview of Aira's support for the EU Digital Operational Resilience Act (Regulation 2022/2554) — incident management, ICT third-party risk, resilience testing.
DORA third-party risk register (Articles 28-44)
Maintain the DORA register of ICT third-party service providers — criticality classification, exit strategies, and subcontractor tracking.