Four signed hops, one verifiable contract.
A requester wants a machine. A provider has one spare. Nothing changes hands until both sides have signed a record that says so — and anyone watching the firehose can check the whole chain later.
Publish the RFP
The requester signs a compute.vm record describing the machine — cpus, memory, disk, network, a role, and optional cloud-init user data — then wraps a strong reference to it in a market.rfp envelope. Both land on the requester's own PDS. The requester discovers bidders through the relay's offering index and vouch graph, then pushes the RFP to each bidder's submitRfp endpoint.
$type: market.rfp
payload:
uri: at://did:plc:alice/compute.vm/3mm3dolfolz2c
cid: bafyrei...vm
Bids arrive from the firehose
Bids arrive through two channels: direct submitBid XRPC calls (primary) and firehose discovery (fallback). Bidders create a market.bids.free payload (cost: 0 by default; x402 paid pricing is an alternative) and bind it to the RFP in a signed market.bid record.
$type: market.bid
rfp: {uri: at://did:plc:alice/market.rfp/3mm3d..., cid: bafyrei...rfp}
payload: {uri: at://did:plc:bob/market.bids.free/3mm4..., cid: bafyrei...free}
submitAccept: did:plc:bob#pdr_temp_market
Score bids, accept one
Once the window closes, the requester's policy filter and scorer — lowest cost, by default — pick a winner. Locking it in means signing a market.accept record that references both the RFP and the winning bid, then calling the provider's submitAccept endpoint.
$type: market.accept
rfp: {uri: at://did:plc:alice/market.rfp/3mm3d..., cid: bafyrei...rfp}
bid: {uri: at://did:plc:bob/market.bid/3mm4..., cid: bafyrei...bid}
submitEvent: did:plc:alice#pdr_temp_compute_event
Provision, settle, receipt
The provider mints a signed market.receipt immediately — the contract is settled before the VM finishes booting. Then cloud-init (tunnel-subscriber + sshd + ephemeral SSH key) provisions the guest. The receipt anchors rfp, bid and accept behind one content-addressed CID.
$type: market.receipt
rfp: {uri: ..., cid: bafyrei...rfp}
bid: {uri: ..., cid: bafyrei...bid}
accept: {uri: ..., cid: bafyrei...accept}
Verify receipt, SSH in
The requester verifies the receipt's signatures and proof CID binding (verifyRecordSignatures + verifyRemoteProof). Once valid, SSH connects through the relay tunnel: websocat ProxyCommand → dispatcher WebSocket → tunnel-subscriber on guest → sshd. The guest was bootstrapped with the requester's ephemeral SSH public key via cloud-init.
If no bid passes the requester's policy, scoring ends in Rejected instead of Accepted — the RFP simply closes.
Accept.rfp and Bid.rfp strongRefs must be identical (both uri and cid). Error: ContractGraphError 'Accept.rfp does not match Bid.rfp'
The bid must carry a valid inline network.attested.signature by the bidder. Error: 'Bid is missing a valid badge.blue signature'
The RFP must carry a valid inline network.attested.signature by the requester. Error: 'RFP is missing a valid badge.blue signature'
The service-auth token issuer must be the author of the record being submitted. Error: 'service-auth token issuer must author the referenced record' (HTTP 403)