Skip to main content

Module gate

Module gate 

Source
Expand description

CLEANLIB-657 (CX-8 P1-b) — the verdict() / enforce() dual consumption API.

CX-8 thesis: a blocked verdict is a SUCCESSFUL assessment, not an error. Modelling “blocked” as an exception conflates a policy/security STOP (we assessed it and the answer is “do not proceed”) with a SYSTEM FAILURE (we could not assess it at all). The two must stay distinguishable, because a caller that treats a couldn’t-assess as “no block seen → proceed” has built exactly the [Absence≠safe] false-clear the taxonomy exists to prevent.

So this module offers the same assessment through two ergonomics over one raw acquisition outcome (Result<CustomerState, CleanLibraryError>Ok(state) = we got a verdict of some tier; Err(e) = we could not):

  • verdict — RETURNS style. A completed assessment of ANY tier (Block included) passes through as an Assessment value; Err is reserved strictly for “couldn’t get a verdict”.
  • enforce — RAISES style for gate use. Ok(()) iff clean-to-proceed; a non-clean completed assessment becomes GateError::Blocked, and a couldn’t-assess propagates as GateError::NotAssessed. Fail-closed: a NotYetAssessed / RangeNotResolved (Warn tier) REFUSES — it never passes the gate, so “not assessed” can never read as “allowed”.

The three other SDKs (py StrEnum, js discriminated union, go typed const + Valid()) mirror this contract against the shared conformance fixture (CX-8 P2), so the return-vs-raise split is byte-for-byte identical across surfaces.

§Quickstart (CX-8 P3)

Two ways to consume one assessment. A blocked verdict is a successful assessment, not an error — only couldn’t get a verdict is an Err, so a transport / coverage failure can never be mistaken for “no findings, proceed” ([Absence≠safe]). This example runs as a doctest.

use cleanlib_client::{verdict, enforce, CustomerState, Tier, GateError, CleanLibraryError};

// `outcome` is what your acquisition produced: `Ok(state)` (a verdict of
// some tier) or `Err(e)` (you could not get one at all).

// 1. verdict() — RETURNS style. A Block is a VALUE, never an `Err`.
let a = verdict(Ok(CustomerState::Malicious)).unwrap();
assert_eq!(a.tier(), Tier::Block);
assert_eq!(a.exit_code(), 1);
assert!(!a.is_allowed());

// The "not assessed" path is still a returned VALUE — and it is NOT clean:
let na = verdict(Ok(CustomerState::NotYetAssessed)).unwrap();
assert!(!na.is_allowed());
assert_eq!(na.exit_code(), 2);            // warn-tier, fail-closed

// A couldn't-get-a-verdict is the ONLY thing verdict() yields as `Err`:
let acq = Err(CleanLibraryError::CoverageIncomplete {
    reason_code: "SCAN_ABORTED".into(),
    message: "3 of 40 coordinates unreachable".into(),
});
assert!(verdict(acq).is_err());           // a real failure — never a clean result

// 2. enforce() — RAISES style for CI gates. `Ok(())` ONLY when clean.
assert!(enforce(Ok(CustomerState::Clean)).is_ok());         // proceed

match enforce(Ok(CustomerState::NotYetAssessed)) {
    Err(GateError::Blocked { exit_code, .. }) => assert_eq!(exit_code, 2),
    other => panic!("not-yet-assessed must block, got {other:?}"),
}

// A couldn't-assess fails CLOSED to the block exit code (1) — never 0:
let gate = enforce(Err(CleanLibraryError::CoverageIncomplete {
    reason_code: "SCAN_ABORTED".into(),
    message: "coverage failure".into(),
}));
assert!(matches!(gate, Err(GateError::NotAssessed(_))));
assert_eq!(gate.unwrap_err().exit_code(), 1);

Structs§

Assessment
A COMPLETED assessment of a coordinate. A Block is a normal Assessment value — never an error. “Couldn’t get a verdict” is the Err arm of the acquisition Result, kept strictly distinct from any Assessment.

Enums§

GateError
Why a gate refused. The two arms preserve the CX-8 distinction the whole module exists to keep:

Functions§

enforce
enforce() — RAISES style for gate use. Ok(()) iff clean-to-proceed.
verdict
verdict() — RETURNS style. Passes a completed assessment through as an Assessment value (a Block is a value, NOT an Err) and reserves Err strictly for “couldn’t get a verdict” (coverage incomplete / attestation invalid / transport / server — whatever the acquisition surfaced).