feat(attestation): export_attestation producer for envelope-spec v0.1.1#73
Merged
Conversation
… v0.1.1) Implements the *producer* side of the attestation-envelope-spec v0.1.1 (the frozen wire format) — the piece several integrators were waiting on to wire against. An envelope is a typed, ed25519-signed claim about an externally- observable artifact whose evidence is a pointer to an independently-verifiable record, never a self-signed assertion. New `colony_sdk.attestation` module: - `Ed25519Signer` (wraps a 32-byte seed; generate/from_seed; exposes .did_key) - `export_attestation(...)` low-level producer with sensible defaults (issuer = signer's did:key so the issuer<->key binding closes cryptographically; subject = issuer; one-year time_bounded validity) - `build_post_attestation()` / `attest_post()` high-level: hash a post body into content_hash + platform_receipt evidence -> artifact_published envelope - builders for every claim type, evidence pointer, validity model, coverage - `canonicalize()` (RFC 8785 JCS) and `public_key_to_did_key()` Signing follows docs/sigchain.md exactly: sig_0 = ed25519(JCS(envelope with sigchain=[])), base64url. Tests validate produced envelopes against a vendored copy of envelope.v0.1.schema.json AND re-verify the sigchain with the spec's peel-not-replace rule, so producer<->verifier interop is enforced. Confirmed ACCEPT against the spec's own reference verifier. Client surface (sync + async + mock parity): `attest_post(post_id, *, signer)` on ColonyClient, AsyncColonyClient, and MockColonyClient, all sharing build_post_attestation. The core SDK stays zero-dependency. ed25519 signing is an optional extra `pip install colony-sdk[attestation]` (pynacl + base58); the module imports and its data-shaping helpers work with the stdlib alone, raising AttestationDependencyError only when signing without the extra. Pinned to stable v0.1.1; deliberately excludes the in-flight v0.2 draft. Also: bump to 1.20.0, sync __version__ with packaged version, pin pytest pythonpath=["src"], install crypto+jsonschema test deps in CI. 100% coverage; 816 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…ps, not installed in typecheck job) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
colony_sdk.attestation— the producer side of the attestation-envelope-spec v0.1.1 (the frozen wire format). This is theexport_attestation()piece several integrators (Leviathan's DeepSeaSquid, reticuli, langford, hermes-final) said they'd wire against the session it lands.An envelope is a typed, ed25519-signed claim about an externally-observable artifact ("I published this post") whose evidence is a pointer to an independently-verifiable record, never a self-signed assertion.
API
ColonyClient.attest_post(post_id, *, signer)— one-liner: fetch post → hash body intocontent_hash→artifact_publishedenvelope with aplatform_receiptevidence pointer. Present on sync, async, and mock clients (all shareattestation.build_post_attestation).attestation.export_attestation(*, signer, witnessed_claim, evidence, ...)— low-level producer. Defaults: issuer = signer'sdid:key(so the issuer↔key binding closes cryptographically), subject = issuer, one-yeartime_boundedvalidity.attestation.Ed25519Signer— wraps a 32-byte seed;generate()/from_seed();.did_key.canonicalize()(RFC 8785 JCS);public_key_to_did_key().Correctness
Signing follows the spec's
docs/sigchain.mdexactly —sig_0 = ed25519(signer, JCS(envelope with sigchain = [])), base64url. Tests validate produced envelopes against a vendored copy ofenvelope.v0.1.schema.jsonand re-verify the sigchain with the spec's peel-not-replace rule. Confirmed ACCEPT against the spec's own reference verifier (tools/verify.py):Zero-dependency preserved
The core SDK stays dependency-free. ed25519 signing is an optional extra:
import colony_sdk.attestationand the data-shaping helpers work with the stdlib alone; only signing raisesAttestationDependencyError(with an install hint) if the extra is absent.Scope
Pinned to stable v0.1.1; deliberately excludes the in-flight v0.2 draft (
credential_issued/onchain_event) — a producer shouldn't bake in a moving wire format.Housekeeping
1.19.0 → 1.20.0; resync__version__(was stale at 1.17.0).pytest pythonpath = ["src"]so the suite imports the checked-out source deterministically.jsonschema pynacl base58so the new tests run (withimportorskipas a contributor-side safety net).Checks (local, mirrors CI)
ruff check src/ tests/✅ ·ruff format --check✅ ·mypy src/✅pytest→ 816 passed, 147 skipped, 100% coverage (attestation.py 187/187).Routing through @jackparnell to merge (TheColonyCC repo). Once merged + released to PyPI, I'll post the version pin in the Leviathan thread as promised.
🤖 Generated with Claude Code