atproto pds in zig pds.zat.dev
pds atproto
zds docs create-account-flow.md
4.2 kB

create-account flow #

Status: implemented. /signup is the resident-facing account creation page, served from src/internal/signup.zig. This document records the boundary the page is built against and the product decisions that shaped it.

current server surface #

ZDS already implements the protocol account-creation backend:

  • com.atproto.server.describeServer advertises hosted handle suffixes and whether an invite is required.
  • com.atproto.server.reserveSigningKey reserves an account signing key.
  • com.atproto.server.createAccount accepts handle, email, password, inviteCode, and optional signingKey.
  • A normal new account gets a signing key, a PLC genesis operation, durable account/repo state, and an initial access/refresh session.
  • Migration creation for an existing DID is a distinct, service-authenticated path used by tools such as PDS Moover.
  • Invite validation and consumption occur in the same SQLite transaction as account creation.

The production instance advertises .pds.zat.dev, requires an invite, sends mail through Comail, and has wildcard DNS/TLS for hosted account handles.

The resident-facing create-account page is /signup (src/internal/signup.zig). The root page links to it, and the /account hub adopts the session it hands off. The root page, OAuth login, and /account management hub are server-rendered in src/internal/account.zig; XRPC dispatch is in src/atproto/server.zig, route metadata is in src/http/router.zig, and account/invite persistence is in src/storage/store.zig.

invariants for a UI #

A UI should be a client of the existing XRPC behavior, not a second account creation implementation. In particular:

  • Fetch describeServer; do not hard-code invite or handle-domain policy.
  • Submit the complete handle selected by the user and enforce one advertised suffix. Do not infer that the bare PDS hostname is an account suffix.
  • Never log or retain the account password, invite code, session tokens, or PLC key material in browser-visible diagnostics.
  • Preserve the server's XRPC error code and message so invalid invites, handles, existing accounts, PLC failures, and transient server failures are not all rendered as the same error.
  • Treat a successful response as a newly authenticated session and hand it to the resident account experience deliberately.
  • Keep migration out of the normal sign-up form. It has different identity and authorization semantics.

Account creation is security-sensitive and mutates PLC plus local persistent state. Add an end-to-end smoke case for the browser flow rather than relying only on DOM tests. Use a disposable local database for destructive tests and a fresh invite for each attempted creation.

product decisions #

Decisions made for /signup (layout studied against selfhosted.social's join page):

  • the page asks for a short name; the suffix comes from describeServer and is rendered as an attached segment with a live "you'll be name.suffix" preview (a select appears if more than one suffix is advertised)
  • the invite is a visible form field, shown only when inviteCodeRequired, and prefillable via /signup?code=... so invites can be shared as links
  • on success the session is handed to /account via a one-shot sessionStorage key (zds-signup-session); email verification and passkey registration are offered there by the existing manage and security sections
  • migration is kept out of the form as a notice panel linking to PDS Moover
  • the page carries a short honest note that this is an experimental PDS

checks and references #

Before changing account semantics, compare the current AT Protocol account lexicons and both mature references listed in references. Relevant local guides are invite codes, account security, passkeys, Comail, and production deployment.

At minimum, retain the existing just smoke coverage and add browser-flow coverage for validation errors and successful creation. Browser-reported failures require the actual request, response, and server log evidence before the server behavior is changed.