chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
# Track Tuesdays
A run club on permissioned data (proposal 0016). Two accounts on two PDS
instances share a private space: Maya organizes the club and logs runs on her
PDS, Sam logs his on his own, and a feed page assembles the week the way a real
application would — as a syncer, the one role the PDS itself does not play.
```bash
docker compose up -d # local PLC directory
npm run dev:runclub # boots everything, feed at http://localhost:2800
```
What the demo exercises, over plain HTTP:
1. `com.atproto.space.createSpace` under the `com.atproto.memberspace.policy`
policy, then `com.atproto.memberspace.putMember` for Sam. Maya's PDS is the
space authority, and every policy admits the authority, so she is not on
the member list.
2. `com.atproto.space.createRecord` — each member's runs land in their own
repo on their own PDS. Sam's PDS notifies the authority, which is how his
repo enters the writer set.
3. `getDelegationToken` → `getSpaceCredential` — the app trades Maya's session
for a credential signed by the space authority and bound to a P-256 key the
app made for it (`credentialKid`).
4. `listRepos` → `getRepo` per member — the writer set from the authority,
then each repo from its own host as a STAR archive, using only the
credential, signed by its key for the account each read is addressed to.
5. Client-side verification before rendering (`sync.js`): each `getRepo` asks
for a MAC against the member's `#atproto_kem` key; the commit must carry
it, and every record, folded into a set hash, must reproduce the commit's
data. The page's footer shows the receipts.
Run records use integers (`distanceMeters`, `durationSec`) — atproto records
avoid floats; the page derives km and pace.
State lives in `.data/` and is wiped on every boot, so the demo is repeatable.