#[non_exhaustive]pub enum CustomerState {
BlockedByPolicy,
Compromised,
Malicious,
RansomwareLinked,
ActivelyExploited,
Vulnerable,
RangeNotResolved,
NotYetAssessed,
Clean,
}Expand description
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).
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
BlockedByPolicy
Customer’s OWN policy rule blocked this package (operative gate).
Compromised
Tampered-with in a supply-chain attack (curated compromise list).
Malicious
Known-malicious package (malware / typosquat).
RansomwareLinked
Vulnerability tied to active ransomware campaigns.
ActivelyExploited
Vulnerability being exploited in the wild (CISA KEV).
Vulnerable
Has known CVEs (review + upgrade).
RangeNotResolved
CLEANLIB-518 (§3): the requested semver range could not be resolved to a
concrete version (source_state = RANGE_NOT_RESOLVED). Distinct from
NotYetAssessed — the package is not un-assessed, the range is; the
customer must pin an exact version. Fail-closed needs-input (Warn).
NotYetAssessed
No verdict on file yet — fail-closed needs-review.
Clean
No known issues found.
Implementations§
Source§impl CustomerState
impl CustomerState
Sourcepub fn from_wire(source: &str) -> CustomerState
pub fn from_wire(source: &str) -> CustomerState
Derive the customer state from the wire source string (the values in
crate::envelope::ALL_VERDICT_SOURCES). Unknown / future variants fail
CLOSED to NotYetAssessed (warn) — never silently Clean.
Two variants carry a note:
DM_THRESHOLD_BLOCK→BlockedByPolicy(the customer’s own rule). The spec also routes aDM_THRESHOLD_BLOCKfrom the curated supply-chain-compromise list (CLEANLIB-177) toCompromised, but that distinction is carried by which rule fired, not bysourcealone, and 177 is not yet shipped. Until 177 lands + the App tags curated-list blocks, everyDM_THRESHOLD_BLOCKis the customer’s policy. Seefrom_block_origin.VECTOR_VERDICTis the legacy pre-176 full-eval source, preserved for backward-compat. Post-176 the App projects findings into the specificCVE_FINDING*variants, so a bareVECTOR_VERDICTreaching a render surface is a legacy non-clean signal →Vulnerable(fail-safe).
Sourcepub fn from_block_origin(
source: &str,
curated_compromise: bool,
) -> CustomerState
pub fn from_block_origin( source: &str, curated_compromise: bool, ) -> CustomerState
Same as from_wire but lets the caller
resolve the DM_THRESHOLD_BLOCK ambiguity when it knows the block
origin. Use once CLEANLIB-177 ships and the App tags curated-list
blocks: curated_compromise = true routes DM_THRESHOLD_BLOCK to
Compromised instead of BlockedByPolicy.
Sourcepub fn from_wire_with_source_state(
source: &str,
source_state: Option<&str>,
) -> CustomerState
pub fn from_wire_with_source_state( source: &str, source_state: Option<&str>, ) -> CustomerState
CLEANLIB-518 (§3): resolve the customer state taking the wire
source_state into account. A RANGE_NOT_RESOLVED source_state
(CLEANLIB-513 — App could not resolve the requested semver range) maps to
RangeNotResolved so the render banner reads “Range not resolved” and
agrees with the reasoning body, instead of collapsing to the generic
NotYetAssessed banner. All other source_states defer to
from_wire on source.
Sourcepub fn as_str(self) -> &'static str
pub fn as_str(self) -> &'static str
Stable machine string for --output json state field + structured
MCP/SDK fields. snake_case, customer-vocabulary, NOT the wire variant.
Sourcepub fn label(self) -> &'static str
pub fn label(self) -> &'static str
Customer-facing display label (Title-case, no codenames). §2 of spec.
Sourcepub fn copy(self) -> &'static str
pub fn copy(self) -> &'static str
One-line, action-first customer copy (no codenames, no raw tier words). §2 of spec — verbatim.
Sourcepub fn tier(self) -> Tier
pub fn tier(self) -> Tier
Derive tier (block / warn / clean). NotYetAssessed is fail-closed →
Warn. Per §1 “Tier” column.
Sourcepub fn is_needs_input(self) -> bool
pub fn is_needs_input(self) -> bool
The “needs-input” family: warn-tier states that are NOT a security
finding but a gap the customer must resolve themselves — either no
verdict is on file yet (NotYetAssessed) or the requested version range
could not be resolved to a concrete version (RangeNotResolved,
CLEANLIB-518). Both share the --cl-unknown colour token + ❔ glyph
(§5). Render surfaces that distinguish “we found a problem” from “we
need input” — e.g. the LSP diagnostic severity, which shows this family
as INFORMATION rather than a WARNING finding — key on this predicate, so
a future needs-input state is threaded in ONE canonical place rather than
re-listed per surface (sister of the silent-drift discipline).
Sourcepub fn color_token(self) -> &'static str
pub fn color_token(self) -> &'static str
CSS custom-property name for the soft severity token (extension + SDKs consume these for theming). §1 “Soft colour token” column.
Sourcepub fn color_hex(self) -> &'static str
pub fn color_hex(self) -> &'static str
Soft severity hex (draft-ratified working palette, §5). Brand cyan for Clean; distinct mauve for policy so “your rule” reads apart from “our finding” reds.
Sourcepub fn emoji(self) -> &'static str
pub fn emoji(self) -> &'static str
Text-surface emoji for MCP human_message + CLI text output. §1
“MCP/CLI emoji” column. One concept per tier; states differentiate by
label + colour, not a bespoke glyph family (§5 — reuse, don’t cut).
Sourcepub fn all() -> [CustomerState; 9]
pub fn all() -> [CustomerState; 9]
All 9 states, severity order (highest first). For exhaustive contract tests + doc generation. CLEANLIB-518(§3) added RangeNotResolved (8→9).
Trait Implementations§
Source§impl Clone for CustomerState
impl Clone for CustomerState
Source§fn clone(&self) -> CustomerState
fn clone(&self) -> CustomerState
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more