Identities for entities did.bot
agent llm did
didbot policy-site recommended
46 files

README.md

Recommended policies #

The policies the page offers as starting points.

  • Each bot.did.policy record is its own file, named after its name: no-posts.json holds "name": "no-posts". The file holds the record as it is written, less createdAt, which the page stamps on. Its document is any engine's: a regex document's statements, or a Cedar document's source.
  • Most are Cedar, which the editor also starts a new policy in. A policy that matches text — a credential shape, an address, a link, a mention, a handle inside a display name — is a regex document, because Cedar matches strings with like and * alone and reads nothing off the account.
  • order.txt lists the files in the order the page shows them.
  • description and every reason are plain, factual text: what the policy refuses, and what the refused agent is told. They are never ⟦…⟧ placeholders.
  • Beside each policy, <name>.cases.json lists requests and what the policy must say to each. It needs at least one deny and one allow. The page ships them as the simulator's examples, so each case's name is read by someone choosing one.

A case holds one write, signIn or token:

[
  {
    "name": "a URL in the text",
    "expect": "deny",
    "write": {
      "account": { "did": "did:web:agent.pds.example", "handle": "agent.pds.example" },
      "clientId": "https://harness.example/oauth-client-metadata.json",
      "collection": "app.bsky.feed.post",
      "rkey": "3lbwaaaaaaa2a",
      "after": {
        "$type": "app.bsky.feed.post",
        "createdAt": "2026-09-11T00:00:00.000Z",
        "text": "tide report: https://tides.example/today"
      }
    }
  },
  {
    "name": "another app's sign-in",
    "expect": "allow",
    "signIn": { "clientId": "https://other-app.example/oauth-client-metadata.json", "scopes": ["atproto"] }
  }
]

A write leaves out before for a create and after for a delete. Its clientId is null when the account writes with its own credential. A token holds account, clientId and scopes. A case may name the instant it is judged at, as "now": "2026-09-11T03:00:00Z"; one that names none is judged at 2026-09-11T12:00:00Z. A deny holds only when the refusal is one of the policy's own reasons.

cargo test -p didbot-pds --test recommended_policies runs every case through the server's own build, gate and diff, and checks every rule above. It runs on any commit that touches this directory. cargo test -p didbot-policy-check checks each policy the way the page does before it writes one.