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.