Studio tour
What each Studio screen does, from signing in to the Table editor and the SQL editor.
Studio is Chelabase's web app. In a local stack it runs at http://studio.chelabase.localhost:8000 (just workbench up starts it). Everything it does goes through the gateway on :8000 with your member access token, so anything you can click you can also do through the Management API (the reference is in Studio's API reference page and under Reference in these docs).
Open Studio at studio.chelabase.localhost:8000, not an IP address: the gateway routes by host name, and the sign-in redirect and the gateway's CORS origin are registered for that host.
Signing in
Studio has its own sign-in pages: /login, /register, /accept-invite, /verify, /password-reset, /pending and /logout. They call the auth service through the gateway (/auth/v1/*); the session and the step state live in encrypted HttpOnly cookies, and Studio holds only a short-lived token in memory (Identity service). The Quickstart walks through signing in as the bootstrap admin.
- Self-hosted mode (the default,
CHELABASE_MODE=self-hosted) takes no self-sign-up unless a tenant admin switches it on (PATCH /v1/instance/settingswithopen_signup). The first admin is whoever claims the instance with the setup code (Install); an admin invites everyone else, by an email, or by a link to hand over when no SMTP server is configured (GET /v1/invites/deliverysays). The sign-in page offers Create account only while sign-up is open, and always says "No account? Ask your admin for an invite" otherwise. Platform mode takes no self-sign-up yet. - With sign-up open, a new person is a pending member who can do nothing until an admin approves them (
approveMember, with their first grants) or declines them. Sign-ups are created with the email already verified in self-hosted mode; setCHELABASE_REQUIRE_EMAIL_VERIFICATION=trueto require a code (codes and password-reset emails land in Mailpit athttp://mail.chelabase.localhost:8000);=falseturns it off in any mode. - A sign-up for an email that is taken says so and sends you to sign in.
- Everyone who joins is in the same tenant: a shared team workspace, by design for self-hosting. An admin can give the tenant a display name (
PATCH /v1/tenant); the invite page andGET /v1/meuse it, falling back to the slug.
Projects
The dashboard lists your tenant's projects, with New project. Opening a project shows up to four tabs:
- Databases: the project's databases and a form to create one.
- Users: the project's app users. It appears once app users are enabled.
- Access: who has which role on the project, Add people, per-database narrowing and Access changes.
- Settings: the project name, App users (enable, change or disable) and a danger zone that deletes the project and every database in it.
Databases
The Databases tab lists each database with its status and endpoint. Each row has Reset password and Delete (Admin), and Branches, Merges, Connect and Open. Reset password sets a new owner password; Delete destroys the database with all its branches and data (you type its name to confirm). Open goes to the Table editor. The other three open a panel under the row, once the database is ready:
- Branches: the branch tree with each branch's status and endpoint, a form for a new branch, and the database's settings (history window, branch limit, max rows, statement timeout, max connections). Each branch has Connection details, Reset password, Protect (or, once protected, Protection and Unprotect), Reset to parent, Restore, Delete branch, Roles and, with a parent, Merge into and Update from it (see Merging schema). A disabled action says why next to the buttons; while a schema merge holds the branch, a link opens the merge. See Branches and Login roles.
- Merges: the database's schema merges, newest first, each opening its merge page.
- Connect: the owner's connection (Admin), a link to your personal Postgres login, and the Data API endpoint and public key, with Manage Data API.
Data API
The Data API page in the left rail has the endpoint and public key (with Rotate public key), the Postgres databases it serves, secret keys, row-level security and generated types. See Data API.
RLS warning
The Data API page's Row-level security card lists every table, view or foreign table that anon or authenticated can reach without row-level security protecting it, with a button to copy the SQL that fixes it:
- a table with RLS off:
ALTER TABLE … ENABLE ROW LEVEL SECURITY; - a view that runs with its owner's rights:
ALTER VIEW … SET (security_invoker = true); - a materialized view or foreign table, which can't have RLS:
REVOKE ALL … FROM anon, authenticated.
It also names the app users table while its RLS is off, even before any role can reach it, because the table holds your users' emails.
Table editor
The Table editor in the left rail browses and edits rows and changes table structure. See Table editor. Rows are read and written through the console endpoint below.
Over the API, the console is POST /v1/databases/{id}/branches/{branch_id}/console/query with:
{ "role": null | "<role>", "database": null | "<name>", "tree": <a data API request> }role is null (the owner) or a role name, database is null (the branch's main database) or a Postgres database name, and tree is a data API request, the JSON that POST /data/v1/query takes (see Data API). Every operation is allowed, batches included, in one transaction with the data API's max_rows and statement timeout. The answer is the data API's.
- As the owner (
role: null, Studio's default): the orchestrator runs the request itself, on a small pool per branch and database (at most 2 connections, closed after 60 seconds idle), with the owner password it holds. Row-level security doesn't apply to the owner.restnever sees the owner's password. When the owner's password was set in SQL, Chelabase doesn't know it: the answer is 409owner_password_unknownuntil you reset it (Reset password, orPOST …/branches/{branch_id}/reset-password), which works at once. - As another role (
anon,authenticated, a plain role you made): the worker checks the role the first time (the result is remembered for five minutes) and grants it toauthenticator;restthen runs the request as that role. An owner-level role (a superuser, or one withCREATEROLE,CREATEDBorREPLICATION, or aneon_superusermember), or one that doesn't exist, is refused: 403role_refused, saying why. A role withBYPASSRLSalone is allowed and reads past row-level security. A role dropped after its check answers 503unavailablefor up to 30 seconds, then 404unknown_role. - Errors: a Postgres database that isn't served is 409
data_api_disabled(Studio offers Enable data API); one that doesn't exist is 404not_found; everything else is the data API's code. See Error codes. - Audit: every write is logged at
info(platform user, branch, database, role, operation kind), never the values.
API reference
The API reference item in the left rail opens the Management, Data and Auth API references, each with Try it out; only the Management reference fills in your signed-in token. Nothing on that page calls an outside service.
How Studio behaves
- Lists refresh every 2 seconds while a database or branch is pending, provisioning, resetting or deleting, and stop when the status settles.
- A write refreshes exactly the data it changes.
- Secrets (connection details, passwords, created or rotated API keys) never enter Studio's query or mutation cache or any stored state. They live in the open panel and disappear when it closes. Keys are shown once, at creation or rotation.
- The SQL editor keeps its run history, open buffer and timeout in your browser's
localStorage. - Studio is English-only and dark-only today.
Table API
List a branch's tables, read a table's structure and the type catalog, change the schema with structured operations (dry runs, drops with dependents, concurrent indexes), insert a row of defaults and fetch a full cell.
Self-hosted vs platform
Every rule that differs between self-hosted mode and platform mode, from one policy table in the code.