# 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](references.md). Relevant local guides are [invite codes](invite-codes.md), [account security](account-security.md), [passkeys](passkeys.md), [Comail](comail.md), and [production deployment](deployment.md). 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.