Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion services/orchestrator/capabilities/src/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub enum RestoreOutcome {
/// and the orchestrator gates the component per its failure policy right
/// away instead of waiting for the retry cap. Errors are actuation faults
/// only, such as an unreachable source or a failed write, and the
/// orchestrator treats them fail-closed. Source exhaustion travels on the
/// orchestrator treats them fail-secure. Source exhaustion travels on the
/// `Ok` side because it is a known condition: the orchestrator applies
/// per-component policy to it instead of locking unconditionally.
///
Expand Down
2 changes: 1 addition & 1 deletion services/orchestrator/driver/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ loop {
```

Implemented executors: `ReadFirmware`, `VerifyFirmware`, `ReleaseReset`
(arms the boot walk), `AssertReset` (stops it). Everything else fails closed
(arms the boot walk), `AssertReset` (stops it). Everything else fails secure
until its pillar lands (recovery, update path, attestation, reporting,
lockdown latch).
2 changes: 1 addition & 1 deletion services/orchestrator/driver/src/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub enum Report {
///
/// Infallible by design: a report names something that already happened, so
/// an undeliverable one costs information, not containment. An error channel
/// would put reports on the fail-closed path, letting the act of reporting a
/// would put reports on the fail-secure path, letting the act of reporting a
/// contained failure escalate it.
pub trait ReportSink {
/// Receives one report. A sink that cannot deliver immediately queues on
Expand Down
16 changes: 8 additions & 8 deletions services/orchestrator/driver/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub enum DriverError {
/// The component's boot control could not actuate the reset line.
BootControlFault,
/// A floor commit was asked for a component with no verified image,
/// so the SVN to advance to is unknown; fail closed.
/// so the SVN to advance to is unknown; fail secure.
NoVerifiedImage,
/// The component's SVN floor could not be advanced.
SvnFloorFault,
Expand Down Expand Up @@ -214,7 +214,7 @@ impl<B: BoardCapabilities, const N: usize> PlatformDriver<B, N> {
/// component the staged candidate is for and `len` as how much of the
/// staging region the candidate occupies. Must succeed BEFORE
/// [`Event::UpdateRequest`] is dispatched; `AuthenticateStageUpdate`
/// with no stored job fails closed. Refuses an unknown id and a
/// with no stored job fails secure. Refuses an unknown id and a
/// second submit while one update is in flight; nothing is stored on
/// refusal, so a refused request can never surface as an update
/// event.
Expand Down Expand Up @@ -370,7 +370,7 @@ impl<B: BoardCapabilities, const N: usize> PlatformDriver<B, N> {
}
Step::Staged => {
job.phase = UpdatePhase::Staged;
// Fail closed: no UpdateVerified until the crypto
// Fail secure: no UpdateVerified until the crypto
// verify-client is wired. The pump parks here.
UpdatePoll::idle()
}
Expand Down Expand Up @@ -595,7 +595,7 @@ impl<B: BoardCapabilities, const N: usize> PlatformDriver<B, N> {
/// Restore `id`'s image from its recovery source. The verdict travels
/// as an event, not an error: `Restored` and `SourceExhausted` are
/// outcomes the SM handles per failure policy, while an `Err` from
/// the mechanism is a genuine actuation fault that fails closed.
/// the mechanism is a genuine actuation fault that fails secure.
pub fn recover_component(
&mut self,
id: ComponentId,
Expand All @@ -614,7 +614,7 @@ impl<B: BoardCapabilities, const N: usize> PlatformDriver<B, N> {
}

/// Hands one report to the board's sink. Cannot fail, so reporting stays
/// off the fail-closed path; reports arrive in the order the SM emitted
/// off the fail-secure path; reports arrive in the order the SM emitted
/// them.
pub fn report(&mut self, report: Report) {
self.board.report_sink.report(report);
Expand Down Expand Up @@ -660,15 +660,15 @@ impl<B: BoardCapabilities, const N: usize> Platform for PlatformDriver<B, N> {
/// variant must get an executor before this compiles. Synchronous
/// results (the verification verdict) come back as the returned event;
/// every executor error reports as [`EffectError`], the SM treats all
/// actuation failures the same, fail-closed.
/// actuation failures the same, fail-secure.
fn execute(&mut self, effect: Effect) -> Result<Option<Event>, EffectError> {
match effect {
Effect::ReadFirmware(id) => self.stage_firmware(id).map(|_| None),
Effect::VerifyFirmware(id) => self.verify_firmware(id).map(Some),
Effect::ReleaseReset(id) => self.release_reset(id).map(|_| None),
Effect::AssertReset(id) => self.assert_reset(id).map(|_| None),
Effect::CommitSvnFloor(id) => self.commit_svn_floor(id).map(|_| None),
// Reports carry no error, so they never reach the fail-closed
// Reports carry no error, so they never reach the fail-secure
// group below.
Effect::ReportIsolated(id) => {
self.report(Report::Isolated(id));
Expand Down Expand Up @@ -707,7 +707,7 @@ impl<B: BoardCapabilities, const N: usize> Platform for PlatformDriver<B, N> {
Effect::ActivateUpdate => self.activate_update().map(|_| None),
Effect::DiscardStaged => self.discard_staged().map(|_| None),
// No board capability is composed for these seams yet, so they
// fail closed here instead of behind stub methods.
// fail secure here instead of behind stub methods.
Effect::SignAttestation | Effect::LatchLockdown => return Err(EffectError),
// Emit is consumed by the orchestrator; receiving one is a
// driver bug.
Expand Down
2 changes: 1 addition & 1 deletion services/orchestrator/driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! [`PlatformDriver`] implements the SM's [`Platform`] seam, delegating each
//! `Effect` to a board-composed capability per the platform-boundary contract
//! (`docs/src/design/orchestrator/orchestrator-model.md` §6). Effects whose
//! capability is not composed yet fail closed in `execute`; the driver grows
//! capability is not composed yet fail secure in `execute`; the driver grows
//! an executor only when the capability it delegates to exists.
//!
//! Synchronous results (the verification verdict) return through `execute`;
Expand Down
4 changes: 2 additions & 2 deletions services/orchestrator/driver/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,7 @@ fn floor_fault_is_reported() {
}

// Every report effect reaches the board's sink, in emission order, and none
// hands back an error for the SM to fail closed on.
// hands back an error for the SM to fail secure on.
#[test]
fn reports_reach_the_board_sink() {
let mut driver = PlatformDriver::<MockBoard, 1>::new(
Expand Down Expand Up @@ -1443,7 +1443,7 @@ fn reports_reach_the_board_sink() {

// An Isolable component is contained and reported, and the platform keeps
// running: executing a report returns no error, so it never reaches the
// fail-closed path.
// fail-secure path.
#[test]
fn reporting_an_isolated_component_does_not_lock_the_platform() {
let mut driver = PlatformDriver::<MockBoard, 2>::new(
Expand Down
6 changes: 3 additions & 3 deletions services/orchestrator/sm/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ pub enum Event {
/// when it executes [`Effect::ActivateUpdate`] and cancels it on
/// [`Effect::CommitSvnFloor`].
CommitTimeout,
/// The platform driver could not carry out an emitted [`Effect`]; fail-closed, it
/// The platform driver could not carry out an emitted [`Effect`]; fail-secure, it
/// latches to [`State::Locked`] from any state. Injected by the driver when
/// a [`Platform::execute`](crate::Platform::execute) call fails; never
/// produced by a handler.
Expand All @@ -302,7 +302,7 @@ impl Event {
/// [`Event::UpdateRequest`] is the exception: it carries a component but
/// returns `None`. The caller records the job before dispatching it, so
/// dropping the event here would leave that job with nothing to answer it
/// and wedge every later request. An unknown target instead fails closed in
/// and wedge every later request. An unknown target instead fails secure in
/// the executor, which has the board's component list to check against.
pub(crate) fn component_id(&self) -> Option<ComponentId> {
match self {
Expand Down Expand Up @@ -476,7 +476,7 @@ impl State {
/// Build one with [`TryFrom`]/[`TryInto`] from a `heapless::Vec` of
/// `(ComponentId, ComponentAttrs)` pairs. The conversion is the single place
/// the state machine's structural invariants are enforced, so a malformed chain
/// fails closed at the boundary instead of misbehaving later:
/// fails secure at the boundary instead of misbehaving later:
///
/// - the chain is non-empty,
/// - every [`ComponentId`] is unique,
Expand Down
8 changes: 4 additions & 4 deletions services/orchestrator/sm/src/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl<const N: usize, const E: usize> Orchestrator<N, E> {
///
/// If `on_effect` reports an [`EffectError`], the orchestrator injects an
/// [`Event::EffectFailed`] at the *front* of the queue, so a failed
/// actuation is handled fail-closed: the latch settles next, and feedback
/// actuation is handled fail-secure: the latch settles next, and feedback
/// still queued behind it drains into [`State::Locked`] (discarded)
/// instead of actuating hardware after a failure. A pending-queue
/// overflow is handled the same way: losing a returned event would break
Expand All @@ -89,7 +89,7 @@ impl<const N: usize, const E: usize> Orchestrator<N, E> {
event: Event,
mut on_effect: impl FnMut(Effect) -> Result<Option<Event>, EffectError>,
) {
// Fail-closed latch: `EffectFailed` goes to the *front*, so it settles
// Fail-secure latch: `EffectFailed` goes to the *front*, so it settles
// next and everything still queued drains into `Locked` (discarded)
// instead of actuating hardware after a failure. Prefer evicting the
// newest queued event over losing the latch itself.
Expand Down Expand Up @@ -122,7 +122,7 @@ impl<const N: usize, const E: usize> Orchestrator<N, E> {
external => match on_effect(external) {
Ok(follow_up) => follow_up,
Err(_) => {
// Fail-closed AND fail-fast: abandon the rest of
// Fail-secure AND fail-fast: abandon the rest of
// this batch. `step` has already advanced the
// state as if the whole batch applied, and the
// latch overrides that transition, so nothing
Expand All @@ -140,7 +140,7 @@ impl<const N: usize, const E: usize> Orchestrator<N, E> {
&& !failed
{
// Queue full: `next` would be lost, breaking the
// honest-feedback contract. Fail closed instead.
// honest-feedback contract. Fail secure instead.
failed = true;
latch(&mut pending);
break;
Expand Down
4 changes: 2 additions & 2 deletions services/orchestrator/sm/src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::model::{Effect, Event};

/// Signals that the platform driver could not carry out an [`Effect`]. The machine does
/// not need the driver's error detail — **every** actuation failure is treated
/// the same, fail-closed: the orchestrator injects [`Event::EffectFailed`] and the
/// the same, fail-secure: the orchestrator injects [`Event::EffectFailed`] and the
/// machine latches to [`State::Locked`]. This blanket policy is deliberate and
/// is what lets the failure signal stay a payload-less marker; a future design
/// that needs per-effect recovery must add a *new*, descriptive event rather
Expand Down Expand Up @@ -56,7 +56,7 @@ pub struct EffectError;
/// component are exhausted, it feeds back [`Event::RecoveryUnavailable`]
/// instead — never [`EffectError`]. `EffectError` from a `RecoverComponent`
/// call is reserved for a genuine actuation fault (e.g. a bus error during
/// the image swap), which fails closed to [`State::Locked`] unconditionally.
/// the image swap), which fails secure to [`State::Locked`] unconditionally.
/// Reporting "out of images" that way would lock the whole platform down
/// even for an `Isolable`/`Cascading` component, instead of letting it be
/// gated per [`FailurePolicy`] like the count-driven exhaustion path.
Expand Down
2 changes: 1 addition & 1 deletion services/orchestrator/sm/src/rot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ impl<const N: usize, const E: usize> Rot<N, E> {
Outcome::Handled
}
// Commit watchdog. If the activated-but-not-committed window is
// still open, fail closed: never commit an unproven image, and
// still open, fail secure: never commit an unproven image, and
// never leave the downgrade window open indefinitely. Outside
// the window this is a stale watchdog fire and is dropped.
Event::CommitTimeout => {
Expand Down
4 changes: 2 additions & 2 deletions services/orchestrator/sm/src/sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::model::{Effect, State};
/// pops as it settles, so this bounds *in-flight* events, not a run's total
/// length: one batch can queue at most one `Emit` follow-up plus one returned
/// event per external effect. Executors that return an event for many effects
/// of one batch can overflow this; overflow is fail-closed (see
/// of one batch can overflow this; overflow is fail-secure (see
/// `dispatch_with`), never silent loss.
pub(crate) const PENDING_CAP: usize = 8;

Expand Down Expand Up @@ -63,7 +63,7 @@ impl<const E: usize> Sink<E> {
/// handler emits more than `2 * N + 2` effects into one `Sink`, so the push
/// below can never fail. A `cfg(test)` assert catches a stale derivation
/// in the test suite; in the release binary the push is unchecked
/// (fail-closed: fewer effects means more lockdown, never less).
/// (fail-secure: fewer effects means more lockdown, never less).
///
/// The driver runs the effects from one handler in the order they were
/// emitted, and it does not run them as a single all-or-nothing group: if
Expand Down
10 changes: 5 additions & 5 deletions services/orchestrator/sm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2106,7 +2106,7 @@ fn svn_floor_commits_on_boot_confirmed_not_on_activation() {

/// Commit-or-lock watchdog: while the activated-but-not-committed window is
/// open (update activated, `BootConfirmed` not yet seen), a `CommitTimeout`
/// fails closed — the machine latches `Locked` rather than leaving the
/// fails secure — the machine latches `Locked` rather than leaving the
/// downgrade window open indefinitely, and never commits the unproven image.
#[test]
fn commit_timeout_while_pending_latches_locked() {
Expand Down Expand Up @@ -2438,7 +2438,7 @@ impl Platform for FailOn {
}
}

/// A failed reset actuation is fail-closed: the orchestrator injects `EffectFailed`
/// A failed reset actuation is fail-secure: the orchestrator injects `EffectFailed`
/// and the machine latches to `Locked`, emitting `LatchLockdown`.
#[test]
fn effect_failure_latches_lockdown() {
Expand All @@ -2456,7 +2456,7 @@ fn effect_failure_latches_lockdown() {
assert!(plat.recorded.contains(&Effect::LatchLockdown));
}

/// A failed isolation actuation (`AssertReset`) is equally fail-closed: even a
/// A failed isolation actuation (`AssertReset`) is equally fail-secure: even a
/// non-required component's containment failing latches the platform.
#[test]
fn failed_isolation_actuation_latches_lockdown() {
Expand All @@ -2477,7 +2477,7 @@ fn failed_isolation_actuation_latches_lockdown() {
assert!(plat.recorded.contains(&Effect::LatchLockdown));
}

/// A failed recovery actuation is fail-closed too: if the platform driver cannot even
/// A failed recovery actuation is fail-secure too: if the platform driver cannot even
/// recover a required component, the platform latches rather
/// than continuing with an unrecovered component.
#[test]
Expand Down Expand Up @@ -2964,7 +2964,7 @@ fn returned_verdicts_settle_in_one_dispatch() {
}

/// A batch whose executors return more events than the pending queue holds
/// fails closed: the run latches `Locked` instead of losing feedback.
/// fails secure: the run latches `Locked` instead of losing feedback.
#[test]
fn returned_event_overflow_latches_locked() {
struct Chatty;
Expand Down
Loading