// lavinmq's provisioner — the adapter that makes lavinmq a provider of the mesh `amqp` 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 lavinmq creates and removes a consumer's own // broker (novox/hq ADR 0039/0040/0048). // // The `amqp` interface: a consumer connects as `as` with the password the mesh minted, to a vhost // named for that same login — its own message broker, isolated from every other consumer's by the // vhost boundary. It is a broker of its own, not a shared account on the mesh's control-plane broker. // // **The login and password are the mesh's, not the provisioner's (novox/hq ADR 0048).** The mesh // derives the login and hands it to both ends so they agree, and mints the password and delivers a // copy to each. lavinmq creates exactly that user with exactly that password — a name or password the // provisioner invented is one the consumer could never present. // // Vhost-per-login is the isolation model, the exact analog of postgres's database-per-login: the // consumer owns one vhost, named for its login, and a user with full rights on that vhost and no // rights anywhere else. lavinmq enforces it — a user with no permission on `/` is refused the moment // it opens that vhost (`NOT_ALLOWED`), so a login is a broker the consumer alone can reach. import { runProvisioner, type Provision } from "@novox/mesh-sdk/provisioner"; import { emit } from "@novox/mesh-sdk/events"; import { LavinmqClient } from "../client.js"; const lavinmq = LavinmqClient.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:amqp] emit ${type} failed: ${err}`); } } runProvisioner("amqp", { async create(p: Provision): Promise { // The vhost and the user share the consumer's login, so one cannot reach another's broker. await lavinmq.waitReady(); await lavinmq.createConsumer(p.as, p.password); await announce("module.lavinmq.amqp.provisioned", { consumer: p.consumer ?? "", user: p.as, vhost: p.as, }); }, async remove(p: { as: string }): Promise { await lavinmq.removeConsumer(p.as); await announce("module.lavinmq.amqp.deprovisioned", { user: p.as, vhost: 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 lavinmq.holdsConsumer(p.as, p.password); }, });