- TypeScript 51%
- Svelte 48%
- CSS <1%
- JavaScript <1%
- HTML <1%
PDS MOOver (OAuth beta) #
A SvelteKit app that moves an Atmosphere account from one PDS to another. This branch is the OAuth beta: the user's current account is signed in through their own PDS with atproto OAuth and granular permission scopes instead of a password. Everything runs in the browser; the server only serves pages and the OAuth client metadata.
What it does #
/moover– migrate an account (create the account on the new PDS with a service-auth token, import the repo, copy blobs and preferences, sign the PLC operation, activate, deactivate the old account). The user picks a password for the new account. Deactivating the old account needs theaccount:status?action=manageOAuth permission; PDSs that don't allow it get the UI explaining how to do it by hand./missing-blobs– copy blobs a previous migration missed from the old PDS to the current one./rotation-key– add a rotation key the user controls to their did:plc identity.
OAuth scopes #
Each page requests only what it needs; /oauth-client-metadata.json advertises the union.
| Page | Scope |
|---|---|
| Migration | atproto account:email rpc:com.atproto.server.createAccount?aud=* rpc:app.bsky.actor.getPreferences?aud=did:web:api.bsky.app#bsky_appview identity:* |
| Missing blobs | atproto blob:*/* |
| Rotation key | atproto identity:* |
See src/lib/oauth/scopes.ts for what each permission unlocks.
Development #
pnpm install
pnpm dev # http://127.0.0.1:5173 (must be 127.0.0.1, see below)
pnpm check # svelte-check
pnpm lint
pnpm test # vitest
pnpm lex:generate # regenerate src/lib/lexicons from ./lexicons
Locally the app uses an atproto loopback OAuth client: the redirect URI and scope are encoded
in the client_id, and authorization servers only accept 127.0.0.1 as the redirect host. Vite is
pinned to 127.0.0.1:5173 for that reason; opening localhost will not sign in.
Deploying (Railway) #
railway.json uses Railpack (pnpm, pnpm build, node build). Set these variables:
| Variable | Value |
|---|---|
PUBLIC_APP_URL |
https://<your domain> – builds the client_id and redirect URI |
ORIGIN |
same URL, required by @sveltejs/adapter-node |
PUBLIC_XRPC_BASE |
host (no scheme) of the PDS MOOver XRPC API for backups/restore/stats; defaults to xrpc.pdsmoover.com |
PUBLIC_HUBBLE_URL |
base URL of the Hubble mirror used as an alternate restore source; defaults to the test instance |
Destination PDSs are listed by the public com.pdsmoover.pds.listPds/searchPds endpoints on the
same PUBLIC_XRPC_BASE API.
PORT is injected by Railway. After deploying, https://<your domain>/oauth-client-metadata.jsonn must
be reachable; that URL is the OAuth client_id.
License #
MIT, see LICENSE.md.