From a6509f6456f586084870dfcf6b9c61f380059396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Sun, 23 Aug 2026 21:02:14 +0000 Subject: [PATCH] docs: account creation exists, and has since 69a31051 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three files said there was no way to create a second account. There is: POST /api/users, owner-gated, with a form under Settings -> User Management, plus role change, password reset, Linux provisioning and delete. The plan went further and sequenced a whole phase around building it. It cost something today. A recommendation to "do phase 5 first, it unblocks everything" was made from this text, and withdrawn only because opening api/users/ to write the spec found the route already there. Worth naming the shape rather than just fixing the sentences: docs:check compares numbers, so the counts stay honest while the prose rots. Both times this has bitten, the stale claim was a paragraph nothing could verify. A phase marked "not built" is worth checking against the tree before planning around it — a plan is written once, the code moves daily. The root CLAUDE.md carries the same correction plus the roles-as-a-table state; it is not in a git repo, so it is fixed on disk only. Co-Authored-By: Claude Opus 5 Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043 --- CLAUDE.md | 13 +++++++++---- docs/roles-and-teams.md | 19 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e13ac457..d946be26 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -38,10 +38,15 @@ anything under `execution`. **Mounting a router without a registry entry makes the server refuse to boot** — see "Permissions" below before adding one. -**Still single-user: account creation.** `createUser` has exactly one call site, `auth/bootstrap.ts`, -gated on an empty table. There is no signup route, no invite flow and no admin create-user handler, so -every existing member was inserted into Postgres by hand. That is the largest gap in the model, not a -deliberate boundary. +**Account creation exists.** `POST /api/users` (owner-gated), with a form under Settings → User Management: +it validates the password with the same rules bootstrap uses, refuses a role that is not a row in `roles`, +refuses `Super Admin` outright because there is exactly one owner, optionally takes an inbound SSH key, and +provisions the Linux account. `POST /users/:id/provision-linux` retries that half if the host was not ready. + +This file said "there is no way to create a second account" for some days after `69a31051` shipped one, and +`docs/roles-and-teams.md` sequenced a whole phase around building it. Neither is checkable by +`bun run docs:check` — it compares numbers, and this was prose. Worth knowing as the shape of the failure: +the counts stay right and the sentences rot. ## Architecture diff --git a/docs/roles-and-teams.md b/docs/roles-and-teams.md index 8818f813..44b44bed 100644 --- a/docs/roles-and-teams.md +++ b/docs/roles-and-teams.md @@ -179,14 +179,21 @@ D8's warning in front of whoever writes the first script. code — `permissions/authorize.test.ts` is already pure and mockless, which is what makes that possible. 4. Teams UI, and the account screen showing which teams a user is in and as what. -### Phase 5 — the thing that actually unblocks all of it +### Phase 5 — account creation — **DONE, and it was done before this phase was written** -**There is still no way to create a second account.** `createUser` has one call site, `auth/bootstrap.ts`, -gated on an empty table; the existing accounts were inserted by hand. Roles and teams are a permission model -for accounts that cannot yet exist. +`POST /api/users` is owner-gated and live, with a form under Settings → User Management: same password +validator as bootstrap, a role checked against the `roles` table, `Super Admin` refused outright, an +optional inbound SSH key, and Linux provisioning with `POST /users/:id/provision-linux` to retry it. +Alongside it: role change, password reset, delete. -Sequenced last here because it is orthogonal, and flagged because a reader will otherwise finish phase 4 and -find nothing to test it with. **It may be worth doing first.** +It shipped in `69a31051`. This section spent days telling readers it did not exist and sequencing work +around building it — and on 2026-08-23 it produced a concrete cost, when a recommendation to "do phase 5 +first" was made from this text and withdrawn only because someone opened `api/users/` to write the spec. + +The general lesson, since it is the second time this exact shape has bitten: `bun run docs:check` compares +numbers, so counts stay honest while prose rots quietly. **A phase marked as not built is worth verifying +against the tree before it is planned around**, not because the plan was careless but because a plan is +written once and the code moves every day. ---