Compliance Overview
The Compliance Overview API is the single endpoint that powers
the dashboard's Compliance Posture card on the Overview page. It
aggregates four runtime signals — Hash Chain status, Active
Incidents, FRIA completeness, and a derived alerts band —
into one rollup the dashboard renders without a second query.
Tested against API version v1. Mounted at
/api/v1/compliance-overview. JWT auth on the only endpoint;
plan-gating happens inside the handler so plans below
Governance receive 200 OK with data: null rather than
403 UPGRADE_REQUIRED.
The graceful-degradation posture exists deliberately: the
Overview card calls this endpoint on every dashboard load, and a
hard 403 would force the frontend to special-case lower-tier
plans. Returning data: null lets the same UI render with a
"Compliance posture available on Governance and above" prompt.
Endpoint
GET /api/v1/compliance-overview/posture
The legacy mount /api/compliance-overview/posture returns the
same payload with a Deprecation header.
Request
curl https://api.adjudon.com/api/v1/compliance-overview/posture \
-H "Authorization: Bearer $ADJUDON_JWT"
No query parameters. The handler reads the active org from the
caller's JWT and aggregates synchronously across the four
sections. Each section's contribution is plan-gated independently
— an Enterprise plan with FRIA disabled receives the
hashChain + incidents sections populated and fria: null.
Response shape
{
"success": true,
"data": {
"score": 88,
"status": "healthy",
"sections": {
"hashChain": {
"metric": 1247,
"label": "Verified entries",
"status": "healthy",
"detail": "Chain intact; last verified 12 minutes ago",
"href": "/dashboard/compliance/hash-chain"
},
"incidents": {
"metric": 2,
"label": "Active incidents",
"status": "warning",
"detail": "Next deadline in 3 h 14 min (DORA Art. 19 initial notification)",
"href": "/dashboard/incidents/65b1f2c4",
"nextDeadlineIncidentId": "65b1f2c4"
},
"fria": {
"metric": 5,
"label": "Approved FRIAs",
"status": "healthy",
"detail": "1 FRIA below 70% completeness",
"href": "/dashboard/fria",
"incompleteCount": 1
},
"alerts": [
{
"id": "fria-incomplete",
"status": "warning",
"kind": "fria_overdue",
"message": "1 FRIA assessment(s) below 70% completeness",
"href": "/dashboard/fria"
}
]
}
}
}
data: null is returned (with 200 OK) for orgs whose plan
includes none of the contributing features (hashChainAudit,
multiClockIncidents, friaWizard).
The four sections
| Section | Source | Plan gate |
|---|---|---|
hashChain | hashChainService.getStatus(orgId) — verified count + last-verify timestamp | hashChainAudit (Governance+) |
incidents | Incident.find({ status: $in active states }) — active count + next deadline | multiClockIncidents (Governance+) |
fria | friaService.listForOrg() filtered to non-terminal states — counts + completeness check below 70% threshold | friaWizard (Governance+) |
alerts | Derived band — one entry per overdue FRIA, breached incident clock, or stale hash-chain verify | (computed; not separately gated) |
Each section's status is one of healthy, warning,
critical, or unknown. The top-level score is a 0-100
composite weighted across the populated sections; sections that
returned null from a plan gate do not contribute to the score.
How score is computed
The composite is a weighted average across populated sections,
with each section contributing in [0, 100]:
- Hash Chain: 100 if intact, last verify within 1 h; drops linearly to 0 if a chain entry fails verify or last verify exceeded 24 h.
- Incidents: 100 if no active incidents; minus 25 per
incident in
warning(next deadline < 24 h); minus 50 per incident inbreached. Floor at 0. - FRIA: 100 if every active FRIA is ≥ 70% complete; minus 10 per FRIA below the threshold. Floor at 0.
The weights are equal (33 / 33 / 33) when all three sections are
populated, and re-normalise when one or more sections are
plan-gated to null. The numeric value is stable enough to
trend over time on the CPI dashboard but should not be used as
a threshold gate — switch on status instead.
Status semantics
| Status | When the rollup returns it |
|---|---|
healthy | Every populated section is healthy; no alerts band entries |
warning | At least one section is warning (e.g. one incident's clock is < 24 h from deadline; FRIA below 70% completeness) |
critical | At least one section is critical (e.g. an incident clock is breached; a hash-chain entry failed verify) |
unknown | The handler could not compute the section (downstream service unreachable; plan-gated to null) |
The dashboard's Overview card colour-codes the rollup card off
this enum directly. Programmatic consumers (an internal Slack
bot, a custom CISO digest) should switch on status rather than
parsing score thresholds — the score's weighting may
evolve, but the four-state enum is stable.
Common gotchas
- Plan-aware, not plan-gated. This endpoint deliberately
returns
200 OKwithdata: nullfor plans below Governance. The Compliance Posture card on the dashboard renders an upgrade prompt when it seesdata: null; do not treat null as an error. - Synchronous aggregation. The handler queries hash-chain, incidents, and FRIA in parallel. The 5-minute cache on the dashboard side absorbs repeated calls; backend-side, each section read is sub-100 ms.
alerts[]is bounded. The derived alerts band caps at five entries; consume the underlying APIs (Incidents, FRIA) for the full list.- Idempotency is irrelevant. Read-only endpoint; nothing to replay.
- No write surface here. Compliance posture is a derived view. Mutations go to the underlying resources (Incidents, FRIA, policies attached via the Hash Chain trace path).
See also
- Hash Chain API — the
authoritative source for the
hashChainsection - Incidents API — the
authoritative source for the
incidentssection - FRIA API — the authoritative
source for the
friasection - Plans & Features —
the
hashChainAudit,multiClockIncidents, andfriaWizardfeature gates - Error Codes — the broader error taxonomy