Identities for entities did.bot
agent llm did
didbot docs testing.md
16 kB
Markdown
at main

The pre-launch test matrix #

Every check this project wants green before anything reaches a real zone, in the three tiers it runs in: what an agent can break on one machine, what needs an unadvertised instance on a real zone, and what needs a login in somebody else's system. Each row names the test or scenario that covers it, and says none where nothing here does.

Tiers are ordered. Nothing in tier 2 starts until tier 1 is green; nothing in tier 3 touches an account that is not disposable. This page is the map, not the gate: the gate is the irreversibles — the DID scheme, the lexicon shapes, the zone, and what is written into other people's servers.

A none is a row somebody has to do something about, and the two ways to do that are a test and a tier. Moving a row up a tier is the better one: a check that needs a real zone is a check that runs once a week, and a check that runs in this repository runs on every push.

Tier 1 — local, sandboxed, agent-driven #

Everything here runs on one machine with stand-ins for the network. The command column is what runs it.

The harness itself #

Check Command What covers it
An ecosystem replica in one compose file: the reference PDS, an appview, an indigo relay, goat, an ACME directory and a resolver for the zone none none
A local TLS and DNS story a foreign resolver accepts: a local CA the replica trusts, so did:web resolves over HTTPS none crates/didbot-tls/tests/acme_conformance.rs drives ACME against an in-process directory; nothing yet issues into a replica
Local TLS: a .localhost zone served from an authority kept per machine, reused across starts, refused for any other zone, and verified by a real client cargo test -p didbot-tls crates/didbot-tls/tests/local_authority.rs completes a handshake against the leaf a zone serves and shows the authority's name constraint refusing one outside .localhost; src/local.rs covers reuse and the refusal
Every binary in one scenario over TLS, against one authority, with each zone's port named scripts/scenarios.sh crates/didbot/tests/scenarios.rs starts didbot-pds with --tls local and drives didbot, didbot-agentd and a browserless dashboard sign-in over https
Sandboxed agent hosts: several containers, each with the plugin and the daemon none none
A red-team brief handed to agents, with the replica's oracles deciding none none

Wire and sync #

Check Command What covers it
A relay inverts every commit kind with no MST inversion failures cargo test -p didbot --test conformance crates/didbot/tests/conformance/mst_inversion.rs, against the vectors rather than against a relay
The stream survives a restart, a snapshot restore, a certificate swap and a reconnect from an old cursor cargo test -p didbot-pds --test sequence_restart and cargo test -p didbot-tls --test rotation the sequence floor and the certificate swap each have a test; a relay's own view of the two does not
goat repo export and verify, for every account state cargo test -p didbot --test announce_states the states and their events; the export is read by this project's own CAR reader in crates/didbot-repo/tests/car_framing.rs
An appview indexes a provisioned account: profile, self-label, repo status and account events agreeing none none
getRepo with since, listBlobs and getBlob round-tripping through a foreign client cargo test -p didbot --test conformance crates/didbot/tests/conformance/wire.rs drives them against the vendored documents, not through a foreign client

Identity #

Check Command What covers it
did:web and handle resolution for an account, the server's apex, and a tombstoned account cargo test -p didbot-identity crates/didbot-identity/tests/spec_conformance.rs
A document rewrite, and what a reader does with signatures made before it none none
Server-minted DIDs: one account per correlation key, a deleted DID never reissued, a caller's label ignored cargo test -p didbot-pds --test provisioning crates/didbot-pds/tests/provisioning.rs and crates/didbot-pds/tests/naming.rs

OAuth #

