// postgres's provisioner — the adapter that makes postgres a provider of the mesh // `postgres-database` interface. The reconcile loop, the contributions file, and reading the mesh's // minted password are the sdk harness's; this writes only the per-service half: how postgres creates // and removes a consumer's database + owning role (novox/hq ADR 0039/0040/0048). // // The `postgres-database` interface: a consumer connects to a database it alone owns, as `as` with // the password the mesh minted. // // **The role name and password are the mesh's, not the provisioner's (ADR 0048).** The mesh derives // the login and hands it to both ends, and mints the password. postgres creates a role and a // same-named database under exactly that login — a name the consumer cannot learn is a database it // cannot reach. // // The DDL runs through PostgresClient.query(), which is the module's one pending boundary (see // client.ts). import { runProvisioner, type Provision } from "@novox/mesh-sdk/provisioner"; import { emit } from "@novox/mesh-sdk/events"; import { PostgresClient } from "../client.js"; const postgres = PostgresClient.fromEnv(); /** Emit a lifecycle event without letting a broker hiccup fail the provisioning itself. */ async function announce(type: string, body: Record): Promise { try { await emit(type, body); } catch (err) { console.error(`[provisioner:postgres-database] emit ${type} failed: ${err}`); } } runProvisioner("postgres-database", { async create(p: Provision): Promise { // Database and owning role share the consumer's login, so the consumer owns exactly its own. const database = p.as; await postgres.createDatabaseAndRole(database, p.as, p.password); await announce("module.postgres.database.provisioned", { consumer: p.consumer ?? "", database, user: p.as, }); }, async remove(p: { as: string }): Promise { await postgres.dropDatabaseAndRole(p.as, p.as); await announce("module.postgres.database.deprovisioned", { database: p.as }); }, // Asked every minute by the harness: whether the backend still holds this consumer exactly as // the mesh gave it, so a login lost behind the provisioner's back is made again (novox/hq issue 120). async holds(p: Provision): Promise { return postgres.canConnectAs(p.as, p.as, p.password); }, });