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

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
215 lines · 8.7 KB Raw History

PDS Endpoint Comparison: pds.js vs atproto/packages/pds

Comparison of endpoints and parameters between this implementation and the official AT Protocol PDS.


Endpoints Missing from pds.js

com.atproto.admin.* (entire namespace missing)

EndpointParams
deleteAccountdid
disableAccountInvitesaccount, note
disableInviteCodesaccounts, codes
enableAccountInvitesaccount, note
getAccountInfodid
getAccountInfosdids
getInviteCodescursor, limit, sort
getSubjectStatusblob, did, uri
searchAccountscursor, email, limit
sendEmailcomment, content, recipientDid, senderDid, subject
updateAccountEmailaccount, email
updateAccountHandledid, handle
updateAccountPassworddid, password
updateAccountSigningKeydid, signingKey
updateSubjectStatusdeactivated, subject, takedown

com.atproto.identity.* (partially implemented)

Still missing:

EndpointParamsNotes
refreshIdentityidentifier
resolveDiddid
resolveIdentityidentifier

pds.js implements: resolveHandle, updateHandle, getRecommendedDidCredentials, requestPlcOperationSignature, signPlcOperation, submitPlcOperation

updateHandle submits a did:plc operation repointing the DID document's alsoKnownAs at the new handle, persists it, and emits an #identity firehose event so consumers re-resolve. It only accepts a handle that resolves back to the account: the server's own address is taken as-is, a subdomain of it is refused (a single-user PDS answers only at its own host), and any other domain must already resolve to the DID via a _atproto DNS TXT record or the HTTPS well-known.

requestPlcOperationSignature mails a confirmation code when the deployment has a sender and the account has a confirmed address, and signPlcOperation then requires it — one code, one operation. Without both, no code is issued and the session remains the only authorization, as before.

com.atproto.server.* (many missing)

EndpointParams
confirmEmailemail, token
createInviteCodeforAccount, useCount
createInviteCodescodeCount, forAccounts, useCount
deleteAccountdid, password, token
getAccountInviteCodescreateAvailable, includeUsed
requestAccountDelete(none)
requestEmailConfirmation(none)
requestEmailUpdate(none)
requestPasswordResetemail
reserveSigningKeydid
resetPasswordpassword, token
updateEmailemail, emailAuthFactor, token

pds.js implements: createAccount, createSession, getSession, refreshSession, deleteSession, createAppPassword, listAppPasswords, revokeAppPassword, describeServer, activateAccount, deactivateAccount, checkAccountStatus, getServiceAuth

createAccount supports the account-migration shape only (adopt an existing did onto an empty single-tenant server), authorized by a service token from the current PDS or the configured account password. The node and cloudflare packages verify the token's signature against the issuer's atproto key — P-256 in core, secp256k1 (the curve the reference PDS gives every account) via @noble/curves — resolving the issuer's DID document to find the key. A token that cannot be verified is rejected. A core-only deployment with no verifier injected falls back to validating the token's claims alone.

com.atproto.sync.* (some missing)

EndpointParams
getBlockscids, did
getHostStatushostname
listHostscursor, limit
listReposByCollectioncollection, cursor, limit
notifyOfUpdatehostname
requestCrawlhostname

pds.js implements: listRepos, getLatestCommit, getRepoStatus, getRepo, getRecord, getBlob, listBlobs, subscribeRepos

com.atproto.repo.* (complete)

pds.js implements: createRecord, deleteRecord, putRecord, applyWrites, getRecord, describeRepo, listRecords, uploadBlob, importRepo, listMissingBlobs

com.atproto.moderation.*

EndpointParams
createReportmodTool, reason, reasonType, subject

com.atproto.temp.* (entire namespace missing)

EndpointParams
addReservedHandlehandle
checkHandleAvailabilitybirthDate, email, handle
checkSignupQueue(none)
dereferenceScopescope
fetchLabelslimit, since
requestPhoneVerificationphoneNumber
revokeAccountCredentialsaccount

Missing Parameters in Shared Endpoints

Endpoints that exist in both implementations, but pds.js is missing parameters:

Endpointpds.js hasMissing from pds.js
repo.createRecordcollection, record, rkey, validaterepo, swapCommit
repo.deleteRecordcollection, rkeyrepo, swapCommit, swapRecord
repo.putRecordcollection, rkey, record, validaterepo, swapCommit, swapRecord
repo.applyWriteswrites, validaterepo, swapCommit
sync.getRepodidsince
sync.listBlobsdid, cursor, limitsince
sync.listRepos(none)cursor, limit
server.createSessionidentifier, passwordallowTakendown, authFactorToken

Bold = likely important for compatibility


app.bsky.* Coverage

Both implementations handle app.bsky.* the same way:

CategoryEndpointsNotes
Native (stored in PDS)actor.getPreferences, actor.putPreferencesBoth implementations
Proxied to AppView~87 endpointsfeed., graph., notification.*, etc.

Extra in pds.js (not in atproto spec)

Custom endpoints specific to this implementation:

EndpointPurpose
POST /initInitialize PDS with DID/keys
GET /statusHealth check

OAuth 2.0 Stack (full implementation)

EndpointPurpose
GET /.well-known/oauth-authorization-serverOAuth server metadata
GET /.well-known/oauth-protected-resourceProtected resource metadata
GET /oauth/jwksJSON Web Key Set
POST /oauth/parPushed Authorization Request
GET/POST /oauth/authorizeAuthorization endpoint
POST /oauth/authorize/passkeyApprove a request with a passkey assertion
POST /oauth/tokenToken endpoint (with DPoP)
POST /oauth/revokeToken revocation

Account pages

Server-rendered, like the consent page; the reference PDS serves the same paths from the React app in @atproto/oauth-provider-ui.

EndpointPurpose
GET /accountAccount home, or the sign-in form when signed out
POST /account/sign-inVerify the account password, start a cookie session
POST /account/sign-outClear the cookie session
GET /account/appsApps holding an OAuth session
POST /account/apps/revokeEnd one app's OAuth session
GET /account/sessionsLogins opened with a password
POST /account/sessions/revokeEnd one password login
GET /account/spacesPermissioned-data spaces, when enabled
GET /account/spaces/recordsThe records in one space collection
GET /account/passkeysRegistered passkeys, and the form to add one
POST /account/passkeys/registerStore a credential the browser created
POST /account/passkeys/revokeForget one passkey
GET /account/passkey/challengeStart a passkey sign-in
POST /account/passkey/sign-inOpen a session from a passkey assertion
GET/POST /account/emailAddress and confirmation state; POST sets it
POST /account/email/verifyExchange the emailed code
POST /account/email/cancelDrop a pending address change
POST /account/email/removeForget the address
GET /account/app-passwordsApp password list and creation form
POST /account/app-passwords/createCreate one, shown exactly once
POST /account/app-passwords/revokeRevoke one by name
GET /account/repoRecord counts by collection, blobs, latest commit
GET /account/repo/recordsThe records in one repo collection
GET /account/identityPublished identity and account status
POST /account/statusActivate or deactivate the account

Summary

Categorypds.jsatproto PDS
com.atproto.admin.*015
com.atproto.identity.*69
com.atproto.moderation.*01
com.atproto.repo.*1010
com.atproto.server.*925
com.atproto.sync.*814
com.atproto.temp.*07
app.bsky.* (native)22
app.bsky.* (proxied)~87~87
Total XRPC (native)3485
Custom endpoints20
OAuth endpoints87 (via @atproto/oauth-provider)
Account pages252 + SPA routes (via @atproto/oauth-provider)