chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
Spaces follow the October 29 alpha
MergedThis moves spaces to the October 29 alpha. A space now holds one policy (personal, member or managed). createSpace, updateSpace, deleteSpace, getSpace and removeWriter are added, and simplespace.* is cut. The memberspace.* methods answer PolicyMismatch on another policy. The policy and member records are published in the authority's repo, and clearRecords is added. The storage migration adds policy_json and converts owned spaces once.
I did not read the whole diff, which is about 5,000 lines. I read CLAUDE.md, the manage.js handlers, the clearRecords handler and the space-schema.js migration. I did not read the clients, the UI, the credential-order change or the test changes.
I found nothing that must change.
- The migration is idempotent. Each statement runs on its own, and the conversion only touches owned spaces whose
policy_jsonis still null. Members are deleted before the conversion, so only managed-app spaces lose them. removeMemberandputMemberwithwrite: falseboth drop the writer, as the description says.updateSpacewithdraws a published member list when a migration discards it.- The changesets are present and CI passed on both runs.
Two small notes, neither blocking:
clearRecordsrunsguardWriteonce per record before any delete, so clearing a very large repo is many sequential awaits. It also loads every record throughlistAllSpaceRecords. Consider a cheaper path if spaces get large.- A member who has been removed may be refused by
guardWritewhen they callclearRecords. That would stop them deleting their own records. Please confirm this matches the reference.
6 passed
Brings spaces up to the reference's October 29 alpha (atproto
11c5d98cd,@atproto/space@0.0.0-spaces-alpha-20261029171913). The knotless side isspaces/memberspaceon knotless, which waits on this.Server
com.atproto.personalspace.policy,com.atproto.memberspace.policyorcom.atproto.managedspace.policy.com.atproto.space.createSpace,updateSpace,deleteSpaceandgetSpacemanage it.com.atproto.simplespace.*is cut, with the older spellings it accepted.com.atproto.memberspace.putMember,removeMemberandlistMembersanswerPolicyMismatchon another policy. Removing a member, or taking itswrite, drops it from the writer set.com.atproto.space.removeWriteris new.getSpaceCredentialchecks the user before the app. A refused user getsSpaceNotFound, a refused appAppNotAuthorized.publishPolicyandpublishMemberskeepcom.atproto.space.policy/selfandcom.atproto.memberspace.member/{did}records in the authority's repo. Direct writes to those collections are refused.com.atproto.space.clearRecordsdeletes the caller's records in a space. It keeps the published records in the authority's repo.Storage migration
SQLite and Durable Object storage add
space.policy_jsonand convert each owned space once, on start, as the reference's migration 006 does. A space with a managing app on either side becomes a managedspace, and its members are dropped. Every other space becomes a memberspace and keeps its members and their rights, so knotless's private-repo spaces keep their collaborators. Public flags and an app allow list carry over. The old columns stay, unread.Clients
spaces-ui edits the policy union. git-ui, the git README, the run club and
dev-spaces-demouse the new methods. The reference harness pins11c5d98cd, and its fixtures are refreshed. It passes in both directions.Not implemented
importRepo,exportSpaceMeta,importSpaceMeta).docs/permissioned-data.mdsays so.clearRecordswrites delete ops to the oplog, where the reference clears it.SpaceAlreadyExists, as before.test/fixtures/space-vectors.jsonstill recordsac0c9f15. The primitives it covers have not changed since then, as the two-way harness shows.Checks
npm run cipasses: 216 test files, 3284 tests.🤖 Generated with Claude Code