diff --git a/docs/src/design/orchestrator/orchestrator-machine.md b/docs/src/design/orchestrator/orchestrator-machine.md
index 69c9dfad..d216a964 100644
--- a/docs/src/design/orchestrator/orchestrator-machine.md
+++ b/docs/src/design/orchestrator/orchestrator-machine.md
@@ -24,7 +24,7 @@ stateDiagram-v2
AwaitingReady --> Recovering : Timeout(id) [id == awaiting]
/ RestoreGoldenImage
state SupervisingPlatform {
- Ready --> Updating : UpdateRequest
/ AuthenticateUpdate · StageUpdate
+ Ready --> Updating : UpdateRequest
/ AuthenticateStageUpdate
Updating --> Ready : UpdateVerified / ActivateUpdate
Updating --> Ready : UpdateRejected / DiscardStaged
Ready --> Recovering : CorruptionDetected
/ RestoreGoldenImage
@@ -189,7 +189,7 @@ only a fresh `Rot` on `PowerOnReset` releases it.
An update is in progress.
-**Entry action**: emit `AuthenticateUpdate` + `StageUpdate`.
+**Entry action**: emit `AuthenticateStageUpdate`.
> **Rejected** here has a specific meaning from the CSA authenticated-update
> sequence: the staged candidate failed verification — its signature did not
diff --git a/docs/src/design/orchestrator/orchestrator-model.md b/docs/src/design/orchestrator/orchestrator-model.md
index 3d39187d..4891825f 100644
--- a/docs/src/design/orchestrator/orchestrator-model.md
+++ b/docs/src/design/orchestrator/orchestrator-model.md
@@ -419,7 +419,7 @@ policy deployments configure.
delivered as `PowerOnResult` in `Event::PowerGood`.
- **Attestation** (`AttestationChallenge` / `SignAttestation`): handled in the
`SupervisingPlatform` superstate, not part of the boot-time verification chain.
-- **Firmware update verification** (`AuthenticateUpdate`): handled in the
+- **Firmware update verification** (`AuthenticateStageUpdate`): handled in the
`Updating` state, distinct from boot-time chain verification.
- **Multiple intermediate boot-progress checkpoints per component**: the CSA
architecture allows platform policy to require multiple intermediate
diff --git a/services/orchestrator/driver/src/driver.rs b/services/orchestrator/driver/src/driver.rs
index 2bb1ffa2..45117543 100644
--- a/services/orchestrator/driver/src/driver.rs
+++ b/services/orchestrator/driver/src/driver.rs
@@ -110,7 +110,7 @@ impl PlatformDriver {
/// The frontend half of the update handshake: record `target` as the
/// component the staged candidate is for. Must succeed BEFORE
- /// [`Event::UpdateRequest`] is dispatched; `StageUpdate` with no stored
+ /// [`Event::UpdateRequest`] is dispatched; `AuthenticateStageUpdate` with no stored
/// job fails closed. 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.
@@ -381,12 +381,11 @@ impl Platform for PlatformDriver {
// No board capability is composed for these seams yet, so they
// fail closed here instead of behind stub methods. Each group
// gains an executor when its capability joins
- // [`BoardCapabilities`], as BootControl did above: update
- // staging, authentication and trial activation for the update
- // quartet; evidence signing for SignAttestation; the terminal
- // latch for LatchLockdown.
- Effect::AuthenticateUpdate
- | Effect::StageUpdate
+ // [`BoardCapabilities`], as BootControl did above: staging
+ // plus verification, trial activation and discard for the
+ // update effects; evidence signing for SignAttestation; the
+ // terminal latch for LatchLockdown.
+ Effect::AuthenticateStageUpdate
| Effect::ActivateUpdate
| Effect::DiscardStaged
| Effect::SignAttestation
@@ -402,7 +401,7 @@ impl Platform for PlatformDriver {
/// The connection between an update frontend and the SM: called (by the
/// event loop, on the frontend's behalf) once a complete candidate for
/// `target` sits in the staging region. Records the job first, then injects
-/// [`Event::UpdateRequest`]; that order is load-bearing, `StageUpdate` can
+/// [`Event::UpdateRequest`]; that order is load-bearing, `AuthenticateStageUpdate` can
/// never run without a target. On refusal no event is injected and the
/// frontend answers the requester over its own protocol.
pub fn request_update(
diff --git a/services/orchestrator/driver/src/tests.rs b/services/orchestrator/driver/src/tests.rs
index a443cc3e..f49c9165 100644
--- a/services/orchestrator/driver/src/tests.rs
+++ b/services/orchestrator/driver/src/tests.rs
@@ -1315,7 +1315,7 @@ fn submit_update_refuses_a_second_in_flight() {
// The frontend connection end to end: request_update records the job and
// the SM receives UpdateRequest. Ready accepts it and enters Updating,
-// whose entry effects (AuthenticateUpdate, StageUpdate) have no executors
+// whose entry effect (AuthenticateStageUpdate) has no executor
// yet, so the machine latches Locked — that latch is the proof the event
// arrived. Flips to an Updating/Ready assertion when the pump lands.
#[test]
diff --git a/services/orchestrator/sm/src/lib.rs b/services/orchestrator/sm/src/lib.rs
index 53abfa8b..5ed572e2 100644
--- a/services/orchestrator/sm/src/lib.rs
+++ b/services/orchestrator/sm/src/lib.rs
@@ -978,8 +978,7 @@ impl Rot {
// A new update supersedes any activated-but-not-committed image;
// the prior commit window is void.
self.pending_commit = false;
- ctx.emit(Effect::AuthenticateUpdate);
- ctx.emit(Effect::StageUpdate);
+ ctx.emit(Effect::AuthenticateStageUpdate);
}
State::Recovering(failed) => {
// Recovery voids any activated-but-not-committed image: the
diff --git a/services/orchestrator/sm/src/model.rs b/services/orchestrator/sm/src/model.rs
index a7774bdc..5e67e3b8 100644
--- a/services/orchestrator/sm/src/model.rs
+++ b/services/orchestrator/sm/src/model.rs
@@ -337,8 +337,9 @@ pub enum Effect {
/// component is gated without triggering (or continuing) a recovery cycle.
AssertReset(ComponentId),
SignAttestation,
- AuthenticateUpdate,
- StageUpdate,
+ /// Stage the candidate, then verify it. The driver knows the protocol
+ /// order; the SM does not split these into sub-phases.
+ AuthenticateStageUpdate,
ActivateUpdate,
DiscardStaged,
/// Advance the anti-rollback (SVN) floor past `id`'s now-confirmed image.
diff --git a/services/orchestrator/sm/src/tests.rs b/services/orchestrator/sm/src/tests.rs
index 17a1d585..88d1b7b7 100644
--- a/services/orchestrator/sm/src/tests.rs
+++ b/services/orchestrator/sm/src/tests.rs
@@ -156,14 +156,10 @@ fn update_rollback_is_not_recovery() {
Event::UpdateRejected,
],
);
- let tail = &effects[effects.len() - 3..];
+ let tail = &effects[effects.len() - 2..];
assert_eq!(
tail,
- &[
- Effect::AuthenticateUpdate,
- Effect::StageUpdate,
- Effect::DiscardStaged
- ],
+ &[Effect::AuthenticateStageUpdate, Effect::DiscardStaged],
);
assert_eq!(state, State::Ready);
assert!(!effects.contains(&Effect::LatchLockdown));
@@ -2465,7 +2461,7 @@ fn corruption_during_update_discards_staged() {
BOOT,
Event::VerificationPassed(C0),
Event::VerificationPassed(C1), // → Ready
- Event::UpdateRequest, // → Updating (AuthenticateUpdate, StageUpdate)
+ Event::UpdateRequest, // → Updating (AuthenticateStageUpdate)
Event::CorruptionDetected(C1), // Required corruption preempts the update
],
);