Skip to main content

Module customer_state

Module customer_state 

Source
Expand description

CLEANLIB-178 — canonical customer-facing state taxonomy (Rust surfaces).

Single source of truth for the 8 customer states that the malicious-vs- vulnerable cluster (CLEANLIB-176 wire-shape + 177 policy overlay + 178 aesthetic) surfaces. The design contract lives at decisions/2026-06-12-cleanlib-178-state-aesthetic-mapping.md; this module is its executable form for the Rust render surfaces — cleanlib-cli, cleanlib-lsp (CLEANLIB-209), and any consumer of cleanlib-client. The TS extension / Python MCP / JS+Go+Py SDKs mirror this table in their own languages, each with a contract test asserting the same wire→state map (anti-drift, sister of the silent-schema-drift discipline).

§Why this lives in cleanlib-client, not cleanlib-core

cleanlib-core is publish = false; the customer-state taxonomy is a presentation concern consumed only by published render surfaces (the App emits the wire source; it never renders a customer state). Keying on the wire string (Verdict.source: String) — rather than cleanlib-core’s VerdictSource enum — keeps this crate publishable to crates.io and avoids a render-side dependency on the service-internal core crate.

§Design rules baked in (§0 of the spec — non-negotiable)

  1. Customer-language only — wire/engine codenames never appear in label() / copy().
  2. Soft severity tokens (dark-theme-safe); brand cyan #50C0E0 is reserved for CLEAN.
  3. Three derive tiers (block / warn / clean) → exit codes (1 / 2 / 0).

§Derive-once + fail-closed

Derive the state ONCE from the wire source (CustomerState::from_wire). The App applies severity precedence server-side when it picks the single source, so this map is 1:1 — no precedence is re-implemented here. An unrecognized / future source fails CLOSED to NotYetAssessed (warn, needs-review) — never silently Clean.

Enums§

CustomerState
The 9 canonical customer-facing states, severity order (highest first) per the BD-ratified ordering in §1: Blocked-by-policy, Compromised, Malicious, Ransomware-linked, Actively-exploited, Vulnerable, Range-not-resolved, Not-yet-assessed, Clean. CLEANLIB-518(§3) added Range-not-resolved (8→9).
Tier
The three derive tiers — drive exit codes (block=1, warn=2, clean=0) and the colour family, and map onto the universal ALLOW/WARN/DENY render bucket.

Functions§

is_curated_supply_chain_compromise
CLEANLIB-855: true iff matched_rule_id names a curated supply-chain-compromise-bridge policy rule (the App-side prefix convention for the CLEANLIB-177 curated compromise list), rather than an ordinary customer policy rule. This is the one place that prefix convention is checked on the render side — callers should go through this function (or CustomerState::from_wire_with_source_state_and_origin directly) rather than re-implementing the starts_with check, so the convention only needs to change in one place if it ever does.