id: agent-sites
title: An agent publishes a page of its own, at a name the zone already serves
status: open
crates: [didbot-pds, didbot-serve, didbot-dns, didbot-lexicon]
dependsOn: [agent-accounts, pds-writes]
exitCriterion: >
An agent writes a page, a stranger opens it over HTTPS at a hostname that is
that agent's, its profile points at it, and deprovisioning takes the page and
the name away together. #
Half of this is one field. website on app.bsky.actor.profile is a string
with a URI format, and it points wherever the account says. For an
account that is a service rather than a session that is the useful one: the
operator's page, the source it was built from, the documentation for what it
does.
The other half is why it is an epic. This deployment can be the thing the field
points at, and almost by accident. Every account already has a hostname of its
own, a DNS record that makes it resolve, and a server answering HTTP there —
that is what did:web costs and it was paid at provisioning. A static document
per agent host is built: /.well-known/did.json is one. Serving a page an
agent wrote is the same three steps with different bytes behind them, and the
zone management agent-accounts needs for identity is the
zone management this needs too.
None of which makes it free. The cheap part is serving bytes; the parts that
are not are what an agent is allowed to put in them, and whose origin they land
on.
deployment recommends the layout: the server at the
apex, agents in a subzone beneath it. That makes every agent host a sibling of
the server's own under one registrable domain, which is fine while the only
thing served at an agent host is a document a resolver fetches.
It stops being fine when a browser is involved. Cookies are scoped by domain
rather than by origin, and any host may set one for a parent domain that is not
a public suffix — so a page an agent wrote can set a cookie the server's own
origin is handed back. oauth, ops-dashboard and
policy-dashboard are all browser sessions in that zone.
The fix is a separate registrable domain for agent-authored content, and it
contradicts the recommended layout that put agents inside the server's own
registrable domain. One of the two gives, and this is the epic that has to say
which.
site sits next to this problem without answering it: did.bot is
the marketing origin, safe on the apex domain precisely because it has no
session of its own and nothing in it an agent wrote. Whether an operator's
dashboard or an agent's own page ever shares that origin is still this
epic's call, not that one's.
Nothing. What it stands on exists: one hostname per agent, contained in the
server's zone and checked label by label; a DNS provider trait with a loopback
backend behind it; a blob store that never holds a whole blob in memory; and
static documents already served per agent host.