Waterflow

Database roles

Who connects to Postgres, as what, and what each can do.

Migrations create roles. The server’s migration runner (app/jobs/migrate.py) creates one login per role on the first start and sets its password again on every start, with passwords it made on the first start and keeps in the secrets volume (on Google Cloud Run, a Secret Manager secret). No login is superuser or has BYPASSRLS; the runner checks that on every start, so an owner that isn’t a superuser (Supabase’s) works. Through Supabase’s session pooler each login gets the owner’s project suffix: api_login.PROJECTREF.

Role Login Used by Can do
app_user api_login The API Whatever the user’s role in each book allows, through row-level security; the sign-in and admin functions
account_purger purge_login The daily purge, and the scheduler Run the purge and delete expired sessions; read the jobs’ schedule and record their runs (job_schedule(), job_started(), job_finished()). Nothing else
fx_updater fx_login The daily rates job Write market exchange rates. No user data
owner postgres (built-in database) or the operator’s owner login Migrations and the backup Change the schema; pg_dump must see every row. The API never has it

anon and authenticated (Supabase’s browser roles, on an operator’s own Supabase) have no access to any table or function. An AI role comes with AI.

Book roles (inside RLS)

Book role Can
owner Everything: invite and remove people, change roles, settings, delete the book
editor Add, edit, delete accounts, categories, people, transactions, budgets, exchange rates
viewer Read only

The server’s admin

Not a database role: users.is_admin, set by the database for the account made with the setup code (or by python -m app.admin make-admin). The admin’s functions check it with am_admin().

Edit this page · Report a problem