~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0

Spaces follow the October 29 alpha

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/pds.js:spaces-alpha-20261029

Brings spaces up to the reference's October 29 alpha (atproto 11c5d98cd, @atproto/space@0.0.0-spaces-alpha-20261029171913). The knotless side is spaces/memberspace on knotless, which waits on this.

Server

  • A space holds one policy: com.atproto.personalspace.policy, com.atproto.memberspace.policy or com.atproto.managedspace.policy. com.atproto.space.createSpace, updateSpace, deleteSpace and getSpace manage it. com.atproto.simplespace.* is cut, with the older spellings it accepted.
  • com.atproto.memberspace.putMember, removeMember and listMembers answer PolicyMismatch on another policy. Removing a member, or taking its write, drops it from the writer set. com.atproto.space.removeWriter is new.
  • getSpaceCredential checks the user before the app. A refused user gets SpaceNotFound, a refused app AppNotAuthorized.
  • publishPolicy and publishMembers keep com.atproto.space.policy/self and com.atproto.memberspace.member/{did} records in the authority's repo. Direct writes to those collections are refused.
  • com.atproto.space.clearRecords deletes 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_json and 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-demo use the new methods. The reference harness pins 11c5d98cd, and its fixtures are refreshed. It passes in both directions.

Not implemented

  • Account migration of spaces (importRepo, exportSpaceMeta, importSpaceMeta). docs/permissioned-data.md says so.
  • clearRecords writes delete ops to the oplog, where the reference clears it.
  • Re-creating a deleted space is still SpaceAlreadyExists, as before.
  • test/fixtures/space-vectors.json still records ac0c9f15. The primitives it covers have not changed since then, as the two-way harness shows.

Checks

npm run ci passes: 216 test files, 3284 tests.

🤖 Generated with Claude Code

Approved

This 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_json is still null. Members are deleted before the conversion, so only managed-app spaces lose them.
  • removeMember and putMember with write: false both drop the writer, as the description says.
  • updateSpace withdraws a published member list when a migration discards it.
  • The changesets are present and CI passed on both runs.

Two small notes, neither blocking:

  • clearRecords runs guardWrite once per record before any delete, so clearing a very large repo is many sequential awaits. It also loads every record through listAllSpaceRecords. Consider a cheaper path if spaces get large.
  • A member who has been removed may be refused by guardWrite when they call clearRecords. That would stop them deleting their own records. Please confirm this matches the reference.
Merged as 6e99621