lavinmq becomes a provider of a user-facing amqp interface: a consumer
that requires a message queue is given its OWN broker — a scoped vhost
and user on a lavinmq provider — not an account on the mesh's own
control-plane broker (ADR 0048). Vhost-per-login is the isolation model,
the exact analog of postgres's database-per-login: the provider names a
vhost after the consumer's login and a user with full rights on that
vhost and none elsewhere, so a login is a broker the consumer alone can
reach.
The provider drives lavinmq through its HTTP management API (client.ts,
the module's one impure seam), with a run-once bootstrap that computes
the RabbitMQ-compatible password hash lavinmq's config wants from the
plain admin secret the mesh mints — the value no ${secret:...}
placeholder can produce and the reason the bootstrap exists (ADR 0052).
serves.amqp carries the port so consumers reference ${bound:amqp:port}.
amqp-ping is a demo consumer: it contributes nothing (the vhost is the
login), reads its grant from an env-file the mesh fills, and uses
${bound:amqp:as} for BOTH its username and its vhost — the db-name
lesson applied to AMQP. It speaks AMQP 0-9-1 over a raw socket with no
npm dependency (the way redis speaks RESP) and round-trips one message.
It carries a slug so its identity fits the 20-char backend bound
(ADR 0049).
Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
65 lines
1.4 KiB
JSON
65 lines
1.4 KiB
JSON
{
|
|
"module": "amqp-ping",
|
|
"slug": "ping",
|
|
"version": "1",
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"requires": [
|
|
"amqp"
|
|
],
|
|
"contributes": {},
|
|
"binds": {
|
|
"amqp": "/var/lib/amqp-ping/amqp.json"
|
|
},
|
|
"secrets": {
|
|
"amqp": "/var/lib/amqp-ping/amqp.secret"
|
|
},
|
|
"own-secrets": {
|
|
"broker": "/var/lib/mesh/amqp-ping/broker"
|
|
},
|
|
"resources": [
|
|
{
|
|
"id": "mesh-state",
|
|
"type": "directory",
|
|
"path": "/var/lib/mesh/amqp-ping",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "state",
|
|
"type": "directory",
|
|
"path": "/var/lib/amqp-ping",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "amqp-env",
|
|
"type": "file",
|
|
"path": "/var/lib/amqp-ping/amqp.env",
|
|
"mode": "0600",
|
|
"content": "MESH_AMQP_HOST=${bound:amqp:at}\nMESH_AMQP_PORT=${bound:amqp:port}\nMESH_AMQP_USER=${bound:amqp:as}\nMESH_AMQP_VHOST=${bound:amqp:as}\nMESH_AMQP_PASSWORD=${secret:amqp}\n"
|
|
},
|
|
{
|
|
"id": "net",
|
|
"type": "network",
|
|
"name": "amqp-ping"
|
|
},
|
|
{
|
|
"id": "runtime",
|
|
"type": "container",
|
|
"name": "amqp-ping",
|
|
"image": "mesh-runtime-amqp-ping@sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
|
"network": "amqp-ping",
|
|
"env-file": [
|
|
"/var/lib/amqp-ping/amqp.env"
|
|
],
|
|
"args": [
|
|
"run",
|
|
"/app/modules/amqp-ping/dist/index.js"
|
|
],
|
|
"restart-on": [
|
|
"amqp-env"
|
|
]
|
|
}
|
|
]
|
|
}
|