From 6b5fd3cf253a79fa306f4568808a15706e753a75 Mon Sep 17 00:00:00 2001 From: ruv Date: Thu, 11 Jun 2026 23:10:01 -0400 Subject: [PATCH] fix(cog-person-count): emit real signed manifest from CLI (ADR-159 A4) cmd_manifest emitted a null skeleton (binary_sha256: null) while the real signed manifest existed on disk at cog/artifacts/manifests//manifest.json. - New manifest module include_str!-embeds the real signed manifests (x86_64 + arm), selected by build target arch. - cmd_manifest parses-then-emits the embedded signed manifest, mirroring cog-pose-estimation manifest_roundtrips. CLI now reports the real binary_sha256, weights_sha256, Ed25519 signature, and honest build_metadata (training_class1_accuracy = 0.343). Failing-on-old test: manifest::tests::embedded_manifest_has_non_null_binary_sha256 (+ embedded_manifest_is_signed, embedded_manifest_id_matches_cog). Verified end-to-end: cog-person-count manifest -> non-null sha256. Co-Authored-By: claude-flow --- v2/crates/cog-person-count/src/lib.rs | 1 + v2/crates/cog-person-count/src/main.rs | 19 ++---- v2/crates/cog-person-count/src/manifest.rs | 77 ++++++++++++++++++++++ 3 files changed, 83 insertions(+), 14 deletions(-) create mode 100644 v2/crates/cog-person-count/src/manifest.rs diff --git a/v2/crates/cog-person-count/src/lib.rs b/v2/crates/cog-person-count/src/lib.rs index 168696cc..375773d3 100644 --- a/v2/crates/cog-person-count/src/lib.rs +++ b/v2/crates/cog-person-count/src/lib.rs @@ -9,6 +9,7 @@ pub mod fusion; pub mod inference; +pub mod manifest; pub mod publisher; pub mod runtime; diff --git a/v2/crates/cog-person-count/src/main.rs b/v2/crates/cog-person-count/src/main.rs index e5697440..5ff76046 100644 --- a/v2/crates/cog-person-count/src/main.rs +++ b/v2/crates/cog-person-count/src/main.rs @@ -12,7 +12,6 @@ use cog_person_count::{ publisher, COG_ID, COG_VERSION, }; use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; use std::path::PathBuf; #[derive(Parser)] @@ -83,19 +82,11 @@ fn cmd_version() -> Result<(), Box> { } fn cmd_manifest() -> Result<(), Box> { - println!( - "{}", - serde_json::to_string_pretty(&json!({ - "id": COG_ID, - "version": COG_VERSION, - "binary_url": Value::Null, - "binary_bytes": Value::Null, - "binary_sha256": Value::Null, - "binary_signature": Value::Null, - "installed_at": Value::Null, - "status": Value::Null, - }))? - ); + // Emit the real, signed manifest embedded at compile time (ADR-159 §A4) — + // not the old hollow null skeleton. Parse-then-emit so a malformed embedded + // artifact fails loudly and the output is canonical JSON. + let spec = cog_person_count::manifest::embedded_manifest_value()?; + println!("{}", serde_json::to_string_pretty(&spec)?); Ok(()) } diff --git a/v2/crates/cog-person-count/src/manifest.rs b/v2/crates/cog-person-count/src/manifest.rs new file mode 100644 index 00000000..2f7a28f8 --- /dev/null +++ b/v2/crates/cog-person-count/src/manifest.rs @@ -0,0 +1,77 @@ +//! Embedded signed cog manifest (ADR-100 §"manifest.json", ADR-159 §A4). +//! +//! The `cog-person-count manifest` subcommand emits the **real, signed** +//! manifest the release pipeline produced — byte-for-byte the artifact served +//! from GCS, with a real `binary_sha256`, `weights_sha256`, Ed25519 +//! `binary_signature`, and honest `build_metadata` (e.g. `training_class1_accuracy +//! = 0.343`, not inflated). The previous implementation printed a hollow +//! skeleton with `binary_sha256: null`, which made the CLI look unsigned even +//! though the signed manifest existed on disk. +//! +//! The matching manifest for the build's target arch is selected via `cfg!`. + +/// Real signed manifest for `x86_64-unknown-linux-gnu`. +pub const MANIFEST_X86_64: &str = + include_str!("../cog/artifacts/manifests/x86_64/manifest.json"); + +/// Real signed manifest for `aarch64`/`arm` (the Seed appliance). +pub const MANIFEST_ARM: &str = include_str!("../cog/artifacts/manifests/arm/manifest.json"); + +/// The embedded signed manifest matching the build's target arch. +pub fn embedded_manifest_str() -> &'static str { + if cfg!(any(target_arch = "aarch64", target_arch = "arm")) { + MANIFEST_ARM + } else { + MANIFEST_X86_64 + } +} + +/// Parse the embedded manifest into canonical JSON. Returns an error if the +/// embedded artifact is malformed (so the CLI fails loudly rather than printing +/// garbage). +pub fn embedded_manifest_value() -> Result { + serde_json::from_str(embedded_manifest_str()) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// ADR-159 §A4 — the embedded manifest the CLI emits must carry a real + /// `binary_sha256` (the field the old hollow `cmd_manifest` left null). + #[test] + fn embedded_manifest_has_non_null_binary_sha256() { + let v = embedded_manifest_value().expect("embedded manifest parses"); + let sha = v.get("binary_sha256").and_then(|s| s.as_str()); + assert!( + sha.is_some(), + "embedded manifest must have a non-null binary_sha256 (got {:?})", + v.get("binary_sha256") + ); + let sha = sha.unwrap(); + assert_eq!(sha.len(), 64, "binary_sha256 must be a 32-byte hex digest"); + assert!( + sha.chars().all(|c| c.is_ascii_hexdigit()), + "binary_sha256 must be hex" + ); + } + + #[test] + fn embedded_manifest_is_signed() { + let v = embedded_manifest_value().expect("parse"); + assert!( + v.get("binary_signature").and_then(|s| s.as_str()).is_some(), + "embedded manifest must carry an Ed25519 binary_signature" + ); + assert_eq!( + v.get("sig_algo").and_then(|s| s.as_str()), + Some("Ed25519") + ); + } + + #[test] + fn embedded_manifest_id_matches_cog() { + let v = embedded_manifest_value().expect("parse"); + assert_eq!(v.get("id").and_then(|s| s.as_str()), Some(crate::COG_ID)); + } +}