03 / Develop · Shell · Database

Shell database ​

shell_db is one database with four concerns. Read it a cluster at a time:

A satellite never reads shell_db. It gets identity from the service token and keeps its own tables — so the schema below is the Shell's private concern.

Identity ​

The users table is the centre: one row per person, provisioned on first sign-in. Everything about how they authenticate hangs off it — a password (1:1), live sessions, linked SSO identities, and API tokens. Each sign-in method is a row in identity_providers.

TableWhat it holdsKey columns
usersEvery platform useremail (unique), username, status; FK provider_id, organization_id (NULL = system-admin, no org)
identity_providersConfigured sign-in methods (local, keycloak, google, org-scoped)provider_id (unique), type, client_id / client_secret (encrypted), auth_url / token_url, status
user_credentialsPassword + MFA state — 1:1 with userspassword_hash, mfa_status, failed_login_count, locked_until
user_sessionsActive login sessionssession_token, refresh_token (hashed, unique), expires_at, ip_address
oauth_accountsLinks a user to an external SSO identityprovider_user_id, access_token / refresh_token (encrypted); FKs user_id, provider_id
personal_access_tokensPATs for CLI / scripted accesstoken_hash (SHA-256, unique), name, expires_at, last_used_at

Organizations ​

Organizations are the tenants. A user has one home org (users.organization_id) and can be a member of others through organization_members. Each org can carry its own IdP (idp_provider_id) and a vanity portal_domain, and invite people via user_invitations.

TableWhat it holdsKey columns
organizationsTenantsslug (unique), domain (email domain), portal_domain (vanity domain), subscription_plan, status; FK idp_provider_id → the org's own IdP
organization_membersJoin — users ↔ organizationsrole (admin / member), status, joined_at; FKs user_id, organization_id (unique pair)
user_invitationsPending invites into an orgtoken (unique), email, role_ids (jsonb), expires_at, accepted_at; FKs organization_id, invited_by

RBAC ​

Authorization is a classic role → permission model — made many-to-many by two join tables, and made multi-tenant by one column: user_roles.organization_id scopes an assignment to an org. These are the roles and permissions a satellite reads from its token.

TableWhat it holdsKey columns
rolesRBAC roles, platform- or org-scopedname, service_scope, is_default, is_system; FK organization_id (NULL = system-wide role)
permissionsresource:action grants, optionally app-scopedcode (unique), resource, action; FK app_id (NULL = platform-wide, set = app-scoped)
role_permissionsJoin — roles ↔ permissionsFKs role_id, permission_id (unique pair)
user_rolesJoin — users ↔ roles, org-scopedexpires_at; FKs user_id, role_id, organization_id (NULL = system-wide)

App registry ​

The apps table is the launchpad — one row per registered app, with its URLs and visibility. An app can scope its own permissions, expose dashboard widgets, and report health.

TableWhat it holdsKey columns
appsThe launchpad registryslug, name, api_url, ui_url, status, visibility flags, allowed_roles (jsonb); organization_id (NULL = platform app, set = org-owned, can shadow a platform slug)
app_widgetsDashboard widgets an app exposeskey, exposed_module, gating (permission, min_plan, feature_flag); FK app_id (unique per key)
app_health_checksPer-app health-check resultscheck status + timing; FK app_id

Beyond the core ​

Present in shell_db but outside the four clusters above:

ConcernTablesPurpose
Billing & planssubscription_plans, plan_apps, plan_limits, plan_usage, billing_invoices, organization_plan_historyPlan catalog, the apps each plan includes, per-plan limits, per-org usage, invoices, plan-change history
Stripestripe_webhook_eventsIdempotency log for incoming Stripe webhooks
RAGrag_documents, rag_token_usageEmbedded documents for search + embedding-token accounting
SCIMscim_api_tokensBearer tokens for SCIM provisioning
Platformaudit_log, onboarding_requests, provider_credentialsActivity/audit history, signup requests, stored provider credentials

See also ​

  • Overview — what the Shell is and how it's built.
  • API — the endpoints over this data.