Skip to content

feat(exchange): add capability exchange with listings, receipts, and settlement - #115

Open
kivtxs wants to merge 5 commits into
mainfrom
claude/hopeful-galileo-09c6br
Open

feat(exchange): add capability exchange with listings, receipts, and settlement#115
kivtxs wants to merge 5 commits into
mainfrom
claude/hopeful-galileo-09c6br

Conversation

@kivtxs

@kivtxs kivtxs commented Jun 15, 2026

Copy link
Copy Markdown
Member

Summary

Introduces the Offline Protocol Capability Exchange — a complete system for publishing attested listings (services and adapters), discovering them across the mesh, invoking priced services, issuing signed usage receipts, and settling payment through a pluggable backend. This is the v1 definition-of-done for the exchange feature.

Key Changes

Core Exchange Engine (offline-protocol-exchange crate)

  • ExchangeCore state machine (manager.rs): owns all exchange state (published listings, discovered-listing cache, in-flight invocations, prepaid ledger, receipt store, reputation). Performs no I/O — returns messages to send and events to emit for the host to wire to transport and persistence.
  • Listings (types.rs, listing.rs): wraps ServiceDescriptor with commercial terms, OfflineID attestation, and artifact references. Embedded in descriptor's capabilities map so exchange-unaware nodes see normal services.
  • Attestation (attestation.rs, canonical.rs): listings and receipts are signed by the publisher's MLS identity key; verification is stateless via ExchangeVerifier trait.
  • Prepaid ledger (ledger.rs): tracks available and held balances per currency; holds are placed before invocation, committed when receipt is issued, released on failure/timeout.
  • Usage receipts (receipt.rs): dual-signed claims (consumer issues, provider counter-signs) that settle through a backend; includes metered billing support.
  • Reputation (reputation.rs): local-only trust reads derived from verified attestations, settled receipts, and key consistency.
  • Settlement (settlement.rs): pluggable backend trait for clearing receipts; includes MockClearing for CI.
  • Adapter artifacts (artifact.rs, runtime.rs): content-addressed integrity verification; loading gate via AdapterRuntime trait.

Protocol Integration (offline-protocol)

  • Exchange module (protocol/exchange.rs): wires ExchangeCore to the protocol instance — MLS identity key signs listings/receipts, exchange control messages ride send_internal_message (signed, TOFU-checked, MLS-encrypted), settlement-bearing messages gated on confirmed MLS session, adapter artifacts move over media transfer path with hash verification.
  • Events (events.rs): new event types — ListingDiscovered, ReceiptIssued, ReceiptReceived, ReceiptAcknowledged, BalanceChanged, InvocationFailed.
  • Integration tests (protocol/tests/exchange_tests.rs): full two-node loop covering listing publication/discovery, adapter pulls, priced invocations, receipt issuance, balance debits, and settlement.

Headless Node (offline-protocol-node crate)

  • HTTP control API (server.rs): localhost-only REST interface for the MCP server's node mode — routes mirror TypeScript MeshBridge interface exactly.
  • Node runtime (state.rs): protocol instance, receive/process pump, event-waiter registry that turns async events into synchronous HTTP responses.
  • File storage (storage.rs): file-backed MlsStorage for headless deployments; entries stored as <data_dir>/<key_type>/<hex(key_id)>.
  • Configuration (config.rs): environment-driven setup with conservative defaults.
  • Entrypoint (main.rs): daemon startup with transport initialization.

FFI & Bindings

  • UniFFI (offline-protocol-uniffi): MeshExchange class with methods for publishing, discovering, invoking, pulling adapters, managing prepaid balance, and querying receipts.
  • React Native (bindings/react-native): TypeScript types and iOS/Android module integration for MeshExchange.
  • Generated bindings: Kotlin, Swift, and C header updates.

Documentation

  • docs/capability-exchange.md: overview of listings, adapters, metered billing, settlement, and the priced invocation lifecycle.

https://claude.ai/code/session_01CaTnb3PX8mFfX5dFLBBRjY

claude added 5 commits June 9, 2026 20:29
Capability exchange layer over service discovery: attested listings
(versioned envelope embedded in ServiceDescriptor capabilities, wire
format unchanged), Ed25519 attestation via host-supplied signer traits,
prepaid ledger with two-phase holds, signed dual-party usage receipts,
local reputation reads, content-addressed adapter artifact verification
gating a stub AdapterRuntime, and a SettlementBackend trait with a
MockClearing backend for CI. Pure action-based core (no I/O), mirroring
the MeshServices integration pattern.
- Listing publish/discover wired through service discovery: envelopes
  verified on ServiceDiscovered, surfaced as ListingDiscovered events
  with attestation status and local reputation
- Priced invocations gated on a confirmed MLS session, with prepaid
  holds reserved before send and released on failure/timeout
- Settlement messages (__XCHG_USAGE__/__XCHG_RCPT__/__XCHG_RCPT_ACK__)
  added to the signed control plane and refused without a confirmed
  session; receipts counter-signed and persisted via MlsStorage
- Adapter pulls auto-served over the media transfer path; received
  artifacts verified against the attested content hash and surfaced as
  AdapterPullCompleted/Rejected (never as plain FileReceived)
- MeshExchange UniFFI interface mirroring the MeshServices pattern
- New exchange events covered by telemetry catalogue, scrubber, and
  redacting Debug
- Correct stale multi-hop discovery-response docs (relay is implemented)
- Fix pre-existing bench compile error (send_message arity drift)

Integration tests cover the full v1 definition-of-done loop over the
in-memory transport: attested publish/discover, fund/invoke/receipt/
settle with protocol fee, plaintext refusal, adapter pull with hash
mismatch rejection, free listings, and metered billing.
- MeshExchange UniFFI bindings regenerated for Swift and Kotlin
- Native module bridge methods on iOS (Swift + ObjC declarations) and
  Android (Kotlin), mirroring the MeshServices pattern
- TypeScript MeshExchange class with typed listings, terms, receipts,
  balances, reputation reads, and the eight new exchange event types
- docs/capability-exchange.md covering the envelope format, attested
  publish, the plaintext rule, the metered invocation lifecycle,
  settlement, adapter distribution, and Rust + RN examples
offline-protocol-node runs a full node (MLS identity, capability
exchange, transports) as a daemon and exposes a localhost HTTP API
mirroring the Capability Exchange MeshBridge interface: discovery and
the listing cache, blocking invoke that waits for the mesh response and
the signed receipt, hash-verified adapter pulls, mesh-ledger balance and
credit, pending-receipt export/mark-settled, and attested publish
endpoints (service + adapter) signed with the node's MLS identity key.

The control API is a trusted local plane: 127.0.0.1 by default, optional
bearer token (warned when absent), 256 KB body cap, clamped long-poll
timeouts. Agent-side guardrails stay in the MCP server in front of it.

Includes a file-backed MlsStorage for headless deployments (atomic
temp+rename writes, hex-encoded key ids so hostile ids cannot escape the
data dir, 0700 permissions) and docs/headless-node.md. Nine tests cover
storage semantics and the HTTP wiring (auth gating, publish/discover,
clean 4xx error shapes, malformed-body handling) over a MockTransport
node with real MLS signing.
@github-actions

Copy link
Copy Markdown


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants