Evidence Carrier Contract
Universal interface for carrying verifiable evidence across transports. The PeacEvidenceCarrier type (Layer 0, zero runtime) and CarrierAdapter<TInput, TOutput> pattern decouple receipt production from transport-specific encoding.
Types in @peac/kernel. Validation schemas in @peac/schema. Normative spec: EVIDENCE-CARRIER-CONTRACT.md.
PeacEvidenceCarrier Type
The carrier type defines the fields that travel with evidence across any transport:
interface PeacEvidenceCarrier {
/** SHA-256 of receipt_jws: "sha256:<64 hex chars>". MUST. */
receipt_ref: string;
/** JWS Compact Serialization. SHOULD for embed carriers. */
receipt_jws?: string;
/** HTTPS URL locator hint. MAY. v0.11.2+. */
receipt_url?: string;
/** Policy binding status. MAY. */
policy_binding?: PolicyBindingStatus;
/** Actor binding reference. MAY. */
actor_binding?: string;
/** Request nonce for replay prevention. MAY. */
request_nonce?: string;
}Field Reference
| Field | Requirement | Description |
|---|---|---|
receipt_ref | MUST | SHA-256 of the receipt_jws value: sha256:<64 hex chars> |
receipt_jws | SHOULD | JWS Compact Serialization of the signed receipt. Required for embed-mode transports. |
receipt_url | MAY | HTTPS-only URL (max 2048 chars). Locator hint only: no credentials, no implicit fetch (DD-55). v0.11.2+. |
policy_binding | MAY | Three-state policy binding status: verified, failed, or unavailable |
actor_binding | MAY | Reference binding the carrier to a specific actor identity |
request_nonce | MAY | Nonce for replay prevention across transports |
CarrierAdapter Interface
Each transport implements a CarrierAdapter<TInput, TOutput> with three methods:
interface CarrierAdapter<TInput, TOutput> {
/** Extract carriers from transport-specific input. */
extract(input: TInput): PeacEvidenceCarrier[];
/** Attach carriers to transport-specific output. */
attach(output: TOutput, ...carriers: PeacEvidenceCarrier[]): TOutput;
/** Validate transport constraints (size limits, format). */
validateConstraints(carriers: PeacEvidenceCarrier[]): ValidationResult;
}Transport Size Limits
Each transport enforces a maximum carrier size. Embed transports carry the full JWS inline. Header transports use the PEAC-Receipt header with compact JWS.
| Transport | Placement | Max Size | Mode |
|---|---|---|---|
MCP | _meta | 64 KB | Embed |
A2A | metadata | 64 KB | Embed |
ACP | PEAC-Receipt header | 8 KB | Header |
UCP | peac_evidence field | 64 KB | Embed |
x402 | PEAC-Receipt header | 8 KB | Header |
HTTP | PEAC-Receipt header | 8 KB | Header |
Protocol-Specific Placement
MCP
Evidence is carried in the _meta object of MCP tool responses using reverse-DNS keys:
{
"_meta": {
"org.peacprotocol/receipt_ref": "sha256:abc123...",
"org.peacprotocol/receipt_jws": "eyJhbGciOi..."
}
}A2A
Evidence is carried in A2A metadata keyed by extension URI:
{
"metadata": {
"https://www.peacprotocol.org/ext/traceability/v1": {
"carriers": [{
"receipt_ref": "sha256:abc123...",
"receipt_jws": "eyJhbGciOi..."
}]
}
}
}ACP, x402, HTTP
Evidence is carried in the PEAC-Receipt HTTP header as compact JWS:
PEAC-Receipt: eyJhbGciOiJFZERTQSIsInR5cCI6InBlYWMtcmVjZWlwdC8wLjEiLC...
UCP
Evidence is carried in the peac_evidence field of UCP webhook payloads:
{
"peac_evidence": {
"receipt_ref": "sha256:abc123...",
"receipt_jws": "eyJhbGciOi..."
}
}receipt_ref Integrity (DD-129)
The receipt_ref field is a content-addressable identifier computed as sha256(receipt_jws). Extractors MUST verify this relationship before processing:
import { computeReceiptRef } from '@peac/schema';
const carrier = adapter.extract(input)[0];
// Verify receipt_ref matches the JWS content
const computedRef = computeReceiptRef(carrier.receipt_jws);
if (computedRef !== carrier.receipt_ref) {
throw new Error('receipt_ref integrity check failed');
}
// Proceed with JWS signature verification...This check runs before signature verification to detect transport-level tampering.
receipt_url Constraints (DD-135)
The optional receipt_url field is a locator hint for retrieving receipts that exceed embed size limits. It is subject to strict constraints:
| Constraint | Value |
|---|---|
| Scheme | HTTPS only |
| Max length | 2048 characters |
| Credentials | MUST NOT contain credentials in URL |
| Implicit fetch | MUST NOT trigger implicit fetch (SSRF prevention, DD-55) |
| Post-fetch verification | sha256(receipt_jws) == receipt_ref |
Callers that fetch from receipt_url MUST verify the receipt_ref integrity check after retrieval.
Packages
| Package | Layer | Provides |
|---|---|---|
@peac/kernel | Layer 0 | PeacEvidenceCarrier, CarrierAdapter types (zero runtime) |
@peac/schema | Layer 1 | Zod schemas, computeReceiptRef(), validation-only (no I/O) |
@peac/mappings-mcp | Layer 4 | MCP _meta carrier adapter |
@peac/mappings-a2a | Layer 4 | A2A metadata carrier adapter |
@peac/mappings-acp | Layer 4 | ACP header carrier adapter |
@peac/mappings-ucp | Layer 4 | UCP webhook carrier adapter |
@peac/adapter-x402 | Layer 4 | x402 header carrier adapter |
Links
Transport Integrations
Each transport has a dedicated mapping or adapter package that implements the CarrierAdapter interface. See the integrations page for transport-specific documentation.