Expand description
On-disk wire shape for a JSONL row that participates in the Ed25519 signature chain (T-3.D.6, ADR 0010 §1-§2).
A SignedRow is the canonical envelope written one-per-line to
events.jsonl. It flattens the existing cortex_core::Event fields
at the top level (so legacy tools that parse Event-shaped rows still
see every field they expect) and adds one new field, signature,
carrying the Ed25519 RowSignature over the row’s canonical
attestation preimage.
§Why a wrapper instead of a new field on Event
Event lives in cortex-core and is part of the BUILD_SPEC §9.1
wire-shape contract. Extending it would ripple through every consumer
crate. The wrapper keeps the change local to cortex-ledger: we own
the persistence layer, so we own the on-disk envelope.
§Backward compatibility on read
signature is Option<RowSignature>; an old row that pre-dates this
lane (no signature field on disk) deserializes with signature: None.
That is NOT a silent pass — the audit verifier flags it as
crate::audit::FailureReason::MissingSignature (per ADR 0010 §1
“Single asymmetric trust domain”: rows without a valid Ed25519
signature do not verify; there is no symmetric-MAC fallback). A
one-shot resign of any pre-3.D.6 fixture is required and documented
in scripts/resign-jsonl.sh.
§Wire shape (illustrative — exact bytes are normative in code)
{
"id": "evt_…",
"schema_version": 1,
"observed_at": "2026-05-03T12:00:00.000000Z",
"recorded_at": "2026-05-03T12:00:00.100000Z",
"source": { "type": "user" },
"event_type": "cortex.event.user_message.v1",
"trace_id": null,
"session_id": "s-001",
"domain_tags": [],
"payload": { "text": "hello" },
"payload_hash": "…",
"prev_event_hash": null,
"event_hash": "…",
"signature": {
"schema_version": 1,
"key_id": "fp:abc…",
"signed_at": "2026-05-03T12:00:00.000000Z",
"bytes": "<base64 64-byte ed25519 signature>"
}
}Structs§
- RowSignature
- Per-row Ed25519 signature persisted alongside the
Eventfields. - Signed
Row - On-disk envelope for one JSONL row.
Functions§
- b64_
decode - Decode URL-safe base64 (no padding). Returns
Noneon any invalid byte or truncated final group; the verifier treats that ascrate::audit::FailureReason::BadSignature. - b64_
encode - Encode bytes as URL-safe base64 (no padding). Local helper so the crate
does not pull in the
base64crate for one signature field.