Nothing published didbot's lexicons, so no stranger could validate a bot.did.* record and no authorization server could expand a permission set we define — bsky.social refuses a scope naming an unresolvable set at the pushed authorization request. This adds the mechanism: scripts/publish-lexicons.sh writes one com.atproto.lexicon.schema record per file in lexicons/, and scripts/check-lexicons.sh walks the whole path a resolver walks — the _lexicon TXT record, the repository it names, then the document — and says which step failed.
The record shape comes from upstream rather than from a reading of the spec: com.atproto.lexicon is now vendored at the commit scripts/refresh-atproto-lexicons.sh already pins, its schema document keys records by NSID and requires only lexicon, so the record is the file byte for byte with a $type added, and a test validates every built record against the vendored meta-schema. Records are built and refused before any sign-in, so a document didbot-schema cannot parse is never written, and an unchanged document is not rewritten.
_lexicon.did.bot goes in infra/site/, pointing at the account the project already answers as: did.bot, did:plc:tt4svy4uvsnuhyvcqd7pgxpw. It is a variable with an output, so rotating the authority is one apply and a reader can ask the zone who it trusts. The checker proves itself against a live authority — app.bsky.feed.post resolves end to end — and reports our own four as unresolvable until the record is applied. Along the way hickory-resolver moves to 0.26 to clear two advisories it carried, and didbot-claim's file session store moves into didbot-authstore so the publisher can reuse it.
🤖 Generated with Claude Code