A zero-dependency AT Protocol Personal Data Server written in JavaScript
atproto pds

docs: add endpoint comparison vs official atproto PDS

Documents coverage gaps and parameter differences between pds.js and
the official AT Protocol PDS implementation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Changed files
+195
docs
+2
README.md
··· 24 24 - [ ] Admin/moderation 25 25 - [ ] Rate limiting 26 26 27 + See [endpoint comparison](docs/endpoint-comparison.md) for detailed coverage vs the official atproto PDS. 28 + 27 29 ## Prerequisites 28 30 29 31 - Node.js 18+
+193
docs/endpoint-comparison.md
··· 1 + # PDS Endpoint Comparison: pds.js vs atproto/packages/pds 2 + 3 + Comparison of endpoints and parameters between this implementation and the official AT Protocol PDS. 4 + 5 + --- 6 + 7 + ## Endpoints Missing from pds.js 8 + 9 + ### com.atproto.admin.* (entire namespace missing) 10 + 11 + | Endpoint | Params | 12 + |----------|--------| 13 + | deleteAccount | did | 14 + | disableAccountInvites | account, note | 15 + | disableInviteCodes | accounts, codes | 16 + | enableAccountInvites | account, note | 17 + | getAccountInfo | did | 18 + | getAccountInfos | dids | 19 + | getInviteCodes | cursor, limit, sort | 20 + | getSubjectStatus | blob, did, uri | 21 + | searchAccounts | cursor, email, limit | 22 + | sendEmail | comment, content, recipientDid, senderDid, subject | 23 + | updateAccountEmail | account, email | 24 + | updateAccountHandle | did, handle | 25 + | updateAccountPassword | did, password | 26 + | updateAccountSigningKey | did, signingKey | 27 + | updateSubjectStatus | deactivated, subject, takedown | 28 + 29 + ### com.atproto.identity.* (mostly missing) 30 + 31 + | Endpoint | Params | Notes | 32 + |----------|--------|-------| 33 + | getRecommendedDidCredentials | (none) | | 34 + | refreshIdentity | identifier | | 35 + | requestPlcOperationSignature | (none) | | 36 + | resolveDid | did | | 37 + | resolveIdentity | identifier | | 38 + | signPlcOperation | alsoKnownAs, rotationKeys, services, token, verificationMethods | | 39 + | submitPlcOperation | operation | | 40 + | updateHandle | handle | | 41 + 42 + *pds.js only implements: resolveHandle* 43 + 44 + ### com.atproto.server.* (many missing) 45 + 46 + | Endpoint | Params | 47 + |----------|--------| 48 + | activateAccount | (none) | 49 + | checkAccountStatus | (none) | 50 + | confirmEmail | email, token | 51 + | createAccount | did, email, handle, inviteCode, password, plcOp, recoveryKey, verificationCode, verificationPhone | 52 + | createAppPassword | name, privileged | 53 + | createInviteCode | forAccount, useCount | 54 + | createInviteCodes | codeCount, forAccounts, useCount | 55 + | deactivateAccount | deleteAfter | 56 + | deleteAccount | did, password, token | 57 + | deleteSession | (none) | 58 + | getAccountInviteCodes | createAvailable, includeUsed | 59 + | getServiceAuth | aud, exp, lxm | 60 + | listAppPasswords | (none) | 61 + | requestAccountDelete | (none) | 62 + | requestEmailConfirmation | (none) | 63 + | requestEmailUpdate | (none) | 64 + | requestPasswordReset | email | 65 + | reserveSigningKey | did | 66 + | resetPassword | password, token | 67 + | revokeAppPassword | name | 68 + | updateEmail | email, emailAuthFactor, token | 69 + 70 + *pds.js implements: createSession, getSession, refreshSession, describeServer* 71 + 72 + ### com.atproto.sync.* (some missing) 73 + 74 + | Endpoint | Params | 75 + |----------|--------| 76 + | getBlocks | cids, did | 77 + | getHostStatus | hostname | 78 + | listHosts | cursor, limit | 79 + | listReposByCollection | collection, cursor, limit | 80 + | notifyOfUpdate | hostname | 81 + | requestCrawl | hostname | 82 + 83 + *pds.js implements: listRepos, getLatestCommit, getRepoStatus, getRepo, getRecord, getBlob, listBlobs, subscribeRepos* 84 + 85 + ### com.atproto.repo.* (some missing) 86 + 87 + | Endpoint | Params | 88 + |----------|--------| 89 + | importRepo | (binary) | 90 + | listMissingBlobs | cursor, limit | 91 + 92 + *pds.js implements: createRecord, deleteRecord, putRecord, applyWrites, getRecord, describeRepo, listRecords, uploadBlob* 93 + 94 + ### com.atproto.moderation.* 95 + 96 + | Endpoint | Params | 97 + |----------|--------| 98 + | createReport | modTool, reason, reasonType, subject | 99 + 100 + ### com.atproto.temp.* (entire namespace missing) 101 + 102 + | Endpoint | Params | 103 + |----------|--------| 104 + | addReservedHandle | handle | 105 + | checkHandleAvailability | birthDate, email, handle | 106 + | checkSignupQueue | (none) | 107 + | dereferenceScope | scope | 108 + | fetchLabels | limit, since | 109 + | requestPhoneVerification | phoneNumber | 110 + | revokeAccountCredentials | account | 111 + 112 + --- 113 + 114 + ## Missing Parameters in Shared Endpoints 115 + 116 + Endpoints that exist in both implementations, but pds.js is missing parameters: 117 + 118 + | Endpoint | pds.js has | Missing from pds.js | 119 + |----------|------------|---------------------| 120 + | repo.createRecord | collection, record, rkey | **repo**, **validate**, swapCommit | 121 + | repo.deleteRecord | collection, rkey | **repo**, swapCommit, swapRecord | 122 + | repo.putRecord | collection, rkey, record | **repo**, **validate**, swapCommit, swapRecord | 123 + | repo.applyWrites | writes | **repo**, validate, swapCommit | 124 + | sync.getRepo | did | since | 125 + | sync.listBlobs | did, cursor, limit | since | 126 + | sync.listRepos | (none) | cursor, limit | 127 + | server.createSession | identifier, password | allowTakendown, authFactorToken | 128 + 129 + **Bold** = likely important for compatibility 130 + 131 + --- 132 + 133 + ## app.bsky.* Coverage 134 + 135 + pds.js implements only 2 app.bsky endpoints natively (rest proxy to AppView): 136 + 137 + | Implemented Natively | Count | 138 + |---------------------|-------| 139 + | actor.getPreferences | | 140 + | actor.putPreferences | | 141 + 142 + | Proxied to AppView | ~87 endpoints | 143 + |--------------------|---------------| 144 + | actor.getProfile, actor.getProfiles, feed.*, graph.*, notification.*, etc. | | 145 + 146 + --- 147 + 148 + ## Extra in pds.js (not in atproto spec) 149 + 150 + Custom endpoints specific to this implementation: 151 + 152 + | Endpoint | Purpose | 153 + |----------|---------| 154 + | `POST /init` | Initialize PDS with DID/keys | 155 + | `GET /status` | Health check | 156 + | `POST /register-did` | Register a DID | 157 + | `GET /get-registered-dids` | List registered DIDs | 158 + | `POST /register-handle` | Register a handle | 159 + | `GET /resolve-handle` | Resolve handle (non-XRPC path) | 160 + | `POST /forward-event` | Forward sync events to other instances | 161 + | `GET /repo-info` | Get repository info | 162 + | `GET /oauth-public-key` | Get OAuth public key | 163 + | `POST /check-dpop-jti` | DPoP replay protection | 164 + 165 + ### OAuth 2.0 Stack (full implementation) 166 + 167 + | Endpoint | Purpose | 168 + |----------|---------| 169 + | `GET /.well-known/oauth-authorization-server` | OAuth server metadata | 170 + | `GET /.well-known/oauth-protected-resource` | Protected resource metadata | 171 + | `GET /oauth/jwks` | JSON Web Key Set | 172 + | `POST /oauth/par` | Pushed Authorization Request | 173 + | `GET/POST /oauth/authorize` | Authorization endpoint | 174 + | `POST /oauth/token` | Token endpoint (with DPoP) | 175 + | `POST /oauth/revoke` | Token revocation | 176 + 177 + --- 178 + 179 + ## Summary 180 + 181 + | Category | pds.js | atproto PDS | 182 + |----------|--------|-------------| 183 + | com.atproto.admin.* | 0 | 15 | 184 + | com.atproto.identity.* | 1 | 9 | 185 + | com.atproto.moderation.* | 0 | 1 | 186 + | com.atproto.repo.* | 8 | 10 | 187 + | com.atproto.server.* | 4 | 25 | 188 + | com.atproto.sync.* | 8 | 14 | 189 + | com.atproto.temp.* | 0 | 7 | 190 + | app.bsky.* (native) | 2 | 89 | 191 + | **Total XRPC** | **23** | **170** | 192 + | Custom endpoints | 10 | 0 | 193 + | OAuth endpoints | 7 | 7 (via @atproto/oauth-provider) |