# The elvix Console (developer dashboard)

> What a developer does in the elvix Console: create and configure applications, manage users, roles, scopes, memberships, API keys, webhooks, and take an app live. Plus the exact publish requirements, which elvix enforces server-side.

The Console lives at `https://elvix.is/console`. It is where a developer configures an Application. Everything here is also reachable over the REST API (see the Developers guide) and the MCP, so an agent can do the same things programmatically.

## Application settings tabs

Each Application has tabs at `/console/applications/<id>/`. What each one controls:

- **Branding**: app name, light+dark logo, light+dark icon, brand colour.
- **Domains & redirects**: app type(s) (web/mobile/api), primary domain, redirect URIs, allowed origins (CORS).
- **Sign-in methods**: toggle Google, Email OTP, Passkey, Username; layout, presentation, theme. At least one method must be enabled.
- **Legal**: Privacy Policy URL, Terms of Service URL (both probed for a 2xx), support email.
- **Credentials**: view the clientId, rotate the client secret (shown once, the old one stops immediately), and the Endpoints block (base URL, sign-in URL, plus the token and API-key verify endpoints). Session tokens are opaque — verify one with `POST /api/v1/session`. A backend that wants local verification instead exchanges it once via `POST /api/v1/token` for a signed RS256 JWT, then points any OIDC resource server at `https://elvix.is`: both `/.well-known/jwks.json` and `/.well-known/openid-configuration` are served. See the Verify on your backend guide.
- **Sessions**: session TTL (days) and renewal interval for this app's users.
- **Sign-in gate** (limited access): `public` (anyone), `private_beta` (allowlist), `closed` (existing members only) + the beta-interest list.
- **Publish / Lifecycle**: the readiness checklist and the draft → test → live ladder; archive, unarchive, delete (90-day grace), restore.

## People + access

- **Users**: list, invite, open a user to see sign-in history, profile, sessions, activity, and to block / deactivate / delete them.
- **Roles / Scopes / Memberships**: three independent catalogs. Create, edit, reorder by priority, mark one default (default is backfilled to all users). Grant/revoke per user. Roles = security, Scopes = purposes, Memberships = tiers.
- **API keys** (`eak_`): two scopes. PER-APPLICATION keys live on this tab and carry per-key roles, scopes, memberships. WORKSPACE keys live at the workspace-level **Console > API keys** page and reach every app in the workspace (or a chosen subset) for agents / the MCP / back-office tools. Both support Read or Full (read + write) access, rotate (with a grace window), revoke, rate limits, and usage. Each key carries a `source` of `console` (minted here) or `device` (granted by a CLI device-login such as `plm login`); device-granted keys are also revocable by the user from their Account > Connected devices. Each key also has a **Connected devices** tab: every distinct caller that authenticated with it (parsed client + user-agent, country, first and last seen, request count), captured from the verify endpoint.
- **Webhooks**: add an endpoint, choose events, test delivery, inspect deliveries. Signed with an HMAC secret (verify with `verifyElvixWebhook`).
- **Activity / Logs / Insights**: auth-event log, per-user logs, aggregated analytics.

## Taking an app live (publish requirements)

An Application moves **draft → test → live**. `POST /api/applications/<id>/publish` promotes draft → test; `POST /api/applications/<id>/go-live` promotes test → live. Both re-validate readiness and **reject server-side** if anything is missing, so an agent cannot force an app live with an incomplete config.

All of these must be satisfied before publish or go-live succeeds:

- App name (at least 2 characters).
- Light and dark logo, light and dark icon (uploaded).
- At least one app type (web / mobile / api).
- A primary domain.
- At least one redirect URI (no wildcards; http only for localhost).
- At least one sign-in method enabled.
- Privacy Policy URL and Terms of Service URL that each return 2xx (elvix probes them).
- A support email.

> **Warning:** If any requirement is unmet, `publish` / `go-live` return HTTP 400 `incomplete` with the failing checks. `go-live` also returns 409 `not_on_test` if the app is not on the test tier, and archived / deleting apps are rejected. This is enforced in the API, not just the UI: an agent calling the endpoint directly is blocked the same way.

> **Note:** The clientId never changes across draft / test / live. It is an identity, not a tier marker, so integrations keep working after go-live.
