Skip to main content

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 landed in PR #1403, and the drift-rule severity follow-up (#1402) landed in PR #1404 — so every step under #1395 is now shipped (see "What shipped" below).


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:

PriorityCondition
CriticalObserved 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.
HighStructural wildcard/destructive authority (a verified effective-privilege capability, e.g. dangerous_blast_radius); or observed execution on a sensitive path with no aggravator.
ModerateAny single posture signal with zero proven impact — structural sensitive reach, governance/attribution gap, dormant authority, or an egress finding type.
LowResidual — 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 severity available 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 emits permission_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 flat medium severity.
  • PR #1401 (issue #1399) — cluster priority gating: computeClusterPriority introduced; posture (standing authority, structural dangerous actions, attribution/drift gaps) can no longer reach Critical with zero execution; ownership-vs-attribution governance failures separated.
  • PR #1404 (issue #1402) — drift-rule severity made evidence-independent: scope_drift and reachability_drift no longer fold execution into severity. Severity is now sensitivity-only (sensitive → high, else medium) across all four emitters — the entity rules (scope-drift.ts, reachability-drift.ts) and the path-evaluator's path-level duplicates — so the two layers agree (the path-level scope_drift also dropped an egress → high escalation the entity rule never had). Execution drives cluster priority, not finding severity. (The W1 demo seed that hand-stamped a critical scope_drift was corrected in #1412.)

Consequences

Positive

  • Action surfaces stop contradicting their own evidence — no more Critical · Standing authority on a never-exercised path.
  • severity stays a stable analytics/filtering axis; priority becomes 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.
  • priority is 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.

Resolved — drift-rule severity realignment (#1402 → #1404)

  • The entity- and path-level drift rules (scope_drift, reachability_drift) previously folded execution evidence into severity (exercised && touchesSensitive → critical / exercised || touchesSensitive → high / else medium). PR #1404 made their severity sensitivity-only (sensitive → high, else medium) across all four emitters, so severity is now evidence-independent everywhere and the entity/path layers agree. Execution drives cluster priority via computeClusterPriority, not finding severity. (#1400 had already aligned the path-evaluator's external_egress/reachable_sensitive_domain/unproven_execution findings; #1404 finished the two drift rules.)

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.