Launch + auth
Same binary, three deployment shapes. Pick by who's on the other end.
Mode 1 — local (default)
zanith studio# → http://localhost:4321 — single user, no auth.Binds to localhost only. No auth check — anyone on 127.0.0.1 with that port reachable can use it. Right for solo dev. Wrong for anything else.
Mode 2 — staff (token-gated)
# Generate a one-off token (rotates every launch).zanith studio --mode staff# → token: zsk_8f4a… (printed once, copy now)# → http://0.0.0.0:4321/?t=zsk_8f4a… # Or pass an existing token (persisted in CI):zanith studio --mode staff --token $ZANITH_STUDIO_TOKEN| What changes | vs local mode |
|---|---|
| Bind address | 0.0.0.0 — reachable from outside the host. |
| Auth | Token required on every request. Token in URL, header, or cookie. |
| Privilege | Same as local — full read/write per the connection's Postgres role. |
| Audit | Every action records the token's hash so you can correlate later. |
Mode 3 — viewer (read-only)
zanith studio --mode viewer# → http://0.0.0.0:4321/?role=viewer# - SELECT-only on every connection.# - Edit / insert / delete UI is gone.# - Plan and EXPLAIN still work.Use when you want non-engineers to inspect data but not change it. The viewer mode is enforced two ways: the UI removes mutating actions, AND the Postgres connection is wrapped in a SET TRANSACTION READ ONLY on every query. Either failure surfaces as an error, not a silent allow.
| Action | Viewer mode |
|---|---|
| Browse tables, run SELECTs | Allowed. |
| Edit a row | UI hidden; raw API call rejected with 403. |
| Run a non-SELECT query | Postgres rejects: cannot execute INSERT in a read-only transaction. |
| Schema diff, EXPLAIN, lock graph | Allowed — these are SELECT-only. |
Auth model
Studio doesn't have its own user database. It trusts the launch flag and the Postgres role on the connection. If you need per-user audit trails, point Studio at a Postgres connection that authenticates each user separately (e.g. a connection pooler in sessionmode that proxies the user's auth) — then the audit table records the real session_user.
Stopping Studio
Ctrl-Cin the terminal. There's no daemon mode — Studio runs in the foreground on purpose, so the process is visible to whoever is on call.