When the service is first deployed and there are no users in the database, the UI should present a setup wizard prompting for creation of the first admin account. This bootstrap flow must only be available during initial deployment — once the first admin account is created, the feature is permanently disabled.
Requirements
Backend
New endpoint: GET /api/v1/setup/status (unauthenticated)
Returns { "needs_setup": true } if the volunteers table has zero rows
Returns { "needs_setup": false } otherwise
New endpoint: POST /api/v1/setup/admin (unauthenticated)
Accepts { "name", "email", "password" } to create the first admin account
Guard: Must check that zero users exist in the database before proceeding — if any user exists, return 403 Forbidden
Creates the volunteer with role = 'admin'
Returns a JWT so the user is immediately logged in after setup
Both endpoints should live in a new internal/setup package following the existing domain-based packaging convention
Frontend
Setup page (/setup)
Form with fields: name, email, password, confirm password
If needs_setup is true, redirect all routes to /setup
If needs_setup is false, the /setup route should redirect to /login (or dashboard if authenticated)
Security Considerations
The POST /api/v1/setup/admin endpoint must perform an atomic check-and-insert (e.g., within a transaction) to prevent race conditions where two simultaneous requests could both create admin accounts
Once any user exists, both setup endpoints effectively become no-ops — the backend is the source of truth, not a feature flag
No new environment variables or config flags required — the zero-users check is self-disabling
Acceptance Criteria
Fresh deploy with empty database → UI redirects to /setup
Setup form creates an admin account and logs the user in
After setup, /setup is no longer accessible (redirects away)
POST /api/v1/setup/admin returns 403 if any user already exists
Race condition: two simultaneous setup requests → only one succeeds
All new backend code has corresponding _test.go tests
Setup page has React Testing Library .test.tsx coverage
## Summary
When the service is first deployed and there are no users in the database, the UI should present a setup wizard prompting for creation of the first admin account. This bootstrap flow must only be available during initial deployment — once the first admin account is created, the feature is permanently disabled.
## Requirements
### Backend
- **New endpoint: `GET /api/v1/setup/status`** (unauthenticated)
- Returns `{ "needs_setup": true }` if the `volunteers` table has zero rows
- Returns `{ "needs_setup": false }` otherwise
- **New endpoint: `POST /api/v1/setup/admin`** (unauthenticated)
- Accepts `{ "name", "email", "password" }` to create the first admin account
- **Guard:** Must check that zero users exist in the database before proceeding — if any user exists, return `403 Forbidden`
- Creates the volunteer with `role = 'admin'`
- Returns a JWT so the user is immediately logged in after setup
- Both endpoints should live in a new `internal/setup` package following the existing domain-based packaging convention
### Frontend
- **Setup page (`/setup`)**
- Form with fields: name, email, password, confirm password
- Client-side validation (non-empty fields, password match, minimum password length)
- On success, store JWT and redirect to dashboard
- **App-level routing guard**
- On app load, call `GET /api/v1/setup/status`
- If `needs_setup` is `true`, redirect all routes to `/setup`
- If `needs_setup` is `false`, the `/setup` route should redirect to `/login` (or dashboard if authenticated)
### Security Considerations
- The `POST /api/v1/setup/admin` endpoint **must** perform an atomic check-and-insert (e.g., within a transaction) to prevent race conditions where two simultaneous requests could both create admin accounts
- Once any user exists, both setup endpoints effectively become no-ops — the backend is the source of truth, not a feature flag
- No new environment variables or config flags required — the zero-users check is self-disabling
## Acceptance Criteria
- [x] Fresh deploy with empty database → UI redirects to `/setup`
- [x] Setup form creates an admin account and logs the user in
- [x] After setup, `/setup` is no longer accessible (redirects away)
- [x] `POST /api/v1/setup/admin` returns 403 if any user already exists
- [x] Race condition: two simultaneous setup requests → only one succeeds
- [x] All new backend code has corresponding `_test.go` tests
- [x] Setup page has React Testing Library `.test.tsx` coverage
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
When the service is first deployed and there are no users in the database, the UI should present a setup wizard prompting for creation of the first admin account. This bootstrap flow must only be available during initial deployment — once the first admin account is created, the feature is permanently disabled.
Requirements
Backend
New endpoint:
GET /api/v1/setup/status(unauthenticated){ "needs_setup": true }if thevolunteerstable has zero rows{ "needs_setup": false }otherwiseNew endpoint:
POST /api/v1/setup/admin(unauthenticated){ "name", "email", "password" }to create the first admin account403 Forbiddenrole = 'admin'Both endpoints should live in a new
internal/setuppackage following the existing domain-based packaging conventionFrontend
Setup page (
/setup)App-level routing guard
GET /api/v1/setup/statusneeds_setupistrue, redirect all routes to/setupneeds_setupisfalse, the/setuproute should redirect to/login(or dashboard if authenticated)Security Considerations
POST /api/v1/setup/adminendpoint must perform an atomic check-and-insert (e.g., within a transaction) to prevent race conditions where two simultaneous requests could both create admin accountsAcceptance Criteria
/setup/setupis no longer accessible (redirects away)POST /api/v1/setup/adminreturns 403 if any user already exists_test.gotests.test.tsxcoverageResolved by #2