atproto-attestation
Sign and verify ATProto records with did:key signatures over a canonical DAG-CBOR CID. Produces inline network.attested.signature entries, or (with an agent) remote network.attested.proof records referenced via com.atproto.repo.strongRef.
Installation
npm install @atiproto/atproto-attestation
This package is consumed directly by @atiproto/agent. Install it directly when you need to sign or verify records outside of an agent context (e.g. in a worker that produces AppView attestations).
Quick start
Sign a cart record on the AppView side and verify it from the consumer side.
import { Attestation, verify } from "@atiproto/atproto-attestation";const att = new Attestation({privateKey, // multibase string OR { type, bytes }publicKey: "did:key:zDnae...", // optional; derived from privateKeyrole: "appview",issuer: "did:web:appview.example",});const fields = ["items", "currency", "status", "total"];const signedCart = await att.signAndAppend({record: cartRecord,repository: "did:plc:recipient", // DID that will own the recordfields, // restrict to the lexicon-protected fields});// On the consumer side:const result = await verify({record: signedCart,repository: "did:plc:recipient",fields,});if (!result.valid) {console.warn("attestation failed", result.entries);}
Inline vs remote attestations
Inline attestations carry the signature bytes directly on the record's signatures[]. They are self-contained and verify offline given the signer's public key.
Remote attestations replace the inline entry with a com.atproto.repo.strongRef pointing at a separately-stored network.attested.proof record. To produce a remote attestation, pass an agent to the constructor. The agent is used to createRecord the proof on its PDS. The strongRef's authority comes from the repo hosting it, not from the signature bytes, so verifying remote entries requires a recordResolver.
Fields
By default the canonical signing payload covers the entire record (minus the signatures field). Pass fields to restrict the payload to a specific set of record keys. This is what the agent does on a record-write so that ancillary fields (e.g. server-side annotations) can change without breaking the signature. The verifier must use the same field list.
When called from @atiproto/agent, the field list is sourced from signature_scope_collections for the record's collection.
API
- Attestation Sign records inline or via an agent-backed proof record.
- verify Standalone verifier. No keys required at module init.
- KeyResolver & RecordResolver Plug in DID-doc keys and PDS-hosted proof records.
- did:key utilities Parse and format did:key and private-key multibase strings.