diff --git a/v2/crates/cog-ha-matter/cog/Makefile b/v2/crates/cog-ha-matter/cog/Makefile new file mode 100644 index 00000000..7454b995 --- /dev/null +++ b/v2/crates/cog-ha-matter/cog/Makefile @@ -0,0 +1,83 @@ +# Build / sign / upload pipeline for cog-ha-matter. +# See ADR-100 §"Build pipeline" + ADR-116 §"Phases" for the contract. +# Mirrors cog-pose-estimation/cog/Makefile so the Seed runtime treats +# both cogs identically — `cognitum cog install ha-matter` works the +# same as `cognitum cog install pose-estimation`. + +CRATE := cog-ha-matter +VERSION := $(shell cargo pkgid -p $(CRATE) 2>/dev/null | sed -E 's/.*#([0-9.]+).*/\1/') +GCS_BUCKET := gs://cognitum-apps/cogs + +ARCHES := arm x86_64 + +# --- Build targets --- + +.PHONY: build build-arm build-x86_64 + +build: build-arm build-x86_64 + +build-arm: + mkdir -p dist + cargo build -p $(CRATE) --release --target aarch64-unknown-linux-gnu + cp ../../target/aarch64-unknown-linux-gnu/release/$(CRATE) ./dist/cog-$(CRATE)-arm + +build-x86_64: + mkdir -p dist + cargo build -p $(CRATE) --release --target x86_64-unknown-linux-gnu + cp ../../target/x86_64-unknown-linux-gnu/release/$(CRATE) ./dist/cog-$(CRATE)-x86_64 + +# --- Sign --- + +.PHONY: sign sign-arm sign-x86_64 + +sign: sign-arm sign-x86_64 + +sign-arm: dist/cog-$(CRATE)-arm + sha256sum dist/cog-$(CRATE)-arm | cut -d' ' -f1 > dist/cog-$(CRATE)-arm.sha256 + # Signature: gcloud secrets versions access latest --secret=COGNITUM_OWNER_SIGNING_KEY \ + # | openssl pkeyutl -sign -inkey /dev/stdin -rawin -in dist/cog-$(CRATE)-arm.sha256 \ + # | base64 -w0 > dist/cog-$(CRATE)-arm.sig + @echo "TODO: wire Ed25519 sign step once COGNITUM_OWNER_SIGNING_KEY is provisioned to CI." + +sign-x86_64: dist/cog-$(CRATE)-x86_64 + sha256sum dist/cog-$(CRATE)-x86_64 | cut -d' ' -f1 > dist/cog-$(CRATE)-x86_64.sha256 + @echo "TODO: wire Ed25519 sign step once COGNITUM_OWNER_SIGNING_KEY is provisioned to CI." + +# --- Upload to GCS --- + +.PHONY: upload upload-arm upload-x86_64 + +upload: upload-arm upload-x86_64 + +upload-arm: dist/cog-$(CRATE)-arm + gsutil cp dist/cog-$(CRATE)-arm $(GCS_BUCKET)/arm/cog-$(CRATE)-arm + +upload-x86_64: dist/cog-$(CRATE)-x86_64 + gsutil cp dist/cog-$(CRATE)-x86_64 $(GCS_BUCKET)/x86_64/cog-$(CRATE)-x86_64 + +# --- Manifest --- + +.PHONY: manifest + +manifest: + @cargo run -p $(CRATE) --release -- --print-manifest + +# --- Convenience --- + +.PHONY: release verify clean + +release: build sign upload manifest + @echo "Release pipeline complete for cog-$(CRATE) v$(VERSION)" + +verify: + @for arch in $(ARCHES); do \ + f=dist/cog-$(CRATE)-$$arch; \ + if [ ! -f $$f ]; then echo " MISSING $$f"; continue; fi; \ + actual=$$(sha256sum $$f | cut -d' ' -f1); \ + expected=$$(cat $$f.sha256 2>/dev/null); \ + if [ "$$actual" = "$$expected" ]; then echo " OK $$f ($$actual)"; \ + else echo " FAIL $$f (expected $$expected, got $$actual)"; fi; \ + done + +clean: + rm -rf dist/cog-$(CRATE)-* diff --git a/v2/crates/cog-ha-matter/cog/README.md b/v2/crates/cog-ha-matter/cog/README.md new file mode 100644 index 00000000..cc353896 --- /dev/null +++ b/v2/crates/cog-ha-matter/cog/README.md @@ -0,0 +1,71 @@ +# HA-Matter Cog Packaging + +Build / sign / upload pipeline for `cog-ha-matter`, mirroring the +[`cog-pose-estimation`](../../cog-pose-estimation/cog/) precedent so the +Seed runtime treats both cogs identically. + +See [ADR-100 — Cog Packaging Specification](../../../../docs/adr/ADR-100-cog-packaging-specification.md) +and [ADR-116 — HA-Matter Seed Cog](../../../../docs/adr/ADR-116-cog-ha-matter-seed.md). + +## What this cog does + +Wraps the ADR-115 HA-DISCO + HA-MIND MQTT publisher as a Seed-installable +artifact with: + +- mDNS auto-discovery (`_ruview-ha._tcp`) +- Ed25519-signed witness chain for tamper-evident audit logs +- Privacy-mode flag (only semantic primitives, no biometrics) +- One-flag deferral to v0.7 for the embedded broker / v0.8 for the Matter Bridge + +## Layout + +| File | Purpose | +|---|---| +| `manifest.template.json` | Build-time manifest with `{{VERSION}}` / `{{ARCH}}` slots; `make manifest` substitutes them | +| `Makefile` | `build` / `sign` / `upload` / `release` / `verify` / `clean` targets | +| `dist/` | Created by `make build`; gitignored, holds release binaries + sha256 + sig | + +## Local build (dry-run) + +```sh +cd v2/crates/cog-ha-matter/cog +make build # builds aarch64 + x86_64 release binaries +make sign # writes .sha256 + (TODO) .sig sidecars +make manifest # prints the manifest the Seed would record +``` + +`make sign` is currently a no-op for the signature itself — the +`COGNITUM_OWNER_SIGNING_KEY` provisioning is the same TODO that +blocks [`cog-pose-estimation`](../../cog-pose-estimation/cog/Makefile). +Until then, dev cogs ship unsigned and `app-registry.json` lists +them with `"binary_signature": ""`. + +## Upload (requires `gcloud auth`) + +```sh +gcloud auth login +make upload # gsutil cp dist/* gs://cognitum-apps/cogs/{arch}/ +``` + +The GCS bucket is shared with `cog-pose-estimation` and is part of +the `cognitum-apps` project. Write access requires membership in the +`cog-publishers` IAM group. + +## app-registry.json + +Lives in the [`cognitum-one`](https://github.com/ruvnet/cognitum-one) +repo, **not here**. After `make upload` succeeds, file a PR there +that appends: + +```json +{ + "id": "ha-matter", + "version": "", + "binary_url": "https://storage.googleapis.com/cognitum-apps/cogs/{arch}/cog-ha-matter-{arch}", + "binary_sha256": "", + "binary_signature": "", + "description": "Home Assistant + Matter Cognitum Seed cog (mDNS + witness chain)", + "min_seed_version": "0.6.0", + "installable_on": ["arm", "x86_64"] +} +``` diff --git a/v2/crates/cog-ha-matter/cog/manifest.template.json b/v2/crates/cog-ha-matter/cog/manifest.template.json new file mode 100644 index 00000000..aa3e8bd2 --- /dev/null +++ b/v2/crates/cog-ha-matter/cog/manifest.template.json @@ -0,0 +1,10 @@ +{ + "id": "ha-matter", + "version": "{{VERSION}}", + "binary_url": "https://storage.googleapis.com/cognitum-apps/cogs/{{ARCH}}/cog-ha-matter-{{ARCH}}", + "binary_bytes": 0, + "binary_sha256": "", + "binary_signature": "", + "installed_at": 0, + "status": "installed" +}