mirror of
https://github.com/ruvnet/RuView
synced 2026-08-11 20:41:44 +00:00
516331461a
Completes the phase-1 certificate spine; both acceptance tests now pass as code. ruview-ood (ADR-299): domain-distance vs the certified fingerprint and a pure DomainState KNOWN/DEGRADED/UNKNOWN classifier implementing the ADR-297 VALID->DEGRADED->UNKNOWN staleness guard; InferenceGate suppresses the class (UNKNOWN as a first-class value) when domain is not KNOWN; RecalibrationRequest signalled on DEGRADED/UNKNOWN. 25 tests. ruview-witness (ADR-316): ordered, append-only, BLAKE3 hash-linked stage chain (observation->DSP->inference->corroboration->spatial->policy) rooted in an attest VerifiedMeasurement; verify() catches mutation/reorder/dropped/broken links; effective level is the minimum across stages. 19 tests. ruview-certify (ADR-315): signed CapabilityCertificate minted from a single- context evidence slice (never pooled), evidence level capped at the slice floor, valid_until bounded by calibration validity; is_valid(now, domain) returns false when expired OR domain != KNOWN (certificate conditional on the live domain signature). 17 tests incl. non_known_domain_invalidates. ruview-scorecard (ADR-314): multi-domain scorecard with per-domain CIs, worst_domain(), and a promotion gate that fails when only pooled average improved while a worst-domain slice regressed. 17 tests. ruview-policy (ADR-318): fail-closed action gate; Convenience/Security/ SafetyCritical assurance classes; authorize() denies with a named failed condition; UNKNOWN denies high-assurance actions. Includes acceptance_test_b_post_drift_unknown_denies_safety_critical. 10 tests. All five verified green independently (88 tests). Registers the five crates as workspace members. SYNTHETIC/L0 reference crypto; no hardware claims. Co-Authored-By: claude-flow <ruv@ruv.net> Claude-Session: https://claude.ai/code/session_015TcKegTS7QqhWPC2L2SzaS
73 lines
3.3 KiB
Rust
73 lines
3.3 KiB
Rust
//! Cross-ADR adapter: turn an ADR-298 [`CalibrationCertificate`] plus a live
|
|
//! fingerprint into the two OOD inputs it governs — the [`FingerprintDistance`]
|
|
//! and the [`CalibrationCompat`] (ADR-299 §1 inputs 1 and 3).
|
|
//!
|
|
//! This is the point where certificate *staleness* becomes a domain signal:
|
|
//! an expired, tampered, drifted, or identity-mismatched certificate maps to a
|
|
//! non-`Valid` compatibility, which the state machine drives straight to
|
|
//! UNKNOWN (ADR-297 staleness guard). Absence of a certificate is handled by
|
|
//! [`no_certificate`] and likewise defaults to UNKNOWN — absence of evidence is
|
|
//! absence of capability (ADR-299 §3).
|
|
|
|
use wifi_densepose_calibration::certificate::{
|
|
CalibrationCertificate, CertificateStatus, CertificateVerifier, FingerprintDistance, RoomFingerprint,
|
|
};
|
|
|
|
use crate::domain::CalibrationCompat;
|
|
|
|
/// Identity the live inference expects the certificate to attest: which space
|
|
/// (ADR-303) and which signed device (ADR-302). Validated before the
|
|
/// certificate's own status, so a certificate for the wrong room/device can
|
|
/// never present as compatible.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct ExpectedIdentity<'a> {
|
|
/// The canonical space id the inference is running in.
|
|
pub space_id: &'a str,
|
|
/// The signed device id producing the live traffic.
|
|
pub device_id: &'a str,
|
|
}
|
|
|
|
/// Assess a present certificate against the live fingerprint and expected
|
|
/// identity, returning the domain distance and the calibration compatibility.
|
|
///
|
|
/// `now_unix_s` is **injected** — never read from the wall clock — so the
|
|
/// staleness decision is deterministic and testable. The distance is always the
|
|
/// certificate-fingerprint-vs-live distance, computed even for a stale/tampered
|
|
/// certificate so the drift is still reported.
|
|
///
|
|
/// Precedence mirrors ADR-298 `status()` but adds the identity checks first:
|
|
/// space mismatch → device mismatch → tampered → expired → drifted → valid.
|
|
pub fn assess_certificate<V: CertificateVerifier>(
|
|
cert: &CalibrationCertificate,
|
|
live: &RoomFingerprint,
|
|
expected: ExpectedIdentity<'_>,
|
|
now_unix_s: i64,
|
|
verifier: &V,
|
|
) -> (FingerprintDistance, CalibrationCompat) {
|
|
let distance = cert.fingerprint.distance(live);
|
|
|
|
// Identity binding first (ADR-302/303): a certificate for the wrong
|
|
// space/device is incompatible regardless of its own validity.
|
|
if cert.space_id != expected.space_id {
|
|
return (distance, CalibrationCompat::SpaceMismatch);
|
|
}
|
|
if cert.sensor_id != expected.device_id {
|
|
return (distance, CalibrationCompat::DeviceMismatch);
|
|
}
|
|
|
|
let compat = match cert.status(live, now_unix_s, verifier) {
|
|
CertificateStatus::Valid { .. } => CalibrationCompat::Valid,
|
|
CertificateStatus::Expired { .. } => CalibrationCompat::Expired,
|
|
CertificateStatus::Drifted { .. } => CalibrationCompat::DriftedBeyondEnvelope,
|
|
CertificateStatus::TamperedSignature => CalibrationCompat::Tampered,
|
|
};
|
|
(distance, compat)
|
|
}
|
|
|
|
/// The compatibility for a space/device with **no** certificate present. Always
|
|
/// [`CalibrationCompat::Absent`], which the gate treats as UNKNOWN (ADR-299 §3:
|
|
/// the default state without a valid certificate is UNKNOWN, not KNOWN).
|
|
pub fn no_certificate() -> CalibrationCompat {
|
|
CalibrationCompat::Absent
|
|
}
|