Files
mesh-catalog/modules/showcase/module.json
T
jschoubben 71bbc7dab0 Name the two modules after their software: nftables and distribution
A module's identity is the software it is (ADR 0040). Two were named after the
job instead, and the job already had a name.

firewall installs the nftables package and runs nftables.service. The seat it
claims is the-packet-filter, which is correctly named for the role. Calling the
module firewall named neither the software nor the provision, and promised that
any firewall could sit there — the false genericity the naming rule forbids.

registry runs Distribution, the OCI reference implementation, and provides
artifact-store. So registry was a third name for a thing that already had two,
which is how one word ended up meaning the module, the software and the concept
in the same paragraph.

The capability stays firewall, and correctly: a capability IS a functionality, so
a node having one and fail2ban requiring one are both right. Only the module
moves.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-15 20:51:00 +02:00

74 lines
3.1 KiB
JSON

{
"module": "showcase",
"version": "1",
"slug": "show",
"capabilities": ["container-runtime"],
"provides": [{ "name": "greeting", "scope": "mesh" }],
"serves": { "greeting": { "path": "/greeting" } },
"requires": ["postgres-database"],
"binds": { "postgres-database": "/var/lib/showcase/database.json" },
"secrets": { "postgres-database": "/var/lib/showcase/database.secret" },
"own-secrets": { "broker": "/var/lib/mesh/showcase/broker" },
"claims": [{ "name": "the-showcase", "scope": "node" }],
"emits": ["module.showcase.acknowledged"],
"consumes": ["module.showcase.greeted"],
"listens": [
{ "port": 8080, "protocol": "tcp", "from": "mesh",
"why": "the port the daemon itself listens on. The mesh assigns the machine-side number and tells consumers that one (ADR 0038)" }
],
"build": {
"artifacts": [
{ "name": "code", "kind": "bundle", "language": "typescript",
"entrypoints": ["index.js", "tools/index.js", "provisioner/index.js",
"daemon/index.js", "step/index.js", "report/index.js"] },
{ "name": "files", "kind": "archive", "from": "files" },
{ "name": "helper", "kind": "upstream",
"from": "alpine@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b" }
]
},
"resources": [
{ "id": "account", "type": "user", "name": "showcase", "shell": "/usr/bin/nologin",
"home": "/var/lib/showcase" },
{ "id": "logs", "type": "access", "path": "/var/log", "mode": "0755" },
{ "id": "mesh-state", "type": "directory", "path": "/var/lib/mesh/showcase", "mode": "0700" },
{ "id": "state", "type": "directory", "path": "/var/lib/showcase", "mode": "0755" },
{ "id": "settings", "type": "file", "path": "/var/lib/showcase/showcase.env", "mode": "0600",
"content": "SHOWCASE_GREETING=hello\nSHOWCASE_EVERY_SECONDS=30\nSHOWCASE_STATE=/var/lib/showcase\nSHOWCASE_DATABASE=${bound:postgres-database:at}\nSHOWCASE_LISTEN=${port:8080}\n" },
{ "id": "packed", "type": "archive", "path": "/opt/showcase", "artifact": "files" },
{ "id": "net", "type": "network", "name": "showcase" },
{ "id": "tooling", "type": "package", "package": "jq" },
{ "id": "migrate", "type": "process", "name": "showcase-migrate", "artifact": "code",
"run": ["node", "step/index.js"], "run-once": true,
"env-file": ["/var/lib/showcase/showcase.env"] },
{ "id": "server", "type": "process", "name": "showcase", "artifact": "code",
"run": ["node", "daemon/index.js"], "user": "showcase",
"env-file": ["/var/lib/showcase/showcase.env"],
"restart-on": ["settings"] },
{ "id": "reporting", "type": "process", "name": "showcase-report", "artifact": "code",
"run": ["node", "report/index.js"], "schedule": "0 3 * * *",
"env-file": ["/var/lib/showcase/showcase.env"] },
{ "id": "tools", "type": "container", "name": "mesh-showcase", "artifact": "helper",
"network": "showcase",
"volumes": ["/var/lib/mesh/showcase/broker:/run/secrets/broker:ro"],
"env": { "MESH_BROKER_FILE": "/run/secrets/broker" },
"args": ["sleep", "infinity"] }
]
}