Automated release from CI pipeline
Changes:
cog-ha-matter (ADR-116 P4): witness JSONL persistence
Third P4 sub-unit: serialize/parse for the witness hash chain so
audit bundles can be written to disk and replayed.
Wire shape (one record per line, alphabetical field order locked):
{"kind":"...","payload_hex":"...","prev_hash":"...","seq":N,
"this_hash":"...","timestamp_unix_s":N}
Why alphabetical field order: auditors archive whole bundles and
hash them. A rebuild that reordered fields would silently
invalidate every archival hash — locking the order is what makes
the JSONL stable across compiler / serde-json upgrades.
Why hex everywhere: human-greppable, monospace-friendly, no base64
ambiguity, no Vec JSON-array ugliness. Same convention as
ADR-101's binary_sha256.
Critically, from_jsonl_line RE-VERIFIES this_hash against
the canonical bytes derived from the parsed fields. A tampered
bundle fires WitnessParseError::HashMismatch BEFORE the event
loads — the parser is itself an auditor.
New surfaces:
WitnessHash::from_hex(with structured length/parse errors)WitnessEvent::to_jsonl_line,from_jsonl_lineWitnessParseErrorenum: Json | MissingField | WrongType |
HashLength | HashHex | PayloadHex | PayloadLength | HashMismatch- private
hex_encode/hex_decodehelpers (nohexcrate dep)
10 new tests:
- jsonl round-trip preserves all fields
- jsonl line has no embedded \n / \r (one record per line)
- jsonl field order is alphabetical (byte-stable archival)
- parser rejects tampered payload via HashMismatch
- parser rejects non-hex characters in hash
- parser rejects missing field
- hex encode/decode round-trip across empty / single byte / 0xff /
UTF-8 / arbitrary bytes - hex decode rejects odd-length input
- WitnessHash::from_hex round-trip
- WitnessHash::from_hex rejects wrong length
44/44 cog tests green (34 → 44).
ADR-116 P4 row enumerates 4 sub-units now: ✅ mDNS record-builder,
✅ witness chain primitive, ✅ witness JSONL persistence,
⏳ responder + embedded broker + Ed25519 signing.
Co-Authored-By: claude-flow ruv@ruv.net
Docker Image:
ghcr.io/ruvnet/RuView:a3478ea3b50b5a1550dbd8234a575e2978e00183