Trust & policy

Two trust decisions, configured independently

A contract has two sides, and each one has its own thing to worry about. A bidder is deciding who it will let run on its own machines. A requester is deciding who it will trust to run its workload at all. Neither side inherits the other's answer — a bidder can be wide open to the public while a requester is picky about providers, or the reverse. Both use the same four-mode vocabulary, applied to different questions.

Bidder's policy

Who gets to run on my compute

Set as a flag when the bidder software starts up. It gates which RFPs the bidder will even consider bidding on — a filter over incoming requesters, checked before it spends any resources evaluating a job.

Requester's policy

Who I'll trust to run my compute

Set when the requester publishes an RFP, and stamped onto the RFP as a signed record. It governs which bidders the requester is willing to accept a bid from — a filter over incoming providers.

The four modes, read from both sides

Same four names, same underlying mechanics — but the question each one answers depends on which side configured it.

ModeAs the bidder's policyAs the requester's policy
only-meOnly serve RFPs from DIDs the operator itself controls.Only accept bids from the requester's own operator DID.
tangled-vouchOnly serve requesters this bidder has vouched for.Only accept bids from providers this requester has vouched for.
mutualsSame pre-filter shape as tangled-vouch (reads the same vouch set). The per-request check can additionally verify mutual social follows when a Bluesky mutuals resolver is wired up.Same pre-filter shape as tangled-vouch (reads the same vouch set). The per-request check can additionally verify mutual social follows when a Bluesky mutuals resolver is wired up.
dynamicDefer the accept/reject decision to a policy server the bidder configures.Defer the accept/reject decision to a policy server the requester configures.

Nothing requires the two sides to agree, or even to pick the same mode. A tangled-vouch bidder can still bid on an RFP from an only-me requester — the requester's mode only constrains which bid it will accept, not who's allowed to try.

Vouch and denounce

Both tangled-vouch and mutuals read the same graph — vouch records published under Tangled's own namespace (sh.tangled.graph.vouch). A vouch is a signed statement, "I trust this DID," stored as a Tangled record whose rkey is the vouched DID. A denounce is the same shape with kind: "denounce" — the code skips it when building the vouch set, so that DID is never added. Critically, each side queries its own graph independently — a bidder checks who it has vouched for; a requester checks who it has vouched for. Neither reads the other's list.

Vouch

Alice vouches for Bob. If Alice is a bidder running tangled-vouch, she'll now bid on Bob's RFPs.

Denounce

Alice denounces Eve. A denounce record prevents Eve from appearing in the vouched set — she won't pass the tangled-vouch or mutuals scope filter. It does not override an existing vouch for the same DID (the vouch would still be added); use it to affirmatively exclude a specific DID from your vouch graph.

Where this is thinner than it sounds: a vouch today is boolean, not weighted or scored by how many hops away it is. Direct vouches only, on both sides. A denounce prevents a DID from entering the vouch set but does not remove an already-added DID — treat it as an allowlist builder with an exclusion gate, not a reputation system. The association lookup fallback mentioned in the cost table is currently stubbed (always approves).

When each side's policy actually runs

1

Requester creates the RFP. Its own policy mode is written as a signed record and referenced from the RFP — public, fixed before anyone sees it.

2

Bidder's firehose pre-filter. Its own policy mode runs a cheap, immediate check against a pre-loaded allowlist before anything else.

3

Bidder's full evaluation. If the pre-filter doesn't already settle it — and for dynamic — the bidder calls out to its own policy server before deciding whether to bid at all.

4

Requester's pre-accept check. Only under dynamic does the requester call its own policy server again, right before accepting a bid.

5

Accept → provision. Neither side's policy travels any further — provisioning doesn't know or care which mode gated the contract on either end.

What each mode costs to check

ModeInstant checkFalls back toCalls out over the network
only-meIs this the operator's own DID?Never
tangled-vouchIs this DID in the pre-loaded vouch set?— (association lookup stubbed)Never
mutualsSame shape as tangled-vouch— (association lookup stubbed)Never
dynamicNone — always defersYes, every time — a signed HTTP call to the policy server

badge.blue attestations

Every record in the chain carries a signature over its own content-addressed CID, not just an author DID. Both sides' policy evaluation checks this before acting.

$type: market.rfp
payload: {uri: at://did:plc:alice/compute.vm/3mm3d, cid: bafyrei...vm}
signatures:
  - keyId: did:plc:alice
    sig: bafyrei...attestation

Once a workload is running

Policy decides who bids and who's accepted. What credentials the workload itself gets is a separate mechanism — Workload Identity Federation.