--- id: vouch title: What an operator vouches, what an agent vouches, and what the server vouches status: open crates: [didbot-pds, didbot-lexicon] dependsOn: [ownership] exitCriterion: > A verifier reading a disagreement between the operator's, the agent's and the server's statements about one another has a written rule for which one it believes for which purpose, rather than picking one by convention. --- # vouch [ownership](ownership.md) builds the operator relation in both directions — an operator's vouch and an agent's operator claim, checked against each other — and its own exit criterion is a verifier confirming "an agent and its operator claim each other." That is two of three parties. The index — declined here, its code in vibescrobble.com's repository ([index](index.md) records the split) — plans to discover every server by *"following a server's `subscribeRepos`"* and walking `the vouch chain: voucher, repository, vouch, server`. A third statement is already load-bearing there and its own weight is never written down: the server answering, on `ownership`'s words, *"its controlling DID on an unauthenticated status endpoint."* Three statements exist or are proposed. This epic is naming what each one is worth, because a reader of the vouch chain treats disagreement between them as something to resolve, not something the lexicons currently say how to resolve. ## The three claims **Read the first claim with its correction.** `bot.did.vouch` was an earlier, unbuilt design; no schema for it was ever checked in, and `crates/didbot-lexicon/src/nsid.rs` deleted even its retired NSID constant. The record that exists instead is `bot.did.operator`, and it is **not this claim renamed**: `lexicons/bot/did/operator.json` is explicit that it says who runs a *server*, not who governs what it may do, and proves nothing about delegation. So the operator-vouches-for-an-agent claim below has no record behind it, and the three-way analysis in this file needs rewriting against `bot.did.operator` before it is actionable. The server-and-operator half of it is real and polled — see [onboarding](onboarding.md) and `crates/didbot-serve/src/operator_poll.rs`. - **The operator vouches for an agent** (`bot.did.vouch` — **never built, and the name is retired**; see the note under "The three claims" below): *this DID is mine, I am accountable for it.* Signed with the operator's own key, in the operator's own repository. A stranger who trusts the operator's identity can trust this without trusting the server at all — it says nothing about the server the agent happens to live on. - **The agent vouches for its operator** (`bot.did.registration`, at `self` in the account's repository; see [ownership](ownership.md)): *this human is who provisioned me.* Written by the server at provisioning, "never by the agent about itself" — `ownership.md` is explicit that this is not the agent asserting anything; it is the server asserting it on the agent's behalf, inside the agent's own repository. Its trust is bounded by the server: an operator who controls provisioning controls what every agent it mints appears to claim. - **The server vouches for itself, and implicitly for its own agents** (`ownership.md`'s unauthenticated status endpoint, plus [index](index.md)'s practice of trusting a server's own account listing as the enumeration of its agents): *this DID controls me, and these are the agents I minted.* `ownership.md`'s own "Enumeration is derived, and is a lower bound" item already says this is not fully trusted — a compromised server can hide an agent, though containment stops it minting one outside its zone. What is not written down is what a *disagreement* means, only what an omission means. ## What each is worth to a stranger, and where they can disagree - [ ] **Operator vouches, agent silent.** The operator's claim exists but the account carries no `bot.did.registration`. Provisioning here writes one and finishes no account without it, so the claim names an account some other server hosts, or none does. `ownership.md` says a bare vouch, absent the agent's side, "is a claim anybody may make about any account, and the account cannot disagree." Say plainly what a verifier does with this case. - [ ] **Operator and agent agree, server disagrees about which agents exist.** The pair vouches for each other; the server's own listing does not include the agent, or includes an agent neither side named. That epic's lower-bound framing covers omission — a server can hide an agent — but not fabrication: nothing in these lexicons stops a server from *listing* an agent it never truthfully provisioned, since the server writes both the listing and the agent-side claim. - [ ] **Server claims a controlling DID the operator does not vouch for.** The unauthenticated status endpoint is the server's own word about who controls it; `ownership.md`'s "three statements, none written into somebody else's repository" item requires the operator to vouch for the *server* from their own policy dashboard, independently. A server claiming an operator that operator never vouched for is the server lying about itself, and the fix is the same as the agent case above: the claim that matters is the one written in a repository the claimant does not control. - [ ] **Expiry and revocation land on different schedules.** `ownership.md`'s open item says a reader that is not polling learns nothing about a revocation, and DNS is explicitly not the mechanism — a deleted agent stays cached for a day. A verifier holding a cached "agrees" answer across an operator's revocation is holding a claim that has already stopped being true; say what a stale-but-cached agreement is worth compared to a fresh disagreement. ## What a verifier does when they disagree - [ ] **Existence (which agents this server hosts) is decided by the server's own listing, bounded to a lower bound as `ownership.md` already states.** A verifier cannot use a disagreement here to prove an agent exists that the server does not list — only to prove the server is hiding one it does list evidence for elsewhere (an old vouch, a cached DID document). - [ ] **Say which of the two, accountability or existence, [index](index.md) is actually answering when it walks the vouch chain**, since its own description elides the difference: "discovers every vouched server" is an existence question about servers, layered under an accountability question about agents, and a reader of that epic should not have to infer which one is load-bearing for a given query. ## Done - [x] **Who operates an agent (human accountability) is decided by the operator's record, never by the server alone.** The registration's `operator` is the human at any depth, and the human's own `bot.did.operator` record for the account, or for the first entry of its lineage, confirms it; the server's word alone names nobody. [ownership](ownership.md) has the check.