# orchestrate — design
> **Class:** `design` · **Function axis:** `f8` (AIRGAP8: ordered bring-up + telemetry). States
> only the shape we ship.
## Dependency-ordered bring-up
`orchestrate::start_waves(products) -> Vec<Vec<String>>` (`orchestrate.rs:42`) Kahn-topo-sorts the
products into **waves**: wave `i` holds every product whose `depends_on` are all satisfied by
earlier waves. Each wave is sorted for determinism, and products *within* a wave can start
concurrently (the caller uses `std::thread::scope` — no rayon).
- `start_order(products) -> Vec<String>` (`orchestrate.rs:23`) — the flat order (`start_waves`
flattened), sources first.
- `teardown_order(products) -> Vec<String>` (`orchestrate.rs:31`) — the reverse, so a dependent is
stopped before its dependency.
The node is `product::Product` (`product.rs:235`) — `name`, `depends_on`, `user`, `ports` — the
dep-graph view a `ComponentSpec` yields via `as_product()`. Deps that point outside the product set
(e.g. `network.target`) are ignored (`orchestrate.rs:52`). A **cycle** is detected after the Kahn
drain (`orchestrate.rs:87`) and returned as an error naming the stuck products.
`config::LakeSpec::start_waves()` (`lib.rs:137`) is the whole-lake entry point — it maps each
`ComponentSpec` to a `Product` and calls `start_waves`.
## Telemetry — `airgap_events`
Every pipeline boundary emits one row. `events::AirgapEvent` (`events.rs:49`) — `run_id, seq,
ts_micros, product, op, phase, status, detail, depends_on`. Vocab: `op` (`events.rs:24`) =
`pack | fetch | unfold | install | start | matrix_probe`; `phase` (`events.rs:35`) =
`start | end | skip`; `status` (`events.rs:40`) = `ok | fail | running`.
`events::EventSink { append(&event) }` (`events.rs:71`) is the seam; `JsonlSink` (`events.rs:76`)
is the default — an append-only JSONL under the **warehouse root** (`under_warehouse`,
`events.rs:83`), never `/tmp`. `EventEmitter` (`events.rs:116`) mints the `run_id` + a monotonic
`seq` and emits best-effort (a sink error logs to stderr, never aborts the bring-up,
`events.rs:132`). `read_jsonl` (`events.rs:161`) reads rows back sorted by `seq`.
## Introspection — `functional_status` surface emits (nornir's coverage gate)
Separate from the `airgap_events` DAG, each **lifecycle surface** self-reports an `ok`/RED verdict
into nornir's constellation-wide introspection matrix via the `functional_status` shim
(`lib.rs:44`, → `nornir-testmatrix`, **reused** — no twin). The emit is **implanted** in the runtime
path itself (via the `surface_status!` macro, `lib.rs`), so the matrix sees the surface's *actual*
return/state, not a test's re-derivation. Compiled out entirely unless `--features testmatrix` is on
(the lean core stays dep-free, zero `format!` cost). Wired surfaces + components:
| surface | component | check | fires |
|---|---|---|---|
| pack | `skidbladnir/pack` | `pack_collect_staging_tree` | `pack::pack` (`pack.rs`) — RED if the staging tree can't be walked |
| fetch | `skidbladnir/fetch` | `verify_on_receipt` | `fetch::verify_on_receipt` (`fetch.rs`) — RED on a corrupt/unauthentic bundle |
| unfold | `skidbladnir/unfold` | `extract_all` | `archive::TarZstd::extract_all` (`archive.rs`) — RED on a bad/missing bundle |
| install | `skidbladnir/install` | `install_product` | `install::install_product` (`install.rs`) — RED if any step throws |
| start | `skidbladnir/start` | `start_waves_ordered` | `orchestrate::start_waves` (`orchestrate.rs`) — RED on a dependency cycle |
| pki | `skidbladnir/pki` | `issue_leaf` | `pki::MachineCa::issue_leaf` (`pki.rs`) — RED if rcgen can't sign the leaf |
| systemd | `skidbladnir/systemd` | `install_unit` | `systemd::install_systemd_scoped` (`systemd.rs`) — RED when a secret-carrying spec has no private env-file |
`drain_functional_rows` (`lib.rs`, testmatrix-only) reads the process-global buffer back — the
seam the red-when-broken test uses. The matrix harness collects the same rows a
`cargo test --features testmatrix` subprocess wrote (nornir #32), exactly like the sibling crates
(ordning-core, korp-collectors).
## Contract (inject-assert tests)
`topo_waves_from_fixture_dep_graph` (`orchestrate.rs:118`),
`teardown_is_reverse_of_start` (`orchestrate.rs:155`),
`cycle_is_rejected` (`orchestrate.rs:172`),
`external_deps_are_ignored` (`orchestrate.rs:147`),
`emits_install_dag_to_warehouse_jsonl_and_reads_back` (`events.rs:184`).