Skip to content

ADR-026: Protocol Adapters (Adapter-First Strategy)

Status

Accepted (February 2026; ACP + A2A + UCP adapter rollout and E0-E4 stabilization merged on main)

Context

Assay's open-core value is protocol-agnostic governance with deterministic, verifiable evidence. External agent protocols such as ACP, A2A, and related ecosystem formats emit protocol-specific payloads and lifecycle models, not canonical Assay EvidenceEvent records.

Without a controlled adapter layer, protocol adoption creates two problems: - Protocol-specific logic leaks into the evidence core. - Fast-moving protocol revisions create drift between raw protocol payloads and Assay's canonical evidence model.

A dedicated adapter layer allows Assay to ingest protocol payloads, preserve audit-grade provenance, and keep the evidence core stable.

Decision

We adopt an adapter-first strategy: - Introduce a shared adapter API in a central crate such as assay-adapter-api. - Implement protocol-specific adapters as separate crates such as assay-adapter-acp and later assay-adapter-a2a. - Keep adapter crates in open core because they are interoperability infrastructure, not enterprise workflow features. - Preserve raw protocol payloads via host-provided attachment writing and stable references instead of direct filesystem writes from adapters.

v1 execution model

Adapters are native Rust crates linked into the workspace.

v2 execution model (deferred)

The same API may later be hosted in sandboxed Wasm modules, but Wasm/plugin transport is explicitly deferred until the native contract is proven stable.

Adapter API Contract (v1)

Each adapter must implement the following contract surface: - protocol() -> ProtocolDescriptor - capabilities() -> AdapterCapabilities - convert(input, options) -> Result<Vec<EvidenceEvent>, AdapterError> - lossiness() -> LossinessReport on each emitted output unit or batch result

Required protocol metadata

protocol() must expose: - name - spec_version - schema_id - spec_url

Required lossiness metadata

Each conversion result must make loss explicit via: - lossiness_level: none | low | high - unmapped_fields_count - raw_payload_ref: digest-backed reference to preserved source payload

Strictness Modes

Adapters must support at least two conversion modes via ConvertOptions: - strict: fail on malformed or unmappable critical protocol data - lenient: emit evidence plus explicit lossiness metadata and preserved raw payload reference

Normative behavior: - strict contract failures exit with measurement/contract failure semantics (exit 2 in CLI/script harnesses). - lenient mode must not silently drop critical data; it must surface lossiness and retain a raw payload reference.

Raw Payload Preservation

Raw protocol payloads are preserved hash-first for auditability.

Normative rules: - Adapters must not write directly to arbitrary filesystem paths. - Raw payload persistence is performed through a host-provided attachment writer from the evidence/core layer. - Emitted evidence carries only raw_payload_ref { sha256, size, media_type } plus any allowed redaction metadata. - Canonicalization for payload hashing must be deterministic and stable for the adapter contract version.

Versioning and Conformance

Each active adapter must ship with a strict conformance suite.

Definition of Done

Conformance suites must include: - at least N golden happy-path fixtures for the supported protocol version range - at least one negative fixture per supported protocol version - explicit expected outcome per fixture - a determinism check proving identical input fixture -> identical output digest

Negative fixtures must cover at least one of: - malformed packet - missing required fields - oversize payload - invalid enum or discriminant

Expected outcomes must be explicit: - strict mode: measurement/contract fail (exit 2) - lenient mode: emit lossiness plus raw_payload_ref

Upgrade policy

Each adapter crate must declare an explicit supported version range, for example >=2.11 <3.0, and document deprecation policy when upstream protocol revisions break mappings.

Security Posture and Invariants

Adapters process untrusted protocol payloads. The following invariants are mandatory: - payload size caps before deep parsing - schema/shape validation before semantic mapping - no implicit network access from adapter conversion paths - no direct adapter-managed filesystem writes - unsafe remains disallowed under workspace policy unless a future ADR explicitly carves out an exception

Non-Goals

This ADR does not introduce: - protocol-specific business policy enforcement in the evidence core - dynamic plugin loading or Wasm adapter execution - remote adapter registries - workflow changes or CI rollout lanes - enterprise-only middleware surfaces

MVP Scope

The first implementation target is assay-adapter-acp.

Rationale: - ACP is a high-value governance wedge for commerce/intent evidence. - ACP creates immediate pressure for deterministic audit trails around checkout, intent, and authorization flows. - A2A remains the strategic follow-up once the adapter API and conformance harness are proven.

Execution Plan

PR-A (freeze)

  • freeze adapter API contract
  • freeze conformance harness contract
  • freeze ACP as initial implementation target
  • no runtime mapping logic

PR-B (implement)

  • add assay-adapter-acp
  • add happy-path and negative fixtures
  • add strict/lenient determinism tests

PR-C (closure)

  • add checklist and review pack
  • add index/runbook references for adapter entrypoints
  • close the rollout loop with reviewer gates

Acceptance Criteria

  • ADR defines adapter API v1 contract and strictness semantics
  • ADR defines hash-first raw payload preservation using host-provided attachment writing
  • ADR includes explicit negative-fixture conformance requirements
  • ADR freezes ACP as MVP and A2A as follow-up
  • No workflow or runtime behavior changes are introduced in this slice

Implementation Status

Current status on main: - assay-adapter-api exists as the shared adapter contract surface - assay-adapter-acp is implemented with strict/lenient conversion, fixtures, and conformance tests - assay-adapter-a2a is implemented with strict/lenient conversion, fixtures, and conformance tests - assay-adapter-ucp is implemented with strict/lenient conversion, fixtures, and conformance tests - Stabilization through E4 is merged: - E0: adapter identity metadata - E1: ACP lossiness preservation - E2: host-side AttachmentWriter policy - E3: canonical event digests with bytes-exact raw payload hashes - E4: parser caps and property-based hardening

Consequences

Positive

  • keeps the evidence core protocol-agnostic
  • makes protocol drift explicit through conformance fixtures
  • preserves audit-grade provenance for unmapped data
  • opens protocol interoperability as open-core infrastructure

Negative

  • adds maintenance burden for evolving upstream protocols
  • lossiness handling requires strong reviewer discipline
  • adapter version ranges and fixtures become part of the compatibility surface

Mitigations

  • strict conformance suites
  • explicit lossiness reporting
  • host-controlled attachment writing
  • freeze-first A/B/C rollout discipline