Data layer
api and worker talk to one store today: Supabase Postgres (and Supabase Auth). TimescaleDB is the planned place for high-frequency telemetry; it is not connected to these processes yet.
Data ownership model
- Supabase/PostgreSQL — organizations (including a platform-operator org type), accounts, members, API keys, grids. Auth issues JWTs; claims include
app_metadatasuch asaccount_idandorganization_id. - Supabase Auth — interactive login.
apiverifies tokens via JWKS (SUPABASE_JWKS_URL) or, if that is unset,SUPABASE_JWT_SECRET. - TimescaleDB — snapshots and collectors when production-monitoring code moves in. Older TypeORM mapping is under
legacy/libs/timeseries. - Valkey/Redis for meter queues — not in
api/worker. When metering is on,nxt-device-messaginghas its own Valkey.
Key areas
supabase/migrations/— the schema. Current init includes20260710120000_init.sql. New changes are new migration files, not edits to history.supabase/seed.sql— local only: sample orgs, users, a demo grid,dev-api-key-platform-superadmin. Do not use this as a production bootstrap (docs/deployment/supabase.mdin the source repo).supabase/config.toml— local CLI. Seed runs ondb reset, not on everystartagainst an existing volume.- Generated types:
libs/core/src/types/supabase-types.ts(plus adjusted). They come from migrations in this git revision, not from pulling a production database. - No
supabase/functions/in the current tree.
Notes
GET /healthonapiuses the privileged (service_role) client againstorganizations, so it is not an RLS check.- Interactive API calls should use a user-scoped client (RLS).
X-API-KEYstill often continues on the privileged client after the key is resolved — tighten that before exposing powerful machine keys. - Extra Postgres login roles for Grafana/Make-style tools are operator-specific; they are not in the default migrations.
Migration and change flow
- Add SQL under
supabase/migrations/. pnpm exec supabase db reset(or apply locally), thenpnpm generate-types:local.- Update
api/worker(or a feature module) that reads the new columns. - Apply the same migrations to each environment with
supabase db push— not automatically on git push. - When Timescale arrives, keep high-frequency series on that plane, not in
public“for convenience.”
Turning a feature off in JSON stops its code. Tables for a feature you already shipped stay in the database. Tables that were dropped from this baseline on purpose are not revived by a config flag.
Operational guidance
- Seed emails/passwords are local fixtures.
- Take a backup (or PITR checkpoint) before destructive production SQL.
- Do not put high-frequency meter samples into the operational Postgres schema as a shortcut.
Source of truth
supabase/migrations/,supabase/seed.sql,supabase/config.tomldocs/deployment/supabase.mdlibs/core/src/types/