package main // postgres's provisioner — the adapter that makes postgres a provider of the mesh // `postgres-database` interface (novox/hq ADR 0039/0040/0048). 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).** 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. // // **Extensions are the provider's to install.** A contribution may name extensions // (`"extensions": ["vector"]`); most are not trusted, so only the superuser this module holds can // create them, in the consumer's database, on every pass, and never drops one. import ( "context" ) // provisioner is the adapter over the client; announce emits a lifecycle event. type provisioner struct { pg *Client announce func(event string, body map[string]string) } func (a provisioner) Create(ctx context.Context, p Provision) error { // Read before anything runs: a malformed list is refused without touching the server. extensions, err := Extensions(p.Values) if err != nil { return err } // Database and owning role share the consumer's login, so the consumer owns exactly its own. database := p.As if err := a.pg.CreateDatabaseAndRole(ctx, database, p.As, p.Password); err != nil { return err } if err := a.pg.EnsureExtensions(ctx, database, extensions); err != nil { return err } a.announce("database.provisioned", map[string]string{"consumer": p.Consumer, "database": database, "user": p.As}) return nil } // Remove withdraws, never drops (novox/hq issue 241). The login is locked and the database kept under // its own name: on 2026-10-04 a misread contributions file withdrew every consumer at once, and // dropping made that a loss of seven databases. Taking a database out of service is a person's act — // postgres_retire_database — and even that renames rather than drops. func (a provisioner) Remove(ctx context.Context, as string, _ map[string]any) error { if err := a.pg.LockRole(ctx, as); err != nil { return err } a.announce("database.deprovisioned", map[string]string{"database": as, "kept": "true"}) return nil } // Holds is asked every minute: whether the consumer can still log in as the mesh gave it, and finds // the extensions it asked for, so a login or extension lost behind the provisioner's back is made // again (novox/hq issue 120). func (a provisioner) Holds(ctx context.Context, p Provision) (bool, error) { extensions, err := Extensions(p.Values) if err != nil { return false, err } return a.pg.Holds(ctx, p.As, p.As, p.Password, extensions) }