mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-23 01:42:27 +00:00
## Summary Client integration for account-level usernames (backend: openfrontio/infra#434). Players get one canonical account name stored as a base plus a server-assigned 4-digit suffix (`bob.4821`); subscribers display the bare base (`bob`) with an exclusive case-insensitive claim on it. - **Schemas** (`src/core/ApiSchemas.ts`): new `player` username fields on `GET /users/@me`, `UsernameStatusSchema`, `PutUsernameResponseSchema`, and an `isTemporaryUsername()` helper. The display name is rendered exactly as the server resolves it — the client never assembles `base.suffix`. Discriminators stay strings (leading zeros). - **API** (`src/client/Api.ts`): `updateUsername()` for `PUT /users/@me/username`, returning a discriminated result covering every documented failure: `invalid` (400), `profane` (400 + `USERNAME_PROFANE`), `taken` (both 409 bodies), `cooldown` (429 + `Retry-After`), `failed`. - **UI** (`src/client/components/UsernamePanel.ts`, in the Account tab): set/change form prefilled with the base, live 3–20 / `[a-zA-Z0-9_-]` validation (`validateAccountUsername`), form locked with the date while the 30-day cooldown runs, grace-period warning for lapsed claim holders, and a free-rename notice after a server-side `TEMPORARY####` rename. The confirm dialog composes warnings by state: 30-day lock always, case-only-change notice, and abandon-reservation warning for `claimed` players. Suffixes are never mentioned in user-facing copy — subscribers should feel like they own the bare name outright. - **Load prompt** (`src/client/Main.ts`): on a clean homepage load, a subscriber renamed to `TEMPORARY####` is prompted to pick a new name (free); takes priority over the rewards popup (the account modal shows rewards anyway). ## Deploy notes **No deploy-order constraint.** All new `/users/@me` fields are optional in the schema: against the current API the response still parses and the panel simply doesn't render (`usernameStatus === undefined`). The client can ship before or after infra#434. ## Test plan - New schema tests (old-API absence, leading-zero discriminators, unknown statuses, PUT payload) and validation tests (dots, spaces, unicode, trim) — full suite passes (2,031 + 171). - Drove the real app headless with synthetic `/users/@me` payloads: verified all panel states (unclaimed, never-set, claimed+grace, TEMPORARY, cooldown-locked, old API hidden), the confirm-dialog warnings, and the inline error path on a failed PUT. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>