Security & verification

Verify it. Don't just trust it.

There's no operator vouching for a contract's history — the records do that themselves. Signing makes a record's origin checkable; content-addressing makes its content checkable. Together they mean anyone, not just the two participants, can confirm a contract actually happened.

Signed by construction

Every RFP, bid, accept and receipt is a record in the author's own repository, signed with the key behind their DID. Signing uses secp256k1 ECDSA (SHA-256 + curve, low-S normalized). There's nowhere to write an unsigned or misattributed record — the PDS won't accept one.

Content-addressed, not just logged

A strongRef pins both a location (uri) and a hash (cid) — DAG-CBOR over the record, SHA-256, encoded as a CIDv1. Change one byte and the cid no longer matches; a reference can't quietly point somewhere else later.

A receipt anchors the whole contract

The market.receipt is the one record that references all three prior hops — rfp, bid, accept — each by strongRef. Reading a receipt is enough to reconstruct and re-check the entire negotiation.

$type: market.receipt
rfp:    {uri: at://did:plc:alice/market.rfp/3mm3d,    cid: bafyrei...rfp}
bid:    {uri: at://did:plc:bob/market.bid/3mm4,       cid: bafyrei...bid}
accept: {uri: at://did:plc:alice/market.accept/3mlag, cid: bafyrei...accept}
cid: bafyrei...binding        # attestation CID, accept → receipt
signatures:
  - $type: network.attested.signature
    key: did:key:z6Mk...      # did:key of signer; issuer binds it to party DID
    cid: bafyrei...attestation
    signature: { $bytes: "base64-ecdsa-signature" }
    issuer: did:plc:bob

What a provider checks before it settles

Accept.rfp and Bid.rfp strongRefs must be identical (uri + cid). Enforced atomically by refsEqual. Error: ContractGraphError (HTTP 400).

Bid must carry a valid inline network.attested.signature by the bidder. Error: "Bid is missing a valid badge.blue signature" (HTTP 400).

RFP must carry a valid inline network.attested.signature by the requester. Error: "RFP is missing a valid badge.blue signature" (HTTP 400).

Service-auth token issuer must be the record author (per submit handler). For vm.delete: issuer must match the market.accept author. The receipt's proof CID must bind to the accept record via verifyRemoteProof.

Full field-level rules live in the protocol spec.

Verify a receipt yourself

Nothing here requires special access — the same four checks a provider runs before settling are the ones you can run afterward, from either side or neither.

1

Fetch the receipt record and confirm its NSID is market.receipt.

2

Resolve rfp, bid and accept by their uris and recompute each cid — it must match the strongRef.

3

Verify bid and RFP signatures, confirm the service-auth token issuer authored the record, and check the receipt's proof CID binds to the accept.

4

Verify each signature against its key (did:key), and the receipt's own attestation CID binding accept → receipt.

This is alpha software under a temporary NSID namespace. The cryptographic guarantees above hold today; the endpoints and record shapes around them may still change.

Access control is a separate question

Verification proves a contract happened. Whose bids you ever see in the first place is what policy modes decide.