# M-P1A witness-to-daemon delivery report Date: 2026-07-13 Status: implemented. The cloud-witness flag remains default OFF, and daemon acceptance remains behind the existing default-OFF `CORECRUXD_STREAM_RECEIPTS=1` gate. ## A1 — daemon routing, verification, and persistence `post_mediation_receipt` now recognizes a nested cloud-witness envelope before the existing top-level `kind` dispatch. The discriminator is an object with a `witness` object and a `record` object whose `schema` is `cuecrux.mediation.witness.v1`. With stream receipts disabled, the envelope still reaches the legacy parser and is rejected as before. `handle_witness_receipt` uses the same `require_session_write_ctx` posture as stream receipt drafts. It performs one strict Ed25519 verification against the envelope's raw 32-byte public key, validates standard padded Base64 and exact key/signature lengths, and checks that `kid` equals `wit_` plus the first 16 lowercase hexadecimal characters of SHA-256 over the Ed25519 RFC 8410 SPKI DER public key. Invalid signatures return a 400 problem detail with `witness_signature_invalid`; malformed records or key/KID mismatches return `witness_envelope_invalid`. Neither path persists. An internal canonicalization or key-encoding error returns 503 `witness_verification_unavailable`, also without persistence; the non-2xx response causes the shim to use its durable JSONL fallback instead of treating an unpersisted record as delivered. After verification, a deny-unknown-fields wire type constrains the retained record to the metadata-only witness-v1 fields. Provider/path, digest form, bounded model/tool/session/response metadata, and numeric token-only usage are validated. This prevents a signed extension carrying prompt or response content from entering the observation payload. Valid `cloud_request_witnessed` and `cloud_response_witnessed` records are persisted through `append_one`, the signed-observation path used by stream receipts. That produces the chained observation JSONL source of truth, a daemon CROWN Ed25519 signature, and the existing best-effort dataplane observation stream. The exact signed metadata-only `record`, its witness proof, derived `kid`, and `witness_verified: true` are retained. The response is 201 and mirrors the stream receipt response with `receipt_id`, `kind`, `body_hash`, `signature_hex`, `observation_id`, `signed_by`, and `witness_kid`. Request and response records are grouped under `mediation::witness::`, because witness-v1 responses do not carry the request's self-asserted `session_hint`. Incident reconstruction consumes the resulting source-of-truth records through `read_all_observations`; the entity projection receives the existing best-effort dataplane write when that dataplane is configured. ## Server-side canonicalization The signature input exactly matches `crux_claude_hooks::llm_shim::witness::canonical_json_bytes`: 1. Recursively sort every JSON object by Rust `String` ordering of its keys. 2. Preserve array order. 3. Leave strings, numbers, booleans, and null unchanged. 4. Compact-serialize the resulting `serde_json::Value` with `serde_json::to_vec`. 5. Verify the Ed25519 signature directly over those bytes with `VerifyingKey::verify_strict`. This is the witness-v1 sorted-key encoding; it is not claimed to be RFC 8785 JCS. ## A2 — delivery test and assurance documentation `signed_witness_pair_is_delivered_to_daemon_with_auth_without_spool_fallback` constructs `CloudWitnessConfig` with `daemon_receipts=true`, drives the real cloud-witness request/response flow, and uses a two-request daemon stub. It asserts the mediation route, Bearer authentication, nested schema, linked request/response kinds, persisted-key signature verification, and no local spool fallback after two successful daemon responses. The existing helper continues to use `daemon_receipts=false`, so default behavior is unchanged. Daemon-side tests exercise the actual handler and signed store: a valid pair returns 201 and appears through the same aggregate observation read helper used by incidents; an altered record, a signature made by a key different from the claimed public key, and a self-consistent re-sign whose KID is replaced with an existing key's KID are all rejected with no records appended. The cloud-model-call row in `docs/assurance-coverage-matrix.md` and the delivery section in `docs/llm-shim.md` now describe verified daemon delivery, signed observation/incident visibility, configured-only dataplane projection, and spool fallback. They retain the same-UID custody, unauthenticated session hint, no-replay, and no independent key-enrolment/pinning limitations. ## Tests New daemon tests, all passing in the real worktree as part of the 41-test `http::observations::tests::` slice: - `canonical_witness_json_matches_shim_signing_bytes` - `nested_witness_shape_is_recognized_without_top_level_kind` - `valid_witness_pair_routes_verifies_and_persists_for_incidents` - `altered_witness_record_is_rejected_without_persisting` - `wrong_key_witness_signature_is_rejected_without_persisting` - `wrong_key_resign_for_existing_kid_is_rejected_without_persisting` - `signed_content_bearing_extension_is_rejected_without_persisting` - `witness_envelope_is_inert_when_stream_receipts_are_disabled` - `witness_envelope_requires_the_existing_session_write_auth` Regression tests passing: - `post_mediation_receipt_happy_path_records_attributed_receipt` - `mediation_route_lifts_drafts_when_flag_on_and_rejects_when_off` - `usage_route_lifts_when_flag_on_and_rejects_when_off` New hook delivery test: - `signed_witness_pair_is_delivered_to_daemon_with_auth_without_spool_fallback` compiles, but cannot execute in this sandbox: its first loopback stub bind is rejected with `PermissionDenied` (`Operation not permitted`). It is structured as a live listener test for the orchestrator to rerun outside the bind-restricted sandbox. Quality-gate results: - `cargo fmt --all -- --check`: pass. - `cargo clippy --workspace --locked --offline -- -D warnings`: pass. - `cargo doc --no-deps -p corecruxd -p crux-claude-hooks --locked --offline`: pass. - `bash scripts/build-llms-full.sh --check`: pass. - CCL header check for touched Rust files: pass. - `cargo test -p corecruxd -p crux-claude-hooks --locked --offline`: `corecruxd` completed with 1,878 passed, 20 failed, and 2 ignored. Every failure was an existing test's loopback bind rejected with `PermissionDenied`; Cargo stopped after the failed package before running `crux-claude-hooks`. - `cargo test -p crux-claude-hooks --locked --offline`: 151 passed and one existing loopback-bind test failed with `PermissionDenied`; Cargo stopped before integration tests. - `cargo test -p corecruxd --locked --offline http::observations::tests::`: 41 passed, 0 failed. - `cargo test -p corecruxd --locked --offline route_lifts`: 2 passed, 0 failed. ## Deferred / unchanged limits - No witness key registry, enrolment, or daemon-side expected-key pinning was added. Verification proves integrity under the envelope's embedded key and KID derivation. A wholesale, self-consistent replacement of key, KID, record, and signature by a caller already holding daemon write authorization still requires separate identity pinning to detect. - No nonce, sequence, freshness window, deduplication, or replay protection was added. - The witness key remains readable to a same-UID compromise, and the request session hint remains caller-supplied rather than authenticated. - Observation JSONL is the authoritative incident input. Entity-timeline projection remains best effort and depends on a configured dataplane.