API Reference
Package receipt
Section titled “Package receipt”import receipt "github.com/agent-receipts/ar/sdk/go/receipt"Core package for creating, signing, verifying, and chaining Agent Receipts.
Functions
Section titled “Functions”Create
Section titled “Create”func Create(input CreateInput) UnsignedAgentReceiptBuild an unsigned receipt. Auto-generates an ID (urn:uuid:...) and sets the issuance timestamp.
func Sign(unsigned UnsignedAgentReceipt, privateKeyPEM string, verificationMethod string) (AgentReceipt, error)Sign an unsigned receipt with an Ed25519 private key (PEM-encoded). Returns a signed AgentReceipt with an Ed25519Signature2020 proof.
Verify
Section titled “Verify”func Verify(r AgentReceipt, publicKeyPEM string) (bool, error)Verify the Ed25519 signature on a signed receipt.
GenerateKeyPair
Section titled “GenerateKeyPair”func GenerateKeyPair() (KeyPair, error)Generate an Ed25519 key pair in PEM format.
HashReceipt
Section titled “HashReceipt”func HashReceipt(r AgentReceipt) (string, error)Compute the SHA-256 hash of a receipt using canonical JSON serialization. Returns a string in sha256:<hex> format.
VerifyChain
Section titled “VerifyChain”func VerifyChain(receipts []AgentReceipt, publicKeyPEM string) ChainVerificationVerify an entire receipt chain: signatures, hash linkage between consecutive receipts, and sequence numbers.
Canonicalize
Section titled “Canonicalize”func Canonicalize(v any) (string, error)RFC 8785 canonical JSON serialization.
SHA256Hash
Section titled “SHA256Hash”func SHA256Hash(data string) stringCompute a SHA-256 hash, returned as hex.
TruncatePromptPreview
Section titled “TruncatePromptPreview”func TruncatePromptPreview(s string, maxLen int) (preview string, truncated bool)Truncate a prompt preview string to maxLen, returning whether it was truncated.
Context / CredentialType
Section titled “Context / CredentialType”func Context() []stringfunc CredentialType() []stringReturn the W3C VC @context and type arrays used in receipts.
AgentReceipt
Section titled “AgentReceipt”A signed W3C Verifiable Credential with proof.
type AgentReceipt struct { Context []string `json:"@context"` ID string `json:"id"` Type []string `json:"type"` Version string `json:"version"` Issuer Issuer `json:"issuer"` IssuanceDate string `json:"issuanceDate"` CredentialSubject CredentialSubject `json:"credentialSubject"` Proof Proof `json:"proof"`}UnsignedAgentReceipt
Section titled “UnsignedAgentReceipt”Same as AgentReceipt but without the Proof field.
CreateInput
Section titled “CreateInput”type CreateInput struct { Issuer Issuer Principal Principal Action Action Outcome Outcome Chain Chain Intent *Intent Authorization *Authorization}KeyPair
Section titled “KeyPair”type KeyPair struct { PublicKey string PrivateKey string}PEM-encoded Ed25519 key pair.
Issuer
Section titled “Issuer”type Issuer struct { ID string `json:"id"` Type string `json:"type,omitempty"` Name string `json:"name,omitempty"` Operator *Operator `json:"operator,omitempty"` Model string `json:"model,omitempty"` SessionID string `json:"session_id,omitempty"` Runtime *Runtime `json:"runtime,omitempty"` // open metadata container (v0.5.0, ADR-0026)}
// Runtime is the open container for runtime/observability metadata. The typed// members are documented; unknown keys are preserved via Extra so the field// stays open across SDKs.type Runtime struct { AgentID string // runtime.agent_id — the sub-agent that issued the receipt AgentType string // runtime.agent_type — e.g. "general-purpose" Extra map[string]json.RawMessage // any additional runtime keys, preserved verbatim}Principal
Section titled “Principal”type Principal struct { ID string `json:"id"` Type string `json:"type,omitempty"`}Action
Section titled “Action”type Action struct { ID string `json:"id"` Type string `json:"type"` RiskLevel RiskLevel `json:"risk_level"` Target *ActionTarget `json:"target,omitempty"` ParametersHash string `json:"parameters_hash,omitempty"` Timestamp string `json:"timestamp"` TrustedTimestamp string `json:"trusted_timestamp,omitempty"`}Outcome
Section titled “Outcome”type Outcome struct { Status OutcomeStatus `json:"status"` Error string `json:"error,omitempty"` Reversible *bool `json:"reversible,omitempty"` ReversalMethod string `json:"reversal_method,omitempty"` ReversalWindowSeconds *int `json:"reversal_window_seconds,omitempty"` StateChange *StateChange `json:"state_change,omitempty"`}type Chain struct { Sequence int `json:"sequence"` PreviousReceiptHash *string `json:"previous_receipt_hash"` ChainID string `json:"chain_id"`}ChainVerification
Section titled “ChainVerification”type ChainVerification struct { Valid bool `json:"valid"` Length int `json:"length"` Receipts []ReceiptVerification `json:"receipts"` BrokenAt int `json:"broken_at"` Error string `json:"error,omitempty"`}Constants
Section titled “Constants”const Version = "0.3.0"
type RiskLevel stringconst ( RiskLow RiskLevel = "low" RiskMedium RiskLevel = "medium" RiskHigh RiskLevel = "high" RiskCritical RiskLevel = "critical")
type OutcomeStatus stringconst ( StatusSuccess OutcomeStatus = "success" StatusFailure OutcomeStatus = "failure" StatusPending OutcomeStatus = "pending")Parameter disclosure (HPKE)
Section titled “Parameter disclosure (HPKE)”import receipt "github.com/agent-receipts/ar/sdk/go/receipt"HPKE-based envelope for encrypting tool-call parameters into a receipt’s
parameters_disclosure field (ADR-0012, ciphersuite
hpke-x25519-hkdf-sha256-aes-256-gcm). The emitter holds only the forensic
public key and never sees the plaintext again after encryption; the private key
stays offline. For the threat model and operator configuration see the
Parameter Disclosure specification.
For the envelope JSON shape see the schema reference.
This is the SDK-direct path. When emitting through the daemon the operator provides the public key in daemon config; the daemon calls these helpers automatically (ADR-0012 §“Operator config”).
GenerateForensicKeyPair
Section titled “GenerateForensicKeyPair”func GenerateForensicKeyPair() (ForensicKeyPair, error)Generate an X25519 key pair for forensic disclosure. PublicKey (32 raw bytes)
is shared with emitters so they can encrypt disclosures. PrivateKey (32 raw
bytes) must be kept offline — separate from the Ed25519 signing key (ADR-0001 /
ADR-0012). Returns an error if the system CSPRNG fails.
ForensicKeyFingerprint
Section titled “ForensicKeyFingerprint”func ForensicKeyFingerprint(publicKey []byte) (string, error)Return the canonical fingerprint of an X25519 forensic public key in
sha256:<lowercase hex> form (ADR-0015): SHA-256 over the raw 32-byte key.
This is the value the daemon writes as the recipient kid in a
DisclosureEnvelope, and the value a forensic tool recomputes from a held key
to match receipts. publicKey must be the raw 32-byte X25519 key (not
SPKI/PEM). Returns an error if len(publicKey) != 32.
Go SDK only. The TS and Py SDKs do not yet export this helper.
ForensicPublicFromPrivate
Section titled “ForensicPublicFromPrivate”func ForensicPublicFromPrivate(privateKey []byte) ([]byte, error)Derive the X25519 public key (32 raw bytes) from a 32-byte forensic private
key. A forensic responder typically holds only the private key; this function
lets it compute the matching ForensicKeyFingerprint and locate receipts
encrypted to that key without a separate key registry. Returns an error if
len(privateKey) != 32 or the key bytes are invalid.
Go SDK only. The TS and Py SDKs do not yet export this helper.
EncryptDisclosure
Section titled “EncryptDisclosure”func EncryptDisclosure(params map[string]any, recipientPublicKey []byte, kid string) (*DisclosureEnvelope, error)Encrypt params as a v1 HPKE disclosure envelope. params is
RFC 8785 JCS-canonicalized before encryption so all SDKs produce the same
ciphertext for the same parameters object. recipientPublicKey must be 32 raw
bytes; kid is the recipient key identifier (a sha256:<hex> fingerprint from
ForensicKeyFingerprint, or a did:key DID URL). Returns an error if any
argument is invalid or if the system CSPRNG fails.
DecryptDisclosure
Section titled “DecryptDisclosure”func DecryptDisclosure(env *DisclosureEnvelope, recipientPrivateKey []byte) (map[string]any, error)Recover the plaintext parameters from a v1 HPKE disclosure envelope.
recipientPrivateKey must be 32 raw bytes. Returns an error if the envelope
version or algorithm is unsupported, if the key or ciphertext is invalid, or if
AEAD authentication fails.
Usage example
Section titled “Usage example”// Key management (run once offline, store private key securely)kp, err := receipt.GenerateForensicKeyPair()fingerprint, err := receipt.ForensicKeyFingerprint(kp.PublicKey)// fingerprint == "sha256:..." — use as kid and in daemon config
// Emitter side (holds only the public key)env, err := receipt.EncryptDisclosure( map[string]any{"path": "/etc/passwd", "mode": "r"}, kp.PublicKey, fingerprint,)// embed env in action.ParametersDisclosure, then sign the receipt
// Forensic / audit side (holds the offline private key)params, err := receipt.DecryptDisclosure(env, kp.PrivateKey)// params == map[string]any{"mode": "r", "path": "/etc/passwd"}
// Deriving a public key from only the private key (forensic tooling)pub, err := receipt.ForensicPublicFromPrivate(kp.PrivateKey)fp2, err := receipt.ForensicKeyFingerprint(pub)// fp2 == fingerprintRecovering a stored disclosure
Section titled “Recovering a stored disclosure”In practice the envelope comes from a stored receipt and the private key from
the file obsigna-daemon --init-forensic-key wrote — a raw 32-byte X25519
key, not PEM, so read it as bytes and pass it straight in. Pull the envelope out
of the receipt JSON at credentialSubject.action.parameters_disclosure:
import ( "encoding/json" "log" "os"
receipt "github.com/agent-receipts/ar/sdk/go/receipt")
// raw 32-byte private key written by --init-forensic-key (kept offline)priv, err := os.ReadFile("/path/to/forensic.key")if err != nil { log.Fatal(err)}
// from: obsigna receipt show <seq> --json > receipt.jsondata, err := os.ReadFile("receipt.json")if err != nil { log.Fatal(err)}var rec struct { CredentialSubject struct { Action struct { ParametersDisclosure *receipt.DisclosureEnvelope `json:"parameters_disclosure"` } `json:"action"` } `json:"credentialSubject"`}if err := json.Unmarshal(data, &rec); err != nil { log.Fatal(err)}
params, err := receipt.DecryptDisclosure(rec.CredentialSubject.Action.ParametersDisclosure, priv)if err != nil { log.Fatal(err)}// params holds the original tool-call parametersTypes (disclosure)
Section titled “Types (disclosure)”ForensicKeyPair
Section titled “ForensicKeyPair”type ForensicKeyPair struct { PublicKey []byte // 32 bytes; share with emitters PrivateKey []byte // 32 bytes; keep offline}Raw X25519 key bytes. Unlike KeyPair (Ed25519, PEM), these are raw bytes
because X25519 has no widespread PKCS8 PEM convention and raw bytes compose
naturally with HPKE library APIs.
DisclosureEnvelope
Section titled “DisclosureEnvelope”type DisclosureEnvelope struct { V string `json:"v"` Alg string `json:"alg"` Recipients []DisclosureRecipient `json:"recipients"` CT string `json:"ct"`}
type DisclosureRecipient struct { KID string `json:"kid"` Enc string `json:"enc"` // unpadded base64url, 43 chars for X25519}v1 HPKE envelope stored in action.parameters_disclosure. CT is the
base64url-encoded AEAD ciphertext. Field names in DisclosureRecipient follow
RFC 9180 §4.1 (enc, not encap).
Package taxonomy
Section titled “Package taxonomy”import "github.com/agent-receipts/ar/sdk/go/taxonomy"Action type registry and tool call classification.
Functions
Section titled “Functions”ClassifyToolCall
Section titled “ClassifyToolCall”func ClassifyToolCall(toolName string, mappings []TaxonomyMapping) ClassificationResultClassify a tool call to an action type and risk level using the provided mappings.
AllActions
Section titled “AllActions”func AllActions() []ActionTypeEntryReturn all 18 built-in action types (filesystem, system, and data categories, plus unknown).
GetActionType
Section titled “GetActionType”func GetActionType(actionType string) *ActionTypeEntryLook up an action type by name. Returns nil if not found.
ResolveActionType
Section titled “ResolveActionType”func ResolveActionType(actionType string) ActionTypeEntryLike GetActionType but returns an “unknown” fallback instead of nil.
LoadTaxonomyConfig
Section titled “LoadTaxonomyConfig”func LoadTaxonomyConfig(path string) ([]TaxonomyMapping, error)Load taxonomy mappings from a JSON file. Validates that no duplicate tool names exist.
Variables
Section titled “Variables”var FilesystemActions []ActionTypeEntry // 7 filesystem action typesvar SystemActions []ActionTypeEntry // 7 system action typesvar DataActions []ActionTypeEntry // 3 data/API action typesPre-populated slices of action type entries by category. Use AllActions() to get all categories combined.
type ActionTypeEntry struct { Type string `json:"type"` Description string `json:"description"` RiskLevel receipt.RiskLevel `json:"risk_level"`}
type TaxonomyMapping struct { ToolName string `json:"tool_name"` ActionType string `json:"action_type"`}
type ClassificationResult struct { ActionType string `json:"action_type"` RiskLevel receipt.RiskLevel `json:"risk_level"`}Package store
Section titled “Package store”import "github.com/agent-receipts/ar/sdk/go/store"SQLite-backed receipt persistence, querying, and chain verification. Uses pure Go SQLite (no CGO) with WAL mode.
Functions
Section titled “Functions”func Open(dbPath string) (*Store, error)Open or create a SQLite receipt store. Pass ":memory:" for an in-memory store.
Methods on *Store
Section titled “Methods on *Store”Insert
Section titled “Insert”func (s *Store) Insert(r receipt.AgentReceipt, receiptHash string) errorGetByID
Section titled “GetByID”func (s *Store) GetByID(id string) (*receipt.AgentReceipt, error)GetChain
Section titled “GetChain”func (s *Store) GetChain(chainID string) ([]receipt.AgentReceipt, error)QueryReceipts
Section titled “QueryReceipts”func (s *Store) QueryReceipts(q Query) ([]receipt.AgentReceipt, error)func (s *Store) Stats() (Stats, error)Returns aggregate statistics: total receipts, chain count, and breakdowns by risk level, status, and action type.
VerifyStoredChain
Section titled “VerifyStoredChain”func (s *Store) VerifyStoredChain(chainID string, publicKeyPEM string) (receipt.ChainVerification, error)func (s *Store) Close() errortype ReceiptStore interface { Insert(r receipt.AgentReceipt, receiptHash string) error GetByID(id string) (*receipt.AgentReceipt, error) GetChain(chainID string) ([]receipt.AgentReceipt, error) QueryReceipts(q Query) ([]receipt.AgentReceipt, error) Stats() (Stats, error) VerifyStoredChain(chainID string, publicKeyPEM string) (receipt.ChainVerification, error) Close() error}
type Query struct { ChainID *string ActionType *string RiskLevel *receipt.RiskLevel Status *receipt.OutcomeStatus After *string Before *string // When nil, all matching rows are returned (no default cap). Limit *int // When true, returns newest receipts first; ties broken by sequence descending. NewestFirst bool}
type Stats struct { Total int `json:"total"` Chains int `json:"chains"` ByRisk []GroupCount `json:"by_risk"` ByStatus []GroupCount `json:"by_status"` ByAction []GroupCount `json:"by_action"`}
type GroupCount struct { Label string `json:"label"` Count int `json:"count"`}