Db

lib/db (kalt-db) is the Postgres pool. Each service has its own database. {SERVICE}_DATABASE_URL selects it (AUTH_DATABASE_URL, PUBLICATIONS_DATABASE_URL, …). DATABASE_URL is the fallback.

let db = kalt_db::connect(service, &kalt_db::url(service)?).await?;

connect opens that URL and ensures gen_random_okid(). The service runs migrations/ from its own crate. Add a numbered SQL file there to change that service's schema.

pnpm dev starts one Postgres from platform/tables per service. A service opens it with kalt_db::open and then uses state.db.

Draft and live

Content tables come in pairs: a published snapshot and a ledger. Ledger rows are field deltas keyed by id and tz. Live rows are the last published snapshot. GET …/ledger/:id is a server-built projection (latest non-null per field). PATCH appends a delta; it does not rewrite the live row.

Editor reads pass draft=1 so pick_text / pick_json prefer the ledger column.

Auth tables

auth_users and auth_refresh_tokens live in the auth database (svc/auth/migrations). auth_editors is the allow-list that becomes JWT role at approve time. See Auth.