Overview
The auth service is a small, standalone Rust server that holds The Test Cabinet’s user accounts. It exists so that every review a run carries can be attributed to a real person rather than being anonymous: it handles registration and login, and mints the bearer tokens the backend verifies on every mutating run request.
Keeping accounts in their own service — separate from the backend — means the backend never stores credentials. The backend treats the auth service as an external dependency it asks “who is this token?”, and nothing more.
Why a separate service
Section titled “Why a separate service”The Test Cabinet’s services sit on a private network, so reachability is the first line of access control (see Backend authentication). That keeps the public internet out, but on a shared private network it does not say who inside it is acting. Reviews need that: a benchmark is more credible when each assessment is owned by a named reviewer, and when a run can gather several independent reviews from different people.
The auth service adds exactly that identity layer, and nothing more. It is an addition to the network boundary, not a replacement: open self-registration is acceptable precisely because reaching the service already requires being on the private network. There is no public sign-up surface.
Responsibilities
Section titled “Responsibilities”The auth service owns user identity end to end:
- Self-registration. Anyone on the private network can create an account with a username, a password, and a display name. Passwords are hashed with Argon2id; a plaintext password is never stored.
- Login. A username and password are exchanged for an opaque bearer token and the account it identifies. The token is what runners, the consoles, and the worker present on mutating calls.
- Verification. The backend hands each request’s bearer token to the auth service, which resolves it to an account (or rejects it). This is the only way the backend learns who is acting; it stores no credentials of its own.
- Logout. A token can be invalidated.
It does not distribute definitions, store run results, render anything, or reach the public internet. Its only state is its own accounts database.
HTTP API
Section titled “HTTP API”The auth service speaks JSON over HTTP. Bodies are camelCase, matching the rest of
the system’s contracts. Tokens are presented as Authorization: Bearer <token>.
POST /auth/register— open self-registration. Body{ username, password, displayName }. Creates the account.POST /auth/login— body{ username, password }. On success returns{ token, account: { id, username, displayName } }: the opaque bearer token and the account it identifies.POST /auth/verify— given a bearer token (theAuthorizationheader), resolves it to its account, or rejects it. Used by the backend to authenticate each mutating run request; it is not a surface end users call directly.POST /auth/logout— invalidates the presented bearer token.
The account and token shapes are specified in
backend-api/auth.schema.json.
The backend proxies POST /auth/register and
POST /auth/login so the consoles have a single origin to talk to, and verifies a
user’s bearer token against the auth service on review and publish.
Who talks to it
Section titled “Who talks to it”- The CLI (
tcab register/login/logout), the Tauri app, and the web console call it to register and log in, then send the resulting bearer token on review/publish. They are pointed at it withTCAB_AUTH_URL. The CLI stores its token at~/.config/tcab/credentials.json(overridable with$TCAB_CONFIG_DIR). - The backend proxies register/login to it and
verifies tokens against it (
TCAB_BACKEND_AUTH_URL, defaulthttp://127.0.0.1:8789).
Status
Section titled “Status”The auth service ships in v0.3.0 as the
tcab-auth-service crate (crates/auth-service): an Axum server with its own
SQLite store of accounts, Argon2id password hashing, and opaque bearer tokens. It
is configured entirely through environment variables:
TCAB_AUTH_BIND— its bind address (default127.0.0.1:8789). The backend binds to8787and the worker to8788, so the three coexist on one host (local dev) or as distinctServices in a namespace (a cluster deployment) without colliding.TCAB_AUTH_DATABASE_URL— its own accounts database, separate from the backend’s database (SQLite by default, or an external database).
Like the backend, it has no public surface and is meant to live on the private network; it stores only Argon2id password hashes, which the backups page covers alongside the backend’s database.