ADR-032: Severity (Class Taxonomy) vs Priority (Evidence-Gated Urgency)
Status
Accepted — 2026-06-04. Product decision by Sergey on sv0-platform#1395 ("Recalibrate standing-authority cluster severity defaults"), ratified and partially shipped. The priority-gating half landed in PR #1401 (resolving issue #1399), built on the honesty/parity fixes in PR #1400 (resolving issues #1397 and #1398). The user-facing display swap is the remaining step under #1395; one acknowledged inconsistency in the entity-level drift rules is tracked as a follow-up (#1402).
Context
The product surfaced a single number — severity — and used it for two unrelated jobs at once: classifying how bad a kind of problem is, and ranking how urgently to act on a specific instance. Because the cluster/finding severity default is a flat constant ("standing authority is High", "orphaned sensitive is Critical"), action-oriented surfaces produced contradictions that undercut trust:
Critical · Standing authority
when the underlying evidence was a provisioned-but-never-exercised path — i.e. the system was crying wolf. The headline said Critical purely because the cluster's class default is high and the path could reach a sensitive domain, not because anything had happened.
Sergey's framing (#1395) named the two questions the one field was straddling:
- severity answers: how bad is this class of problem if it is real?
- priority answers: how urgently should a human act on this specific instance?
The brief, top-exposure, cluster-card, and list surfaces are action-oriented, so they must lead with priority, not raw class severity.
What "proof" means here
The platform already distinguishes structural claims from observed ones (the evidence-classification layer: claim_type + evidence_strength, surfaced as "Configured" vs "Confirmed"). This ADR makes that distinction govern urgency:
- Proof of impact = observed, resource-scoped execution in the window.
- Posture = everything that describes what could happen but has not been observed: structural reachability to a sensitive domain, a structural wildcard/destructive action, an attribution or governance gap, or standing (dormant) authority.
- A sensitivity label on a reachable path is posture, not confirmed access. "Verified sensitive data access" counts as proof only when access or data movement is actually observed.
Posture is real signal and stays visible — it just must not, on its own, escalate an instance to the most urgent band.
Decision
Keep two separate axes. Stop conflating them.
1. severity — class taxonomy, backend/API only
severity remains the per-cluster / per-finding class default ("how bad if real"). It is evidence-independent and stays in the backend and API for rule taxonomy, analytics, and filtering. It is not the primary incident label on action-oriented UI. The RISK_CLUSTER_DEFS severity values are not recalibrated down — Sergey's explicit call was to retain severity as the taxonomy axis, not to flatten it, because the alarming-headline problem is solved by displaying priority instead.
2. priority — evidence-gated urgency, displayed
priority ∈ {critical, high, moderate, low} is computed from evidence (computeClusterPriority, src/services/risk-cluster-service.ts) and is the value shown on action-ranking surfaces. Its thresholds:
| Priority | Condition |
|---|---|
| Critical | Observed execution plus an aggravator: a destructive/admin action was actually exercised; or active sensitive access with an ownership governance failure (owner missing/lapsed); or confirmed egress of sensitive data. |
| High | Structural wildcard/destructive authority (a verified effective-privilege capability, e.g. dangerous_blast_radius); or observed execution on a sensitive path with no aggravator. |
| Moderate | Any single posture signal with zero proven impact — structural sensitive reach, governance/attribution gap, dormant authority, or an egress finding type. |
| Low | Residual — no posture signal, no execution. |
3. Not all governance gaps are equal
Only an ownership governance failure (orphaned_ownership — an owner is missing or lapsed) is material enough to aggravate observed execution to Critical. An attribution gap (unknown_identity_binding) or permission drift (scope_drift) is posture only and must not push an instance to Critical priority. Attribution uncertainty is not confirmed harmful access (#1395; the #1401 fidelity fix split the previously-conflated hasGovernanceFailure signal into hasOwnershipGovernanceFailure vs the rest).
4. UI consequence (the #1395 display swap)
On briefs, top exposure, cluster cards, and other action-ranking surfaces:
- Replace the visible severity chip with priority — labels
Critical priority/High priority/Moderate priority/Low priority. - Keep the existing activity chip (
Active/Standing authority). - Keep
severityavailable in the backend/API (taxonomy, analytics, filtering). - Do not introduce a new evidence chip as part of this change.
What shipped under this decision
- PR #1400 (issues #1397, #1398) — path-evaluator honesty + cross-layer severity parity. Honesty (#1397): the not-exercised branch no longer claims
execution_observed; a finding with zero execution evidence emitspermission_exists/structural("Configured", not "Confirmed"). Parity (#1398): the same condition no longer emits one severity from the entity-rule pass and a different one from the path-evaluator pass; the affected path-evaluator findings (external_egress,reachable_sensitive_domain,unproven_execution) were unified to a flatmediumseverity. - PR #1401 (issue #1399) — cluster priority gating:
computeClusterPriorityintroduced; posture (standing authority, structural dangerous actions, attribution/drift gaps) can no longer reach Critical with zero execution; ownership-vs-attribution governance failures separated.
Consequences
Positive
- Action surfaces stop contradicting their own evidence — no more
Critical · Standing authorityon a never-exercised path. severitystays a stable analytics/filtering axis;prioritybecomes the single action-ranking signal, gated on observed execution.- The "Configured vs Confirmed" honesty signal and the urgency model now agree.
Negative / trade-offs
- Two parallel axes to keep coherent. Docs and UI must be explicit about which one a given surface shows, or the conflation creeps back.
priorityis deliberately conservative — a genuinely urgent instance with no captured execution evidence reads as Moderate until evidence lands. This is the intended bias (don't cry wolf), but it shifts weight onto execution-evidence coverage.
Known inconsistency (follow-up #1402)
- The entity-level drift rules
scope-drift.tsandreachability-drift.tsstill compute finding severity fromexercised && touchesSensitive(critical) /exercised || touchesSensitive(high) / else (medium) — i.e. they still fold execution evidence into severity, which under this ADR belongs to priority. PR #1400 (issue #1398) brought the path-evaluator findings into line but did not touch these two rules. Realigning them changes emitted finding severities, demo seed data, and rule tests, so it is deferred to its own PR. Until then, 09-drift-evaluator-framework documents the ladders as-is with this caveat.
When to Reconsider
- A customer needs severity-driven SLAs (act-within-N-hours keyed to the class taxonomy) — then severity re-enters the action path and the two axes must be reconciled explicitly rather than by display choice.
- Stakeholders demand a single combined score. If so, derive it from both axes deterministically; do not collapse back to one ungated field.
- Priority gating proves too conservative in the field (real urgency consistently sitting at Moderate because execution evidence is under-collected) — fix the evidence pipeline first; only loosen the thresholds if that is insufficient.
- The follow-up (#1402) lands and the drift rules move to priority-gated urgency — update this ADR's "Known inconsistency" section and 09-drift-evaluator-framework.