From 127c563c1deee517024bf7668325a2afb236e157 Mon Sep 17 00:00:00 2001 From: OpenVelo Agent Date: Tue, 21 Jul 2026 17:38:20 +0000 Subject: [PATCH] docs: update documentation to OKF v0.1 format --- docs/api/setup.md | 2 +- docs/database/users.md | 24 ++++++++++++++++++++---- docs/index.md | 2 +- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/docs/api/setup.md b/docs/api/setup.md index 0a8ad8b..2afaed7 100644 --- a/docs/api/setup.md +++ b/docs/api/setup.md @@ -3,7 +3,7 @@ type: api title: Setup Endpoint description: Dedicated POST /api/v1/setup/create-admin endpoint used only while no administrator exists. tags: [api, setup, bootstrap, first-admin] -timestamp: 2026-07-21T17:18:08Z +timestamp: 2026-07-21T17:37:18Z --- # Endpoint diff --git a/docs/database/users.md b/docs/database/users.md index c09c6c9..30b0e66 100644 --- a/docs/database/users.md +++ b/docs/database/users.md @@ -3,7 +3,7 @@ type: database title: User Table description: The `user` table — accounts, roles, and statuses. tags: [database, user, auth] -timestamp: 2026-07-21T14:43:00Z +timestamp: 2026-07-21T17:37:18Z --- # Schema @@ -37,14 +37,30 @@ timestamp: 2026-07-21T14:43:00Z When the `user` table is empty of admins, the dedicated `POST /api/v1/setup/create-admin` endpoint (see [Setup Endpoint](/api/setup.md)) creates the very first admin and -auto-issues a session. Once any admin row exists the endpoint becomes -inert and returns `404 NOT_FOUND`, so the route is effectively hidden -in production. +auto-issues a session. Once any admin row exists the endpoint rejects +further attempts with `409 SYSTEM_INITIALIZED`, so the route is +effectively hidden in production. The legacy `POST /api/v1/auth/register-first-admin` route is preserved for compatibility but the canonical first-admin flow now lives in the `SetupModule`. +# Concurrent bootstrap safety + +Two near-simultaneous `POST /api/v1/setup/create-admin` requests cannot +both succeed. `SetupService.createAdmin` serializes callers on an +in-process promise chain (`#bootstrapChain` + private +`runBootstrap()` in `backend/src/modules/setup/setup.service.ts:111-130`) +so that the first request commits inside its `DataSource.transaction` +before the second request's transaction executes. The loser's +transaction observes `adminCount > 0` and throws +`ApiError(SYSTEM_INITIALIZED, 409)`; the winner is the only request that +creates a `UserEntity(role='admin')` row and mints a refresh token. +The lock is per-process; multi-replica deployments rely on the unique +index and transaction guard, not on this chain. The regression test is +`tests/backend/setup-create-admin.spec.ts` ("only one of two concurrent +first-admin requests succeeds"). + # See also - [Auth and Settings Tables](/database/auth-settings.md) diff --git a/docs/index.md b/docs/index.md index 52a3e5d..24c2b2a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ scoreboard, an event window with a public countdown, theming, and admin controls. The docs below are organized by purpose so agents can pull just the slice -they need. Last regenerated 2026-07-21T17:18:08Z. +they need. Last regenerated 2026-07-21T17:37:18Z. # Architecture