Check Command What covers it
A full sign-in from a foreign client: push, decision, approval, code, bound token, write, refresh, replay cargo test -p didbot-serve --test oauth_account_flow the whole flow against the real router, with this project's own client
Bluesky's own @atproto/oauth-client-node signs in to a running server as a public native client and writes before and after a refresh; as a confidential web client it pushes with its key, is refused approval because a browser would carry its code, and is declined npm ci --prefix tools/oauth-interop, then cargo test -p didbot-serve --test oauth_interop crates/didbot-serve/tests/oauth_interop.rs runs tools/oauth-interop/sign-in.mjs against didbot-pds and answers each sign-in as didbot-agentd does; without node or the installed tree it passes having said so
The loopback client form, and a client whose metadata is served from a hostile origin cargo test -p didbot-serve --test oauth_standard_client and --test oauth_interop jacquard-oauth's loopback client and @atproto/oauth-client-node's sign in; a hostile origin is not driven
Scope narrowing: a token cannot write outside its grant, a tightened ceiling narrows the next write cargo test -p didbot-serve --test token_scope crates/didbot-serve/tests/token_scope.rs and crates/didbot-scope/tests/ceiling_boundary.rs
Every scope form the permission spec defines reads without a warning; each other form reads as its warning says, and PAR logs it at warn with the client; a never-granted scope is dropped and Leaflet and Tangled sign in cargo test -p didbot-scope, then cargo test -p didbot-serve --test scope_warnings --test permission_sets --test token_scope crates/didbot-scope/src/tests.rs, and the three didbot-serve suites against the real router
A scripted agent that approves everything, against the default ceiling none none
A second agent cannot redeem a consent reference it did not receive cargo test -p didbot-serve --test oauth_account_flow the account check is the credential's, and the flow test drives it from both sides
Every bot.did.* route answers in the shape its document declares cargo test -p didbot --test conformance bot_did crates/didbot/tests/conformance/bot_did.rs

Policy and the e-stop #

Check Command What covers it
The operator's repository unreachable at boot, mid-run, and answering empty: no denial is lost cargo test -p didbot-serve --test policy_poll_restart crates/didbot-serve/tests/policy_poll_restart.rs restarts with the operator's repository gone, and the kept set refuses before any poll runs
One malformed record beside a valid new denial: the valid one binds cargo test -p didbot-policy-records crates/didbot-policy-records/tests/last_good_across_builds.rs covers a revision a later build will not honour beside the one it keeps enforcing; the pairing with a valid new record at another key is not driven
Policy change latency end to end, measured and published as the poll interval none none
--pause and --revoke under load: no write lands after the throw, and a restart keeps the stop cargo test -p didbot-pds --test freeze_race and cargo test -p didbot-pds --test estop_restart writes queued behind a judgment when the stop is thrown, and the latch across a restart; not under swarm load
An ownership lapse: the record deleted, the grace window passed, the self-pause, the record restored cargo test -p didbot --test handshake crates/didbot/tests/handshake.rs, in one process against a stand-in repository
The dashboard against real servers, in a browser DIDBOT_E2E=1 scripts/test-policy-e2e.sh a server, the operator's stand-in PDS, the built site and headless Chrome

Attestation #

Check Command What covers it
A replayed claim inside the window, after a restart, and after the account it minted was erased cargo test -p didbot-serve --test proof_restart the spent-proof window across a restart
A copied node key on a second container, and the honest limit that draws none docs/trust-model.md states the limit; nothing exercises it
Clock skew of ten minutes either way: the refusal names skew none none
A node key retired on a running server: the next claim refused, existing contexts locked none none

Agent hosts #

Check Command What covers it
Real sessions in containers: session start, a fan-out of subagents, and every record authored by the context the hook fired for none none
A daemon restart mid-session, a hook race at startup, a daemon unreachable, and a socket only its owner's uid can reach cargo test -p didbot-agentd the command line and the configuration; the socket's permissions and the races are not driven
A hostile in-process subagent acting as its parent none docs/trust-model.md states the custody limit
The dispatcher on a host holding only the agent install: the operator verbs are absent and say so cargo test -p didbot-dispatch crates/didbot-dispatch/tests/dispatch.rs

Durability, restart and restore #

Check Command What covers it
A kill at every sync boundary under load: every acknowledged write present, no unacknowledged one cargo test -p didbot-pds --test durability and cargo test -p didbot-pds --test record_heap the crash-and-reopen cases, and a power cut after another store's sync of the shared journal; not thousands of them under swarm load
A restore from a directory copied mid-load: the sequence floor, the relay's view, the blob check cargo test -p didbot-pds --test restore and cargo test -p didbot-serve --test restore_drill the store half and the deployment half
Compaction, boot time as a function of history, and the refusal at the log budget cargo test -p didbot-pds --test write_scale -- --ignored the benchmark prints what a write costs as history grows; the boot time and the budget's refusal are not driven
Pending sign-ins across a restart none none
A binary opening a directory another binary wrote cargo test -p didbot-pds --test upgrade crates/didbot-pds/tests/upgrade.rs

