-
Notifications
You must be signed in to change notification settings - Fork 24
Orchestrator spec and reference impl #357
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
rusty1968
wants to merge
44
commits into
OpenPRoT:main
Choose a base branch
from
rusty1968:orchestrator-sm
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+4,487
−0
Open
Changes from all commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
9757f87
Orchestrator spec and reference impl
rusty1968 28e6b23
fixed ci faulures
rusty1968 acf2a34
re-walk of the chain explained
rusty1968 15a75bc
Aligning to the latest CSA
rusty1968 af598c9
docs: add orchestrator state machine walkthrough and transitions
rusty1968 663bf48
Add a high level topology without effects
rusty1968 1e90f42
Update code and docs to the latest CSA
rusty1968 a4e2f7a
delete redundant docs
rusty1968 564fe54
Remove misleading pseudostate
rusty1968 c942aa9
PlatformHalt is a consequence of the Policy::Required
rusty1968 8d6eeae
orchestrator: document PreSupervision/CorruptionDetected gap as accepted
rusty1968 f903148
orchestrator/sm: size effect buffer to N+2 via const generic
rusty1968 aa91c93
orchestrator-sm: durable gate + unified gate_by_policy
rusty1968 4b0efed
orchestrator-sm: per-device retry budget
rusty1968 5cdcce2
orchestrator-sm: move tests to sibling tests.rs
rusty1968 1d47942
orchestrator-sm: validated Chain newtype for construction
rusty1968 a251304
orchestrator-sm: factor out model types from lib.rs into model.rs
rusty1968 9df7a78
orchestrator-sm: fail-closed effect-failure channel, panic-free buffe…
rusty1968 26a95e9
orchestrator-sm: replace statig with hand-written reducer
rusty1968 5dd3213
orchestrator-sm: fold awaiting/failed into State variants
rusty1968 3f33bb1
orchestrator-sm: abort effect batch on first actuation failure
rusty1968 efc6500
orchestrator-sm: clarify Sink::emit partial-batch safety in plain lan…
rusty1968 04f5ab4
orchestrator-sm: add degraded-mode isolation/recovery-failure reports
rusty1968 de7dd3d
orchestrator-sm: test degraded-mode reporting
rusty1968 ff54b7c
orchestrator-sm: add Timeout event and AwaitingReady recovery arm
rusty1968 aad7432
orchestrator-sm: discard staged image on update preemption; id-check …
rusty1968 bb5e6cd
orchestrator-sm: fold gated+retries into per-component ComponentStatus
rusty1968 175328e
orchestrator docs: de-duplicate diagrams, fix stale field names, comp…
rusty1968 b35dc0c
orchestrator-sm: reword ComponentStatus doc comments to present-tense
rusty1968 603f52d
docs: drop TOC entries for deleted orchestrator walkthrough/transitio…
rusty1968 02e27f0
orchestrator/sm: test transitive cascade and mid-recovery corruption …
rusty1968 ab584d7
orchestrator/sm: commit SVN floor on proven boot, not activation
rusty1968 745dc32
orchestrator/sm: device-agnostic boot-progress watchdog
rusty1968 3a5ce14
orchestrator sm: report deferred and aborted updates
rusty1968 50989bd
third_party: restore crate_universe lock to origin/main pins
rusty1968 c47b868
orchestrator docs: add consolidated invariant catalogue
rusty1968 91b14e8
orchestrator docs: define 'rejected' per CSA at first use
rusty1968 e9cf424
orchestrator docs: rename shell to platform driver; trim redundant IN…
rusty1968 42eac7e
orchestrator docs: drop inaccurate 'three orthogonal axes' claim
rusty1968 6ec0be0
docs(orchestrator): add core/platform separation-of-concerns section
rusty1968 223025b
docs(orchestrator): note the core is policy-free and drops out-of-cha…
rusty1968 1084ecc
orchestrator/sm: drop out-of-chain ids at the dispatch boundary
rusty1968 8144f89
docs(orchestrator): recovery-is-a-reboot, INV8 catalogue, shell→platform
rusty1968 bf06603
orchestrator/sm: recovery re-boots; guard out-of-turn verification ve…
rusty1968 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Orchestrator State Machine | ||
|
|
||
| The orchestrator is the eRoT's boot-sequence controller. It walks the platform | ||
| trust chain — verifying each component's firmware and releasing it from reset in | ||
| order — and then governs the operational lifecycle (attestation, firmware update, | ||
| corruption recovery). | ||
|
|
||
| It lives in `services/orchestrator/sm` as a pure state machine: it never touches | ||
| hardware directly. Every action is described as an [`Effect`] value that the | ||
| surrounding platform carries out; every piece of outside information arrives as an | ||
| [`Event`]. This keeps the core testable without hardware and free of I/O. | ||
|
|
||
| ## State Topology | ||
|
|
||
| The reachable states, the events (with guards) that drive transitions between | ||
| them, and the effects each transition emits are all shown in the full state | ||
| diagram in [State Machine](./orchestrator-machine.md#state-machine). That diagram | ||
| is the single source of truth for the topology; it is not duplicated here to | ||
| avoid the two drifting apart. | ||
|
|
||
| ## Documents | ||
|
|
||
| - [**Verification Model**](./orchestrator-model.md): The two-tier firmware | ||
| verification model (eRoT gate + optional iRoT gate), the verification | ||
| boundary, `ComponentAttrs`, and concrete sequencing examples. | ||
| - [**State Machine**](./orchestrator-machine.md): All states, shared storage, entry | ||
| actions, transition table, and the `SupervisingPlatform` superstate. | ||
|
|
||
| ## Design Principles | ||
|
|
||
| **Effects, not actions; reads as events.** Handlers only call | ||
| `ctx.emit(Effect::…)` to describe what should happen, and receive every piece of | ||
| outside information in event payloads — the core never reads flash, drives a | ||
| GPIO, opens a channel, or touches a provisioning store. The full core/platform | ||
| split is the [Platform Boundary](./orchestrator-model.md#5-the-platform-boundary) | ||
| in the Verification Model. | ||
|
|
||
| **Feedback as data.** Internal follow-up signals (e.g. the retry-cap lockdown | ||
| `RecoveryFailed`) are emitted as `Effect::Emit(event)`. The orchestrator queues | ||
| and handles them immediately, making them visible in the effect trace rather than | ||
| hiding them as implicit state changes. See the | ||
| [`Recovering` state](./orchestrator-machine.md#recovering) for a worked example. | ||
|
|
||
| **Board-supplied policy.** The core hard-codes no deployment-specific values. | ||
| The platform supplies the trust chain (component ids, kinds, and required/optional | ||
| policy) and the recovery-retry cap at startup. | ||
|
|
||
| ## Relationship to CSA Architecture | ||
|
|
||
| The state machine is a direct implementation of the boot sequence described in | ||
| the CSA architecture document: | ||
|
|
||
| | CSA concept | State machine encoding | | ||
| |---|---| | ||
| | eRoT holds component in reset until firmware verified | `PreSupervision` emits `ReleaseReset` only on `VerificationPassed` | | ||
| | Component with Caliptra iRoT requires two independent checks | `ComponentKind::Active` → `AwaitingReady` until `ComponentReady` | | ||
| | Passive component (no iRoT): eRoT check only | `ComponentKind::Passive` → advance immediately after `ReleaseReset` | | ||
| | Isolable component: failure skips, not blocks | `FailurePolicy::Isolable` → skip (held in reset); advance without `Recovering`; no cascade | | ||
| | Cascading skip: failure also holds dependents | `FailurePolicy::Cascading` + `ComponentAttrs::depends_on` → cascade-skip via `statuses` (`Isolated`) | | ||
| | Boot-progress watchdog: component must signal readiness in time | `Timeout(ComponentId)` event → `AwaitingReady` → `Recovering` | | ||
| | Recovery scope groups components that restore together | `ComponentAttrs::recovery_region` (`RegionId`) → platform restores full region on `RestoreGoldenImage` | | ||
|
|
||
| ## Applicability Across Admissible Architectures | ||
|
|
||
| The orchestrator is **eRoT-scoped**: one instance runs per discrete eRoT chip | ||
| running OpenPRoT firmware. The same crate and binary are used at every such | ||
| tier — the only difference between deployments is the chain configuration | ||
| supplied at startup. eRoT chips not running OpenPRoT (e.g. a third-party AMC | ||
| or a legacy DC-SCM implementation) appear as opaque `ComponentId` entries in | ||
| the chain of the nearest OpenPRoT eRoT above them. | ||
|
|
||
| **Model 1 — Module** (single PCIe add-in card): a discrete eRoT is optional. | ||
| When present, it runs one orchestrator instance with a short chain containing | ||
| the card's SoC. When absent, the module relies on the parent node's eRoT | ||
| instance to verify and release it as a `ComponentId` in the node's chain. | ||
|
|
||
| **Model 2 — Single Node Compute**: the DC-SCM discrete eRoT runs one | ||
| orchestrator instance whose chain covers all critical node devices (CPU, BMC, | ||
| NIC, storage). This is the canonical single-instance deployment. | ||
|
|
||
| **Model 3 — Complex Heterogeneous Compute**: the three-tier hierarchy maps to | ||
| independent orchestrator instances at each tier: | ||
|
|
||
| - Each **AMC / EAM** (subsystem eRoT) runs one instance whose chain covers the | ||
| GPU or AI accelerator devices it manages. | ||
| - The **DC-SCM node eRoT** runs one instance whose chain covers CPUs, BMC, | ||
| SmartNICs, storage, and the AMC/EAM chips themselves. | ||
|
|
||
| The node eRoT treats each AMC/EAM as just another `ComponentId` — `Active` if | ||
| the AMC has its own integrated iRoT, `Passive` if not. It has no visibility | ||
| into the AMC's internal chain walk; it only observes the AMC's | ||
| `VerificationPassed` / `ComponentReady` signals, like any other component. | ||
|
|
||
| | Admissible Architecture | Orchestrator instances | Chain scope per instance | | ||
| |---|---|---| | ||
| | Module (eRoT present) | 1 | Card SoC | | ||
| | Module (no eRoT) | 0 | — (verified by parent node eRoT) | | ||
| | Single Node Compute | 1 | All node critical devices | | ||
| | Complex Heterogeneous Compute | 1 per subsystem eRoT + 1 node eRoT | Subsystem devices / all node devices including subsystem eRoTs | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Licensed under the Apache-2.0 license | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") | ||
|
|
||
| rust_library( | ||
| name = "orchestrator_sm", | ||
| srcs = [ | ||
| "src/lib.rs", | ||
| "src/model.rs", | ||
| "src/tests.rs", | ||
| ], | ||
| crate_name = "openprot_orchestrator_sm", | ||
| edition = "2024", | ||
| visibility = ["//visibility:public"], | ||
| deps = [ | ||
| "@rust_crates//:heapless", | ||
| ], | ||
| ) | ||
|
|
||
| rust_test( | ||
| name = "orchestrator_sm_test", | ||
| crate = ":orchestrator_sm", | ||
| edition = "2024", | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <!-- Licensed under the Apache-2.0 license --> | ||
| <!-- SPDX-License-Identifier: Apache-2.0 --> | ||
|
|
||
| # orchestrator state machine (`openprot_orchestrator_sm`) | ||
|
|
||
| Pure-reducer eRoT boot-sequence state machine. Walks the platform trust chain | ||
| — verifying each component's firmware and releasing it from reset in order — | ||
| then governs the operational lifecycle (attestation, firmware update, corruption | ||
| recovery). | ||
|
|
||
| **No I/O, no hardware.** Every action is an [`Effect`] the surrounding shell | ||
| carries out. Every piece of outside information arrives as an [`Event`]. | ||
|
|
||
| ## Key types | ||
|
|
||
| | Type | Role | | ||
| |---|---| | ||
| | `ComponentId` | Opaque `u8` — the shell maps it to hardware; the core never inspects it. | | ||
| | `ComponentKind` | `Active` (eRoT + iRoT gates) or `Passive` (eRoT gate only). | | ||
| | `ComponentAttrs` | `kind` + `required`: if `false`, a failed component is skipped (held in reset) rather than triggering recovery. | | ||
| | `Orchestrator<N>` | Public handle for the caller's event loop. Call `dispatch` or `dispatch_with` once per event. | | ||
| | `Platform` | Implement this to carry out effects (drives reset GPIOs, reads flash, etc.). | | ||
|
|
||
| ## Usage | ||
|
|
||
| ```rust | ||
| use openprot_orchestrator_sm::{ | ||
| ComponentAttrs, ComponentId, Orchestrator, Event, PowerOnResult, State, | ||
| }; | ||
|
|
||
| const CAPACITY: usize = 3; | ||
| const BMC: ComponentId = ComponentId::new(0); | ||
| const HOST: ComponentId = ComponentId::new(1); | ||
| const NIC: ComponentId = ComponentId::new(2); | ||
|
|
||
| let mut chain = heapless::Vec::<_, CAPACITY>::new(); | ||
| let _ = chain.push((BMC, ComponentAttrs::active_required())); | ||
| let _ = chain.push((HOST, ComponentAttrs::active_required())); | ||
| let _ = chain.push((NIC, ComponentAttrs::passive_optional())); | ||
|
|
||
| let mut orch = Orchestrator::new(chain, /*max_retry=*/ 3); | ||
| let mut board = MyBoard; | ||
|
|
||
| orch.dispatch(&mut board, Event::PowerGood(PowerOnResult::Provisioned)); | ||
| // ...deliver VerificationPassed / ComponentReady events as they arrive... | ||
| assert_eq!(orch.state(), State::Ready); | ||
| ``` | ||
|
|
||
| ## Design docs | ||
|
|
||
| Full domain model, verification boundary, and state transition tables are in the | ||
| OpenPRoT book: | ||
|
|
||
| - `docs/src/design/orchestrator/verification-model.md` | ||
| - `docs/src/design/orchestrator/state-machine.md` | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.