The names an agent has #
An account is two hostnames, a DID document and a plain-text DID. None of that is a DNS record. This page works one example all the way through: what exists in the zone, what the server answers, and what a stranger reads to get from a name to a repository.
Deployment states the rules this example obeys; the shape of the system draws the hosts around it.
The example #
A zone pds.example, delegated to one server at 203.0.113.10. One account,
minted with a namer, so it has both hostnames a deployment can issue: the
opaque one the DID is minted from, and the issued handle.
| zone | pds.example |
| DID | did:web:7f3a9c.pds.example |
| handle | basalt-kestrel.pds.example |
| PDS endpoint | https://pds.example |
A deployment without a namer has one hostname per account rather than two: the
handle is then the DID's own host, which Provisioner::issued_handle reports
as no issued handle at all, because there is nothing extra to resolve or
withdraw.
A namer draws its name from word lists, and a spec may add n for the
deployment's monotonic counter: mineral+creature+n issues
basalt-kestrel-4813. One counter feeds every template a deployment
configures, so changing the spec keeps counting rather than starting over, and
no count is ever issued twice. What the label then discloses is the count
itself — how many accounts this deployment has minted, and in what order. t
is the other such part: it stamps the current unix time in whole seconds, so
mineral+creature+t issues basalt-kestrel-1790000000 and the label
discloses when the account was minted, to the second. Nothing about the zone
changes; a counted or stamped handle resolves through the same wildcard as any
other.
Everything that exists in DNS #
Three names, and none of them is per-account:
pds.example. NS ns-… (in the parent zone,
added by hand)
pds.example. A 203.0.113.10
*.pds.example. A 203.0.113.10
_acme-challenge.pds.example. TXT "<token>" "<token>" (only while a
certificate is
being issued)
Minting an account writes nothing here. 7f3a9c.pds.example and
basalt-kestrel.pds.example resolve because *.pds.example synthesizes an
answer for them, and they do so the instant the name is chosen — there is no
propagation to wait for and no external call on the provisioning path.
infra/pds/route53.tf writes the wildcard beside the apex, both at the
instance's address. didbot-dns is the zone's writer for the two records a
wildcard cannot stand in for — the _acme-challenge TXT values below and
the apex CAA — and nothing else in the zone changes after tofu apply.
Deployment says what the credential that writes those can
reach.
Everything the server answers #
Both hostnames land on the same listener, and the Host header is the only
thing that says which account a request means. did_json and atproto_did in
didbot-serve's routes both read it, and both derive their answer from one
registry, so the bidirectional check holds by construction: a resolver
following the handle to the DID and the DID to its document always finds the
handle again in alsoKnownAs.
A name no account holds is a 404 rather than an NXDOMAIN, because the
wildcard resolves it and the TLS handshake completes. That is a conformant
answer — a resolver treats any non-200 as unresolvable — and it is the only
one that can express a decommissioned account, which keeps serving its
document and its verification method while its repository is gone.
What the wildcard does not cover #
The apex. *.pds.example does not answer for pds.example. That is a
separate record, and the reason deployment keeps agents off
the apex in the first place.
Any type that is not at the wildcard node. A wildcard holding A answers
NODATA for a TXT query at a synthesized name. Nothing wildcards the ACME
DNS-01 challenge: the authority asks for a literal token at
_acme-challenge.<name>, so a deployment issuing its own certificates needs a
provider that writes real records, and needs two values present at one name
simultaneously to cover both the apex and the wildcard in one order.
Anything below a name that exists. DNS wildcards synthesize at any depth,
but only while no closer node exists — publish a real record at
basalt-kestrel.pds.example and x.basalt-kestrel.pds.example stops
resolving, because the lookup now wants *.basalt-kestrel.pds.example and
finds nothing. The zone holds no per-account record, so nothing shadows the
wildcard; the TLS certificate rules out the deep names anyway.
DNS wildcards and TLS wildcards are not the same rule #
They are easy to conflate and they differ where it matters:
| matches | |
|---|---|
*.pds.example in DNS |
any depth — a.pds.example, a.b.pds.example — while no closer node exists |
*.pds.example in a certificate |
exactly one label, and never the bare parent |
So the constraint on how deep an agent hostname may sit is the certificate,
not the zone. No authority issues a multi-label wildcard, which is why a
deployment with two zones holds two certificates and
didbot_tls::fleet::CertificateFleet keeps one manager per zone.