Abuse and load #

Check Command What covers it
A create flood and a push flood from many addresses cargo test -p didbot-swarm --test decision_bounds the decision store's bounds under a real swarm; the address-keyed budgets are unit-tested in crates/didbot-serve/src/rate_limit.rs
A blob flood to the quota cargo test -p didbot-pds --test blob_storage crates/didbot-pds/tests/blob_storage.rs drives the upload path against the quota
A subscriber that stops reading, with others still on the stream cargo test -p didbot --test subscribe_backpressure crates/didbot/tests/subscribe_backpressure.rs
A swarm at a thousand and at ten thousand accounts: memory per account, restart time, the account wall cargo test -p didbot-pds --test store_cost the per-account and per-record cost; the restart time and the wall at ten thousand are not driven
A swarm behind one address against the per-address budgets none none

Operations #

Check Command What covers it
An image upgrade against a data directory, a rollback by restore, and the crash-loop brake cargo test -p didbot-pds --test upgrade the directory half; the brake and the rollback are docs/operations.md's runbook
Every boot refusal in the operations table, produced on purpose cargo test -p didbot-pds --test upgrade, cargo test -p didbot-pds --test second_writer and cargo test -p didbot-serve --test startup_refusal upgrade.rs produces the three stamp refusals and second_writer.rs the lock; startup_refusal.rs refuses --tls acme under .localhost before the data directory is claimed
A graceful stop on the signal a deployment sends cargo test -p didbot-serve --test graceful_shutdown crates/didbot-serve/tests/graceful_shutdown.rs
The ownership scenarios with the real binaries scripts/scenarios.sh crates/didbot/tests/scenarios.rs

Vibescrobble #

Check Command What covers it
The index reads a relay's stream and survives a relay and a server restart none none
A scrobble written by a real containerised session appears on the canvas with the right operator and parent none none

Tier 2 — an unadvertised instance on a real zone #

A real zone, a real certificate, no announcement, on a zone whose every account will be tombstoned. Nothing here runs from this repository: each row is an operator following docs/deployment.md and recording what happened in docs/conformance.md.

Check Where it runs What covers it
tofu apply from an empty state, the delegation, the wildcard and apex records, and staging issuance before production the zone crates/didbot-dns/tests/route53_zone.rs and crates/didbot-tls/tests/dns01_zone.rs drive the record writes against a hosted zone that answers like the real one
The public checkers: pdscheck, the debug tools, the directories, the TLS and header graders the instance, from outside none
Certificate transparency: a monitor subscribed, our own issuance seen and nothing else the zone none
Our own relay in another region crawling over the internet the instance, from outside none
Agent hosts across the internet: hook latency, a daemon behind NAT, real clock skew a laptop and the instance none
A backup and restore drill on real volumes, an image swap, a disk fill, and break-glass reaching the e-stop the instance crates/didbot-pds/tests/restore.rs drills the store half locally
A week of background scanning on 443 the instance none
Vibescrobble deployed against the instance the instance none
The whole zone tombstoned, and what a relay and an appview do with it the zone none

Tier 3 — an external login or an external operator #

Everything here leaves a record in somebody else's system, so every row uses a throwaway account.

Check What it needs What covers it
didbot operate and the policy site writing against a real personal data server an account on that server crates/didbot/tests/scenarios.rs drives the command against a stand-in repository
bot.did.* permission sets expanded by somebody else's authorization server the published schema records, and that server only an external authorization server can answer this
An announcement to the network from the disposable zone: admission, the per-host cap, an account visible in a client, and an account signing in to a third-party site the network none
A preference record read against real accounts that publish one those accounts none
A report filed against a disposable account, and what reaches the operator somebody else's moderation service none
What a relay and an appview do when the disposable zone is tombstoned the network none