runlot
ReferenceAPI

App user authentication

Covers 6 API operations in the app-auth category.

MethodPathDescription
GET/v1/orgs/{orgSlug}/projects/{projectName}/authEnd-user auth status (runlot auth)
POST/v1/orgs/{orgSlug}/projects/{projectName}/authTurns on auth (runlot deploy calls this after reading the "auth": true declaration)
PATCH/v1/orgs/{orgSlug}/projects/{projectName}/authChange settings (runlot auth set)
DELETE/v1/orgs/{orgSlug}/projects/{projectName}/authDisables auth (runlot auth delete)
PUT/v1/orgs/{orgSlug}/projects/{projectName}/auth/providers/{provider}Register or replace a social provider (runlot auth provider set)
DELETE/v1/orgs/{orgSlug}/projects/{projectName}/auth/providers/{provider}Disconnect a login provider (runlot auth provider rm)

GET /v1/orgs/{orgSlug}/projects/{projectName}/auth

Whether granted, configured, registered providers, and the host to point callbacks at (docs/auth.md §9).

The subscriber table is not part of this API. User information is stored in the runlot_auth schema of the project's Postgres (docs/auth.md §6), and CP does not query this table. You can check the current user list via the worker's env.auth.users.* and runlot pg shell.

providers carries only the client id. The client secret is sealed and never appears in any response (the secret-surface rule).

viewer or above — whether this app has login is a fact anyone in the org should be able to know.

operationId getAuth

Status codeDescriptionResponse body
200Auth statusAuthStatus
403
404
503no_core — no connection to cp-coreError

POST /v1/orgs/{orgSlug}/projects/{projectName}/auth

This is idempotent — calling it twice leaves the settings and login providers unchanged. Because the sole representation of enablement is the record's existence (migration 0024), there is no "on but disabled" state.

A database is required. Without one, it returns 409 database_required. Because the subscriber table lives inside the project DB (docs/auth.md §1), enabling auth alone leaves the worker without the table it needs at startup. This is why declaring "auth": true also enables the database, and deploys grant it in that order, so this 409 is never seen there.

Once enabled, the node starts the auth system worker as the socket's entry service on the next convergence. As with env.db and env.storage, no redeploy is needed. Table initialization is idempotent, so enabling it twice performs it only once.

There is no request body. Settings start at their defaults (the defaults of AuthSettings), and changing them is done with PATCH.

member and above. Audited as auth.grant.

operationId grantAuth

Status codeDescriptionResponse body
200Grant status (existing value if it was already there)AuthStatus
403
404
409database_required — this project has no database. Set "database": true in runlot.json and deploy.Error
503no_coreError

PATCH /v1/orgs/{orgSlug}/projects/{projectName}/auth

Is a partial update. Only the fields you send change, and the rest stay as they are. If the UI sends all three brand settings every time a single switch changes, a later save can overwrite an earlier one when two users edit the same settings.

Returns 404 not_granted if the usage setting does not exist. You cannot save settings alone ahead of time, because the setting values are stored together with the usage setting record.

sessionDays is a setting that also determines the size of the session table (docs/auth.md §13 — it stays within the 150 MB cap).

Requires member or higher. Audited as auth.settings.

operationId updateAuthSettings

Request body: application/json · AuthSettingsPatch

Status codeDescriptionResponse body
200The status that changedAuthStatus
400
403
404not_granted — this project has no auth. When the project itself does not exist, the code is not_found, not this one.Error
503no_coreError

DELETE /v1/orgs/{orgSlug}/projects/{projectName}/auth

Subscriber data is not deleted. The runlot_auth table stays in the project DB as is (docs/auth.md §9) — the data belongs to the DB, and deleting it is runlot pg's job. Turning it back on lets the same people log in as before.

Starting from the next convergence, the auth system worker goes down, and /__runlot/auth/* passes straight through to the user worker — if that path has no route, it's a 404.

Disabling is also idempotent. It returns 204 even when auth was not enabled.

admin and above — enabling it takes member, but disabling it signs out everyone who is logged in. Audited as auth.revoke.

operationId revokeAuth

Status codeDescriptionResponse body
204detached
403
404
503no_coreError

PUT /v1/orgs/{orgSlug}/projects/{projectName}/auth/providers/{provider}

A project registers its own OAuth app. There is no shared platform app because the consent screen, review, and privacy are all owned by the app's owner (docs/auth.md §12).

The callback URL to register with the provider is per host: https://<host>/__runlot/auth/callback/<provider>. The host list is in AuthStatus.hosts.

clientSecret is sealed with the same DEK and the same AAD as project_secrets (named with the reserved prefix auth/<provider>), and never appears in any response again. Rotation uses the same PUT — it is idempotent, so retries are safe.

Requires admin or higher — this is a credential. Audit auth.provider.set (the secret is not recorded).

operationId setAuthProvider

Request body: application/json · AuthProviderPut

Status codeDescriptionResponse body
200The status that changedAuthStatus
400invalid_provider — the name is outside github, google, kakao, or clientId/clientSecret is empty.Error
403
404
503no_coreError

DELETE /v1/orgs/{orgSlug}/projects/{projectName}/auth/providers/{provider}

Anyone who used only that login provider will no longer be able to log in. The user record remains, and only the matching entry in identities is deleted. Registering it again restores login with the same account.

Deleting a login provider that does not exist also returns 204.

admin or above. Audit auth.provider.delete.

operationId deleteAuthProvider

Status codeDescriptionResponse body
204detached
403
404
503no_coreError

On this page