docs(adr): renumber ADR-094 to ADR-095 to avoid collision with body tracking PR

PR #487 (body tracking platform) was filed first and claims ADR-094.
Rename docs/adr/ADR-094-pull-based-ota.md → ADR-095-pull-based-ota.md
and update all references in CHANGELOG.md, Cargo.toml, and main.rs comments.
This commit is contained in:
Deploy Bot 2026-04-28 14:16:57 -04:00
parent 7a8b72de76
commit 41d3378817
4 changed files with 9 additions and 9 deletions

View File

@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added ### Added
- **Pull-based OTA firmware updates** (ADR-094) — - **Pull-based OTA firmware updates** (ADR-095) —
ESP32 sensing nodes now poll `GET /api/v1/firmware/latest` on a configurable ESP32 sensing nodes now poll `GET /api/v1/firmware/latest` on a configurable
interval (default 5 min) and self-upgrade when the server advertises a newer interval (default 5 min) and self-upgrade when the server advertises a newer
version. SHA-256 integrity is verified before writing the OTA partition; the version. SHA-256 integrity is verified before writing the OTA partition; the
@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
tests). New server endpoints: `GET /api/v1/firmware/latest`, tests). New server endpoints: `GET /api/v1/firmware/latest`,
`GET /api/v1/firmware/download`, `POST /api/v1/firmware/upload`. `GET /api/v1/firmware/download`, `POST /api/v1/firmware/upload`.
Operators stage firmware via upload; nodes fetch updates without any Operators stage firmware via upload; nodes fetch updates without any
push-side connectivity to individual node IPs. See `docs/adr/ADR-094-pull-based-ota.md`. push-side connectivity to individual node IPs. See `docs/adr/ADR-095-pull-based-ota.md`.
- **`nvsim` crate — deterministic NV-diamond magnetometer pipeline simulator** (ADR-089) — - **`nvsim` crate — deterministic NV-diamond magnetometer pipeline simulator** (ADR-089) —
New standalone leaf crate at `v2/crates/nvsim` modeling a forward-only New standalone leaf crate at `v2/crates/nvsim` modeling a forward-only

View File

@ -1,4 +1,4 @@
# ADR-094: Pull-based OTA Firmware Update # ADR-095: Pull-based OTA Firmware Update
## Status ## Status

View File

@ -50,7 +50,7 @@ wifi-densepose-wifiscan = { version = "0.3.0", path = "../wifi-densepose-wifisca
# build without vcpkg/openblas (issue #366, #415). # build without vcpkg/openblas (issue #366, #415).
wifi-densepose-signal = { version = "0.3.0", path = "../wifi-densepose-signal", default-features = false } wifi-densepose-signal = { version = "0.3.0", path = "../wifi-densepose-signal", default-features = false }
# SHA-256 for firmware registry integrity verification (pull-based OTA, ADR-094) # SHA-256 for firmware registry integrity verification (pull-based OTA, ADR-095)
sha2 = { workspace = true } sha2 = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }

View File

@ -169,7 +169,7 @@ struct Args {
#[arg(long)] #[arg(long)]
calibrate: bool, calibrate: bool,
/// Directory holding ESP32 firmware binaries for pull-based OTA (ADR-094). /// Directory holding ESP32 firmware binaries for pull-based OTA (ADR-095).
/// On startup, the newest `.bin` file in this directory is registered /// On startup, the newest `.bin` file in this directory is registered
/// as the current firmware. Operators upload new versions via /// as the current firmware. Operators upload new versions via
/// `POST /api/v1/firmware/upload`. /// `POST /api/v1/firmware/upload`.
@ -651,7 +651,7 @@ struct AppStateInner {
multistatic_fuser: MultistaticFuser, multistatic_fuser: MultistaticFuser,
/// SVD-based room field model for eigenvalue person counting (None until calibration). /// SVD-based room field model for eigenvalue person counting (None until calibration).
field_model: Option<FieldModel>, field_model: Option<FieldModel>,
// ── Firmware registry (pull-based OTA, ADR-094) ────────────────────── // ── Firmware registry (pull-based OTA, ADR-095) ──────────────────────
/// In-memory registry of the currently-blessed ESP32 firmware binary. /// In-memory registry of the currently-blessed ESP32 firmware binary.
/// Nodes poll `GET /api/v1/firmware/latest` to learn the current version /// Nodes poll `GET /api/v1/firmware/latest` to learn the current version
/// and download it via `GET /api/v1/firmware/download`. Operators upload /// and download it via `GET /api/v1/firmware/download`. Operators upload
@ -3462,7 +3462,7 @@ async fn calibration_status(State(state): State<SharedState>) -> Json<serde_json
} }
} }
// ── Firmware Registry Endpoints (pull-based OTA, ADR-094) ──────────────────── // ── Firmware Registry Endpoints (pull-based OTA, ADR-095) ────────────────────
/// Scan a firmware directory and return the newest .bin file by mtime. /// Scan a firmware directory and return the newest .bin file by mtime.
/// Returns `Ok(None)` if the directory exists but contains no .bin files. /// Returns `Ok(None)` if the directory exists but contains no .bin files.
@ -5046,7 +5046,7 @@ async fn main() {
} else { } else {
None None
}, },
// Firmware registry (pull-based OTA, ADR-094) — seeded from disk below. // Firmware registry (pull-based OTA, ADR-095) — seeded from disk below.
firmware_registry: Arc::new(tokio::sync::RwLock::new(FirmwareRegistry::new())), firmware_registry: Arc::new(tokio::sync::RwLock::new(FirmwareRegistry::new())),
firmware_dir: args.firmware_dir.clone(), firmware_dir: args.firmware_dir.clone(),
})); }));
@ -5173,7 +5173,7 @@ async fn main() {
.route("/api/v1/calibration/start", post(calibration_start)) .route("/api/v1/calibration/start", post(calibration_start))
.route("/api/v1/calibration/stop", post(calibration_stop)) .route("/api/v1/calibration/stop", post(calibration_stop))
.route("/api/v1/calibration/status", get(calibration_status)) .route("/api/v1/calibration/status", get(calibration_status))
// Firmware registry / pull-based OTA (ADR-094) // Firmware registry / pull-based OTA (ADR-095)
.route("/api/v1/firmware/latest", get(firmware_latest_endpoint)) .route("/api/v1/firmware/latest", get(firmware_latest_endpoint))
.route("/api/v1/firmware/download", get(firmware_download_endpoint)) .route("/api/v1/firmware/download", get(firmware_download_endpoint))
.route("/api/v1/firmware/upload", post(firmware_upload_endpoint)) .route("/api/v1/firmware/upload", post(firmware_upload_endpoint))