ENISA Reporting — Overview
FLEET includes an ENISA Single Reporting Platform (SRP) module that lets a defender prepare and submit the staged notifications required by CRA Article 14 — actively-exploited vulnerabilities and severe incidents — and disseminate them to ENISA when a submission channel is available.
It is designed as an alternative pathway for collecting and disseminating this data: capture it now, in a queryable, versioned, audit-grade store, and hand it off to ENISA’s platform when its API exists (manual/form export until then).
What it gives you
Section titled “What it gives you”- Versioned OpenAPI 3.1 + Swagger UI — see REST API & Swagger.
- GraphQL query surface over the same data — see GraphQL.
- Obligation matrix — exactly which fields are required at each stage — see Obligation Matrix.
- MCP tools so an AI assistant can drive the whole flow — see MCP Tools.
How it is built
Section titled “How it is built”The feature lives in a self-contained workspace crate, crates/enisa-srp, that
takes a PostgreSQL pool and exposes an axum router, an OpenAPI document, and a
GraphQL schema. FLEET mounts it under /api/v1/enisa.
┌─────────────────────────────┐ │ Obligation matrix (versioned)│ source of truth │ X / C / O / I / A per field │ └───────────────┬──────────────┘ │ drives validation ┌───────────────────────────┼───────────────────────────┐ ▼ ▼ ▼ ┌───────────┐ ┌───────────────┐ ┌─────────────────┐ │ PostgreSQL│◀────────────▶│ REST + OpenAPI│ │ GraphQL │ │ (relational│ immutable │ + Swagger UI │ │ (query surface) │ │ revisions)│ revisions │ (utoipa) │ │ (async-graphql) │ └───────────┘ └───────────────┘ └─────────────────┘ │ ▼ ┌──────────────────────────┐ │ ENISA export adapter │ file / API stub → live ENISA API later └──────────────────────────┘Three kinds of versioning
Section titled “Three kinds of versioning”The module is “versioned” on three independent axes:
- API version — everything is served under
/api/v1/enisa. - Report lifecycle — the same case is re-submitted as it matures (24h → 72h → final); each submission is an immutable revision.
- Audit / chain-of-custody — revisions are append-only. Database triggers
reject
UPDATE/DELETE, and each revision links to its predecessor, so you can prove what was known when. This matters because the reporter’s own systems may be compromised.
Cumulative snapshots & carry-forward
Section titled “Cumulative snapshots & carry-forward”Each revision is a complete snapshot. Fields you don’t resubmit at a later stage
are carried forward from the previous revision (the matrix C rule), so a
72h or final report doesn’t need to repeat everything from the 24h warning.
Storage is relational; GraphQL is a projection
Section titled “Storage is relational; GraphQL is a projection”The store is plain PostgreSQL. GraphQL is a query projection over it (e.g.
notification { revisions { … } }) — there is no separate graph database, which
keeps FLEET’s single-database deployment intact.
Export adapters
Section titled “Export adapters”Submission to ENISA is abstracted behind a pluggable EnisaExporter. FLEET
delivers the form-ready document through its existing notification channels —
email (via Resend) or a webhook — when one is configured (see
Notifications & Report Delivery); otherwise it falls
back to a file exporter / API stub. ENISA’s Single Reporting Platform has no
public submission API yet, so that direct hop is the one piece still stubbed —
when it ships, only the adapter changes; FLEET stays the stable interface. Every
export, whichever adapter handles it, is recorded as an append-only receipt.
Schema version
Section titled “Schema version”The OpenAPI document’s info.version tracks the obligation-matrix schema
version (currently cra-2026.1). When ENISA revises the form, the matrix and
this version are bumped together, so the contract and the rules never drift.