100 lines
3.7 KiB
Rust
100 lines
3.7 KiB
Rust
//! Cog manifest — same shape as `cog-pose-estimation/cog/manifest.template.json`
|
|
//! per ADR-101 / ADR-102 / ADR-116. Generated at build time by the cog's
|
|
//! Makefile, signed by the project's Ed25519 release key, uploaded to
|
|
//! `gs://cognitum-apps/cogs/<arch>/cog-ha-matter-<arch>` for Seeds to fetch
|
|
//! via `app-registry.json`.
|
|
//!
|
|
//! The runtime ships the typed view here so the cog can self-report its
|
|
//! manifest to the Seed's control plane (`/api/v1/cog/status`).
|
|
//!
|
|
//! Kept in lib.rs's nearest sibling module so manifest format drift between
|
|
//! build-time template and runtime serializer fires a named test.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// Wire-format mirror of `cog/manifest.template.json`.
|
|
///
|
|
/// Every field is required at install time; `binary_signature` is the
|
|
/// Ed25519 sig over `binary_sha256` so the Seed can verify the cog
|
|
/// binary wasn't tampered with between GCS and the device.
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct CogManifest {
|
|
/// Stable cog identifier ("ha-matter"). Becomes the directory name
|
|
/// under `/var/lib/cognitum/apps/<id>/` on the Seed.
|
|
pub id: String,
|
|
/// SemVer of the cog binary. Bumped by the Makefile from
|
|
/// `cargo pkgid` at release time.
|
|
pub version: String,
|
|
/// Where the Seed fetches the binary from. Arch-specific URL with
|
|
/// the `{{ARCH}}` template slot filled in (e.g. `arm`, `x86_64`).
|
|
pub binary_url: String,
|
|
/// Bytes of the binary blob. Set at build time after `wc -c`.
|
|
pub binary_bytes: u64,
|
|
/// SHA-256 of the binary, hex-lowercase, no `0x` prefix. The Seed
|
|
/// verifies this before exec().
|
|
pub binary_sha256: String,
|
|
/// Ed25519 signature over `binary_sha256`, base64-encoded. Optional
|
|
/// for unsigned dev builds; required for cogs listed in
|
|
/// `app-registry.json`.
|
|
pub binary_signature: String,
|
|
/// Unix epoch seconds at install time. The Seed stamps this when it
|
|
/// completes a successful install/upgrade.
|
|
pub installed_at: u64,
|
|
/// One of `"installed"`, `"upgrading"`, `"degraded"`, `"removed"`.
|
|
pub status: String,
|
|
}
|
|
|
|
impl CogManifest {
|
|
pub fn id() -> &'static str {
|
|
super::COG_ID
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
/// Lock the JSON wire shape against accidental field renames. Both
|
|
/// the Seed's control plane and the build-time signer parse this —
|
|
/// any drift fires a named test instead of silently breaking ops.
|
|
#[test]
|
|
fn manifest_round_trip_matches_template() {
|
|
let m = CogManifest {
|
|
id: "ha-matter".into(),
|
|
version: "0.1.0".into(),
|
|
binary_url:
|
|
"https://storage.googleapis.com/cognitum-apps/cogs/arm/cog-ha-matter-arm"
|
|
.into(),
|
|
binary_bytes: 4_200_000,
|
|
binary_sha256:
|
|
"a".repeat(64),
|
|
binary_signature: "Zm9v".into(),
|
|
installed_at: 1_779_512_400,
|
|
status: "installed".into(),
|
|
};
|
|
let json = serde_json::to_value(&m).unwrap();
|
|
// Eight required fields, no extras.
|
|
for key in [
|
|
"id",
|
|
"version",
|
|
"binary_url",
|
|
"binary_bytes",
|
|
"binary_sha256",
|
|
"binary_signature",
|
|
"installed_at",
|
|
"status",
|
|
] {
|
|
assert!(json.get(key).is_some(), "missing manifest field `{key}`");
|
|
}
|
|
let m2: CogManifest = serde_json::from_value(json).unwrap();
|
|
assert_eq!(m, m2);
|
|
}
|
|
|
|
#[test]
|
|
fn manifest_id_constant_matches_cog_id() {
|
|
// The id helper must agree with the crate-level COG_ID constant
|
|
// (regression guard for a future rename).
|
|
assert_eq!(CogManifest::id(), super::super::COG_ID);
|
|
}
|
|
}
|