Adds payload_commitment / metadata_commitment / verify_payload_commitment
and assert_commitment_safe_numbers to the Python, TypeScript, and Go SDKs,
each building on the frozen canonical_json/domain_hash primitives (no change
to their byte output). The number preflight is a byte-for-byte port of the
backend assert_commitment_safe_numbers (floats rejected, |int| > 2^53-1
rejected, bool exempt) and is wired into the v2 log_event / log_events send
path, raising a typed AttestoUnsafeNumberError with the JSON path so the rule
fails at dev time rather than as a production 422; preflight=False /
SkipPreflight defers to the server.
New shared corpus golden-vectors/sdk-parity/canonical-numbers.json (15 accept
+ 8 reject), accept-hashes generated from the backend _commitment. Proven:
Python = TypeScript = Go = backend produce byte-identical commitment hashes
for every accept vector and identical reject paths (the Go float64-vs-Python-
int serialization parity holds). READMEs updated per SDK.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FIX 11 — reject cross-language-divergent numbers in committed payloads.
append_stream_event now rejects non-integer numbers and integers beyond
±(2^53−1) in payload/metadata at ingestion (HTTP 422), so a customer
recomputing a commitment in a Go/TS verifier can never read it as
tampering. Documented in the protocol spec + all three SDK READMEs; 9
tests.
FIX 12 — Nova IVC chain-continuity invariant. record_ivc_epoch now takes
a per-stream transaction-scoped advisory lock and fails closed (409) if
an epoch does not extend the latest verified epoch's next_state_root or
would skip an unproven checkpoint — so two concurrent provers cannot fork
Attesto's own lane and a failed proof cannot be chained over. The worker
stops the pass on a failed proof (break, not continue) and always
backfills the oldest unproven checkpoint first so holes heal. Tests cover
both 409 paths plus in-order record + replay.
FIX 13 — pin the e2e v1 checkpoint shape. Config now requires
PROOFSTREAM_WINDOW_MAX_EVENTS=1 (alongside CHECKPOINT_MAX_WINDOWS=4) when
Nova is enabled, and the worker refuses to close an aged checkpoint below
the 4-window shape (which would be unprovable). Documented as the
deliberate fail-closed v1 behavior; config + worker tests.
VERIFY-1 — investigation: the standard production ingestion path
(SDK → append_stream_event → persist_stream_event_receipt) does NOT write
the nova_e2e boundary metadata the prover requires; no writer exists in
backend/app, and _e2e_vector_for_checkpoint requires (not derives) it. So
Nova proofs currently cover golden-vector/harness inputs, not live
customer receipts — the open Route A/B item. Recorded in
CRYPTO_REVIEW_CHECKLIST as a coverage-scope note; no Route A/B
implementation in this release.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>