IsotopeAI / docs

Guides

Getting started Configuration Supabase setup Sync & backup Backup console Community

Reference

Architecture API reference Database CLI Android APK Admin console

Help

Troubleshooting FAQ Contributing Changelog

Legal

Security Privacy Terms License

Admin console

Owner-only tooling for schema verification, SQL patching, backup repair and storage cleanup. Admin mode is off by default and every route is disabled until you explicitly enable it.

Admin mode is a privileged surfaceIt grants row-level-security bypass through the service-role key, and /__admin/apply-sql can execute arbitrary SQL against your database. Enable it on a machine you control, and leave ENABLE_ADMIN_MODE=false otherwise.

Enabling admin mode #

Two conditions must both hold. This is deliberate — a stray ENABLE_ADMIN_MODE=true on an install with no service key must not half-open the console.

# .env
ENABLE_ADMIN_MODE=true
SUPABASE_SERVICE_ROLE_KEY=<your-service-role-key>   # required
ADMIN_SECRET=<long-random-string>            # how you unlock
ADMIN_EMAIL=you@example.com                  # optional: unlock via Supabase login

Internally this resolves to a single flag:

const ADMIN_MODE_READY = ENABLE_ADMIN_MODE && !!SUPA_SERVICE_KEY && !!ADMIN_COOKIE_SECRET;

Without ADMIN_SECRET, unlock does not persistWhen ADMIN_SECRET is unset the cookie signing key becomes crypto.randomBytes(32) — fresh on every boot. The console still works, but every restart invalidates your session. Set it if you use admin mode regularly.

Unlocking #

Visit /__admin/login. Two paths are accepted:

MethodHow it works
ADMIN_SECRETType the secret. On success you receive a signed iso_admin cookie at Path=/.
Supabase sessionClick Use Supabase Login. The existing browser access token is verified server-side, then checked against ADMIN_EMAIL/ADMIN_EMAILS or an admin row in user_roles.

The cookie is scoped to Path=/ rather than /__admin so that non-prefixed protected routes — notably /api/update-now — can also authorise against it.

Schema verification #

GET /__admin/verify admin

An in-server test suite, roughly 800 lines, run on demand. It checks the live project rather than asserting against the migration files, so it catches drift the SQL cannot see.

CategoryWhat it asserts
Table schemaEvery expected table and column exists.
RPC functionalEach community function is callable and returns the expected shape.
RLS recursion safetyNo membership policy recurses infinitely.
Edge-function interceptorsLeaderboard, analytics and finish-session return the intended 502 rather than fabricated data.
Server endpointsLocal routes respond with the expected status.
Auth pipelineSignup, login and bootstrap smoke test.
Storage bucketsAll four buckets exist with the correct visibility. Checks group-icons and study-material too — both were missing while the app uploaded to them, and the old check verified notes, which nothing used.
Local integration driftServed bundles match what the patcher expects.

Failures link to the fixWhen a check fails the page surfaces a bar linking to /__admin/patch, because most schema failures are resolved by applying the cumulative patch.

SQL patch manager #

GET /__admin/patch admin
POST /__admin/apply-sql admin

Serves community-patch-v6.sql with two ways to apply it: a one-click button that proxies through the Management API, or copy-paste into the Supabase SQL editor.

The proxy exists because api.supabase.com does not permit cross-origin browser requests. Your PAT is sent to your own local server, which forwards it — it is never stored.

GET /__admin/schema admin

Downloads isotope-complete.sql, the authoritative fresh-install schema.

Backup diagnostics #

GET /__admin/sync admin
POST /__admin/sync/repair-user-backup admin

Shows, per user, which stored backup would win the comparison ladder and why. Repair supports a dry run, so you can see the outcome before writing anything.

Dry run firstdry_run: true reports exactly what would change without touching storage. There is no undo for a backup overwrite, so use it.

Storage console #

GET /__admin/storage admin
POST /__admin/storage/cleanup-preview admin
POST /__admin/storage/cleanup-apply admin

Lists stored objects per user and identifies prunable older revisions. Preview and apply are separate endpoints — apply additionally requires confirm: true.

Role management #

GET /__admin/roles admin
POST /__admin/roles admin
DELETE /__admin/roles admin

Grants and revokes admin roles in user_roles. A user holding an admin role can unlock the console with their Supabase login, without knowing ADMIN_SECRET.

Browser proof #

GET /__admin/browser-proof admin
POST /__admin/browser-proof-result run token

Some behaviour cannot be asserted server-side: whether the service worker actually registered, whether IndexedDB persisted, whether a real login round-trips. Browser proof opens a page that performs those checks in a real browser and reports back.

browser-proof-result is the one admin route exempt from cookie auth — it is authorised by a per-run token instead, because the reporting page may run in a context without the admin cookie.

Update endpoint #

GET /api/update-status none to call
POST /api/update-now admin cookie or loopback

Note this pair is not under /__admin/ and does not require admin mode. It accepts an admin cookie or a loopback connection, so the in-app Update button works on an ordinary install. Full detail in API reference.

If you expose the server #

The server binds 0.0.0.0 so a phone on your network can reach it. That also means anything on the network can. Before doing that: