devarno
read
back to downlink

$ downlink · build

the atmosphere, part 1: the map

my account started this series with two posts and no followers. its repo already holds records from two different apps. a map of atproto, drawn by walking one record outward from a server i run.

Devarno·September 28, 2026·6min

atproto · bluesky · did_web · protocols · devlog

the atmosphere, part 1: the map

§ sections

  • start with one question to my own server
  • pick one record and follow it
  • the repo is a signed ledger, and it has a version
  • where the record goes when i'm not looking
  • a stranger reads it back
  • what's next

my account on the atmosphere started this series with two posts and no followers. it's a good specimen. nothing about it is big enough to hide how it works.

the identity is did:web:devarno.com. the handle is @null0.blue. the data lives on pds.devarno.com, a server i run, which takes new accounts by invite only, and every account on it is one of mine. this series is five walks through that account, one a week. this first one draws the map by starting at a single record and following it outward until it reaches someone who has never heard of me.

$ downlink · the tapestry

devarno.com

panel 1 of 5. i keep a notebook at my own address. anyone can read it, and anyone can check it's mine.

  1. devarno.com

    1 · this part

  2. 2 · not yet woven

  3. ???

    3 · not yet woven

  4. 4 · not yet woven

  5. app.bskysh.tangled

    5 · not yet woven

start with one question to my own server

every request in this piece is live. the button on each one sends the same request from your browser and shows what the server says today next to what it said when i wrote this.

$ xrpc

GET pds.devarno.com/xrpc/com.atproto.repo.describeRepo

repo = did:web:devarno.com

handle
null0.blue
handleIsCorrect
true
collections
  • bsky.appapp.bsky.actor.profileapp.bsky.feed.postapp.bsky.graph.follow
  • bsky.chatchat.bsky.actor.declaration
  • tangled.sh (a different app)sh.tangled.actor.profile

published response · run it to compare with what the server says now

five collections. four of them start with bsky. the fifth belongs to tangled, a code forge with no connection to bluesky, and its profile record for me sits in the same repo as my posts.

the repo is mine. what goes into it is decided by whichever apps i let write there, and each one labels its records with a name it owns.

pick one record and follow it

the record i trust most is my profile. i wrote it with putRecord in june to prove the identity worked. its address:

$ at-uri

at://did:web:devarno.com/app.bsky.actor.profile/self

at://did:web:devarno.comwhose repo/app.bsky.actor.profilewhat kind of record/selfwhich one

read left to right, that address is a route. the did says whose repo. the collection says what kind of record. self is the key inside the collection. nothing in it names a server. to find the bytes, you resolve the did first.

resolving one record from its address to the bytesthe handle null0.blue resolves, through a dns txt record and a well-known file, to the identity did:web:devarno.com. that identity resolves to a did document served from devarno.com. the document names a pds at pds.devarno.com and a signing key. the pds serves the repo, the repo holds the profile record, and the published key checks the signature on the repo.dns txt / well-knownhttps fetchservice endpointverification keychecks the signature on@null0.bluedid:web:devarno.comdid.json on devarno.compds.devarno.com#atproto signing keyrepoprofile/self

the did document is a small json file on devarno.com. it says two things that matter here: my data is at https://pds.devarno.com, and commits to that data are signed by the key listed under #atproto. change either line and the account moves or re-keys. no directory has to agree.

i came to this from networking, and the shape is familiar. the handle is an advertised route. the did is the address that routes resolve to. software stores the did and looks the handle up when it needs a name to show, which is why i can change the handle without breaking anything that points at me.

the repo is a signed ledger, and it has a version

$ xrpc

GET pds.devarno.com/xrpc/com.atproto.sync.getLatestCommit

did = did:web:devarno.com

cid
bafyreiep3lpk46ujw5wymhkt5337un2rybh52ue25za7c2mhx6ll72n5fa
rev
3mour3bhkkk2p

published response · run it to compare with what the server says now

every write to the repo produces a new commit, signed with the key from the did document. the rev moves forward with each one. anyone holding the commit and the did document can check the signature without asking my server whether it's telling the truth.

the repo is designed to be audited by people who don't trust the host. i build verifiable-state systems for a living, and i want to know whether this one holds the way mine have to. part 2 opens it up.

where the record goes when i'm not looking

my server doesn't wait to be asked. when the repo changes, it announces the change on an outbound stream, and anything that wants my data can subscribe. i don't run anything on the reading side. that belongs to other people.

the parts of this account i run and the parts i borrowon my side, the handle null0.blue points at the did document on devarno.com, which points at the pds at pds.devarno.com holding the repo. the pds streams repo changes outward. on the side i do not run, stream consumers pass what they collect to readers such as the public bluesky appview at public.api.bsky.app, which checks what it reads against the did document on my domain.change streamchecks againstrun by othersstream consumerspublic.api.bsky.apprun by menull0.bluedid.json on devarno.compds.devarno.com

so the map has a border, and it's easy to find. everything on my side of it i can change with a deploy. everything past it, i can only check.

a stranger reads it back

in june i ran one check to close out the setup. i asked the public bluesky appview, which i've never configured or contacted, who null0.blue is. it still answers the same way:

$ xrpc

GET public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle

handle = null0.blue

did
did:web:devarno.com

published response · run it to compare with what the server says now

and what it knows about the account:

$ xrpc

GET public.api.bsky.app/xrpc/app.bsky.actor.getProfile

actor = did:web:devarno.com

handle
null0.blue
postsCount
2
followersCount
0
createdAt
2026-06-18T21:29:55Z

published response · run it to compare with what the server says now

it learned all of that from the stream, then checked it against the file on my domain. my server never told it anything directly.

what's next

part 2 goes inside the repo: what a commit holds and what the rev counts. the test i care about is whether i can verify my own history from the raw bytes without trusting the server i run.

if you want the whole protocol laid out in one long read first, kuba suder's introduction to at protocol is the reference i'd hand anyone starting out.

every claim above was checked against live endpoints on 23 september 2026. you can rerun them:

$ verifychecks run from your browser
identity docdevarno.com/.well-known/did.json
repo contentspds.devarno.com/xrpc/com.atproto.repo.describeRepo?repo=did:web:devarno.com
read it backpublic.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?handle=null0.blue

photos: alexander gluschenko (cover) and liane metzler (card), via unsplash.

$ the atmosphere · part 1 of 5

  1. part 1you are here
  2. part 2 · inside the repocan i verify my own history from the raw bytes, without trusting my own server?
  3. part 3 · two keys and a domainwhat does it cost to own the root of an identity?
  4. part 4 · who's listeningwho picks up what my server announces, and what do they check?
  5. part 5 · the second appwhat carries over when the same identity signs into an app that isn't bluesky?

part 2, inside the repo, is on its way. subscribe below and it lands in your inbox.

$ related field reports

  • my automation factory: step inside

    March 1, 2026read →
  • the spec was already correct. then i watched the film.

    June 29, 2026read →
  • building skyflow 1.1

    February 5, 2025read →
$ sharex ↗linkedin ↗hacker news ↗

downlink shows the off-duty hours across everything i build. the protocol work is logged at null0.blue/journal.

i don't post often. when i do, something happened.

$ what comes next

stratt.blue ↗devaqua.blue ↗tangled ↗