User Management
Sovrium provisions and manages users without ever requiring you to touch the database. The first administrator is created at boot; every subsequent user is created, listed and managed through the authenticated admin API. Each operation is RBAC-gated and audit-logged.
User management is available only when authentication is configured. The admin plugin turns on the moment an auth block exists — there is no separate flag.
Admin Bootstrap
The first admin cannot be created by another admin (there is none yet) or by self-registration (you do not want a stranger claiming the admin seat). Three complementary paths provision that account on a fresh database.
| Path | When to use | Mechanism |
|---|---|---|
| Env-var bootstrap | Automated / IaC deploys | Set AUTH_ADMIN_EMAIL + AUTH_ADMIN_PASSWORD (+ optional AUTH_ADMIN_NAME); the admin is created on first boot. |
| One-time token | You do not want credentials in env vars | Boot with no AUTH_ADMIN_EMAIL and no users; a 64-hex token is printed in the startup banner and claimed once via POST /api/admin/bootstrap/claim. |
| CLI | Interactive provisioning | sovrium admin create <email> works against the configured database (or the default SQLite file) with no app.yaml required. |
Env-var bootstrap (no-config)
AUTH_ADMIN_EMAIL=admin@example.com
AUTH_ADMIN_PASSWORD=SecureP@ssw0rd!
AUTH_ADMIN_NAME=System Administrator # optional, defaults to "Administrator"On first boot against a fresh database the server provisions the admin with a verified email and full admin-endpoint access. On later startups the path no-ops: it never creates a duplicate and never modifies an existing user, even when the email already maps to a different role. Success is logged without the password.
| Env var | Description |
|---|---|
AUTH_ADMIN_EMAIL |
Email for the bootstrap admin. Required for the env-var path. Must be a valid email format. |
AUTH_ADMIN_PASSWORD |
Initial password. Required for the env-var path. Must meet the minimum length (8 characters). |
AUTH_ADMIN_NAME |
Display name. Optional — defaults to Administrator. |
Bootstrap is gated on a configured auth block. With auth absent, or either of AUTH_ADMIN_EMAIL / AUTH_ADMIN_PASSWORD missing, no admin is created and the server boots without one. The env-var path is also a no-op once any user exists.
One-time token bootstrap
When the server boots with no AUTH_ADMIN_EMAIL set and no users in the database, it generates a 256-bit random token, prints it once in the startup banner, and accepts a single claim:
# Token appears in the banner as:
# → First-admin token (POST /api/admin/bootstrap/claim): <64-hex-token>
curl -X POST http://localhost:3000/api/admin/bootstrap/claim \
-H 'Content-Type: application/json' \
-d '{ "token": "<64-hex-token>", "email": "admin@example.com", "password": "SecureP@ssw0rd!", "name": "Admin" }'- Only the SHA-256 hash is persisted; the plaintext is printed to stdout exactly once and never logged.
- The token expires after 1 hour and can be claimed once — replays return
401. - Once any admin exists the route returns 404: the window has closed, and even a leaked valid token cannot reopen it.
This is the path that makes "run the binary on a fresh server, open the URL, build the app live" possible. See Database Infrastructure for the zero-config database it pairs with.
Creating & Managing Users
Once an admin exists, every user-lifecycle operation runs through the admin API. Each endpoint needs an authenticated admin session — unauthenticated requests return 401, and non-admin sessions get 404: the admin surface is invisible to anyone who cannot use it, so its existence is not discoverable.
| Operation | Endpoint | Notes |
|---|---|---|
| Create user | POST /api/auth/admin/create-user |
Engineer chooses the password; no email is sent. Returns 200. |
| List users | GET /api/auth/admin/list-users |
Paginated (limit/offset), returns count metadata, supports search by email or name. |
| Get user | GET /api/auth/admin/get-user/:id |
Full detail incl. role, ban status, email-verified flag. 404 for unknown ids. |
| Set role | POST /api/auth/admin/set-role |
Assign admin / member / viewer (or any custom role). |
| Set password | POST /api/auth/admin/set-user-password |
Reset a user's password administratively. |
| List sessions | GET /api/auth/admin/list-user-sessions |
Active sessions for a user. |
| Revoke session | POST /api/auth/admin/revoke-user-session |
Force-logout a specific session. |
| Impersonate | POST /api/auth/admin/impersonate-user |
Start/stop impersonation for support workflows. |
Validation is enforced server-side. Create-user returns 400 for a missing or malformed email, a missing password, or an email that already exists. An assigned role must be one the app knows about — a built-in admin / member / viewer, an operator role, or a name declared in auth.roles — and anything else is rejected with 400 listing the valid roles. A role change that would remove the last admin able to sign in is refused with 409. See Roles & RBAC.
create-user requires you to invent and transmit the user's password, and sends them nothing. For onboarding real people, use an invitation instead.
Role Assignment
Moved to Invitations.
Invitation Flow
Moved to Invitations.
Related Pages
- Invitations — passwordless onboarding and the role a new user receives.
- Registration Control — whether the public may self-register.
- Roles & RBAC — role model and field-level permissions.
- Sessions — session lifetime, revocation, multi-device.
- Admin Dashboard — operator-grade read console over users and tables.
- Activity Monitoring — audit trail of user and admin actions.
- Environment Variables — full env-var reference incl.
AUTH_ADMIN_*.
Last updated August 11, 2026
This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.