Skip to main content
View as Markdown

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)

>_ terminal
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.

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:

>_ terminal
# 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.

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.

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.

Built with Sovrium