A trimmed (~1.7 KB) copy of the cross-language parity vectors now ships inside
each package (Python package-data JSON, Go go:embed, TS generated module). On
the first hashing operation per process each SDK recomputes the commitment
hash, the receipt domain-hash, and an inclusion fold against the vendored
vectors and fails closed (AttestoSelfTestError / ErrSelfTest) on any mismatch
— a corrupted install or diverging runtime can never silently produce wrong
evidence. Result is cached (including failure); cost <5 ms once. Corrupting a
vendored vector is test-asserted to fail closed in all three languages. The
frozen canonical primitives are untouched; the gate lives in the commitment/
verify entry points built on top of them.
attesto doctor: Go CLI subcommand and Python attesto.doctor(), producing a
deterministic {"ok", "checks"} report — vendored self-test, head-store
writability, number-policy dry-run on a sample payload, Ed25519 availability
(Python), and with credentials: reachability, protocol-header acceptance, and
clock skew vs the server Date header (warn >30 s; webhooks break at 300 s).
package_artifact_policy allows exactly attesto/_selftest_vectors.json in the
wheel (verified: built wheel contains it, policy green). READMEs updated.
This completes the last Phase-1 build item.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Completes the offline verification stack (P1.2 -> P1.1 -> P1.3) in all three
SDKs, each a faithful port of the backend windows.py / checkpoints.py math on
top of the frozen canonical/domain-hash primitives:
- verify_inclusion_proof: fold a window inclusion proof to the window root
(domain attesto.v2.window; left sibling -> node(sibling,current), right ->
node(current,sibling)).
- verify_checkpoint_root: recompute a checkpoint root from window hashes
(domain attesto.v2.checkpoint), with an odd node at any level **promoted
unchanged** rather than duplicated/hashed with itself (the place a naive
Merkle port silently diverges).
- verify_checkpoint_extension: current.from_seq_no == previous.to_seq_no + 1
and current.previous_checkpoint_hash == previous.checkpoint_hash.
- verify_completeness: proves no events were omitted in a range -- gap-free
seq_no coverage plus prev_event_hash chaining to the previous event_hash.
New corpus golden-vectors/sdk-parity/inclusion.json (5-leaf window exercising
the promoted odd node, 3-window checkpoint root, extension + completeness
negatives), exported from the backend functions. Proven: Python = TypeScript =
Go = backend agree on every case. READMEs updated per SDK.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>