Authentication
Two credentials reach /v1: a session cookie for a person at a browser, and a bearer API key for a program. Both resolve to scopes.
Registration
POST /v1/auth/register is public and unauthenticated — it is how a caller obtains the credential everything under /v1 requires. It creates the account as an admin, creates the project it names, and sets the session cookie. Later accounts are invited instead, through POST /v1/users, which takes a role and needs users:write.
Rate limiting belongs at the edge
Key format
Authorization: Bearer neu_<environment>_<prefix>.<secret>The part before the dot is the indexed lookup prefix; the comparison against the stored digest is constant time. Only a SHA-256 digest is stored, so a key you did not record at creation is gone — issue a new one rather than hunting for it.
Scopes are the model
A key is not attached to a project. Scopes are the entire authorization model, so pinning a key to one project would both duplicate that decision and cap the key for no reason. Projects scope resources, not callers.
["apps:read", "apps:write",
"deployments:read", "deployments:write",
"builds:read",
"executions:read", "executions:write",
"projects:read", "projects:write",
"users:read", "users:write",
"api_keys:read", "api_keys:write",
"*"]A limited key cannot mint an unlimited one
* covers everything, including scopes added in later releases.Dashboard sessions
POST /v1/auth/login answers with an HttpOnly, Secure, SameSite=Strict cookie, so the dashboard holds no credential a script could read. GET /v1/auth/session returns the dashboard, their role and their scopes; POST /v1/auth/logout ends it. A signed-in user is unrestricted by project — roles are admin, operator and viewer.
Where a key may live
- allowed
- A server-side secret store, a CI secret, an environment variable on the machine that calls the API.
- refused
- localStorage, a query string, a URL fragment, a breadcrumb, a log line, or anything the browser persists across tabs.
Revocation
DELETE /v1/api-keys/{id} sets revoked_at and is idempotent — revoking twice keeps the first timestamp. Nothing restores a revoked key; no configuration re-asserts it at boot. Deleting the user who created a key leaves the key working, with its attribution cleared.