Add lavinmq amqp provider and amqp-ping consumer
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
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"module": "lavinmq",
|
||||
"version": "1",
|
||||
"provides": [
|
||||
{
|
||||
"name": "amqp",
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"module.lavinmq.amqp.provisioned",
|
||||
"module.lavinmq.amqp.deprovisioned"
|
||||
],
|
||||
"consumes": [
|
||||
"module.lavinmq.amqp.provisioned",
|
||||
"module.lavinmq.amqp.deprovisioned"
|
||||
],
|
||||
"serves": {
|
||||
"amqp": {
|
||||
"port": 5672
|
||||
}
|
||||
},
|
||||
"receives": {
|
||||
"amqp": "/var/lib/lavinmq-module/grants/mesh.json"
|
||||
},
|
||||
"grants": {
|
||||
"amqp": "/var/lib/lavinmq-module/grants"
|
||||
},
|
||||
"own-secrets": {
|
||||
"default": "/var/lib/lavinmq-module/default.secret",
|
||||
"broker": "/var/lib/mesh/lavinmq/broker"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
"port": 5672,
|
||||
"protocol": "tcp",
|
||||
"from": "mesh",
|
||||
"why": "modules on any machine that were granted a queue"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh/lavinmq",
|
||||
"mode": "0700"
|
||||
},
|
||||
{
|
||||
"id": "state",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/lavinmq-module",
|
||||
"mode": "0700"
|
||||
},
|
||||
{
|
||||
"id": "grants-dir",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/lavinmq-module/grants",
|
||||
"mode": "0700"
|
||||
},
|
||||
{
|
||||
"id": "data",
|
||||
"type": "directory",
|
||||
"path": "/services/lavinmq/data",
|
||||
"mode": "0700"
|
||||
},
|
||||
{
|
||||
"id": "net",
|
||||
"type": "network",
|
||||
"name": "lavinmq"
|
||||
},
|
||||
{
|
||||
"id": "bootstrap",
|
||||
"type": "container",
|
||||
"name": "lavinmq-bootstrap",
|
||||
"image": "mesh-runtime-lavinmq@sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"run-once": true,
|
||||
"volumes": [
|
||||
"/var/lib/lavinmq-module:/var/lib/lavinmq-module",
|
||||
"/var/lib/lavinmq-module/default.secret:/run/secrets/default:ro"
|
||||
],
|
||||
"env": {
|
||||
"MESH_PROVISION_ADMIN_USER": "mesh-admin",
|
||||
"MESH_PROVISION_PASSWORD_FILE": "/run/secrets/default",
|
||||
"MESH_LAVINMQ_CONFIG_OUT": "/var/lib/lavinmq-module/lavinmq.ini",
|
||||
"MESH_LAVINMQ_DATA_DIR": "/var/lib/lavinmq"
|
||||
},
|
||||
"args": [
|
||||
"run",
|
||||
"/app/modules/lavinmq/dist/bootstrap/index.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "lavinmq",
|
||||
"image": "cloudamqp/lavinmq@sha256:3eb54c12916d700a978c2ea86e6362cd4974b0e3189508718006d4e6d341246b",
|
||||
"network": "lavinmq",
|
||||
"ports": [
|
||||
"5672"
|
||||
],
|
||||
"volumes": [
|
||||
"/services/lavinmq/data:/var/lib/lavinmq",
|
||||
"/var/lib/lavinmq-module/lavinmq.ini:/etc/lavinmq/lavinmq.ini:ro"
|
||||
],
|
||||
"args": [
|
||||
"--config",
|
||||
"/etc/lavinmq/lavinmq.ini"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "runtime",
|
||||
"type": "container",
|
||||
"name": "mesh-lavinmq",
|
||||
"image": "mesh-runtime-lavinmq@sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"network": "lavinmq",
|
||||
"volumes": [
|
||||
"/var/lib/mesh/lavinmq/broker:/run/secrets/broker:ro",
|
||||
"/var/lib/lavinmq-module/grants:/var/lib/lavinmq-module/grants:ro",
|
||||
"/var/lib/lavinmq-module/default.secret:/run/secrets/default:ro"
|
||||
],
|
||||
"env": {
|
||||
"MESH_BROKER_FILE": "/run/secrets/broker",
|
||||
"MESH_RECEIVES": "/var/lib/lavinmq-module/grants/mesh.json",
|
||||
"MESH_PROVISION_LAVINMQ": "http://lavinmq:15672",
|
||||
"MESH_PROVISION_ADMIN_USER": "mesh-admin",
|
||||
"MESH_PROVISION_PASSWORD_FILE": "/run/secrets/default"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user