Capture the catalogue's module.json files at mesh-catalog bb0fe93b for the moved catalogue tests (issue 1379)

Part 2 of 4 of go/testdata/beside; each kept as module.json.captured.
This commit is contained in:
2026-10-20 08:18:33 +00:00
parent e58761afce
commit a706310d34
133 changed files with 16933 additions and 0 deletions
@@ -0,0 +1,65 @@
{
"module": "artifact-store-tools",
"version": "1",
"invokes": [
"seat:mesh-controller.artifacts",
"seat:mesh-controller.collect",
"mesh-catalog.catalog_modules",
"mesh-catalog.catalog_module"
],
"tools": [
"artifact_store_repositories",
"artifact_store_usage",
"artifact_store_references",
"artifact_store_collect"
],
"config": {
"older-store-names": {
"type": "string",
"description": "The names the artifact store had before, as host names or host:port separated by spaces, or none when it had no other. artifact_store_references reads every definition under these as well as under the store's current name, so an image a definition pins under one is said to be named by a definition (novox/hq issue 323).",
"pattern": "none|[A-Za-z0-9.:-]+( [A-Za-z0-9.:-]+)*",
"default": "none"
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "store-names",
"type": "file",
"path": "${dir:state}/store-names",
"mode": "0600",
"trusted": false,
"template": "files/store-names"
}
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/artifact-store-tools",
"binary": "artifact-store-tools",
"loads": [
"artifact-store-tools"
],
"env": {
"MESH_ARTIFACT_STORE_CONTAINER": "mesh-registry",
"MESH_ARTIFACT_STORE_NAMES_FILE": "${dir:state}/store-names"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,229 @@
{
"module": "asus-zephyrus-g14",
"version": "1",
"moved": true,
"templates": "templates",
"capabilities": [
"package-manager",
"service-manager"
],
"requires": [
"x11-display"
],
"emits": [
"profile.switched"
],
"tools": [
"zephyrus_brightness",
"zephyrus_battery",
"zephyrus_charge_limit",
"zephyrus_gpu_mode",
"zephyrus_profile",
"zephyrus_thermals",
"zephyrus_power_draw",
"zephyrus_profile_policy",
"zephyrus_fan_curves",
"zephyrus_keys",
"zephyrus_check"
],
"resources": [
{
"id": "asusctl",
"type": "package",
"package": "asusctl"
},
{
"id": "playerctl",
"type": "package",
"package": "playerctl"
},
{
"id": "asusd",
"type": "service",
"unit": "asusd.service",
"state": "running"
},
{
"id": "supergfxd",
"type": "service",
"unit": "supergfxd.service",
"state": "running",
"boot": "enabled"
},
{
"id": "scripts",
"type": "archive",
"path": "/usr/local/lib/asus-zephyrus-g14",
"artifact": "scripts",
"unknown": "program"
},
{
"id": "nvidia-options",
"type": "file",
"path": "/etc/modprobe.d/g14-nvidia-power.conf",
"mode": "0644",
"template": "templates/modprobe.d/g14-nvidia-power.conf"
},
{
"id": "video-options",
"type": "file",
"path": "/etc/modprobe.d/video-brightness-switch.conf",
"mode": "0644",
"template": "templates/modprobe.d/video-brightness-switch.conf"
},
{
"id": "suspend-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/systemd-suspend.service.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "nvidia-on-suspend",
"type": "file",
"path": "/etc/systemd/system/systemd-suspend.service.d/asus-zephyrus-g14-nvidia.conf",
"mode": "0644",
"template": "templates/systemd/system/systemd-suspend.service.d/asus-zephyrus-g14-nvidia.conf"
},
{
"id": "hibernate-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/systemd-hibernate.service.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "nvidia-on-hibernate",
"type": "file",
"path": "/etc/systemd/system/systemd-hibernate.service.d/asus-zephyrus-g14-nvidia.conf",
"mode": "0644",
"template": "templates/systemd/system/systemd-hibernate.service.d/asus-zephyrus-g14-nvidia.conf"
},
{
"id": "suspend-then-hibernate-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/systemd-suspend-then-hibernate.service.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "nvidia-on-suspend-then-hibernate",
"type": "file",
"path": "/etc/systemd/system/systemd-suspend-then-hibernate.service.d/asus-zephyrus-g14-nvidia.conf",
"mode": "0644",
"template": "templates/systemd/system/systemd-suspend-then-hibernate.service.d/asus-zephyrus-g14-nvidia.conf"
},
{
"id": "powerd-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/nvidia-powerd.service.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "powerd-opt-in",
"type": "file",
"path": "/etc/systemd/system/nvidia-powerd.service.d/asus-zephyrus-g14.conf",
"mode": "0644",
"template": "templates/systemd/system/nvidia-powerd.service.d/asus-zephyrus-g14.conf"
},
{
"id": "backlight-rule",
"type": "file",
"path": "/etc/udev/rules.d/90-backlight.rules",
"mode": "0644",
"template": "templates/udev/rules.d/90-backlight.rules"
},
{
"id": "udev",
"type": "service",
"unit": "systemd-udevd.service",
"reload-on": [
"backlight-rule"
]
},
{
"id": "upower-package",
"type": "package",
"package": "upower"
},
{
"id": "upower-drop-ins",
"type": "directory",
"path": "/etc/UPower/UPower.conf.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "low-battery",
"type": "file",
"path": "/etc/UPower/UPower.conf.d/50-asus-zephyrus-g14.conf",
"mode": "0644",
"template": "templates/UPower/UPower.conf.d/50-asus-zephyrus-g14.conf"
},
{
"id": "upower",
"type": "service",
"unit": "upower.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"low-battery"
]
},
{
"id": "xorg-drop-ins",
"type": "directory",
"path": "/etc/X11/xorg.conf.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "touchpad",
"type": "file",
"path": "/etc/X11/xorg.conf.d/30-asus-zephyrus-g14-touchpad.conf",
"mode": "0644",
"template": "templates/X11/xorg.conf.d/30-asus-zephyrus-g14-touchpad.conf"
}
],
"items": [
{
"collection": "shell:after-wake:normal",
"template": "templates/after-wake"
},
{
"collection": "contribution:node-hotkeys:trigger",
"template": "templates/hotkeys-triggers"
},
{
"collection": "contribution:node-display-session:config",
"name": "display-session",
"template": "templates/display-session"
}
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/zephyrus",
"binary": "zephyrus",
"loads": [
"zephyrus"
]
},
{
"name": "scripts",
"kind": "archive",
"from": "files"
},
{
"name": "templates",
"kind": "archive",
"from": "templates"
}
]
}
}
@@ -0,0 +1,69 @@
{
"module": "audit-logger",
"version": "1",
"slug": "audit",
"consumes": [
"**"
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"AUDIT_LOG": "${dir:trail}/audit.log",
"AUDIT_SPOOL": "${dir:spool}"
}
}
]
},
"data": {
"own": [
{
"id": "trail",
"path": "${dir:trail}",
"class": "valuable",
"why": "the audit trail, written nowhere else"
},
{
"id": "spool",
"path": "${dir:spool}",
"class": "valuable",
"why": "events the trail could not take yet; after the bus gives one up, the only copy"
}
]
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "trail",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "spool",
"type": "directory",
"mode": "0700",
"unknown": "program"
}
],
"capabilities": [
"container-runtime"
]
}
@@ -0,0 +1,43 @@
{
"module": "avahi",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"tools": [
"avahi_status",
"avahi_browse",
"avahi_resolve",
"avahi_services"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "avahi"
},
{
"id": "daemon",
"type": "service",
"unit": "avahi-daemon.service",
"state": "running",
"boot": "enabled"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/avahi-tools",
"binary": "avahi-tools",
"loads": [
"avahi-tools"
]
}
]
}
}
@@ -0,0 +1,158 @@
{
"module": "baserow",
"version": "1",
"capabilities": [
"container-runtime"
],
"requires": [
"postgres-database",
"route"
],
"contributes": {
"postgres-database": {
"name": "baserow"
},
"route": {
"label": "baserow",
"endpoint": "web"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"own-secrets": {
"admin": "${dir:state}/admin.secret"
},
"listens": [
{
"name": "web",
"port": 80,
"protocol": "tcp",
"from": "mesh",
"why": "the Baserow web UI and REST API, served by the image's own Caddy; a public name is the route's"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "uploaded files and media; the tables are in the database"
}
]
},
"config": {
"host": {
"type": "string",
"description": "The Host header the module's tools send to Baserow, a host name; the file's default is the name the module's route was given.",
"trusted": true,
"default": "${bound:route:name}"
},
"email": {
"type": "string",
"description": "The email address of the Baserow account the module's tools sign in as; unset, the code falls back to its environment.",
"trusted": true,
"default": ""
},
"url": {
"type": "string",
"description": "The address the module's tools reach Baserow at, as a URL; unset, the code falls back to its environment, else this machine's Baserow on port 80.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0755",
"owner": "9999:9999",
"unknown": "program"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "net",
"type": "network",
"name": "baserow"
},
{
"id": "server",
"type": "container",
"name": "baserow",
"image": "baserow/baserow@sha256:263ea6c4b72c9eccabcd975ffe9fdebf23913a293a514bec6a3897a5e0a5a080",
"health": {
"kind": "runtime"
},
"network": "baserow",
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"80"
],
"volumes": [
"${dir:data}:/baserow/data",
"${dir:state}/database.secret:/run/secrets/database:ro"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": ["host", "email", "url"],
"protected": ["password"]
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_BASEROW_URL": "http://127.0.0.1:${port:80}",
"MESH_BASEROW_CONFIG_FILE": "${dir:mesh-state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,253 @@
{
"module": "betterbird",
"version": "1",
"upgrade": {
"policy": "record",
"why": "a new build may remove the community package betterbird-bin and replaces the installation in /opt/betterbird, which a running Betterbird has open: the switch on each node and every upgrade wait for the operator, who quits Betterbird first and then pushes (novox/hq ADR 0316 §4, §5)"
},
"requires": [
"x11-display"
],
"invokes": [
"seat:mesh-controller.settings",
"seat:mesh-controller.nodes",
"seat:mesh-controller.node",
"betterbird.betterbird_derive"
],
"tools": [
"betterbird_status",
"betterbird_prefs",
"betterbird_config",
"betterbird_config_apply",
"betterbird_user_js",
"betterbird_log",
"betterbird_restart",
"betterbird_check",
"betterbird_accounts",
"betterbird_identities",
"betterbird_calendars",
"betterbird_address_books",
"betterbird_filters",
"betterbird_tags",
"betterbird_derive",
"betterbird_drift",
"betterbird_reminder_test"
],
"config": {
"prefs": {
"type": "object",
"description": "Betterbird's preferences the operator sets, by their own names (mailnews.*, calendar.* and the like), laid into prefs.json; an account's, a server's and a tag's are refused, as accounts, the four kinds and tags own them (novox/hq ADR 0329 §6).",
"trusted": true,
"default": {}
},
"accounts": {
"type": "object",
"description": "The mail accounts Betterbird is set up with, each by a name of the operator's: its address, its sender's name and its incoming and outgoing servers; no password, token or cookie (novox/hq ADR 0329 §2).",
"trusted": true,
"default": {}
},
"identities": {
"type": "object",
"description": "The identities beside an account's own, each by a name of the operator's: the address and name it sends as, its signature as a list of lines, and the profile's key to adopt on a node.",
"trusted": true,
"default": {}
},
"calendars": {
"type": "object",
"description": "The calendars Betterbird shows, each by a name of the operator's: where it is and how it is reached, and the profile's key to adopt on a node.",
"trusted": true,
"default": {}
},
"address-books": {
"type": "object",
"description": "The address books Betterbird uses, each by a name of the operator's: where it is and how it is reached, and the profile's key to adopt on a node.",
"trusted": true,
"default": {}
},
"filters": {
"type": "object",
"description": "The message filters of each account, by account: what each matches and what it does with the mail.",
"trusted": true,
"default": {}
},
"tags": {
"type": "object",
"description": "The tags Betterbird offers, each by its own key: its name, colour and order; trusted since issue 751, so a change to it is the operator's to approve.",
"trusted": true,
"default": {}
}
},
"resources": [
{
"id": "configuration-dir",
"type": "directory",
"path": "${machine:account-home}/.config/betterbird",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out",
"knows": ["accounts-record.json", "configuration-record.json", "kept/"]
},
{
"id": "prefs",
"type": "file",
"path": "${machine:account-home}/.config/betterbird/prefs.json",
"owner": "${machine:account}",
"mode": "0644",
"merge": "json",
"takes-config": [
"prefs"
],
"template": "files/prefs.json",
"trusted": true
},
{
"id": "accounts",
"type": "file",
"path": "${machine:account-home}/.config/betterbird/accounts.json",
"owner": "${machine:account}",
"mode": "0600",
"merge": "json",
"takes-config": [
"accounts"
],
"template": "files/accounts.json",
"trusted": true
},
{
"id": "configuration",
"type": "file",
"path": "${machine:account-home}/.config/betterbird/configuration.json",
"owner": "${machine:account}",
"mode": "0600",
"merge": "json",
"takes-config": [
"identities",
"calendars",
"address-books",
"filters"
],
"template": "files/configuration.json",
"trusted": true
},
{
"id": "tags",
"type": "file",
"path": "${machine:account-home}/.config/betterbird/tags.json",
"owner": "${machine:account}",
"mode": "0644",
"merge": "json",
"takes-config": [
"tags"
],
"template": "files/tags.json",
"trusted": true
},
{
"id": "community-package",
"type": "package",
"package": "betterbird-bin",
"absent": true
},
{
"id": "installation",
"type": "archive",
"path": "/opt/betterbird",
"artifact": "archive",
"unknown": "program"
},
{
"id": "owl",
"type": "archive",
"path": "/opt/betterbird/owl",
"artifact": "owl",
"unknown": "program"
},
{
"id": "policies",
"type": "archive",
"path": "/opt/betterbird/distribution",
"artifact": "distribution",
"unknown": "program"
},
{
"id": "spelling",
"type": "archive",
"path": "/opt/betterbird/defaults/pref",
"artifact": "defaults",
"unknown": "program"
},
{
"id": "preparation",
"type": "archive",
"path": "/usr/local/lib/mesh-betterbird",
"artifact": "tools",
"unknown": "program"
},
{
"id": "start",
"type": "file",
"path": "/usr/local/bin/betterbird",
"mode": "0755",
"template": "files/betterbird"
},
{
"id": "launcher",
"type": "file",
"path": "/usr/local/share/applications/eu.betterbird.Betterbird.desktop",
"mode": "0644",
"template": "files/eu.betterbird.Betterbird.desktop"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/betterbird-tools",
"binary": "betterbird-tools",
"loads": [
"betterbird-tools"
]
},
{
"name": "archive",
"kind": "archive",
"url": "https://www.betterbird.eu/downloads/LinuxArchive/betterbird-153.4.0esr-bb10.en-US.linux-x86_64.tar.xz",
"sha256": "38dd24890a66b4cf9a45bc24e15192e00c26b929e1bb8df7974c16a4539129e2",
"version": "153.4.0esr-bb10",
"within": "betterbird",
"names-on-purpose": {
"www.betterbird.eu": "Betterbird's project publishes its Linux release there; the build seat fetches it once, by its pinned sha256 (novox/hq ADR 0316 §2)"
}
},
{
"name": "owl",
"kind": "archive",
"url": "https://www.beonex.com/owl/owl.xpi",
"sha256": "a54cc3d52113b34f97942ee19190947dee23561e2217f18db3d80ac023991221",
"version": "1.5.6.1",
"file": "owl.xpi",
"names-on-purpose": {
"www.beonex.com": "Owl's vendor publishes its xpi there; the build seat fetches it once, by its pinned sha256 (novox/hq ADR 0316 §6)"
}
},
{
"name": "distribution",
"kind": "archive",
"from": "install/distribution"
},
{
"name": "defaults",
"kind": "archive",
"from": "install/defaults-pref"
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,37 @@
{
"module": "blueman",
"version": "1",
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"tools": [
"blueman_status",
"blueman_restart",
"blueman_check"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "blueman"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/blueman-tools",
"binary": "blueman-tools",
"loads": [
"blueman-tools"
]
}
]
}
}
@@ -0,0 +1,53 @@
{
"module": "bluetooth",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"tools": [
"bluetooth_controller",
"bluetooth_power",
"bluetooth_devices",
"bluetooth_scan",
"bluetooth_connect",
"bluetooth_disconnect",
"bluetooth_trust",
"bluetooth_pair",
"bluetooth_remove"
],
"resources": [
{
"id": "stack",
"type": "package",
"package": "bluez"
},
{
"id": "utilities",
"type": "package",
"package": "bluez-utils"
},
{
"id": "daemon",
"type": "service",
"unit": "bluetooth.service",
"state": "running",
"boot": "enabled"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/bluetooth-tools",
"binary": "bluetooth-tools",
"loads": [
"bluetooth-tools"
]
}
]
}
}
@@ -0,0 +1,66 @@
{
"module": "ca-trust",
"version": "1",
"slug": "catrust",
"capabilities": [
"service-manager"
],
"requires": [
"internal-acme-ca"
],
"seats": [
{
"name": "the-mesh-trust-anchor",
"scope": "node"
}
],
"claims": [
{
"name": "the-mesh-trust-anchor",
"scope": "node"
}
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "anchor",
"type": "file",
"path": "${dir:state}/anchor",
"mode": "0755",
"template": "files/anchor"
},
{
"id": "unit",
"type": "file",
"path": "/etc/systemd/system/mesh-ca-trust.service",
"mode": "0644",
"template": "files/mesh-ca-trust.service"
},
{
"id": "trust",
"type": "service",
"unit": "mesh-ca-trust.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"anchor",
"unit"
]
}
],
"build": {
"artifacts": [
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,247 @@
{
"module": "claude-code",
"version": "1",
"moved": true,
"slug": "agent",
"capabilities": [
"package-manager"
],
"requires": [
"mcp-endpoint",
{
"name": "gitea-read",
"optional": true
}
],
"binds": {
"mcp-endpoint": "${dir:state}/mcp-endpoint.json"
},
"secrets": {
"gitea-read": "${dir:state}/gitea-read.secret"
},
"uses": [
"operator-channel"
],
"state": [
"servers",
"holdings",
"config",
"proposals",
"questions",
"memory"
],
"reads": [
"claude-licence-manager.bindings"
],
"tools": [
"claude_code_status",
"claude_code_render",
"claude_code_guard",
"claude_code_pull",
"claude_code_grant",
"claude_code_add_api_key",
"claude_code_registrations",
"claude_code_memory",
"claude_code_mcp_list",
"claude_code_mcp_register",
"claude_code_mcp_unregister",
"claude_code_skill_list",
"claude_code_skill_register",
"claude_code_skill_unregister",
"claude_code_agent_list",
"claude_code_agent_register",
"claude_code_agent_unregister",
"claude_code_command_list",
"claude_code_command_register",
"claude_code_command_unregister",
"claude_code_hook_list",
"claude_code_hook_register",
"claude_code_hook_unregister",
"claude_code_output_style_list",
"claude_code_output_style_register",
"claude_code_output_style_unregister",
"claude_code_instructions_list",
"claude_code_instructions_register",
"claude_code_instructions_unregister",
"claude_code_instructions_propose",
"claude_code_proposals",
"claude_code_ask",
"claude_code_answer",
"claude_code_settings_get",
"claude_code_settings_set",
"claude_code_settings_clear",
"claude_code_permission_add",
"claude_code_permission_remove",
"claude_code_config_list",
"claude_code_config_show",
"claude_code_config_status",
"claude_code_config_import",
"claude_code_home_show",
"claude_code_home_remove",
"claude_code_home_removed",
"claude_code_home_restore",
"claude_code_judge",
"claude_code_judged"
],
"data": {
"own": [
{
"id": "agent-home",
"path": "${dir:agent-home}",
"class": "valuable",
"why": "the operator's agent's own files: its memory, history and projects"
}
]
},
"config": {
"role": {
"type": "string",
"description": "What this machine is for, in a sentence, written into the instructions every Claude Code session on it reads; empty says nothing.",
"trusted": true,
"default": ""
},
"mcp_servers": {
"type": "object",
"description": "The tool servers every session on this machine is given beside the mesh's own, by name, each as Claude Code's managed MCP configuration takes it; empty adds none.",
"trusted": true,
"default": {}
},
"managed_settings": {
"type": "object",
"description": "Keys of Claude Code's managed settings every session on this machine obeys, such as spinnerTipsEnabled, laid over the mesh's own; empty adds none. Falls back to agent-managed-settings, the mesh's or this node's.",
"trusted": true,
"predefined": "agent-managed-settings",
"default": {}
},
"instructions": {
"type": "object",
"description": "The instructions every session on this machine reads, by name, each a text as one line or a list of its lines; empty adds none.",
"trusted": true,
"default": {}
},
"output_styles": {
"type": "object",
"description": "The output styles offered to every session on this machine, by name, each a text as one line or a list of its lines; empty adds none.",
"trusted": true,
"default": {}
},
"skills": {
"type": "object",
"description": "The skills offered to every session on this machine, by name, each its files by path, a text as one line or a list of its lines; a skill without its SKILL.md is left out; empty adds none.",
"trusted": true,
"default": {}
},
"commands": {
"type": "object",
"description": "The slash commands offered to every session on this machine, by name, each a text as one line or a list of its lines; empty adds none.",
"trusted": true,
"default": {}
},
"agents": {
"type": "object",
"description": "The agents offered to every session on this machine, by name, each a text as one line or a list of its lines; empty adds none.",
"trusted": true,
"default": {}
}
},
"resources": [
{
"id": "package",
"type": "package",
"package": "claude-code"
},
{
"id": "managed",
"type": "directory",
"path": "/etc/claude-code",
"mode": "0755",
"unknown": "program"
},
{
"id": "start",
"type": "file",
"path": "/usr/local/bin/claude-agent",
"mode": "0755",
"template": "files/claude-agent"
},
{
"id": "agent-account-name",
"type": "file",
"path": "/etc/claude-code/agent-account",
"mode": "0644",
"template": "files/agent-account"
},
{
"id": "agent-account",
"type": "user",
"name": "${machine:agent-account}",
"home": "${machine:agent-home}",
"root": "${machine:agent-root}"
},
{
"id": "agent-home",
"type": "directory",
"path": "${machine:agent-home}/.claude",
"mode": "0700",
"owner": "${machine:agent-account}",
"unknown": "module"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "${machine:account}",
"place": ".",
"unknown": "program"
},
{
"id": "facts",
"type": "file",
"path": "${dir:state}/facts.json",
"mode": "0600",
"owner": "${machine:account}",
"template": "files/facts.json"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"owner": "${machine:account}",
"takes-config": ["role", "mcp_servers", "managed_settings", "instructions", "output_styles", "skills", "commands", "agents"],
"merge": "json",
"template": "files/settings.json"
}
],
"items": [
{
"collection": "shell:zsh:normal",
"template": "files/zsh-normal"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/claude-code",
"binary": "claude-code",
"loads": [
"claude-code"
],
"env": {
"MESH_CLAUDE_CODE_STATE": "${dir:state}",
"MESH_CLAUDE_CODE_FACTS": "${dir:state}/facts.json",
"MESH_CLAUDE_CODE_SETTINGS": "${dir:state}/settings.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,184 @@
{
"module": "claude-licence-manager",
"version": "1",
"slug": "licmgr",
"requires": [
"postgres-database",
"secret"
],
"contributes": {
"postgres-database": {
"name": "claude_licences",
"readable": [
"audit",
"binding"
]
}
},
"binds": {
"postgres-database": "${dir:state}/database.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret",
"secret": {
"grant-key": "${dir:state}/grant.key"
}
},
"seats": [
{
"name": "anthropic-licence-manager",
"scope": "mesh",
"serves": [
"licences",
"bindings",
"bind",
"switch",
"release",
"refresh",
"usage",
"adopt",
"current",
"public-key"
]
}
],
"claims": [
{
"name": "anthropic-licence-manager",
"scope": "mesh",
"serves": [
"licences",
"bindings",
"bind",
"switch",
"release",
"refresh",
"usage",
"adopt",
"current",
"public-key"
]
}
],
"emits": [
"licence.adopted",
"licence.refused",
"licence.bound",
"licence.switched",
"licence.released",
"licence.rotated",
"licence.failing",
"usage.read"
],
"state": [
"bindings"
],
"reads": [
"claude-code.holdings"
],
"config": {
"cadence_minutes": {
"type": "number",
"description": "How old a licence's grant may grow before it is rotated, in minutes; 0 keeps 240.",
"minimum": 0,
"trusted": true,
"default": 240
},
"floor_minutes": {
"type": "number",
"description": "How little time a grant may have left before it is refreshed in any case, in minutes; 0 keeps 60.",
"minimum": 0,
"trusted": true,
"default": 60
},
"failures_to_notify": {
"type": "number",
"description": "How many refreshes of a licence fail in a row before the operator is told, a count; 0 keeps 3.",
"minimum": 0,
"trusted": true,
"default": 3
},
"cooldown_hours": {
"type": "number",
"description": "How long after telling the operator about a licence nothing more is said about it, in hours; 0 keeps 24.",
"minimum": 0,
"trusted": true,
"default": 24
},
"refresh_warn_days": {
"type": "number",
"description": "How long before a licence's refresh token itself expires the operator is warned, in days; 0 keeps 3.",
"minimum": 0,
"trusted": true,
"default": 3
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "database-url",
"type": "file",
"path": "${dir:state}/database.url",
"mode": "0600",
"template": "files/database.url"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"takes-config": ["cadence_minutes", "floor_minutes", "failures_to_notify", "cooldown_hours", "refresh_warn_days"],
"merge": "json",
"template": "files/settings.json"
},
{
"id": "prepare",
"type": "process",
"name": "claude-licence-manager-prepare",
"artifact": "code",
"run": [
"./claude-licence-manager",
"prepare"
],
"run-once": true,
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
},
"restart-on": [
"database-url"
]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/claude-licence-manager",
"binary": "claude-licence-manager",
"loads": [
"claude-licence-manager"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_LICENCE_STATE": "${dir:state}",
"MESH_LICENCE_KEY_FILE": "${dir:state}/grant.key",
"MESH_LICENCE_SETTINGS": "${dir:state}/settings.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,135 @@
{
"module": "clipmenu",
"version": "1",
"moved": true,
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"claims": [
{
"name": "node-clipboard",
"scope": "node",
"serves": [
"history",
"copy"
]
}
],
"tools": [
"clipmenu_paste",
"clipmenu_clear",
"clipmenu_delete"
],
"items": [
{
"collection": "environment",
"name": "cm-selections",
"attributes": {
"kind": "variable",
"name": "CM_SELECTIONS"
},
"template": "files/env-cm-selections"
},
{
"collection": "environment",
"name": "cm-max-clips",
"attributes": {
"kind": "variable",
"name": "CM_MAX_CLIPS"
},
"template": "files/env-cm-max-clips"
},
{
"collection": "environment",
"name": "cm-histlength",
"attributes": {
"kind": "variable",
"name": "CM_HISTLENGTH"
},
"template": "files/env-cm-histlength"
},
{
"collection": "contribution:node-display-session:config",
"name": "display-session",
"template": "files/i3/50-clipmenu.conf"
}
],
"resources": [
{
"id": "package",
"type": "package",
"package": "clipmenu"
},
{
"id": "greenclip",
"type": "package",
"package": "rofi-greenclip",
"absent": true
},
{
"id": "text-only",
"type": "file",
"path": "/usr/local/lib/mesh-clipmenu/xsel",
"mode": "0755",
"template": "files/bin/xsel"
},
{
"id": "daemon-dropins",
"type": "directory",
"path": "${machine:account-home}/.config/systemd/user/clipmenud.service.d",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out"
},
{
"id": "daemon-dropin",
"type": "file",
"path": "${machine:account-home}/.config/systemd/user/clipmenud.service.d/mesh.conf",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/systemd/clipmenud-mesh.conf"
},
{
"id": "launcher",
"type": "file",
"path": "/usr/local/lib/mesh-clipmenu/clipmenud-session",
"mode": "0755",
"template": "files/bin/clipmenud-session"
},
{
"id": "daemon",
"type": "service",
"unit": "clipmenud.service",
"scope": "user",
"user": "${machine:account}",
"state": "running",
"boot": "enabled",
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/clipmenu-tools",
"binary": "clipmenu-tools",
"loads": [
"clipmenu-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,76 @@
{
"module": "confluence",
"version": "1",
"slug": "confl",
"own-secrets": {
"token": "${dir:state}/token"
},
"config": {
"atlassian-url": {
"type": "string",
"description": "The address of the operator's Atlassian site the confluence tools call, as a URL such as https://example.atlassian.net, laid into the file as ATLASSIAN_URL; unset, the code falls back to its environment and answers no calls until it is given.",
"trusted": true,
"default": ""
},
"atlassian-email": {
"type": "string",
"description": "The email address of the Atlassian account the confluence tools sign in as with its API token, laid into the file as ATLASSIAN_EMAIL; unset, the code falls back to its environment and answers no calls until it is given.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config",
"type": "file",
"path": "${dir:state}/config.json",
"merge": "json",
"template": "files/config.json",
"mode": "0600",
"takes-config": [
{
"key": "atlassian-url",
"as": "ATLASSIAN_URL"
},
{
"key": "atlassian-email",
"as": "ATLASSIAN_EMAIL"
}
]
}
],
"capabilities": [
"container-runtime"
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_CONFLUENCE_TOKEN_FILE": "${dir:state}/token",
"MESH_CONFLUENCE_CONFIG_FILE": "${dir:state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,58 @@
{
"module": "cups",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"tools": [
"cups_printers",
"cups_queue",
"cups_cancel",
"cups_print",
"cups_default",
"cups_resume",
"cups_drivers"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "cups"
},
{
"id": "driverless",
"type": "package",
"package": "cups-filters"
},
{
"id": "socket",
"type": "service",
"unit": "cups.socket",
"state": "running",
"boot": "enabled"
},
{
"id": "scheduler",
"type": "service",
"unit": "cups.service",
"state": "running",
"boot": "enabled"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/cups-tools",
"binary": "cups-tools",
"loads": [
"cups-tools"
]
}
]
}
}
@@ -0,0 +1,67 @@
{
"module": "dbus",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"claims": [
{
"name": "node-message-bus",
"scope": "node"
}
],
"emits": [
"bus.stalled",
"bus.recovered",
"bus.restarted",
"service.appeared",
"service.left",
"policy.denied"
],
"tools": [
"dbus_names",
"dbus_introspect",
"dbus_monitor",
"dbus_check",
"dbus_health"
],
"resources": [
{
"id": "dbus",
"type": "package",
"package": "dbus"
},
{
"id": "broker",
"type": "package",
"package": "dbus-broker"
},
{
"id": "broker-units",
"type": "package",
"package": "dbus-broker-units"
},
{
"id": "system-bus",
"type": "service",
"unit": "dbus-broker.service",
"state": "running"
}
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/dbus-tools",
"binary": "dbus-tools",
"loads": [
"dbus-tools"
]
}
]
}
}
@@ -0,0 +1,106 @@
{
"module": "desk-channel",
"version": "1",
"slug": "desk",
"runs-as": "desk-channel",
"claims": [
{
"name": "channel",
"scope": "mesh",
"kind": "desktop",
"capabilities": [
"deliver",
"silent",
"loud",
"edit",
"private",
"choice",
"exact-render"
]
},
{
"name": "intake",
"scope": "mesh",
"kind": "desktop"
}
],
"consumes": [
"dunst.action-chosen",
"dunst.started",
"dunst.paused"
],
"invokes": [
"seat:node-notifier.send"
],
"state": [
{
"name": "shown",
"ttl-seconds": 2592000
}
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "desk-channel",
"tools": [
"desk_channel_status"
],
"config": {
"desktop-machines": {
"type": "list",
"description": "The machines, by node name, whose desktop shows the operator's questions and notifications, in the order they are tried; empty shows them on none.",
"trusted": true,
"default": []
}
},
"resources": [
{
"id": "account",
"type": "user",
"name": "desk-channel",
"shell": "/usr/bin/nologin",
"home": "/var/lib/desk-channel"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "desk-channel",
"place": ".",
"unknown": "program"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"owner": "desk-channel",
"takes-config": ["desktop-machines"],
"merge": "json",
"template": "files/settings.json"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/desk-channel",
"binary": "desk-channel",
"loads": [
"desk-channel"
],
"env": {
"MESH_DESK_SETTINGS": "${dir:state}/settings.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,49 @@
{
"module": "dev-tools",
"version": "1",
"capabilities": [
"package-manager"
],
"resources": [
{
"id": "go",
"type": "package",
"package": "go"
},
{
"id": "c-compiler",
"type": "package",
"package": "gcc"
},
{
"id": "make",
"type": "package",
"package": "make"
},
{
"id": "nodejs",
"type": "package",
"package": "nodejs"
},
{
"id": "npm",
"type": "package",
"package": "npm"
},
{
"id": "python",
"type": "package",
"package": "python"
},
{
"id": "git",
"type": "package",
"package": "git"
},
{
"id": "jq",
"type": "package",
"package": "jq"
}
]
}
@@ -0,0 +1,26 @@
{
"module": "disk-load",
"version": "1",
"tools": [
"disk_load",
"disk_top",
"disk_filesystems",
"disk_devices",
"cpu_top"
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/disk-load",
"binary": "disk-load",
"loads": [
"disk-load"
]
}
]
}
}
@@ -0,0 +1,96 @@
{
"module": "distribution",
"version": "1",
"provides": [
{
"name": "artifact-store",
"scope": "mesh"
}
],
"claims": [
{
"name": "mesh-artifact-store",
"scope": "mesh"
}
],
"capabilities": [
"container-runtime"
],
"own-secrets": {
"broker": "/var/lib/mesh/registry/broker"
},
"serves": {
"artifact-store": {
"port": 5000
}
},
"listens": [
{
"name": "registry",
"port": 5000,
"protocol": "tcp",
"from": "mesh",
"why": "every machine pulls images and artifacts from here"
}
],
"data": {
"own": [
{
"id": "registry",
"path": "${dir:registry-data}",
"class": "rebuildable",
"backup": "none",
"measure": "shallow",
"why": "the artifact store: every image is built again from its source, and too large to copy every night (ADR 0214 left it out)"
}
]
},
"resources": [
{
"id": "state",
"type": "directory",
"path": "/var/lib/mesh/registry",
"mode": "0700",
"unknown": "program"
},
{
"id": "registry-data",
"type": "directory",
"path": "/var/lib/mesh-registry",
"mode": "0700",
"unknown": "program"
},
{
"id": "store",
"type": "container",
"name": "mesh-registry",
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
"ports": [
"5000:5000"
],
"volumes": [
"/var/lib/mesh-registry:/var/lib/registry"
],
"env": {
"REGISTRY_STORAGE_DELETE_ENABLED": "true"
}
},
{
"id": "collect",
"type": "container",
"name": "mesh-registry-collect",
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
"volumes": [
"/var/lib/mesh-registry:/var/lib/registry"
],
"args": [
"garbage-collect",
"/etc/docker/registry/config.yml"
],
"schedule": "30 3 * * *",
"while-stopped": [
"store"
]
}
]
}
@@ -0,0 +1,33 @@
{
"module": "dmenu",
"version": "1",
"capabilities": [
"package-manager"
],
"tools": [
"dmenu_menu",
"dmenu_session"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "dmenu"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/dmenu-tools",
"binary": "dmenu-tools",
"loads": [
"dmenu-tools"
]
}
]
}
}
@@ -0,0 +1,162 @@
{
"module": "dnsmasq",
"version": "1",
"upgrade": {
"policy": "record",
"why": "the mesh's resolver: a build that breaks it can stop a machine resolving the bus, and then neither the gate's rollback nor a push reaches it (hq ADR 0236, issue 260)"
},
"provides": [
{
"name": "wildcard-resolution",
"scope": "mesh",
"identity": false
}
],
"requires": [
"mesh-addressing"
],
"emits": [
"name.added",
"name.removed",
"restarted",
"restart-judged"
],
"own-secrets": {
"broker": "${dir:mesh-state}/broker"
},
"claims": [
{
"name": "mesh-dns-resolver",
"scope": "mesh"
}
],
"tools": [
"dnsmasq_health",
"dnsmasq_names",
"dnsmasq_resolve"
],
"listens": [
{
"name": "dns-udp",
"port": 53,
"protocol": "udp",
"from": "mesh",
"why": "one of the mesh's resolvers (ADR 0194, 0223): every node's and every container's resolver, beside any other holder of the seat — the mesh's own names answered here, a module's zone forwarded to it, the rest forwarded upstream",
"fixed": true
},
{
"name": "dns-tcp",
"port": 53,
"protocol": "tcp",
"from": "mesh",
"why": "the same names over tcp, which a resolver answers on as well and is asked for whenever an answer will not fit in a datagram. Declared because the daemon serves it: a declaration that covers one of the two protocols its own service listens on leaves the other closed while everything reports success",
"fixed": true
}
],
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "package",
"type": "package",
"package": "dnsmasq"
},
{
"id": "config",
"type": "file",
"path": "/etc/dnsmasq.conf",
"mode": "0644",
"template": "files/dnsmasq.conf"
},
{
"id": "drop-ins",
"type": "directory",
"path": "/etc/systemd/system/dnsmasq.service.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "wait-for-address",
"type": "file",
"path": "/etc/systemd/system/dnsmasq.service.d/mesh.conf",
"mode": "0644",
"template": "files/mesh.conf"
},
{
"id": "service",
"type": "service",
"unit": "dnsmasq.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"config",
"wait-for-address",
"dnsmasq.fact-node-zones",
"dnsmasq.fact-zones"
],
"health": {
"kind": "unit"
}
},
{
"id": "watch-dir",
"type": "directory",
"path": "/var/lib/dnsmasq-watch",
"mode": "0755",
"unknown": "program"
},
{
"id": "watch",
"type": "process",
"name": "dnsmasq-watch",
"artifact": "tools",
"run": [
"./dnsmasq-tools",
"watch"
],
"health": {
"kind": "tool",
"tool": "dnsmasq_health",
"interval": "20s",
"timeout": "10s",
"looks": 2,
"grace": "60s"
}
}
],
"facts": {
"node-zones": {
"path": "/etc/mesh-resolver/nodes.conf",
"template": "# Generated by the mesh. Do not edit — this file is replaced whenever a machine\n# joins or leaves, and an edit would survive until then and vanish.\n\nlocal=/{{.Suffix}}/\n# A machine's own name is a host record as well as a wildcard: asked for an IPv6 address, the\n# resolver then says the name exists and has none, where the wildcard alone said there is no such\n# name — and a resolver that reads that as final (musl, so every Alpine container) failed to find\n# the machine at all (novox/hq issue 262).\n{{range .Machines}}address=/{{.FQDN}}/{{.Address}}\nhost-record={{.FQDN}},{{.Address}}\n{{end}}"
},
"zones": {
"path": "/etc/mesh-resolver/zones.conf",
"template": "# Generated by the mesh. Do not edit — this file is replaced whenever a module declares a zone or\n# its machine moves (novox/hq ADR 0199). One forwarding line per zone, to the module answering it.\n\n{{range .Zones}}server=/{{.Zone}}/{{.Address}}#{{.Port}}\n{{end}}"
}
},
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/dnsmasq-tools",
"binary": "dnsmasq-tools",
"loads": [
"dnsmasq-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,40 @@
{
"module": "docker-compose",
"version": "1",
"capabilities": [
"package-manager"
],
"tools": [
"docker_compose_projects",
"docker_compose_ps",
"docker_compose_logs",
"docker_compose_config",
"docker_compose_up",
"docker_compose_down",
"docker_compose_restart",
"docker_compose_pull",
"docker_compose_job"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "docker-compose"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/docker-compose-tools",
"binary": "docker-compose-tools",
"loads": [
"docker-compose-tools"
]
}
]
}
}
@@ -0,0 +1,179 @@
{
"module": "docker",
"version": "1",
"capabilities": [
"package-manager",
"service-manager",
"privileged"
],
"invokes": [
"seat:mesh-controller.images"
],
"claims": [
{
"name": "node-container-runtime",
"scope": "node"
}
],
"tools": [
"docker_list",
"docker_inspect",
"docker_resolv_conf",
"docker_logs",
"docker_secrets_in_logs",
"docker_secrets_in_events",
"docker_stats",
"docker_start",
"docker_stop",
"docker_restart",
"docker_top",
"docker_images",
"docker_prune",
"docker_prune_images",
"docker_disk_usage",
"docker_networks",
"docker_volumes",
"docker_events",
"docker_daemon_config",
"docker_unlabelled",
"docker_problems",
"docker_ports"
],
"replaces": {
"docker_resolv_conf": [
"docker exec cat /etc/resolv.conf"
]
},
"config": {
"log-max-size": {
"type": "string",
"description": "The size each container's log is cut at, a whole number from 1 with k, m or g after it; the runtime keeps log-max-file of them, so 100m and 10 hold about 1 GB per container (novox/hq issue 452). The runtime reads it only at its next start, which the mesh never forces, and a container created before that keeps the options it was created with until it is created again.",
"pattern": "[1-9][0-9]*[kmg]",
"trusted": true,
"default": "100m"
},
"log-max-file": {
"type": "number",
"description": "How many of a container's log files of log-max-size the runtime keeps, a count from 1 to 99, the oldest dropped first; taken at the runtime's next start and by containers created after it, like log-max-size (novox/hq issue 452).",
"minimum": 1,
"maximum": 99,
"trusted": true,
"default": 10
}
},
"resources": [
{
"id": "package",
"type": "package",
"package": "docker"
},
{
"id": "buildx",
"type": "package",
"package": "docker-buildx"
},
{
"id": "socket",
"type": "service",
"unit": "docker.socket",
"state": "running",
"boot": "enabled"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "log-rotation",
"type": "file",
"path": "${dir:state}/log-rotation.conf",
"mode": "0600",
"trusted": true,
"template": "files/log-rotation.conf"
},
{
"id": "log-rotation-check",
"type": "process",
"name": "docker-log-rotation-check",
"artifact": "tools",
"run": [
"./docker-tools",
"check-log-rotation"
],
"run-once": true,
"env": {
"DOCKER_LOG_ROTATION": "${dir:state}/log-rotation.conf"
},
"restart-on": [
"log-rotation"
]
},
{
"id": "daemon",
"type": "file",
"path": "/etc/docker/daemon.json",
"mode": "0644",
"into": "json",
"trusted": true,
"template": "files/daemon.json"
},
{
"id": "runtime",
"type": "service",
"unit": "docker.service",
"state": "running",
"boot": "enabled",
"reload-on": [
"daemon"
]
},
{
"id": "prune-service",
"type": "file",
"path": "/etc/systemd/system/docker-prune.service",
"mode": "0644",
"template": "files/docker-prune.service"
},
{
"id": "prune-timer",
"type": "file",
"path": "/etc/systemd/system/docker-prune.timer",
"mode": "0644",
"template": "files/docker-prune.timer"
},
{
"id": "prune",
"type": "service",
"unit": "docker-prune.timer",
"state": "running",
"boot": "enabled",
"restart-on": [
"prune-service",
"prune-timer"
]
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/docker-tools",
"binary": "docker-tools",
"loads": [
"docker-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,123 @@
{
"module": "dunst",
"version": "1",
"moved": true,
"capabilities": [
"package-manager"
],
"claims": [
{
"name": "node-notifier",
"scope": "node",
"serves": [
"send",
"history"
]
}
],
"tools": [
"dunst_pause",
"dunst_resume",
"dunst_close_all",
"dunst_rules",
"dunst_count",
"dunst_reload"
],
"config": {
"font-size": {
"type": "number",
"description": "The size of a notification's text, in points of Inter: 10 reads well on a screen of about 100 DPI, and a denser screen needs a larger size.",
"minimum": 6,
"maximum": 72,
"predefined": "font-size",
"default": 10
},
"width": {
"type": "number",
"description": "The width of a notification, in pixels: 250 fits a title of about forty characters at 10 points, and a larger font needs a wider notification.",
"minimum": 50,
"maximum": 4000,
"default": 250
}
},
"resources": [
{
"id": "package",
"type": "package",
"package": "dunst"
},
{
"id": "client",
"type": "package",
"package": "libnotify"
},
{
"id": "configuration-dir",
"type": "directory",
"path": "${machine:account-home}/.config/dunst",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out"
},
{
"id": "dropins",
"type": "directory",
"path": "${machine:account-home}/.config/dunst/dunstrc.d",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out",
"knows": ["50-slack.conf"]
},
{
"id": "configuration",
"trusted": false,
"type": "file",
"path": "${machine:account-home}/.config/dunst/dunstrc",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/dunstrc"
},
{
"id": "notifier",
"type": "service",
"unit": "dunst.service",
"scope": "user",
"user": "${machine:account}",
"reload-on": [
"configuration"
]
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/dunst-tools",
"binary": "dunst-tools",
"loads": [
"dunst-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
},
"emits": [
"action-chosen",
"started",
"paused"
],
"items": [
{
"collection": "contribution:node-display-session:config",
"name": "display-session",
"template": "files/i3/50-dunst.conf"
}
]
}
@@ -0,0 +1,195 @@
{
"module": "fail2ban",
"version": "1",
"capabilities": [
"firewall"
],
"claims": [
{
"name": "node-intrusion-prevention",
"scope": "node",
"serves": [
"status",
"banned",
"ban",
"unban"
]
}
],
"tools": [
"fail2ban_settings",
"fail2ban_health"
],
"jailing": {
"into": "/etc/fail2ban/jail.d/mesh.conf",
"filter-into": "/etc/fail2ban/filter.d"
},
"config": {
"own-addresses": {
"type": "list",
"description": "The addresses and networks outside the mesh that are the operator's own, each an IP address or a CIDR network: every jail ignores them beside the private ranges, the ban verb refuses them, and a failure a jail counted from one is said as a warning; empty is none.",
"trusted": true,
"default": []
}
},
"resources": [
{
"id": "package",
"type": "package",
"package": "fail2ban"
},
{
"id": "state-dir",
"type": "directory",
"path": "/var/lib/mesh-fail2ban",
"mode": "0755",
"unknown": "program"
},
{
"id": "own-addresses-list",
"type": "file",
"path": "/var/lib/mesh-fail2ban/own-addresses",
"mode": "0644",
"create-once": true,
"template": "files/own-addresses"
},
{
"id": "jail-d",
"type": "directory",
"path": "/etc/fail2ban/jail.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "action-d",
"type": "directory",
"path": "/etc/fail2ban/action.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "filter-d",
"type": "directory",
"path": "/etc/fail2ban/filter.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "run-dir",
"type": "directory",
"path": "/var/run/fail2ban",
"mode": "0755",
"unknown": "program"
},
{
"id": "jail-local",
"type": "file",
"path": "/etc/fail2ban/jail.local",
"mode": "0644",
"template": "files/jail.local"
},
{
"id": "jail-sshd",
"type": "file",
"path": "/etc/fail2ban/jail.d/sshd.conf",
"mode": "0644",
"template": "files/sshd.conf"
},
{
"id": "own-addresses",
"type": "file",
"path": "/etc/fail2ban/mesh-own-addresses.json",
"mode": "0644",
"merge": "json",
"takes-config": [
"own-addresses"
],
"trusted": true,
"template": "files/mesh-own-addresses.json"
},
{
"id": "watch",
"type": "process",
"name": "fail2ban-watch",
"artifact": "tools",
"run": [
"./fail2ban-tools",
"watch"
],
"health": {
"kind": "tool",
"tool": "fail2ban_health",
"interval": "60s",
"timeout": "10s",
"looks": 2,
"grace": "90s"
}
},
{
"id": "log",
"type": "file",
"path": "/var/log/fail2ban.log",
"mode": "0640",
"create-once": true,
"template": "files/own-addresses"
},
{
"id": "jail-recidive",
"type": "file",
"path": "/etc/fail2ban/jail.d/recidive.conf",
"mode": "0644",
"template": "files/recidive.conf"
},
{
"id": "action-dualchain",
"type": "file",
"path": "/etc/fail2ban/action.d/iptables-allports-dualchain.conf",
"mode": "0644",
"template": "files/iptables-allports-dualchain.conf"
},
{
"id": "logrotate",
"type": "file",
"path": "/etc/logrotate.d/fail2ban",
"mode": "0644",
"template": "files/fail2ban"
},
{
"id": "run",
"type": "service",
"unit": "fail2ban.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"jail-local",
"jail-sshd",
"jail-recidive",
"action-dualchain",
"composed-jails"
],
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/fail2ban-tools",
"binary": "fail2ban-tools",
"loads": [
"fail2ban-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,75 @@
{
"module": "feh",
"version": "1",
"moved": true,
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"tools": [
"feh_set",
"feh_current"
],
"items": [
{
"collection": "shell:xinitrc:normal",
"name": "xinitrc-normal",
"template": "files/xinitrc-normal"
},
{
"collection": "contribution:node-display-session:config",
"name": "display-session",
"template": "files/i3/50-feh.conf"
}
],
"resources": [
{
"id": "package",
"type": "package",
"package": "feh"
},
{
"id": "wallpapers",
"type": "archive",
"path": "${machine:account-home}/.local/share/feh/wallpapers",
"owner": "${machine:account}",
"artifact": "wallpapers",
"unknown": "move-out"
},
{
"id": "fehbg",
"type": "file",
"path": "${machine:account-home}/.fehbg",
"owner": "${machine:account}",
"mode": "0755",
"template": "files/fehbg"
}
],
"build": {
"artifacts": [
{
"name": "wallpapers",
"kind": "archive",
"from": "wallpaper"
},
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/feh-tools",
"binary": "feh-tools",
"loads": [
"feh-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,42 @@
{
"module": "flatpak",
"version": "1",
"capabilities": [
"package-manager"
],
"tools": [
"flatpak_list",
"flatpak_runtimes",
"flatpak_remotes",
"flatpak_updates",
"flatpak_unused",
"flatpak_disk_usage",
"flatpak_install",
"flatpak_remove",
"flatpak_update",
"flatpak_remove_unused",
"flatpak_job"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "flatpak"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/flatpak-tools",
"binary": "flatpak-tools",
"loads": [
"flatpak-tools"
]
}
]
}
}
@@ -0,0 +1,70 @@
{
"module": "fonts",
"version": "1",
"capabilities": [
"package-manager"
],
"tools": [
"fonts_families",
"fonts_match",
"fonts_glyph",
"fonts_sources",
"fonts_config",
"fonts_cache_rebuild"
],
"resources": [
{
"id": "monospace",
"type": "package",
"package": "ttf-jetbrains-mono-nerd"
},
{
"id": "interface",
"type": "package",
"package": "inter-font"
},
{
"id": "symbols",
"type": "package",
"package": "ttf-nerd-fonts-symbols"
},
{
"id": "noto",
"type": "package",
"package": "noto-fonts"
},
{
"id": "emoji",
"type": "package",
"package": "noto-fonts-emoji"
},
{
"id": "defaults",
"type": "file",
"path": "${machine:account-home}/.config/fontconfig/conf.d/50-mesh-fonts.conf",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/50-mesh-fonts.conf"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/fonts-tools",
"binary": "fonts-tools",
"loads": [
"fonts-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,57 @@
{
"module": "forticlient",
"version": "1",
"upgrade": {
"policy": "record",
"why": "its adapter routes the company's domains on the machine a person works on: a build that breaks it cuts the person off from work names until a person pushes the next (hq ADR 0236, ADR 0247)"
},
"capabilities": [
"service-manager"
],
"requires": [
"x11-display",
"split-dns"
],
"tools": [
"forticlient_status",
"forticlient_restart",
"forticlient_check"
],
"resources": [
{
"id": "scheduler",
"type": "service",
"unit": "forticlient.service",
"state": "running",
"boot": "enabled"
},
{
"id": "split-dns",
"type": "process",
"name": "forticlient-split-dns",
"artifact": "tools",
"run": [
"./forticlient-tools",
"split-dns"
],
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/forticlient-tools",
"binary": "forticlient-tools",
"loads": [
"forticlient-tools"
]
}
]
}
}
@@ -0,0 +1,545 @@
{
"module": "gitea",
"version": "1",
"moved": true,
"requires": [
"postgres-database",
"route",
"secret"
],
"contributes": {
"postgres-database": {
"name": "gitea"
},
"route": {
"web": {
"label": "git",
"endpoint": "web"
},
"internal-api-refused": {
"label": "git",
"path": "/api/internal",
"deny": true,
"priority": 100000
}
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret",
"secret": {
"internal-token": "${dir:state}/internal-token.secret",
"admin": "${dir:state}/admin.secret"
}
},
"capabilities": [
"container-runtime"
],
"emits": [
"repo.created",
"issue.opened",
"pull.merged",
"pull.updated",
"pull.closed",
"forge.push",
"forge.create",
"forge.delete",
"forge.fork",
"forge.status",
"forge.pull-request.opened",
"forge.pull-request.reopened",
"forge.pull-request.synchronized",
"forge.pull-request.edited",
"forge.pull-request.closed",
"forge.pull-request.merged",
"forge.pull-request.labeled",
"forge.pull-request.unlabeled",
"forge.pull-request.assigned",
"forge.pull-request.unassigned",
"forge.pull-request.reviewed",
"forge.pull-request.review-requested",
"forge.pull-request.commented",
"forge.pull-request.changed",
"forge.issue-comment.created",
"forge.issue-comment.edited",
"forge.issue-comment.deleted",
"forge.issues.opened",
"forge.issues.reopened",
"forge.issues.closed",
"forge.issues.edited",
"forge.issues.labeled",
"forge.issues.unlabeled",
"forge.issues.assigned",
"forge.issues.unassigned",
"forge.issues.changed",
"forge.release.published",
"forge.release.updated",
"forge.release.deleted",
"forge.release.changed",
"forge.repository.created",
"forge.repository.deleted",
"forge.repository.changed",
"forge.wiki.changed",
"forge.other"
],
"consumes": [
"mesh-controller.checked",
"node-build-agent.started"
],
"listens": [
{
"name": "web",
"port": 3000,
"protocol": "tcp",
"from": "mesh",
"why": "the forge, over http"
},
{
"name": "ssh",
"port": 22,
"protocol": "tcp",
"from": "mesh",
"why": "git over ssh, gitea's own unmodified sshd. Published on the machine's own side at 222, the mesh's fixed public convention — not 22, which the machine's own daemon holds and a module does not take"
},
{
"name": "forge-events",
"port": 3047,
"protocol": "tcp",
"from": "machine",
"why": "the forge's system webhook, every event signed with a secret the module keeps, from the forge's container on the docker bridge to the module's receiver at the bridge's gateway 172.17.0.1 (novox/hq issue 729)"
}
],
"serves": {
"npm-package-registry": {
"scheme": "http",
"port": 3000,
"npm-path": "/api/packages/novox/npm/",
"public-root": "https://${bound:route:name-web}/api/packages/novox/npm/"
},
"git": {
"scheme": "http",
"port": 3000
}
},
"receives": {
"npm-package-registry": "${dir:grants}/npm.json"
},
"grants": {
"npm-package-registry": "${dir:grants}"
},
"claims": [
{
"name": "npm-package-registry",
"scope": "mesh"
},
{
"name": "git",
"scope": "mesh"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "every repository, its issues and attachments, and the package registry"
}
],
"consumers": {
"npm-package-registry": {
"class": "rebuildable",
"in": "data",
"why": "a consumer's packages are published again from its source"
}
}
},
"config": {
"url": {
"type": "string",
"description": "The address the module's tools reach the forge at, as a URL; unset, the code falls back to its environment, else this machine's gitea on its port.",
"trusted": true,
"default": ""
},
"agent-read-teams": {
"type": "object",
"description": "The read teams of the agents' forge accounts (ADR 0365 clause 3): each team by name, {\"<team>\": {\"repos\": [\"<owner>/<repo>\", ...], \"members\": [\"<node>\", ...]}}. The forge gets a team agent-read-<team> that reads only, with exactly those repositories and the accounts agent-<node>; a team taken out of the value is emptied. Nothing else on the forge is touched; an agent account is in no team until it is listed here.",
"trusted": true,
"default": {}
},
"repositories": {
"type": "object",
"description": "The repositories of the organisation novox the mesh holds (ADR 0428): each by name, {\"<name>\": {\"private\": true, \"description\": \"...\"}}. One that does not exist is made by the module's setup login under its own account, its main protected and given a first commit (a README naming the description and a merge-check.sh), its rule narrowed to no push and the tools' merge requiring mesh/repo-check and mesh/merge-gate, and only then moved into the organisation; one that exists only has main's rule put right, its statuses kept. A repository taken out of the value is never touched.",
"trusted": true,
"default": {}
}
},
"facts": {
"forge-host": {
"path": "/etc/gitea/forge-host",
"template": "{{range .Machines}}{{if eq .Name $.Node}}{{.FQDN}}{{end}}{{end}}\n"
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "runtime-state",
"type": "directory",
"path": "${dir:mesh-state}/state",
"mode": "0700",
"unknown": "program"
},
{
"id": "forge-patches",
"type": "directory",
"path": "/var/lib/mesh/forge-patches",
"mode": "0733",
"owner": "${machine:account}",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "1000:1000",
"unknown": "program"
},
{
"id": "server",
"type": "container",
"health": {
"kind": "http",
"endpoint": "web",
"path": "/api/healthz",
"status": 200,
"needs": "postgres-database"
},
"name": "gitea",
"image": "gitea/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef",
"env": {
"DB_TYPE": "postgres",
"USER_UID": "1000",
"USER_GID": "1000"
},
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"3000",
"222:22"
],
"volumes": [
"${dir:data}:/data"
],
"secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it",
"logging": "journald"
},
{
"id": "admin-bootstrap",
"type": "container",
"name": "mesh-gitea-admin",
"image": "gitea/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef",
"run-once": true,
"env": {
"USER_UID": "1000",
"USER_GID": "1000",
"MESH_GITEA_ADMIN_USER": "mesh-admin"
},
"env-file": [
"${dir:state}/server.env"
],
"volumes": [
"${dir:data}:/data",
"${dir:state}/admin.secret:/run/secrets/admin:ro"
],
"args": [
"/bin/sh",
"-c",
"su-exec git gitea admin user create --admin --username \"$MESH_GITEA_ADMIN_USER\" --email mesh-admin@localhost --password \"$(cat /run/secrets/admin)\" --must-change-password=false || true"
],
"secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it"
},
{
"id": "origins",
"type": "file",
"path": "${dir:mesh-state}/origins",
"mode": "0644",
"template": "files/origins"
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": [
"url"
]
},
{
"id": "agent-teams-file",
"type": "file",
"path": "${dir:mesh-state}/agent-teams.json",
"mode": "0600",
"template": "files/agent-teams.json",
"merge": "json",
"takes-config": [
"agent-read-teams"
]
},
{
"id": "repositories-file",
"type": "file",
"path": "${dir:mesh-state}/repositories.json",
"mode": "0600",
"template": "files/repositories.json"
},
{
"id": "consumers",
"type": "file",
"path": "${dir:state}/consumers.json",
"mode": "0600",
"template": "files/consumers.json"
},
{
"id": "agent-teams",
"type": "process",
"name": "gitea-agent-teams",
"artifact": "agent-teams",
"run": [
"./agent-teams"
],
"run-once": true,
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_ADMIN_USER": "mesh-admin",
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_AGENT_TEAMS_FILE": "${dir:mesh-state}/agent-teams.json"
},
"restart-on": [
"agent-teams-file"
]
},
{
"id": "repositories",
"type": "process",
"name": "gitea-repositories",
"artifact": "repositories",
"run": [
"./repositories",
"sync"
],
"run-once": true,
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_ADMIN_USER": "mesh-admin",
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_GITEA_TOOLS_USER": "mesh-tools",
"MESH_REPOSITORIES_FILE": "${dir:mesh-state}/repositories.json",
"MESH_REPOSITORIES_OUTCOME": "${dir:runtime-state}/repositories-outcome.json"
},
"restart-on": [
"repositories-file"
]
}
],
"provides": [
{
"name": "npm-package-registry",
"scope": "mesh",
"identity": {
"max": 40,
"in": "a Gitea user name"
}
},
{
"name": "git",
"scope": "mesh"
},
{
"name": "gitea-read",
"scope": "mesh",
"credential": {
"issued-by": "software",
"tool": "gitea_agent_token"
}
},
{
"name": "forge-account",
"scope": "mesh"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"loads": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_CONFIG_FILE": "${dir:mesh-state}/config.json",
"MESH_GITEA_ADMIN_USER": "mesh-admin",
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_GITEA_TOOLS_USER": "mesh-tools",
"MESH_GITEA_STATE_DIR": "${dir:runtime-state}",
"MESH_RECEIVES": "${dir:grants}/npm.json",
"MESH_GITEA_HOOK_URL": "http://172.17.0.1:3047",
"MESH_GITEA_HOOK_PORT": "3047",
"MESH_GITEA_HOOK_HOST": "172.17.0.1"
}
},
{
"name": "npm-registry",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/npm-registry",
"binary": "npm-registry",
"loads": [
"npm-registry"
],
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_ADMIN_USER": "mesh-admin",
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_NPM_OWNER": "novox"
}
},
{
"name": "forge",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/forge",
"binary": "forge",
"loads": [
"forge"
],
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_TOOLS_USER": "mesh-tools",
"MESH_GITEA_TOKEN_FILE": "${dir:runtime-state}/token",
"MESH_GITEA_PATCH_DIR": "${dir:forge-patches}"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
},
{
"name": "agent-token",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/agent-token",
"binary": "agent-token",
"loads": [
"agent-token"
],
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_ADMIN_USER": "mesh-admin",
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_GITEA_ORIGINS_FILE": "${dir:mesh-state}/origins"
}
},
{
"name": "agent-teams",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/agent-teams",
"binary": "agent-teams",
"loads": [
"agent-teams"
]
},
{
"name": "repositories",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/repositories",
"binary": "repositories",
"loads": [
"repositories"
]
},
{
"name": "forge-account-provider",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/forge-account-provider",
"binary": "forge-account-provider",
"loads": [
"forge-account-provider"
],
"env": {
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GITEA_ADMIN_USER": "mesh-admin",
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_GITEA_ORIGINS_FILE": "${dir:mesh-state}/origins",
"MESH_GITEA_SSH_PORT": "222",
"MESH_FORGE_HOST_FILE": "/etc/gitea/forge-host"
}
}
]
},
"jails": [
{
"name": "gitea",
"failregex": "^.*Failed authentication attempt for .* from <HOST>(?::\\d+)?\\s*$\n ^.*Invalid user .* from <HOST> port \\d+\\s*$\n ^.*User \\S+ from <HOST> not allowed because .*$",
"jail": "backend = systemd\njournalmatch = CONTAINER_NAME=gitea\nport = http,https,222\nmaxretry = 3\nfindtime = 1d\nbantime = 1d"
}
],
"state": [
"bound",
"announced"
],
"reads": [
"mesh-controller.assignments",
"ssh-client.keys"
]
}
@@ -0,0 +1,65 @@
{
"module": "gitlab",
"version": "1",
"own-secrets": {
"token": "${dir:state}/token"
},
"config": {
"gitlab-url": {
"type": "string",
"description": "The address of the GitLab instance the gitlab tools call, as a URL such as https://gitlab.com, laid into the file as GITLAB_URL; unset, the code falls back to its environment and answers no calls until it is given.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config",
"type": "file",
"path": "${dir:state}/config.json",
"merge": "json",
"template": "files/config.json",
"mode": "0600",
"takes-config": [
{
"key": "gitlab-url",
"as": "GITLAB_URL"
}
]
}
],
"capabilities": [
"container-runtime"
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_GITLAB_TOKEN_FILE": "${dir:state}/token",
"MESH_GITLAB_CONFIG_FILE": "${dir:state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,82 @@
{
"module": "gnome-keyring",
"version": "1",
"moved": true,
"capabilities": [
"package-manager"
],
"claims": [
{
"name": "node-secret-service",
"scope": "node"
}
],
"tools": [
"gnome_keyring_unlocked",
"gnome_keyring_lock",
"gnome_keyring_collections",
"gnome_keyring_ssh_keys"
],
"items": [
{
"collection": "shell:xinitrc:first",
"name": "xinitrc-first",
"template": "files/xinitrc-first"
}
],
"resources": [
{
"id": "package",
"type": "package",
"package": "gnome-keyring"
},
{
"id": "library",
"type": "package",
"package": "libsecret"
},
{
"id": "manager",
"type": "package",
"package": "seahorse"
},
{
"id": "pam-login",
"type": "file",
"path": "/etc/pam.d/login",
"mode": "0644",
"into": "block",
"at": "end",
"template": "files/pam/login"
},
{
"id": "pam-passwd",
"type": "file",
"path": "/etc/pam.d/passwd",
"mode": "0644",
"into": "block",
"at": "end",
"template": "files/pam/passwd"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/gnome-keyring-tools",
"binary": "gnome-keyring-tools",
"loads": [
"gnome-keyring-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,225 @@
{
"module": "grafana",
"version": "1",
"emits": [
"alert.firing"
],
"own-secrets": {
"admin": "${dir:mesh-state}/admin"
},
"capabilities": [
"container-runtime"
],
"listens": [
{
"name": "web",
"port": 3000,
"protocol": "tcp",
"from": "mesh",
"why": "the dashboards. Also 3000 inside, like the forge - which is the mesh's port assignment earning its keep"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "dashboards, users and alert rules"
}
]
},
"config": {
"user": {
"type": "string",
"description": "The Grafana account the module's tools sign in as with the vault's password; the file's default is admin.",
"trusted": true,
"default": "admin"
},
"url": {
"type": "string",
"description": "The address the module's tools reach Grafana at, as a URL; unset, the code falls back to its environment, else this machine's Grafana on its port.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "472:472",
"unknown": "program"
},
{
"id": "admin-secret",
"type": "file",
"path": "${dir:state}/admin.secret",
"mode": "0400",
"owner": "472:472",
"template": "files/admin.secret"
},
{
"id": "oidc-secret",
"type": "file",
"path": "${dir:state}/oidc-client.secret",
"mode": "0400",
"owner": "472:472",
"template": "files/oidc-client.secret"
},
{
"id": "oidc-env",
"type": "file",
"path": "${dir:state}/oidc.env",
"mode": "0644",
"template": "files/oidc.env"
},
{
"id": "influxdb-datasources",
"type": "directory",
"path": "${dir:state}/datasources",
"mode": "0755",
"owner": "472:472",
"unknown": "program"
},
{
"id": "influxdb-credential",
"type": "directory",
"path": "${dir:state}/influxdb",
"mode": "0700",
"owner": "472:472",
"unknown": "program"
},
{
"id": "influxdb-secret",
"type": "file",
"path": "${dir:influxdb-credential}/influxdb-api",
"mode": "0400",
"owner": "472:472",
"template": "files/influxdb-api",
"only-when-bound": "influxdb-api"
},
{
"id": "influxdb-datasource",
"type": "file",
"path": "${dir:influxdb-datasources}/mesh-influxdb.yaml",
"mode": "0644",
"template": "files/mesh-influxdb.yaml",
"only-when-bound": "influxdb-api"
},
{
"id": "server",
"type": "container",
"name": "grafana",
"image": "grafana/grafana@sha256:ac461fb352abc50da10a51c7d02462e9c05488f11f53f14b3ad79a8145f638a0",
"health": {
"kind": "http",
"endpoint": "web",
"path": "/"
},
"ports": [
"3000"
],
"volumes": [
"${dir:data}:/var/lib/grafana",
"${dir:state}/admin.secret:/run/secrets/admin:ro",
"${dir:state}/oidc-client.secret:/run/secrets/oidc-client:ro",
"${dir:influxdb-credential}:/run/secrets/influxdb:ro",
"${dir:influxdb-datasources}:/etc/grafana/provisioning/datasources:ro"
],
"env": {
"GF_SECURITY_ADMIN_PASSWORD__FILE": "/run/secrets/admin"
},
"env-file": [
"${dir:state}/oidc.env"
],
"restart-on": [
"oidc-env",
"oidc-secret",
"influxdb-datasource",
"influxdb-secret"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": ["user", "url"],
"protected": ["password", "token"]
}
],
"requires": [
"route",
"oidc-client",
{
"name": "influxdb-api",
"optional": true
}
],
"contributes": {
"route": {
"label": "grafana",
"endpoint": "web"
},
"oidc-client": {
"label": "grafana",
"endpoint": "web",
"callback": "/login/generic_oauth"
},
"influxdb-api": {
"access": "read"
}
},
"binds": {
"route": "${dir:state}/route.json",
"oidc-client": "${dir:state}/oidc.json",
"influxdb-api": "${dir:state}/influxdb.json"
},
"secrets": {
"oidc-client": "${dir:mesh-state}/oidc-client",
"influxdb-api": "${dir:mesh-state}/influxdb-api"
},
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"MESH_GRAFANA_URL": "http://127.0.0.1:${port:3000}",
"MESH_GRAFANA_CONFIG_FILE": "${dir:mesh-state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,82 @@
{
"module": "hello-web",
"slug": "hello",
"version": "1",
"capabilities": [
"container-runtime"
],
"requires": [
"route"
],
"contributes": {
"route": {
"label": "hello",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json"
},
"listens": [
{
"name": "web",
"port": 8080,
"protocol": "tcp",
"from": "mesh",
"why": "the demo web page; only the route-proxy reaches it, and the public name is a route grant"
}
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "page",
"type": "file",
"path": "${dir:state}/index.html",
"mode": "0644",
"template": "files/index.html"
},
{
"id": "net",
"type": "network",
"name": "hello-web"
},
{
"id": "server",
"type": "container",
"name": "hello-web",
"network": "hello-web",
"ports": [
"8080"
],
"volumes": [
"${dir:state}/index.html:/www/index.html:ro"
],
"args": [
"sh",
"-c",
"while true; do { printf 'HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\nConnection: close\\r\\n\\r\\n'; cat /www/index.html; } | nc -l -p 8080; done"
],
"artifact": "server"
}
],
"build": {
"artifacts": [
{
"name": "server",
"kind": "upstream",
"from": "alpine@sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b"
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,209 @@
{
"module": "home-assistant",
"version": "1",
"slug": "hass",
"capabilities": [
"container-runtime"
],
"emits": [
"state.changed"
],
"own-secrets": {
"token": "${dir:mesh-state}/token"
},
"listens": [
{
"name": "web",
"port": 8123,
"protocol": "tcp",
"from": "mesh",
"why": "the dashboard, the API and the companion apps"
},
{
"name": "sonos-events",
"port": 1400,
"protocol": "tcp",
"from": "mesh",
"why": "the Sonos integration's event callback: speakers push their state changes here"
},
{
"name": "webrtc",
"port": 18555,
"protocol": "tcp",
"from": "mesh",
"why": "the bundled go2rtc's WebRTC port, which camera streams to a browser use"
}
],
"data": {
"own": [
{
"id": "config",
"path": "${dir:config}",
"class": "valuable",
"active": "1d",
"why": "the house's configuration, automations and history; written all the time"
}
]
},
"config": {
"url": {
"type": "string",
"description": "The address the module's tools reach Home Assistant at, as a URL; unset, the code falls back to its environment, else this machine's Home Assistant on its port.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "written",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "server",
"type": "container",
"name": "home-assistant",
"image": "ghcr.io/home-assistant/home-assistant@sha256:d8922685169707fd91e8b9729902d975f06157d005e422874d201e0261dda196",
"network": "host",
"env": {
"TZ": "Etc/UTC"
},
"volumes": [
"${dir:config}:/config"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": ["url"]
},
{
"id": "provisions-env",
"type": "file",
"path": "${dir:state}/provisions.env",
"mode": "0600",
"template": "files/provisions.env"
},
{
"id": "provisions",
"type": "process",
"name": "home-assistant-provisions",
"artifact": "code",
"run": [
"node",
"provisions/index.js"
],
"run-once": true,
"env-file": [
"${dir:state}/provisions.env"
],
"restart-on": [
"provisions-env",
"bound-mqtt-topic",
"secret-mqtt-topic",
"bound-sonarr-api",
"secret-sonarr-api",
"bound-radarr-api",
"secret-radarr-api",
"bound-lidarr-api",
"secret-lidarr-api"
]
}
],
"requires": [
{
"name": "lidarr-api",
"optional": true
},
{
"name": "mqtt-topic",
"optional": true
},
{
"name": "radarr-api",
"optional": true
},
"route",
{
"name": "sonarr-api",
"optional": true
}
],
"contributes": {
"mqtt-topic": {
"topics": [
"#"
]
},
"route": {
"label": "home-assistant",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json",
"mqtt-topic": "${dir:state}/mqtt-topic.json",
"sonarr-api": "${dir:state}/sonarr-api.json",
"radarr-api": "${dir:state}/radarr-api.json",
"lidarr-api": "${dir:state}/lidarr-api.json"
},
"secrets": {
"mqtt-topic": "${dir:state}/mqtt-topic.secret",
"sonarr-api": "${dir:state}/sonarr-api.secret",
"radarr-api": "${dir:state}/radarr-api.secret",
"lidarr-api": "${dir:state}/lidarr-api.secret"
},
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"provisions/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"MESH_HOMEASSISTANT_URL": "http://127.0.0.1:${port:8123}",
"MESH_HOMEASSISTANT_TOKEN_FILE": "${dir:mesh-state}/token",
"MESH_HOMEASSISTANT_CONFIG_FILE": "${dir:mesh-state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,61 @@
{
"module": "hostname",
"version": "1",
"claims": [
{
"name": "node-hostname",
"scope": "node",
"serves": [
"entries",
"add",
"remove"
]
}
],
"config": {
"hostname": {
"type": "string",
"description": "The machine's host name, written to /etc/hostname: the operator's name for this machine, with no default (novox/hq ADR 0112).",
"trusted": true,
"required": true
}
},
"resources": [
{
"id": "own",
"type": "file",
"path": "/etc/hosts",
"mode": "0644",
"into": "block",
"at": "start",
"template": "files/hosts"
},
{
"id": "name",
"type": "file",
"path": "/etc/hostname",
"mode": "0644",
"template": "files/hostname"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/hostname-tools",
"binary": "hostname-tools",
"loads": [
"hostname-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,124 @@
{
"module": "i3",
"version": "1",
"moved": true,
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"claims": [
{
"name": "node-display-session",
"scope": "node",
"serves": [
"reload",
"workspaces",
"windows"
]
}
],
"tools": [
"i3_focus",
"i3_move",
"i3_layout_save",
"i3_layout_restore",
"i3_exec",
"i3_kill",
"i3_bindings",
"i3_config_check",
"i3_marks",
"i3_scratchpad"
],
"items": [
{
"collection": "environment",
"name": "xdg-current-desktop",
"attributes": {
"kind": "variable",
"name": "XDG_CURRENT_DESKTOP"
},
"template": "files/env-xdg-current-desktop"
},
{
"collection": "environment",
"name": "xdg-session-desktop",
"attributes": {
"kind": "variable",
"name": "XDG_SESSION_DESKTOP"
},
"template": "files/env-xdg-session-desktop"
},
{
"collection": "shell:xinitrc:last",
"name": "xinitrc-last",
"template": "files/xinitrc-last"
}
],
"resources": [
{
"id": "package",
"type": "package",
"package": "i3-wm"
},
{
"id": "package-dex",
"type": "package",
"package": "dex"
},
{
"id": "config-dir",
"type": "directory",
"path": "${machine:account-home}/.config/i3",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out",
"knows": ["scripts/"]
},
{
"id": "drop-ins",
"type": "directory",
"path": "${machine:account-home}/.config/i3/config.d",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out",
"knows": ["10-asus.conf", "20-g14.conf"]
},
{
"id": "config",
"type": "file",
"path": "${machine:account-home}/.config/i3/config",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/config"
},
{
"id": "session",
"type": "file",
"path": "/etc/lemurs/wms/i3",
"mode": "0755",
"template": "files/wms/i3"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/i3-tools",
"binary": "i3-tools",
"loads": [
"i3-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,126 @@
{
"module": "i3status-rust",
"version": "1",
"moved": true,
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"claims": [
{
"name": "node-bar",
"scope": "node"
}
],
"tools": [
"i3status_rust_reload",
"i3status_rust_blocks",
"i3status_rust_block_run",
"i3status_rust_themes"
],
"items": [
{
"collection": "shell:xinitrc:normal",
"name": "xinitrc-normal",
"template": "files/xinitrc-normal"
},
{
"collection": "contribution:node-display-session:config",
"name": "display-session",
"template": "files/i3/60-i3status-rust.conf"
}
],
"resources": [
{
"id": "package",
"type": "package",
"package": "i3status-rust"
},
{
"id": "configuration-dir",
"type": "directory",
"path": "${machine:account-home}/.config/i3status-rust",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out"
},
{
"id": "icons-dir",
"type": "directory",
"path": "${machine:account-home}/.config/i3status-rust/icons",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out"
},
{
"id": "top-bar",
"type": "file",
"path": "${machine:account-home}/.config/i3status-rust/top-bar.toml",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/top-bar.toml"
},
{
"id": "bottom-bar",
"type": "file",
"path": "${machine:account-home}/.config/i3status-rust/bottom-bar.toml",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/bottom-bar.toml"
},
{
"id": "icons",
"type": "file",
"path": "${machine:account-home}/.config/i3status-rust/icons/custom-icons.toml",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/icons/custom-icons.toml"
},
{
"id": "updates",
"type": "file",
"path": "${machine:account-home}/.local/bin/i3status-updates",
"owner": "${machine:account}",
"mode": "0755",
"template": "files/bin/i3status-updates"
},
{
"id": "watchdog",
"type": "file",
"path": "${machine:account-home}/.local/bin/i3bar-watchdog",
"owner": "${machine:account}",
"mode": "0755",
"template": "files/bin/i3bar-watchdog"
},
{
"id": "value",
"type": "file",
"path": "${machine:account-home}/.local/bin/i3status-value",
"owner": "${machine:account}",
"mode": "0755",
"template": "files/bin/i3status-value"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/i3status-rust-tools",
"binary": "i3status-rust-tools",
"loads": [
"i3status-rust-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,152 @@
{
"module": "icecast",
"version": "1",
"requires": [
"route",
"secret"
],
"contributes": {
"route": {
"label": "icecast",
"endpoint": "stream"
}
},
"binds": {
"route": "${dir:state}/route.json"
},
"secrets": {
"secret": {
"source": "${dir:state}/source.secret",
"admin": "${dir:state}/admin.secret",
"relay": "${dir:state}/relay.secret"
}
},
"capabilities": [
"container-runtime"
],
"emits": [
"stream.started",
"stream.stopped"
],
"listens": [
{
"name": "stream",
"port": 8000,
"protocol": "tcp",
"from": "mesh",
"why": "streams in from sources (HTTP PUT) and out to listeners, plus the status and admin pages; a public name is its route"
}
],
"data": {
"own": [
{
"id": "logs",
"path": "${dir:logs}",
"class": "cache",
"why": "the streaming server's logs"
}
]
},
"config": {
"url": {
"type": "string",
"description": "The address the module's tools reach Icecast at, as a URL; unset, the code falls back to its environment, else this machine's Icecast on its port.",
"trusted": true,
"default": ""
},
"user": {
"type": "string",
"description": "The Icecast admin account the module's tools sign in as; unset, the code falls back to its environment, else admin.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "logs",
"type": "directory",
"mode": "0700",
"owner": "100:101",
"unknown": "program"
},
{
"id": "server-conf",
"type": "file",
"path": "${dir:state}/icecast.xml",
"mode": "0600",
"template": "files/icecast.xml"
},
{
"id": "net",
"type": "network",
"name": "icecast"
},
{
"id": "server",
"type": "container",
"name": "icecast",
"image": "infiniteproject/icecast@sha256:cd506cf3dfe31ce05fd37d7e672dbd1213e7255cc93d28ecf5a3b547af4e162c",
"network": "icecast",
"ports": [
"8000"
],
"volumes": [
"${dir:state}/icecast.xml:/etc/icecast.xml:ro",
"${dir:logs}:/var/log/icecast"
],
"restart-on": [
"server-conf"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": ["url", "user"]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"MESH_ICECAST_URL": "http://127.0.0.1:${port:8000}",
"MESH_ICECAST_CONFIG_FILE": "${dir:mesh-state}/config.json",
"MESH_ICECAST_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,198 @@
{
"module": "influxdb",
"version": "1",
"provides": [
{
"name": "influxdb-api",
"scope": "mesh",
"identity": {
"in": "an InfluxDB v1 authorization"
}
}
],
"capabilities": [
"container-runtime"
],
"own-secrets": {
"admin": "${dir:state}/admin.secret",
"admin-token": "${dir:state}/admin-token.secret"
},
"listens": [
{
"name": "api",
"port": 8086,
"protocol": "tcp",
"from": "mesh",
"why": "queries, writes and the web UI, over http; consumers granted influxdb-api sign in with the mesh's credential, and a name is a route grant"
}
],
"config": {
"org": {
"type": "string",
"description": "The organisation influxdb-api names to its consumers and the module's tools write to; mesh is the one influxdb makes at its first start (server.env), and a machine whose server was set up with another sets its own (novox/hq issue 696, ADR 0348 clause 11).",
"trusted": true,
"default": "mesh"
},
"bucket": {
"type": "string",
"description": "The bucket influxdb-api names to its consumers and the module's tools write to; default is the one influxdb makes at its first start (server.env), and a machine whose server was set up with another sets its own (novox/hq issue 696, ADR 0348 clause 11).",
"trusted": true,
"default": "default"
},
"url": {
"type": "string",
"description": "The address the module's tools reach influxdb at, as a URL; empty is this machine's influxdb on its port.",
"trusted": true,
"default": ""
}
},
"serves": {
"influxdb-api": {
"scheme": "http",
"port": 8086,
"org": "${config:org}",
"bucket": "${config:bucket}"
}
},
"receives": {
"influxdb-api": "${dir:grants}/mesh.json"
},
"grants": {
"influxdb-api": "${dir:grants}"
},
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "every consumer's time series"
},
{
"id": "config",
"path": "${dir:config}",
"class": "valuable",
"why": "the server's own configuration and its operator token, made at its first start"
}
],
"consumers": {
"influxdb-api": {
"class": "valuable",
"in": "data",
"why": "a consumer's measurements are the only copy"
}
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "1000:1000",
"unknown": "program"
},
{
"id": "config",
"type": "directory",
"mode": "0700",
"owner": "1000:1000",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "server",
"type": "container",
"name": "influxdb",
"image": "influxdb@sha256:f75e48af0598e8aec7986e991a848d19a119101a7d563a2e5db1dfaac9c45daa",
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"8086"
],
"volumes": [
"${dir:data}:/var/lib/influxdb2",
"${dir:config}:/etc/influxdb2",
"${dir:state}/admin.secret:/run/secrets/admin:ro",
"${dir:state}/admin-token.secret:/run/secrets/admin-token:ro"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": [
"bucket",
"org",
"url"
],
"trusted": true
}
],
"requires": [
"route"
],
"contributes": {
"route": {
"label": "influxdb",
"endpoint": "api"
}
},
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js",
"provisioner/index.js"
],
"loads": [
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_INFLUXDB_URL": "http://127.0.0.1:${port:8086}",
"MESH_INFLUXDB_CONFIG_FILE": "${dir:mesh-state}/config.json",
"MESH_INFLUXDB_TOKEN_FILE": "${dir:state}/admin-token.secret",
"MESH_RECEIVES": "${dir:grants}/mesh.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,128 @@
{
"module": "invoicing",
"version": "1",
"slug": "invoice",
"capabilities": [
"container-runtime"
],
"requires": [
"mongodb-database",
"s3-bucket",
"route"
],
"contributes": {
"mongodb-database": {
"name": "invoicing"
},
"route": {
"site": {
"label": "invoicing",
"endpoint": "web"
},
"api": {
"label": "invoicing-api",
"endpoint": "api"
}
}
},
"binds": {
"mongodb-database": "${dir:state}/database.json",
"s3-bucket": "${dir:state}/store.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"mongodb-database": "${dir:state}/database.secret",
"s3-bucket": "${dir:state}/store.secret"
},
"listens": [
{
"name": "web",
"port": 80,
"protocol": "tcp",
"from": "mesh",
"why": "the invoicing web frontend; a public name is a route grant later"
},
{
"name": "api",
"port": 9000,
"protocol": "tcp",
"from": "mesh",
"why": "the invoicing REST API the frontend and integrations call"
}
],
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "api-env",
"type": "file",
"path": "${dir:state}/api.env",
"mode": "0600",
"template": "files/api.env"
},
{
"id": "net",
"type": "network",
"name": "invoicing"
},
{
"id": "app",
"type": "container",
"name": "invoicing-app",
"image": "registry-api.novox.be/novox/invoicing-app@sha256:1e6ed40822f07169b24867cbfe8fc1ab3ef6a15ad642f3b3a2882a8e15c3dbec",
"network": "invoicing",
"env": {
"UID": "2201",
"GID": "2201"
},
"ports": [
"80"
],
"names-on-purpose": {
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
}
},
{
"id": "api",
"type": "container",
"name": "invoicing-api",
"image": "registry-api.novox.be/novox/invoicing-api@sha256:efa6fba1fa9ba78849e94e958d33793a76654df0468e3012da9c02c54c265354",
"network": "invoicing",
"env": {
"UID": "2201",
"GID": "2201"
},
"env-file": [
"${dir:state}/api.env"
],
"ports": [
"9000"
],
"secrets-in-environment": "the application's own code reads MONGO_URL and MINIO_SECRET from the environment (invoicing-app server/src/config.js); converting is that repository's change",
"names-on-purpose": {
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
}
}
],
"build": {
"artifacts": [
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,75 @@
{
"module": "jira",
"version": "1",
"own-secrets": {
"token": "${dir:state}/token"
},
"config": {
"atlassian-url": {
"type": "string",
"description": "The address of the operator's Atlassian site the jira tools call, as a URL such as https://example.atlassian.net, laid into the file as ATLASSIAN_URL; unset, the code falls back to its environment and answers no calls until it is given.",
"trusted": true,
"default": ""
},
"atlassian-email": {
"type": "string",
"description": "The email address of the Atlassian account the jira tools sign in as with its API token, laid into the file as ATLASSIAN_EMAIL; unset, the code falls back to its environment and answers no calls until it is given.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config",
"type": "file",
"path": "${dir:state}/config.json",
"merge": "json",
"template": "files/config.json",
"mode": "0600",
"takes-config": [
{
"key": "atlassian-url",
"as": "ATLASSIAN_URL"
},
{
"key": "atlassian-email",
"as": "ATLASSIAN_EMAIL"
}
]
}
],
"capabilities": [
"container-runtime"
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_JIRA_TOKEN_FILE": "${dir:state}/token",
"MESH_JIRA_CONFIG_FILE": "${dir:state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,78 @@
{
"module": "kernel",
"version": "1",
"capabilities": [
"service-manager"
],
"config": {
"transparent-huge-pages": {
"type": "string",
"description": "madvise is the value the mesh chose for every node (novox/hq ADR 0381), not the always the distribution's kernel boots with; a machine that needs another value is given it as its own setting; madvise gives huge pages only to programs that ask for them, which stops a small write to a mapped file (the journal) dirtying and writing back a whole 2 MiB page on a machine whose disks are slow (novox/hq issue 746)",
"trusted": true,
"default": "madvise"
}
},
"tools": [
"kernel_huge_pages"
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "huge-pages",
"type": "file",
"path": "${dir:state}/huge-pages",
"mode": "0755",
"trusted": true,
"template": "files/huge-pages.sh"
},
{
"id": "unit",
"type": "file",
"path": "/etc/systemd/system/mesh-kernel-huge-pages.service",
"mode": "0644",
"template": "files/mesh-kernel-huge-pages.service"
},
{
"id": "apply",
"type": "service",
"unit": "mesh-kernel-huge-pages.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"unit"
],
"reload-on": [
"huge-pages"
],
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/kernel-tools",
"binary": "kernel-tools",
"loads": [
"kernel-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,245 @@
{
"module": "keycloak",
"version": "1",
"moved": true,
"upgrade": {
"policy": "record",
"why": "every person's sign-in to every site goes through it, and its new version migrates its database on start: a person takes each build, after a backup (hq ADR 0236)"
},
"provides": [
{
"name": "oidc-client",
"scope": "mesh",
"identity": {
"max": 255,
"in": "a Keycloak client id"
}
}
],
"requires": [
"postgres-database",
"route"
],
"contributes": {
"postgres-database": {
"name": "keycloak"
},
"route": {
"label": "keycloak",
"endpoint": "web"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"capabilities": [
"container-runtime"
],
"emits": [
"user.created",
"user.deleted",
"password.reset",
"client.created",
"client.retired",
"group.created",
"role.created",
"admin.repaired",
"admin.unrepaired"
],
"listens": [
{
"name": "web",
"port": 8080,
"protocol": "tcp",
"from": "mesh",
"why": "anything the mesh runs that authenticates a person"
}
],
"serves": {
"oidc-client": {
"authorization-path": "/protocol/openid-connect/auth",
"token-path": "/protocol/openid-connect/token",
"userinfo-path": "/protocol/openid-connect/userinfo",
"issuer": "${config:issuer}"
}
},
"receives": {
"oidc-client": "${dir:grants}/mesh.json"
},
"grants": {
"oidc-client": "${dir:grants}"
},
"own-secrets": {
"admin": "${dir:state}/admin.secret"
},
"data": {
"consumers": {
"oidc-client": {
"class": "rebuildable",
"in": "postgres-database",
"why": "a consumer's client is made again from its declaration, with a new secret"
}
}
},
"config": {
"url": {
"type": "string",
"description": "The address the module's provider reaches Keycloak's admin API at, as a URL; empty is this machine's Keycloak on its port.",
"trusted": true,
"default": ""
},
"user": {
"type": "string",
"description": "The Keycloak administrator the module's provider signs in as; empty is admin.",
"trusted": true,
"default": ""
},
"realm": {
"type": "string",
"description": "The realm the module's provider makes its consumers' clients in; empty is master.",
"trusted": true,
"default": ""
},
"issuer": {
"type": "string",
"description": "The issuer Keycloak's tokens name and oidc consumers are told, as the realm's URL, such as https://keycloak.example.org/realms/Example; the operator's, with no default (novox/hq ADR 0112, ADR 0155).",
"trusted": true,
"required": true
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "consumers",
"type": "file",
"path": "${dir:state}/consumers.json",
"mode": "0600",
"template": "files/consumers.json"
},
{
"id": "admin-env",
"type": "file",
"path": "${dir:state}/admin.env",
"mode": "0600",
"template": "files/admin.env"
},
{
"id": "database-env",
"type": "file",
"path": "${dir:state}/database.env",
"mode": "0600",
"template": "files/database.env"
},
{
"id": "net",
"type": "network",
"name": "keycloak"
},
{
"id": "hostname",
"type": "file",
"path": "${dir:state}/hostname.env",
"mode": "0644",
"template": "files/hostname.env"
},
{
"id": "server",
"type": "container",
"name": "keycloak",
"image": "quay.io/keycloak/keycloak@sha256:ecd43971114b0c764f8a3288dddab73f98cb473daccc4feaffe4dc14adeaf866",
"network": "keycloak",
"args": [
"start-dev"
],
"env": {
"KC_DB": "postgres",
"KC_HTTP_ENABLED": "true",
"KC_HEALTH_ENABLED": "true",
"KC_PROXY_HEADERS": "xforwarded"
},
"env-file": [
"${dir:state}/admin.env",
"${dir:state}/database.env",
"${dir:state}/hostname.env"
],
"ports": [
"8080"
],
"secrets-in-environment": "KC_DB_PASSWORD is convertible through a generated keycloak.conf (db-password=); KEYCLOAK_ADMIN_PASSWORD is env-only before Keycloak 26; not yet converted",
"restart-on": [
"hostname"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": [
"url",
"user",
"realm",
"issuer"
]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/keycloak-provider",
"binary": "keycloak-provider",
"loads": [
"keycloak-provider"
],
"env": {
"MESH_KEYCLOAK_URL": "http://127.0.0.1:${port:8080}",
"MESH_KEYCLOAK_CONFIG_FILE": "${dir:mesh-state}/config.json",
"MESH_KEYCLOAK_PASSWORD_FILE": "${dir:state}/admin.secret",
"MESH_RECEIVES": "${dir:grants}/mesh.json",
"MESH_KEYCLOAK_CONTAINER": "keycloak",
"MESH_CONSUMERS_FILE": "${dir:state}/consumers.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
},
"state": [
"bound"
],
"reads": [
"mesh-controller.assignments"
]
}
@@ -0,0 +1,129 @@
{
"module": "lab",
"version": "1",
"capabilities": [
"container-runtime",
"virtualisation"
],
"requires": [
"npm-package-registry"
],
"contributes": {
"npm-package-registry": {
"access": "read"
}
},
"binds": {
"npm-package-registry": "${dir:state}/package-registry.json"
},
"secrets": {
"npm-package-registry": "${dir:state}/package-registry.secret"
},
"data": {
"own": [
{
"id": "work",
"path": "${dir:work}",
"class": "cache",
"why": "the lab's runs, each thrown away"
}
]
},
"config": {
"forge": {
"type": "string",
"description": "The forge the lab's machines take their packages from, as its address: the operator's, with no default (novox/hq ADR 0112).",
"trusted": true,
"required": true
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "work",
"type": "directory",
"path": "/var/lib/mesh-lab-runs",
"mode": "0700",
"unknown": "program"
},
{
"id": "runtime-env",
"type": "file",
"path": "${dir:state}/lab.env",
"mode": "0600",
"template": "files/lab.env"
},
{
"id": "git",
"type": "package",
"package": "git"
},
{
"id": "make",
"type": "package",
"package": "make"
},
{
"id": "python",
"type": "package",
"package": "python"
},
{
"id": "file",
"type": "package",
"package": "file"
},
{
"id": "iproute2",
"type": "package",
"package": "iproute2"
},
{
"id": "npm",
"type": "package",
"package": "npm"
},
{
"id": "go",
"type": "package",
"package": "go"
},
{
"id": "incus",
"type": "package",
"package": "incus"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_LAB_WORK": "${dir:work}",
"MESH_LAB_ENV_FILE": "${dir:state}/lab.env",
"MESH_LAB_FORGE_BINDING": "${dir:state}/package-registry.json",
"MESH_LAB_FORGE_SECRET": "${dir:state}/package-registry.secret"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,84 @@
{
"module": "lemurs",
"version": "1",
"capabilities": [
"package-manager",
"service-manager",
"seat"
],
"claims": [
{
"name": "node-login-manager",
"scope": "node",
"serves": [
"sessions"
]
}
],
"tools": [
"lemurs_default_session",
"lemurs_logins"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "lemurs"
},
{
"id": "xserver",
"type": "file",
"path": "/etc/lemurs/xserver",
"mode": "0755",
"template": "files/xserver"
},
{
"id": "config",
"type": "file",
"path": "/etc/lemurs/config.toml",
"mode": "0644",
"template": "files/config.toml"
},
{
"id": "xsessions",
"type": "directory",
"path": "/etc/lemurs/xsessions",
"mode": "0755",
"unknown": "program"
},
{
"id": "wayland-sessions",
"type": "directory",
"path": "/etc/lemurs/wayland-sessions",
"mode": "0755",
"unknown": "program"
},
{
"id": "service",
"type": "service",
"unit": "lemurs.service",
"state": "running",
"boot": "enabled"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/lemurs-tools",
"binary": "lemurs-tools",
"loads": [
"lemurs-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,156 @@
{
"module": "letta",
"version": "1",
"capabilities": [
"container-runtime"
],
"requires": [
"postgres-database",
"route"
],
"contributes": {
"postgres-database": {
"name": "letta",
"extensions": [
"vector"
]
},
"route": {
"label": "letta",
"endpoint": "web"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"own-secrets": {
"server-password": {
"path": "${dir:state}/server-password.secret",
"taken": "at-start"
},
"openai-api-key": {
"path": "${dir:state}/openai-api-key.secret",
"taken": "at-start",
"issued-by": "outside"
}
},
"listens": [
{
"name": "web",
"port": 8283,
"protocol": "tcp",
"from": "mesh",
"why": "the Letta agent server REST API and web UI, password-protected (--secure); a public name is the route's"
}
],
"config": {
"url": {
"type": "string",
"description": "The address the module's tools reach Letta at, as a URL; unset, the code falls back to its environment, else this machine's Letta on port 8283.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "pgpass",
"type": "file",
"path": "${dir:state}/pgpass",
"mode": "0600",
"template": "files/pgpass"
},
{
"id": "start",
"type": "file",
"path": "${dir:state}/start.sh",
"mode": "0644",
"template": "files/start.sh"
},
{
"id": "net",
"type": "network",
"name": "letta"
},
{
"id": "server",
"type": "container",
"name": "letta",
"image": "letta/letta@sha256:bfd1e49ce45b9a208c941e832c1d1d194017ff210a3784b0ca6c323aed767a29",
"network": "letta",
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"8283"
],
"volumes": [
"${dir:state}/pgpass:/run/secrets/pgpass:ro",
"${dir:state}/start.sh:/run/letta/start.sh:ro"
],
"args": [
"sh",
"/run/letta/start.sh"
],
"secrets-in-environment": "letta 0.6.x reads its settings from the environment only (pydantic settings, no secrets_dir or _FILE twin): LETTA_SERVER_PASSWORD and OPENAI_API_KEY have no file source. The database password is not here: LETTA_PG_URI, which letta prints at start, names no password, and libpq reads it from the mounted pgpass file (PGPASSFILE)"
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"merge": "json",
"takes-config": ["url"],
"protected": ["password"]
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_LETTA_URL": "http://127.0.0.1:${port:8283}",
"MESH_LETTA_CONFIG_FILE": "${dir:mesh-state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,42 @@
{
"module": "local-model-consumer",
"version": "1",
"slug": "local",
"requires": [
"model-access"
],
"binds": {
"model-access": "${dir:state}/model.json"
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "openai-env",
"type": "file",
"path": "${dir:config}/openai.env",
"mode": "0600",
"template": "files/openai.env"
}
],
"build": {
"artifacts": [
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,61 @@
{
"module": "localization",
"version": "1",
"capabilities": [
"service-manager"
],
"tools": [
"localization_get",
"localization_time_zone",
"localization_locales",
"localization_keymaps"
],
"resources": [
{
"id": "locale",
"type": "file",
"path": "/etc/locale.conf",
"mode": "0644",
"template": "files/locale.conf"
},
{
"id": "keymap",
"type": "file",
"path": "/etc/vconsole.conf",
"mode": "0644",
"template": "files/vconsole.conf"
},
{
"id": "time-zone",
"type": "process",
"name": "localization-time-zone",
"artifact": "tools",
"run": [
"./localization-tools",
"set-time-zone",
"Europe/Brussels"
],
"run-once": true
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/localization-tools",
"binary": "localization-tools",
"loads": [
"localization-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,58 @@
{
"module": "logrotate",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"tools": [
"logrotate_status",
"logrotate_configs",
"logrotate_check",
"logrotate_big_logs",
"logrotate_force",
"logrotate_journal_usage",
"logrotate_journal_vacuum"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "logrotate"
},
{
"id": "config",
"type": "file",
"path": "/etc/logrotate.conf",
"mode": "0644",
"template": "files/logrotate.conf"
},
{
"id": "timer",
"type": "service",
"unit": "logrotate.timer",
"state": "running",
"boot": "enabled"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/logrotate-tools",
"binary": "logrotate-tools",
"loads": [
"logrotate-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,772 @@
{
"module": "mailu",
"version": "1",
"upgrade": {
"policy": "record",
"why": "people's mail: any change to how its containers are declared recreates them together in one send, and the mail is down for everyone until they are up again — a person chooses the moment (hq ADR 0242, issue 295)"
},
"unhealthy": {
"severity": "urgent",
"why": "while mailu is broken, mail is refused or stuck for everyone with a mailbox here (hq ADR 0355, issue 687)"
},
"capabilities": [
"container-runtime"
],
"requires": [
"postgres-database",
"route",
"secret"
],
"contributes": {
"postgres-database": {
"name": "mailu"
},
"route": {
"web": {
"label": "mail",
"endpoint": "web-tls",
"scheme": "https",
"insecure": true
},
"acme": {
"label": "mail",
"path": "/.well-known/acme-challenge",
"endpoint": "web",
"priority": 100
},
"autoconfig": {
"label": "autoconfig",
"endpoint": "autoconfig"
},
"autodiscover": {
"label": "autodiscover",
"endpoint": "autoconfig"
},
"automx": {
"label": "automx",
"endpoint": "autoconfig"
}
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret",
"secret": {
"secret-key": "${dir:state}/secret-key.secret",
"admin": "${dir:state}/admin.secret",
"api-token": "${dir:state}/api-token.secret"
}
},
"tools": [
"mailu_list_users",
"mailu_create_user",
"mailu_change_password",
"mailu_delete_user",
"mailu_list_aliases",
"mailu_create_alias",
"mailu_delete_alias",
"mailu_list_domains",
"mailu_read_mail",
"mailu_search_mail",
"mailu_health"
],
"emits": [
"user.created",
"user.deleted",
"alias.created",
"alias.deleted"
],
"listens": [
{
"name": "smtp",
"port": 25,
"protocol": "tcp",
"from": "anywhere",
"why": "mail from other mail servers",
"fixed": true
},
{
"name": "pop3",
"port": 110,
"protocol": "tcp",
"from": "anywhere",
"why": "POP3, kept at parity with the predecessor; pruning legacy protocols is its own deliberate change",
"fixed": true
},
{
"name": "imap",
"port": 143,
"protocol": "tcp",
"from": "anywhere",
"why": "IMAP with STARTTLS, kept at parity",
"fixed": true
},
{
"name": "smtps",
"port": 465,
"protocol": "tcp",
"from": "anywhere",
"why": "submission over TLS",
"fixed": true
},
{
"name": "submission",
"port": 587,
"protocol": "tcp",
"from": "anywhere",
"why": "submission; also what the smtp provision serves consumers",
"fixed": true
},
{
"name": "imaps",
"port": 993,
"protocol": "tcp",
"from": "anywhere",
"why": "IMAP over TLS",
"fixed": true
},
{
"name": "pop3s",
"port": 995,
"protocol": "tcp",
"from": "anywhere",
"why": "POP3 over TLS, kept at parity",
"fixed": true
},
{
"name": "web",
"port": 7080,
"protocol": "tcp",
"from": "mesh",
"why": "the web front over http; only the ACME HTTP-01 passthrough is routed here — everything else 301s to https and would loop a proxy"
},
{
"name": "web-tls",
"port": 7443,
"protocol": "tcp",
"from": "mesh",
"why": "the web front over its own TLS (admin, webmail, API); its public name is a route grant reaching it here"
},
{
"name": "autoconfig",
"port": 4243,
"protocol": "tcp",
"from": "mesh",
"why": "automx: mail client autoconfiguration; the autoconfig, autodiscover and automx names are route grants reaching it here"
},
{
"name": "admin-api",
"port": 8080,
"protocol": "tcp",
"from": "machine",
"why": "the admin API, which this module's own code reaches on loopback from the node's runtime now that it runs outside the mailu network"
}
],
"data": {
"own": [
{
"id": "mail",
"path": "${dir:data-mail}",
"class": "valuable",
"why": "every mailbox"
},
{
"id": "dkim",
"path": "${dir:data-dkim}",
"class": "valuable",
"why": "the domain's signing keys; a new one means a new DNS record"
},
{
"id": "data",
"path": "${dir:data-data}",
"class": "valuable",
"why": "the server's own data"
},
{
"id": "dav",
"path": "${dir:data-dav}",
"class": "valuable",
"why": "calendars and contacts"
},
{
"id": "webmail",
"path": "${dir:data-webmail}",
"class": "valuable",
"why": "the webmail's own data: its users' settings and address books"
},
{
"id": "queue",
"path": "${dir:data-mailqueue}",
"class": "valuable",
"why": "mail accepted and not yet delivered, kept nowhere else"
},
{
"id": "filter",
"path": "${dir:data-filter}",
"class": "rebuildable",
"why": "the spam filter's learned statistics; it learns again"
},
{
"id": "certs",
"path": "${dir:data-certs}",
"class": "rebuildable",
"why": "certificates, issued again"
},
{
"id": "automx",
"path": "${dir:data-automx}",
"class": "rebuildable",
"why": "client autoconfiguration, written again"
},
{
"id": "fetchmail",
"path": "${dir:data-fetchmail}",
"class": "rebuildable",
"why": "which remote messages were fetched; lost, some are fetched twice"
},
{
"id": "clamav",
"path": "${dir:data-clamav}",
"class": "cache",
"why": "virus signatures, downloaded again"
},
{
"id": "redis",
"path": "${dir:data-redis}",
"class": "cache",
"why": "the filter's working set"
}
],
"consumers": {
"smtp": {
"class": "valuable",
"in": "mail",
"why": "a consumer's mailbox holds the only copy of its mail"
}
}
},
"config": {
"domain": {
"type": "string",
"description": "The mail domain Mailu serves, such as example.org: its first mail domain, the postmaster's and the one consumers send as; the operator's, with no default (novox/hq ADR 0112).",
"trusted": true,
"required": true
},
"proxy-address": {
"type": "string",
"description": "The address of the reverse proxy in front of Mailu, whose X-Real-IP header Mailu believes; the operator's, with no default.",
"trusted": true,
"required": true
},
"sitename": {
"type": "string",
"description": "The name Mailu's web pages show for the mail service; the operator's, with no default.",
"trusted": true,
"required": true
},
"website": {
"type": "string",
"description": "The address of the website Mailu's web pages link to, as a URL; the operator's, with no default.",
"trusted": true,
"required": true
},
"url": {
"type": "string",
"description": "The address the module's tools reach Mailu's API at, as a URL; empty leaves them to MESH_MAILU_URL.",
"trusted": true,
"default": ""
},
"container": {
"type": "string",
"description": "The name of the container holding Mailu's mailboxes, which the module's tools read mail in; empty is mailu-imap.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-automx",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "config-env",
"type": "file",
"path": "${dir:state}/mailu.env",
"mode": "0644",
"template": "files/mailu.env"
},
{
"id": "secret-env",
"type": "file",
"path": "${dir:state}/secret.env",
"mode": "0600",
"template": "files/secret.env"
},
{
"id": "database-env",
"type": "file",
"path": "${dir:state}/database.env",
"mode": "0600",
"template": "files/database.env"
},
{
"id": "admin-env",
"type": "file",
"path": "${dir:state}/admin.env",
"mode": "0600",
"template": "files/admin.env"
},
{
"id": "data-certs",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-data",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-dkim",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-mail",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-mailqueue",
"type": "directory",
"mode": "0755",
"unknown": "program"
},
{
"id": "data-filter",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-clamav",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-redis",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-webmail",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-dav",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-fetchmail",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-overrides-nginx",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-overrides-dovecot",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-overrides-postfix",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-overrides-rspamd",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data-overrides-roundcube",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "mailu"
},
{
"id": "resolver",
"type": "container",
"name": "mailu-resolver",
"image": "ghcr.io/mailu/unbound@sha256:2c037bc5c988b5c0ab7e1b6e6ffa762e14ba1e45c96281ac87f8b9be8eee8b6e",
"health": {
"kind": "runtime"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env",
"${dir:state}/secret.env"
],
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
"ip": "192.168.203.254"
},
{
"id": "redis",
"type": "container",
"name": "mailu-redis",
"image": "redis@sha256:4bed291aa5efb9f0d77b76ff7d4ab71eee410962965d052552db1fb80576431d",
"network": "mailu",
"volumes": [
"${dir:data-redis}:/data"
]
},
{
"id": "admin",
"type": "container",
"name": "mailu-admin",
"image": "ghcr.io/mailu/admin@sha256:6dbfdadc4a9590dcb7652357b505200115b689b74008653bbf369e4599a3be5a",
"health": {
"kind": "runtime"
},
"network": "mailu",
"ports": [
"8080"
],
"env-file": [
"${dir:state}/mailu.env",
"${dir:state}/secret.env",
"${dir:state}/database.env",
"${dir:state}/admin.env"
],
"volumes": [
"${dir:data-data}:/data",
"${dir:data-dkim}:/dkim"
],
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified"
},
{
"id": "imap",
"type": "container",
"name": "mailu-imap",
"image": "ghcr.io/mailu/dovecot@sha256:7f0ed5db996fbdc00adc5c5e38a08492e04f7eb4a9fbd66a03aa9a28ddf23993",
"health": {
"kind": "runtime"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env"
],
"volumes": [
"${dir:data-mail}:/mail",
"${dir:data-overrides-dovecot}:/overrides:ro"
],
"dns": [
"192.168.203.254"
]
},
{
"id": "smtp",
"type": "container",
"name": "mailu-smtp",
"image": "ghcr.io/mailu/postfix@sha256:e2e49f39e53b80eac9e7a2f18d9df11edeb4914fd62dbba89b3155e8e034f62e",
"health": {
"kind": "tool",
"tool": "mailu_health",
"interval": "60s",
"timeout": "30s",
"looks": 3,
"grace": "120s"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env"
],
"volumes": [
"${dir:data-mailqueue}:/queue",
"${dir:data-overrides-postfix}:/overrides:ro"
],
"dns": [
"192.168.203.254"
]
},
{
"id": "antispam",
"type": "container",
"name": "mailu-antispam",
"image": "ghcr.io/mailu/rspamd@sha256:ff3666d8a61f17d309c5c6f6bcf4d40470b82299ca706ac650301175bb1a079d",
"health": {
"kind": "runtime"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env"
],
"volumes": [
"${dir:data-filter}:/var/lib/rspamd",
"${dir:data-overrides-rspamd}:/etc/rspamd/override.d:ro"
],
"dns": [
"192.168.203.254"
]
},
{
"id": "antivirus",
"type": "container",
"name": "mailu-antivirus",
"image": "clamav/clamav-debian@sha256:b12ef8fefddbba7d88de59bea8a32622f365339154adf02d38fd089112e6745a",
"network": "mailu",
"volumes": [
"${dir:data-clamav}:/var/lib/clamav"
],
"dns": [
"192.168.203.254"
]
},
{
"id": "webmail",
"type": "container",
"name": "mailu-webmail",
"image": "ghcr.io/mailu/webmail@sha256:bdbee44cdb05a4658f0e3b62cc448de55ca8f8aea172279fda594826144c04f6",
"health": {
"kind": "runtime"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env",
"${dir:state}/secret.env"
],
"volumes": [
"${dir:data-webmail}:/data",
"${dir:data-overrides-roundcube}:/overrides:ro"
],
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
"dns": [
"192.168.203.254"
]
},
{
"id": "webdav",
"type": "container",
"name": "mailu-webdav",
"image": "ghcr.io/mailu/radicale@sha256:690ed6edf189dfef100a5a8b37c195ebf5d9241ac5f23f2f44b8b7b75726e3de",
"health": {
"kind": "runtime"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env",
"${dir:state}/secret.env"
],
"volumes": [
"${dir:data-dav}:/data"
],
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
"dns": [
"192.168.203.254"
]
},
{
"id": "fetchmail",
"type": "container",
"name": "mailu-fetchmail",
"image": "ghcr.io/mailu/fetchmail@sha256:f881c8412d3bbe73d638469b48321558d6403a9d45bfa043c1e52c752103d42d",
"health": {
"kind": "runtime"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env",
"${dir:state}/secret.env"
],
"volumes": [
"${dir:data-fetchmail}:/data"
],
"secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified",
"dns": [
"192.168.203.254"
]
},
{
"id": "front",
"type": "container",
"name": "mailu-front",
"image": "ghcr.io/mailu/nginx@sha256:36f98897cd1bc9d27628bbb4e04bdf60147af2ec7507d6da77f002c4f256896d",
"health": {
"kind": "exec",
"command": "curl -m3 -skfLo /dev/null http://127.0.0.1:10204/health && kill -0 $(cat /run/dovecot/master.pid) && python3 -c \"import smtplib; s = smtplib.SMTP('127.0.0.1', 25, timeout=5); s.ehlo('health'); s.quit()\" && openssl x509 -checkend 1209600 -noout -in /certs/letsencrypt/live/mailu/nginx-chain.pem",
"interval": "60s",
"timeout": "15s",
"looks": 3,
"grace": "120s"
},
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env"
],
"ports": [
"25",
"110",
"143",
"465",
"587",
"993",
"995",
"7080:80",
"7443:443"
],
"volumes": [
"${dir:data-certs}:/certs",
"${dir:data-overrides-nginx}:/overrides:ro"
],
"dns": [
"192.168.203.254"
],
"logging": "journald"
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"takes-config": ["domain", "proxy-address", "sitename", "website", "url", "container"],
"merge": "json"
},
{
"id": "automx",
"type": "container",
"name": "mailu-automx",
"artifact": "automx",
"network": "mailu",
"env-file": [
"${dir:state}/mailu.env"
],
"ports": [
"4243"
],
"volumes": [
"${dir:data-automx}:/data"
]
}
],
"build": {
"on": [
{
"arg": "PYTHON_BASE",
"image": "python@sha256:25f3cfeaceca14921366af4d1240b56457ef46273bdb508c7b0e8f469f6fd228"
}
],
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"loads": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_MAILU_URL": "http://127.0.0.1:${port:8080}/api/v1",
"MESH_MAILU_API_KEY_FILE": "${dir:state}/api-token.secret",
"MESH_MAILU_IMAP_CONTAINER": "mailu-imap",
"MESH_MAILU_SMTP_CONTAINER": "mailu-smtp",
"MESH_MAILU_CONFIG_FILE": "${dir:mesh-state}/config.json",
"MESH_RECEIVES": "${dir:grants}/mesh.json"
}
},
{
"name": "automx",
"kind": "image",
"from": "automx/Dockerfile"
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
},
"provides": [
{
"name": "smtp",
"scope": "mesh",
"identity": {
"max": 64,
"in": "a mailbox's local part"
}
}
],
"serves": {
"smtp": {
"port": 587,
"domain": "${config:domain}"
}
},
"receives": {
"smtp": "${dir:grants}/mesh.json"
},
"grants": {
"smtp": "${dir:grants}"
},
"jails": [
{
"name": "mailu-front",
"failregex": "^.*(?:imap|pop3|submission|managesieve)-login: .*\\(auth failed, \\d+ attempts(?: in \\d+ secs)?\\):.*rip=<HOST>(?:,|$)\n ^.*client login failed: \"AUTH not supported\" while in http auth state, client: <HOST>, server: \\S+:25,",
"jail": "backend = systemd\njournalmatch = CONTAINER_NAME=mailu-front\nport = smtp,submission,submissions,imap,imaps,pop3,pop3s\nmaxretry = 3\nfindtime = 1d\nbantime = 1d"
}
]
}
@@ -0,0 +1,37 @@
{
"module": "marrytts",
"version": "1",
"capabilities": [
"container-runtime"
],
"listens": [
{
"name": "api",
"port": 59125,
"protocol": "tcp",
"from": "mesh",
"why": "the MaryTTS text-to-speech HTTP API and web interface"
}
],
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "server",
"type": "container",
"name": "marrytts",
"image": "synesthesiam/marytts@sha256:45970ecb3e21a2981c66c60563a70cf00be8e95c02565e7d74b3a73dcec7db2c",
"env": {
"TZ": "Europe/Brussels"
},
"ports": [
"59125"
]
}
]
}
@@ -0,0 +1,257 @@
{
"module": "matrix",
"version": "1",
"capabilities": [
"container-runtime"
],
"listens": [
{
"name": "client",
"port": 6167,
"protocol": "tcp",
"from": "mesh",
"why": "Conduit's client-server and federation APIs over plain HTTP. Both arrive through the route on 443: Conduit answers /.well-known/matrix/server with <its name>:443, so other homeservers federate through the proxy and nothing needs the traditional 8448"
},
{
"name": "web",
"port": 80,
"protocol": "tcp",
"from": "mesh",
"why": "Element Web, the static browser client, served by the image's nginx; reached through its route"
}
],
"requires": [
"route"
],
"contributes": {
"route": {
"homeserver": {
"label": "matrix",
"endpoint": "client"
},
"element": {
"label": "element",
"endpoint": "web"
}
}
},
"binds": {
"route": "${dir:state}/route.json"
},
"data": {
"own": [
{
"id": "db",
"path": "${dir:db}",
"class": "valuable",
"why": "every room, message and account"
}
]
},
"config": {
"default_server_name": {
"type": "string",
"description": "Element's default_server_name setting of config.json: the homeserver Element signs in to by default, by name; the file's default is the module's own route.",
"trusted": true,
"default": "${bound:route:name-homeserver}"
},
"default_server_config": {
"type": "object",
"description": "Element's default_server_config setting of config.json: the homeserver and identity server Element uses by default, by URL.",
"trusted": true,
"default": {
"m.homeserver": {
"base_url": "https://${bound:route:name-homeserver}"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
}
},
"brand": {
"type": "string",
"description": "Element's brand setting of config.json: the name Element shows itself as.",
"trusted": true,
"default": "Element"
},
"integrations_ui_url": {
"type": "string",
"description": "Element's integrations_ui_url setting of config.json: the integration manager's page, a URL.",
"trusted": true,
"default": "https://scalar.vector.im/"
},
"integrations_rest_url": {
"type": "string",
"description": "Element's integrations_rest_url setting of config.json: the integration manager's API, a URL.",
"trusted": true,
"default": "https://scalar.vector.im/api"
},
"integrations_widgets_urls": {
"type": "list",
"description": "Element's integrations_widgets_urls setting of config.json: the URLs whose widgets Element trusts as the integration manager's.",
"trusted": true,
"default": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
]
},
"bug_report_endpoint_url": {
"type": "string",
"description": "Element's bug_report_endpoint_url setting of config.json: where Element sends a bug report, a URL; its default here is empty, and the file's own value (Element's, naming outside servers) stays in the file and is never replaced unless this is set.",
"trusted": true,
"default": ""
},
"uisi_autorageshake_app": {
"type": "string",
"description": "Element's uisi_autorageshake_app setting of config.json: the app name Element files an automatic report of an undecryptable message under.",
"trusted": true,
"default": "element-auto-uisi"
},
"show_labs_settings": {
"type": "boolean",
"description": "Element's show_labs_settings setting of config.json: whether Element shows its Labs settings.",
"trusted": true,
"default": true
},
"room_directory": {
"type": "object",
"description": "Element's room_directory setting of config.json: the servers whose room directories Element offers; its default here is empty, and the file's own value (Element's, naming outside servers) stays in the file and is never replaced unless this is set.",
"trusted": true,
"default": {}
},
"enable_presence_by_hs_url": {
"type": "object",
"description": "Element's enable_presence_by_hs_url setting of config.json: whether Element shows presence, per homeserver URL.",
"trusted": true,
"default": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
}
},
"terms_and_conditions_links": {
"type": "list",
"description": "Element's terms_and_conditions_links setting of config.json: the links Element shows as its terms, each a URL and its text; its default here is empty, and the file's own value (Element's, naming outside servers) stays in the file and is never replaced unless this is set.",
"trusted": true,
"default": []
},
"features": {
"type": "object",
"description": "Element's features setting of config.json: Element's feature switches, each on or off.",
"trusted": true,
"default": {
"feature_video_rooms": true,
"feature_rust_crypto": true
}
},
"element_call": {
"type": "object",
"description": "Element's element_call setting of config.json: where Element starts a call with Element Call, a URL.",
"trusted": true,
"default": {
"url": "https://call.element.dev"
}
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "db",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "conduit-conf",
"type": "file",
"path": "${dir:state}/conduit.toml",
"mode": "0644",
"template": "files/conduit.toml",
"names-on-purpose": {
"matrix.org": "the federation's public key server, trusted by default; the world's, not this mesh's"
}
},
{
"id": "element-conf",
"type": "file",
"path": "${dir:state}/element.json",
"mode": "0644",
"merge": "json",
"takes-config": ["default_server_name", "default_server_config", "brand", "integrations_ui_url", "integrations_rest_url", "integrations_widgets_urls", "bug_report_endpoint_url", "uisi_autorageshake_app", "show_labs_settings", "room_directory", "enable_presence_by_hs_url", "terms_and_conditions_links", "features", "element_call"],
"template": "files/element.json",
"names-on-purpose": {
"matrix.org": "the public room directory and the federation's largest homeserver; the world's",
"matrix-client.matrix.org": "the same homeserver's client endpoint; the world's",
"vector.im": "Element's public identity server; the world's",
"scalar.vector.im": "Element's public integration manager; the world's",
"scalar-staging.vector.im": "Element's staging integration manager, named by the upstream default config; the world's",
"scalar-staging.riot.im": "the same, under its former name; the world's",
"element.io": "Element's bug reports, privacy and cookie pages; the world's",
"gitter.im": "a public room directory; the world's",
"libera.chat": "a public room directory; the world's",
"call.element.dev": "Element Call's public instance; the world's"
}
},
{
"id": "net",
"type": "network",
"name": "matrix"
},
{
"id": "homeserver",
"type": "container",
"name": "matrix",
"image": "matrixconduit/matrix-conduit@sha256:b0d24248e94f944ca49f90f10c429e3d65f4472bdde25661ecea9840134fb133",
"network": "matrix",
"env": {
"CONDUIT_CONFIG": "/etc/conduit/conduit.toml"
},
"ports": [
"6167"
],
"volumes": [
"${dir:db}:/var/lib/matrix-conduit",
"${dir:state}/conduit.toml:/etc/conduit/conduit.toml:ro"
],
"restart-on": [
"conduit-conf"
]
},
{
"id": "element",
"type": "container",
"name": "element-web",
"image": "vectorim/element-web@sha256:a8f415462ab8d2600a592ba1b92bea51efe5a4d10eb738aab9bed769f7099613",
"health": {
"kind": "runtime"
},
"network": "matrix",
"ports": [
"80"
],
"volumes": [
"${dir:state}/element.json:/app/config.json:ro"
],
"restart-on": [
"element-conf"
]
}
],
"build": {
"artifacts": [
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,130 @@
{
"module": "memory-pressure",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"emits": [
"pressure.high",
"pressure.cleared"
],
"tools": [
"memory_status",
"memory_top",
"memory_oom_history",
"memory_zram",
"memory_oomd",
"memory_guard"
],
"resources": [
{
"id": "zram-generator",
"type": "package",
"package": "zram-generator"
},
{
"id": "zram",
"type": "file",
"path": "/etc/systemd/zram-generator.conf",
"mode": "0644",
"template": "files/zram-generator.conf"
},
{
"id": "sysctl-drop-ins",
"type": "directory",
"path": "/etc/sysctl.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "swap-tunables",
"type": "file",
"path": "/etc/sysctl.d/90-memory-pressure.conf",
"mode": "0644",
"template": "files/sysctl.conf"
},
{
"id": "sysctl",
"type": "service",
"unit": "systemd-sysctl.service",
"restart-on": [
"swap-tunables"
]
},
{
"id": "oomd-drop-ins",
"type": "directory",
"path": "/etc/systemd/oomd.conf.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "oomd-limits",
"type": "file",
"path": "/etc/systemd/oomd.conf.d/memory-pressure.conf",
"mode": "0644",
"template": "files/oomd.conf"
},
{
"id": "root-slice-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/-.slice.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "root-slice",
"type": "file",
"path": "/etc/systemd/system/-.slice.d/10-oomd.conf",
"mode": "0644",
"template": "files/root-slice.conf"
},
{
"id": "user-manager-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/user@.service.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "user-manager",
"type": "file",
"path": "/etc/systemd/system/user@.service.d/10-oomd.conf",
"mode": "0644",
"template": "files/user-manager.conf"
},
{
"id": "oomd",
"type": "service",
"unit": "systemd-oomd.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"oomd-limits",
"root-slice",
"user-manager"
]
}
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/memory-pressure",
"binary": "memory-pressure",
"loads": [
"memory-pressure"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,98 @@
{
"module": "mesh-catalog",
"slug": "catalog",
"version": "1",
"capabilities": [
"container-runtime"
],
"claims": [
{
"name": "mesh-catalog",
"scope": "mesh"
}
],
"requires": [
"postgres-database"
],
"contributes": {
"postgres-database": {
"name": "mesh_catalog"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"consumes": [
"node-build-agent.built",
"mesh-build-machine.built",
"mesh-controller.built-before"
],
"emits": [
"registered",
"upgraded",
"rebuild-needed",
"catching-up"
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "database-url",
"type": "file",
"path": "${dir:state}/database.url",
"mode": "0600",
"template": "files/database.url"
},
{
"id": "prepare",
"type": "process",
"name": "mesh-catalog-prepare",
"artifact": "code",
"run": [
"node",
"prepare/index.js"
],
"run-once": true,
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
},
"restart-on": [
"database-url"
]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"prepare/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,37 @@
{
"module": "mesh-cli",
"version": "1",
"moved": true,
"resources": [
{
"id": "program",
"type": "archive",
"artifact": "program",
"path": "/usr/local/bin",
"unknown": "program"
}
],
"items": [
{
"collection": "shell:zsh:normal",
"template": "files/zsh-normal"
}
],
"build": {
"artifacts": [
{
"name": "program",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-cli",
"binary": "mesh-cli"
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,74 @@
{
"module": "mesh-config",
"version": "1",
"runs-as": "mesh-config",
"claims": [
{
"name": "mesh-config",
"scope": "mesh",
"serves": [
"config"
]
}
],
"emits": [
"config-changed"
],
"uses": [
"operator-channel"
],
"invokes": [
"seat:mesh-controller.hand-act",
"seat:mesh-controller.warranted"
],
"reads": [
"mesh-controller.assignments",
"mesh-controller.declared-config",
"mesh-controller.predefined"
],
"state": [
"values",
"resolved",
"predefined",
"proposals"
],
"logs": [
"history"
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-config",
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-config",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-config"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-config",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-config",
"binary": "mesh-config",
"loads": [
"mesh-config"
]
}
]
}
}
@@ -0,0 +1,110 @@
{
"module": "mesh-delivery-gate",
"version": "1",
"slug": "gate",
"claims": [
{
"name": "mesh-delivery",
"scope": "mesh",
"serves": [
"deliveries",
"times",
"show",
"groups",
"what-if",
"checks",
"table",
"stalled",
"recheck",
"release",
"stop",
"close",
"retire-history"
]
}
],
"consumes": [
"gitea.pull.updated",
"gitea.pull.merged",
"gitea.pull.closed",
"gitea.forge.status",
"gitea.forge.pull-request.edited",
"gitea.forge.pull-request.closed",
"mesh-controller.checked",
"mesh-controller.plan-moved",
"mesh-delivery-forge-bridge.forge.**"
],
"emits": [
"transition",
"group",
"merged"
],
"invokes": [
"seat:mesh-controller.deliver",
"seat:mesh-controller.delivery-stop",
"seat:mesh-controller.delivery-backups-again",
"seat:mesh-controller.delivery-walks",
"seat:mesh-controller.delivery-check",
"seat:mesh-controller.forget-checks",
"seat:mesh-controller.plans",
"gitea.gitea_commit_statuses",
"gitea.gitea_contains",
"gitea.gitea_open_pulls"
],
"state": [
"deliveries",
"groups",
"pulls",
{
"name": "asks",
"history": 5
},
{
"name": "merges",
"history": 10
},
{
"name": "owed",
"history": 5
},
{
"name": "source",
"history": 64
}
],
"reads": [
"mesh-delivery.deliveries",
"mesh-delivery.groups",
"mesh-delivery.pulls",
"mesh-delivery-teller.answers",
"mesh-controller.assignments",
"node-engine.have"
],
"tools": [
"delivery_status"
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-delivery-gate",
"binary": "mesh-delivery-gate",
"loads": [
"mesh-delivery-gate"
]
}
]
}
}
@@ -0,0 +1,95 @@
{
"module": "mesh-delivery",
"version": "1",
"slug": "deliver",
"claims": [
{
"name": "mesh-delivery",
"scope": "mesh",
"serves": [
"deliveries",
"times",
"show",
"groups",
"what-if",
"checks",
"table",
"stalled",
"recheck",
"release",
"stop",
"close",
"retire-history"
]
}
],
"consumes": [
"gitea.pull.updated",
"gitea.pull.merged",
"gitea.pull.closed",
"gitea.forge.status",
"gitea.forge.pull-request.edited",
"gitea.forge.pull-request.closed",
"mesh-controller.checked",
"mesh-controller.plan-moved"
],
"emits": [
"transition",
"group",
"merged"
],
"invokes": [
"seat:mesh-controller.delivery-plan",
"seat:mesh-controller.delivery-check",
"seat:mesh-controller.deliver",
"seat:mesh-controller.delivery-backups-again",
"seat:mesh-controller.delivery-stop",
"seat:mesh-controller.delivery-walks",
"seat:mesh-controller.forget-checks",
"gitea.gitea_note_append",
"gitea.gitea_delivery_view",
"gitea.gitea_commit_status",
"gitea.gitea_commit_statuses",
"gitea.gitea_contains",
"gitea.gitea_open_pulls",
"gitea.gitea_merge_pull_request",
"gitea.gitea_add_comment",
"seat:operator-channel.notify"
],
"uses": [
"operator-channel"
],
"state": [
"deliveries",
"groups",
"asked",
"pulls"
],
"tools": [
"delivery_status"
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-delivery",
"binary": "mesh-delivery",
"loads": [
"mesh-delivery"
]
}
]
}
}
@@ -0,0 +1,57 @@
{
"module": "mesh-files",
"version": "1",
"claims": [
{
"name": "node-files",
"scope": "node",
"serves": [
"stat",
"readlink",
"list",
"read",
"search",
"account",
"write",
"copy",
"move",
"delete",
"mkdir",
"chmod",
"chown",
"trash",
"restore"
]
}
],
"invokes": [
"seat:operator-channel.tell"
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-files",
"binary": "mesh-files",
"loads": [
"mesh-files"
],
"env": {
"MESH_FILES_STATE": "${dir:state}"
}
}
]
}
}
@@ -0,0 +1,330 @@
{
"module": "mesh-issues",
"version": "1",
"slug": "issues",
"seats": [
{
"name": "issue-tracker",
"scope": "mesh",
"serves": [
"open",
"get",
"list",
"move",
"note",
"link",
"import",
"groom",
"set",
"tracking",
"reserve",
"fix-times"
]
}
],
"claims": [
{
"name": "issue-tracker",
"scope": "mesh",
"serves": [
"open",
"get",
"list",
"move",
"note",
"link",
"import",
"groom",
"set",
"tracking",
"reserve",
"fix-times"
]
}
],
"emits": [
"opened",
"moved",
"noted",
"linked",
"imported",
"set",
"triaged",
"ready",
"ready-to-verify",
"reserved"
],
"consumes": [
"mesh-issues.opened",
"mesh-issues.moved",
"mesh-delivery.transition",
"mesh-delivery-gate.transition"
],
"invokes": [
"claude-code.claude_code_judge",
"seat:mesh-delivery.checks",
"seat:operator-channel.notify",
"gitea.gitea_pull_reviews",
"records.records_status",
"records.records_list",
"records.records_read",
"mesh-knowledge.knowledge_highest"
],
"logs": [
"changes"
],
"state": [
{
"name": "issues",
"history": 2
},
"counters",
"grooming",
"reservations"
],
"config": {
"first-number": {
"type": "number",
"description": "The number the first issue the tracker numbers gets, read once when its counter starts and never again; the import reads it as the boundary between the folders hq numbered and the tracker's issues.",
"minimum": 1,
"trusted": true,
"default": 365
},
"owners": {
"type": "list",
"description": "The registered places an issue's located-in may name: a repository, or a repository and a folder in it separated by a space.",
"trusted": true,
"default": [
"hq",
"mesh-catalog",
"mesh-catalog modules/adwaita",
"mesh-catalog modules/artifact-store-tools",
"mesh-catalog modules/asus-zephyrus-g14",
"mesh-catalog modules/audit-logger",
"mesh-catalog modules/avahi",
"mesh-catalog modules/baserow",
"mesh-catalog modules/betterbird",
"mesh-catalog modules/blueman",
"mesh-catalog modules/bluetooth",
"mesh-catalog modules/ca-trust",
"mesh-catalog modules/claude-code",
"mesh-catalog modules/claude-licence-manager",
"mesh-catalog modules/clipmenu",
"mesh-catalog modules/confluence",
"mesh-catalog modules/cups",
"mesh-catalog modules/dbus",
"mesh-catalog modules/desk-channel",
"mesh-catalog modules/disk-load",
"mesh-catalog modules/distribution",
"mesh-catalog modules/dmenu",
"mesh-catalog modules/dnsmasq",
"mesh-catalog modules/docker",
"mesh-catalog modules/docker-compose",
"mesh-catalog modules/dunst",
"mesh-catalog modules/fail2ban",
"mesh-catalog modules/feh",
"mesh-catalog modules/flatpak",
"mesh-catalog modules/fonts",
"mesh-catalog modules/forticlient",
"mesh-catalog modules/gitea",
"mesh-catalog modules/gitlab",
"mesh-catalog modules/gnome-keyring",
"mesh-catalog modules/grafana",
"mesh-catalog modules/hello-web",
"mesh-catalog modules/home-assistant",
"mesh-catalog modules/hostname",
"mesh-catalog modules/i3",
"mesh-catalog modules/i3status-rust",
"mesh-catalog modules/icecast",
"mesh-catalog modules/influxdb",
"mesh-catalog modules/invoicing",
"mesh-catalog modules/jira",
"mesh-catalog modules/keycloak",
"mesh-catalog modules/lab",
"mesh-catalog modules/lemurs",
"mesh-catalog modules/letta",
"mesh-catalog modules/local-model-consumer",
"mesh-catalog modules/localization",
"mesh-catalog modules/logrotate",
"mesh-catalog modules/mailu",
"mesh-catalog modules/marrytts",
"mesh-catalog modules/matrix",
"mesh-catalog modules/memory-pressure",
"mesh-catalog modules/mesh-catalog",
"mesh-catalog modules/mesh-cli",
"mesh-catalog modules/mesh-delivery",
"mesh-catalog modules/mesh-delivery-gate",
"mesh-catalog modules/mesh-issues",
"mesh-catalog modules/mesh-vault",
"mesh-catalog modules/mesh-watcher",
"mesh-catalog modules/messenger",
"mesh-catalog modules/minio",
"mesh-catalog modules/model-usage",
"mesh-catalog modules/mongodb",
"mesh-catalog modules/mosquitto",
"mesh-catalog modules/mounts",
"mesh-catalog modules/mssql",
"mesh-catalog modules/n8n",
"mesh-catalog modules/nats",
"mesh-catalog modules/netcheck",
"mesh-catalog modules/networkmanager",
"mesh-catalog modules/nextcloud",
"mesh-catalog modules/nextcloud-client",
"mesh-catalog modules/nfs-server",
"mesh-catalog modules/nftables",
"mesh-catalog modules/nm-applet",
"mesh-catalog modules/node-env",
"mesh-catalog modules/nodered",
"mesh-catalog modules/ollama",
"mesh-catalog modules/only-office",
"mesh-catalog modules/openai-consumer",
"mesh-catalog modules/openrazer",
"mesh-catalog modules/pacman",
"mesh-catalog modules/photos-eef",
"mesh-catalog modules/photos-filip",
"mesh-catalog modules/picom",
"mesh-catalog modules/polychromatic",
"mesh-catalog modules/postgres",
"mesh-catalog modules/power",
"mesh-catalog modules/powerlevel10k",
"mesh-catalog modules/records",
"mesh-catalog modules/redis",
"mesh-catalog modules/restic",
"mesh-catalog modules/rofi",
"mesh-catalog modules/route-adapter",
"mesh-catalog modules/screen-lock",
"mesh-catalog modules/searxng",
"mesh-catalog modules/sensors",
"mesh-catalog modules/showcase",
"mesh-catalog modules/slack",
"mesh-catalog modules/snapd",
"mesh-catalog modules/ssh-client",
"mesh-catalog modules/sshd",
"mesh-catalog modules/step-ca",
"mesh-catalog modules/sudo",
"mesh-catalog modules/supabase",
"mesh-catalog modules/systemd",
"mesh-catalog modules/systemd-networkd",
"mesh-catalog modules/systemd-resolved",
"mesh-catalog modules/telegram",
"mesh-catalog modules/time-sync",
"mesh-catalog modules/triggerhappy",
"mesh-catalog modules/umami",
"mesh-catalog modules/unifi",
"mesh-catalog modules/website",
"mesh-catalog modules/xclip",
"mesh-catalog modules/xdg",
"mesh-catalog modules/xorg",
"mesh-catalog modules/xterm",
"mesh-catalog modules/zfs",
"mesh-catalog modules/zsh",
"mesh-catalog modules/zsh-autosuggestions",
"mesh-catalog modules/zsh-syntax-highlighting",
"mesh-controller",
"mesh-controller modules/build-agent",
"mesh-controller modules/route-proxy",
"mesh-delivery",
"mesh-host",
"mesh-lab",
"mesh-media-catalog",
"mesh-sdk",
"mesh-tools"
]
},
"duplicate-check": {
"type": "string",
"description": "Whether a new issue is checked against the open ones for a duplicate: off stops it, anything else is on (novox/hq ADR 0278 §7).",
"trusted": true,
"default": "on"
},
"judge-model": {
"type": "string",
"description": "The model the duplicate check asks, by the agent's name for it, such as sonnet; empty is the tracker's own default.",
"trusted": true,
"default": "sonnet"
},
"forge-owner": {
"type": "string",
"description": "The owner on the forge of the repositories an issue's fixed-by names, for asking after a pull request's delivery (novox/hq ADR 0279 §3); empty asks no forge.",
"trusted": true,
"default": "novox"
},
"stuck-after": {
"type": "string",
"description": "How long a fix may be merged and not delivered before it is said stuck, as a duration such as 2h (novox/hq ADR 0281); empty is the tracker's own default.",
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
"trusted": true,
"default": "2h"
},
"worker-stale-after": {
"type": "string",
"description": "How long an issue's worker stays current with nothing done on it, as a duration such as 24h (novox/hq ADR 0284 §4); empty is the tracker's own default.",
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
"trusted": true,
"default": "24h"
},
"delivered-not-resolved-after": {
"type": "string",
"description": "How long an issue may stay in fixing once every fix it names is delivered before the operator is warned, as a duration such as 1h (novox/hq issue 483); empty is the tracker's own default.",
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
"trusted": true,
"default": "1h"
},
"decision-floor": {
"type": "number",
"description": "The highest decision number already taken somewhere the tracker cannot read, such as an open branch of hq; the decision sequence's first number is one above it, read once when the counter starts (novox/hq issue 424).",
"minimum": 0,
"trusted": true,
"default": 293
},
"research-floor": {
"type": "number",
"description": "The highest research number already taken somewhere the tracker cannot read; the research sequence's first number is one above it, read once when the counter starts (novox/hq issue 424).",
"minimum": 0,
"trusted": true,
"default": 45
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "settings",
"trusted": true,
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"takes-config": ["first-number", "owners", "duplicate-check", "judge-model", "forge-owner", "stuck-after", "worker-stale-after", "delivered-not-resolved-after", "decision-floor", "research-floor"],
"merge": "json",
"template": "files/settings.json"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-issues",
"binary": "mesh-issues",
"loads": [
"mesh-issues"
],
"env": {
"MESH_ISSUES_SETTINGS": "${dir:state}/settings.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,218 @@
{
"module": "mesh-knowledge",
"version": "1",
"slug": "knowledge",
"requires": [
"postgres-database"
],
"contributes": {
"postgres-database": {
"name": "knowledge"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"seats": [
{
"name": "knowledge-base",
"scope": "mesh",
"serves": [
"ask",
"get",
"list",
"findings",
"holds",
"links",
"history",
"reserve",
"propose",
"import",
"return",
"withdraw"
]
}
],
"claims": [
{
"name": "knowledge-base",
"scope": "mesh",
"serves": [
"ask",
"get",
"list",
"findings",
"holds",
"links",
"history",
"reserve",
"propose",
"import",
"return",
"withdraw"
]
}
],
"tools": [
"knowledge_health",
"knowledge_highest"
],
"emits": [
"reserved",
"proposed",
"reviewed",
"accepted",
"changed",
"imported",
"drafted",
"confirmed",
"returned"
],
"uses": [
"operator-channel"
],
"invokes": [
"seat:issue-tracker.reserve",
"claude-code.claude_code_judge",
"claude-code.claude_code_judged",
"records.records_status",
"records.records_list",
"records.records_read",
"seat:operator-channel.notify"
],
"config": {
"judge-model": {
"type": "string",
"description": "The model the knowledge base's drafting and confirming judgements ask, by the agent's name for it, such as sonnet; empty is sonnet.",
"default": "sonnet"
},
"drafting": {
"type": "string",
"description": "Whether the knowledge base drafts and confirms clauses itself: off stops it, anything else is on.",
"default": "on"
},
"reserved-for": {
"type": "string",
"description": "How long a reserved number waits for its proposal before it is withdrawn, as a duration such as 168h; empty is the knowledge base's own default.",
"pattern": "|[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))*",
"default": "168h"
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "database-url",
"type": "file",
"path": "${dir:state}/database.url",
"mode": "0600",
"template": "files/database.url"
},
{
"id": "settings",
"trusted": false,
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"takes-config": ["judge-model", "drafting", "reserved-for"],
"merge": "json",
"template": "files/settings.json"
},
{
"id": "prepare",
"type": "process",
"name": "mesh-knowledge-prepare",
"artifact": "tools",
"run": [
"./mesh-knowledge",
"prepare"
],
"run-once": true,
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
},
"restart-on": [
"database-url"
]
},
{
"id": "keep",
"type": "process",
"name": "mesh-knowledge-keep",
"artifact": "tools",
"run": [
"./mesh-knowledge",
"keep"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
},
"restart-on": [
"database-url"
],
"health": {
"kind": "unit"
}
},
{
"id": "watch",
"type": "process",
"name": "mesh-knowledge-watch",
"artifact": "tools",
"run": [
"./mesh-knowledge",
"watch"
],
"user": "${machine:account}",
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_KNOWLEDGE_STATUS": "${dir:state}/health.json"
},
"restart-on": [
"database-url"
],
"health": {
"kind": "tool",
"tool": "knowledge_health",
"needs": "postgres-database",
"interval": "60s",
"timeout": "10s",
"looks": 2,
"grace": "180s"
}
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-knowledge",
"binary": "mesh-knowledge",
"loads": [
"mesh-knowledge"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_KNOWLEDGE_SETTINGS": "${dir:state}/settings.json",
"MESH_KNOWLEDGE_STATUS": "${dir:state}/health.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,68 @@
{
"module": "mesh-mail-notifier",
"version": "1",
"runs-as": "mesh-mail-notifier",
"claims": [
{
"name": "mail-notifier",
"scope": "node",
"serves": ["status"]
}
],
"consumes": [
"mesh-mail.mail.*.message.added"
],
"invokes": [
"seat:node-notifier.send",
"seat:mail-store.accounts"
],
"emits": [
"shown"
],
"state": [
{
"name": "shown",
"ttl-seconds": 2592000
}
],
"tools": [
"mail-notifier.status",
"mail_notifier_health"
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-mail-notifier",
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-mail-notifier",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-mail-notifier"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-mail-notifier",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-mail-notifier",
"binary": "mesh-mail-notifier",
"loads": [
"mesh-mail-notifier"
]
}
]
}
}
@@ -0,0 +1,125 @@
{
"module": "mesh-mail-web",
"version": "1",
"slug": "mail-web",
"runs-as": "mesh-mail-web",
"claims": [
{
"name": "mail-webclient",
"scope": "mesh",
"serves": ["open", "status"]
}
],
"invokes": [
"seat:mail-store.accounts",
"seat:mail-store.search",
"seat:mail-store.read",
"seat:mail-store.send",
"seat:mail-store.send-status"
],
"reads": ["mesh-mail.accounts"],
"requires": ["route", "oidc-client"],
"contributes": {
"route": {
"label": "mail",
"endpoint": "web"
},
"oidc-client": {
"label": "mail",
"endpoint": "web",
"callback": "/signed-in"
}
},
"binds": {
"route": "${dir:state}/route.json",
"oidc-client": "${dir:state}/oidc-bound.json"
},
"secrets": {
"oidc-client": "${dir:state}/oidc-bound.secret"
},
"listens": [
{
"name": "web",
"port": 8099,
"protocol": "tcp",
"from": "mesh",
"why": "the mail web client's pages, over http; only the route proxy reaches it, and the operator's own browser through the internal name (novox/hq ADR 0440 §2) — its public name, if any, is a route grant"
}
],
"config": {
"operators": {
"type": "list",
"description": "The Keycloak identities (the ID token's preferred_username) let to sign in; nobody by default (novox/hq ADR 0440 §3).",
"trusted": true,
"default": []
}
},
"tools": [
"mail-webclient.open",
"mail-webclient.status",
"mail_web_health"
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-mail-web",
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-mail-web",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-mail-web"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-mail-web",
"place": ".",
"unknown": "program"
},
{
"id": "operators",
"trusted": true,
"type": "file",
"path": "${dir:state}/operators.json",
"mode": "0600",
"owner": "mesh-mail-web",
"merge": "json",
"template": "files/operators.json",
"takes-config": ["operators"]
},
{
"id": "oidc-config",
"type": "file",
"path": "${dir:state}/oidc.json",
"mode": "0600",
"owner": "mesh-mail-web",
"template": "files/oidc.json"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-mail-web",
"binary": "mesh-mail-web",
"loads": ["mesh-mail-web"],
"env": {
"MESH_MAIL_WEB_OPERATORS": "${dir:state}/operators.json",
"MESH_MAIL_WEB_OIDC": "${dir:state}/oidc.json",
"MESH_MAIL_WEB_LISTEN": "${port:8099}"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,312 @@
{
"module": "mesh-mail",
"version": "1",
"slug": "mail",
"seats": [
{
"name": "mail-store",
"scope": "mesh",
"serves": ["accounts", "search", "read", "send", "send-status"]
},
{
"name": "mail-webclient",
"scope": "mesh",
"serves": ["open", "status"]
},
{
"name": "mail-notifier",
"scope": "node",
"needs": ["node-notifier"],
"serves": ["status"]
}
],
"claims": [
{
"name": "mail-store",
"scope": "mesh",
"serves": ["accounts", "search", "read", "send", "send-status"]
}
],
"requires": [
"postgres-database",
"s3-bucket"
],
"contributes": {
"postgres-database": {
"name": "mail"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"s3-bucket": "${dir:state}/store-binding.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret",
"s3-bucket": "${dir:state}/store.secret"
},
"own-secrets": {
"mail-credential-*": {
"path": "${dir:state}/mail-credential-*.secret",
"issued-by": "outside",
"prompt": "the password of the mail account {member}",
"owner": "mesh-mail-send"
},
"broker-send": {
"path": "${dir:state}/broker-send.secret",
"owner": "mesh-mail-send"
}
},
"config": {
"accounts": {
"type": "object",
"description": "The mail accounts, each by a lower-case name that names it on the bus and its secret: its kind (imap), address, incoming and outgoing servers (host, port, security tls or starttls), and optionally the folders watched and the user it signs in as; no password, which is the own secret mail-credential-<account> (novox/hq ADR 0359 §5).",
"trusted": true,
"default": {}
},
"grants": {
"type": "object",
"description": "Per account, who may read its mail and who may send from it: a module's name (on every machine), <machine>.<module>, or person.<name>. Nobody by default; it restricts the stream MAIL and the tools mail_search, mail_read and mail_send alike (novox/hq ADR 0359 §4).",
"trusted": true,
"default": {}
}
},
"tools": [
"mail_accounts",
"mail_search",
"mail_read",
"mail_health",
"mail_send",
"mail_send_status",
"mail-store.accounts",
"mail-store.search",
"mail-store.read",
"mail-store.send",
"mail-store.send-status"
],
"uses": [
"operator-channel"
],
"state": [
"sends",
"accounts",
"mails"
],
"emits": [
"mail.send.sent",
"mail.send.failed"
],
"streams": [
{
"name": "mail",
"events": [
"mail.*.message.added",
"mail.*.message.changed",
"mail.*.message.removed"
],
"max-age-days": 7,
"grant": {
"config": "grants",
"events": "mail.{key}.**"
}
},
{
"name": "mail-sends",
"events": [
"mail.send.approved"
],
"max-age-days": 1,
"max-mib": 64,
"retention": "work-queue",
"max-deliveries": 5,
"duplicates": 24
}
],
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-mail-send"
},
{
"id": "state",
"type": "directory",
"mode": "0711",
"place": ".",
"unknown": "program"
},
{
"id": "database-url",
"type": "file",
"path": "${dir:state}/database.url",
"mode": "0600",
"template": "files/database-url"
},
{
"id": "store",
"type": "file",
"path": "${dir:state}/store.json",
"mode": "0600",
"template": "files/store.json"
},
{
"id": "accounts",
"trusted": true,
"type": "file",
"path": "${dir:state}/accounts.json",
"mode": "0644",
"merge": "json",
"template": "files/accounts.json",
"takes-config": [
"accounts"
]
},
{
"id": "grants",
"trusted": true,
"type": "file",
"path": "${dir:state}/grants.json",
"mode": "0600",
"merge": "json",
"template": "files/grants.json",
"takes-config": [
"grants"
]
},
{
"id": "prepare",
"type": "process",
"name": "mesh-mail-prepare",
"artifact": "tools",
"run": [
"./mesh-mail",
"prepare"
],
"run-once": true,
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
},
"restart-on": [
"database-url"
]
},
{
"id": "keep",
"type": "process",
"name": "mesh-mail-keep",
"artifact": "tools",
"run": [
"./mesh-mail",
"keep"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
"MESH_MAIL_SECRETS": "${dir:state}",
"MESH_MAIL_STORE": "${dir:state}/store.json"
},
"restart-on": [
"database-url",
"store",
"accounts"
],
"health": {
"kind": "unit"
}
},
{
"id": "watch",
"type": "process",
"name": "mesh-mail-watch",
"artifact": "tools",
"run": [
"./mesh-mail",
"watch"
],
"user": "${machine:account}",
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
"MESH_MAIL_SECRETS": "${dir:state}",
"MESH_MAIL_STATUS": "${dir:state}/health.json"
},
"restart-on": [
"database-url",
"accounts"
],
"health": {
"kind": "tool",
"tool": "mail_health",
"needs": "postgres-database",
"interval": "60s",
"timeout": "10s",
"looks": 2,
"grace": "180s"
}
},
{
"id": "send",
"type": "process",
"name": "mesh-mail-send",
"artifact": "tools",
"run": [
"./mesh-mail",
"send"
],
"user": "mesh-mail-send",
"env": {
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
"MESH_MAIL_SECRETS": "${dir:state}"
},
"restart-on": [
"accounts"
],
"bus": {
"emits": [
"mail.send.sent",
"mail.send.failed"
],
"queues": [
"mail-sends"
],
"state": [
"sends"
],
"asks": true,
"invokes": [
"seat:operator-channel.tell"
]
},
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-mail",
"binary": "mesh-mail",
"loads": [
"mesh-mail"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"MESH_MAIL_ACCOUNTS": "${dir:state}/accounts.json",
"MESH_MAIL_GRANTS": "${dir:state}/grants.json",
"MESH_MAIL_SECRETS": "${dir:state}",
"MESH_MAIL_STORE": "${dir:state}/store.json",
"MESH_MAIL_STATUS": "${dir:state}/health.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,60 @@
{
"module": "mesh-provisioner-client",
"version": "1",
"claims": [
{
"name": "node-provisioner",
"scope": "node"
}
],
"own-secrets": {
"provisioner-broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-provisioner-client",
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-provisioner-client",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-provisioner-client"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-provisioner-client",
"place": ".",
"unknown": "program"
},
{
"id": "client",
"type": "process",
"name": "mesh-provisioner-client",
"artifact": "client",
"run": [
"./mesh-provisioner-client"
],
"env": {
"MESH_PROVISIONER_CREDENTIAL": "${dir:state}/broker",
"MESH_PROVISIONER_STATE": "${dir:state}"
},
"user": "mesh-provisioner-client",
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "client",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-provisioner-client",
"binary": "mesh-provisioner-client"
}
]
}
}
@@ -0,0 +1,56 @@
{
"module": "mesh-provisioner",
"version": "1",
"runs-as": "mesh-provisioner",
"claims": [
{
"name": "mesh-provisioner",
"scope": "mesh",
"serves": [
"provisioning"
]
}
],
"state": [
"registry",
"needs",
"applied",
"collect"
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-provisioner",
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-provisioner",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-provisioner"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-provisioner",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-provisioner",
"binary": "mesh-provisioner",
"loads": [
"mesh-provisioner"
]
}
]
}
}
@@ -0,0 +1,55 @@
{
"module": "mesh-reads",
"version": "1",
"runs-as": "mesh-reads",
"claims": [
{
"name": "node-reads",
"scope": "node",
"serves": [
"stat",
"readlink",
"list",
"read",
"search",
"account"
]
}
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-reads",
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-reads",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-reads"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-reads",
"place": ".",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-reads",
"binary": "mesh-reads",
"loads": [
"mesh-reads"
]
}
]
}
}
@@ -0,0 +1,173 @@
{
"module": "mesh-vault",
"version": "1",
"runs-as": "mesh-vault",
"provides": [
{
"name": "secret",
"scope": "mesh",
"identity": {
"in": "a vault entry"
}
}
],
"emits": [
"provisioned",
"rotated",
"secret-changed"
],
"reads": [
"mesh-controller.assignments"
],
"receives": {
"secret": "${dir:grants}/mesh.json"
},
"grants": {
"secret": "${dir:grants}"
},
"keeps": "/var/lib/mesh-vault/root",
"data": {
"own": [
{
"id": "state",
"path": "${dir:state}",
"class": "valuable",
"why": "the vault's own keys"
},
{
"id": "ledger",
"path": "${dir:ledger}",
"class": "valuable",
"why": "every secret the vault keeps"
},
{
"id": "root",
"path": "${dir:root}",
"class": "valuable",
"why": "the vault's root material"
},
{
"id": "store",
"path": "${dir:store}",
"class": "valuable",
"why": "every secret the vault holds, sealed to its own key and to the operator key"
}
],
"consumers": {
"secret": {
"class": "valuable",
"in": "ledger",
"why": "a secret given to a consumer is kept nowhere else in the clear"
}
}
},
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "mesh-vault",
"runtime-health": {
"kind": "tool",
"tool": "vault_health",
"interval": "60s",
"timeout": "10s",
"looks": 2,
"grace": "60s"
},
"resources": [
{
"id": "account",
"type": "user",
"name": "mesh-vault",
"shell": "/usr/bin/nologin",
"home": "/var/lib/mesh-vault"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"owner": "mesh-vault",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"owner": "mesh-vault",
"unknown": "program"
},
{
"id": "ledger",
"type": "directory",
"mode": "0700",
"owner": "mesh-vault",
"unknown": "program"
},
{
"id": "root",
"type": "directory",
"mode": "0700",
"owner": "mesh-vault",
"unknown": "program"
},
{
"id": "store",
"type": "directory",
"mode": "0700",
"owner": "mesh-vault",
"unknown": "program"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-vault",
"binary": "mesh-vault",
"loads": [
"mesh-vault"
],
"env": {
"MESH_RECEIVES": "${dir:grants}/mesh.json",
"MESH_VAULT_LEDGER": "${dir:ledger}",
"MESH_VAULT_ROOT": "${dir:root}",
"MESH_VAULT_STORE": "${dir:store}",
"MESH_VAULT_STATE": "${dir:state}"
}
}
]
},
"tools": [
"secret_export",
"secret_holders",
"secret_verify",
"secret_handed",
"secret_asks",
"secret_vault_export",
"provisioner_retirement",
"provisioner_retire_approve",
"provisioner_retire_reject",
"provisioner_delete",
"vault_status",
"vault_health"
],
"claims": [
{
"name": "mesh-vault",
"scope": "mesh",
"serves": [
"get",
"accept",
"secret-ask",
"issued",
"rotate",
"move-in",
"node-key",
"move-asks"
]
}
]
}
@@ -0,0 +1,71 @@
{
"module": "mesh-watcher",
"version": "1",
"slug": "watch",
"consumes": [
"mesh-controller.doctor-heartbeat"
],
"invokes": [
"mesh-watcher.watcher_ping",
"seat:mesh-controller.seats"
],
"own-secrets": {
"telegram-token": "${dir:state}/telegram-token"
},
"tools": [
"watcher_status",
"watcher_last_heard",
"watcher_test",
"watcher_ping"
],
"config": {
"telegram-chat-id": {
"type": "string",
"description": "The Telegram chat the watcher reports to: the chat's id, a number, or @name of a channel; empty reports to none.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"takes-config": ["telegram-chat-id"],
"merge": "json",
"template": "files/settings.json"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mesh-watcher",
"binary": "mesh-watcher",
"loads": [
"mesh-watcher"
],
"env": {
"MESH_WATCHER_SETTINGS": "${dir:state}/settings.json",
"MESH_WATCHER_TELEGRAM_TOKEN_FILE": "${dir:state}/telegram-token"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,188 @@
{
"module": "messenger",
"version": "1",
"slug": "msgr",
"runs-as": "messenger",
"seats": [
{
"name": "operator-channel",
"scope": "mesh",
"serves": [
"open",
"history",
"notify",
"tell",
"asks"
],
"accepts": [
"ask",
"cancel",
"condition"
],
"emits": [
"decided"
],
"by-caller": [
"ask",
"cancel",
"condition",
"decided"
],
"records": [
"asks"
]
},
{
"name": "channel",
"scope": "mesh",
"kinded": true,
"accepts": [
"show",
"edit",
"send"
]
},
{
"name": "intake",
"scope": "mesh",
"kinded": true,
"emits": [
"choice",
"link",
"failed",
"standing"
],
"proofs": [
"code"
]
}
],
"claims": [
{
"name": "operator-channel",
"scope": "mesh",
"serves": [
"open",
"history",
"notify",
"tell",
"asks"
]
}
],
"uses": [
"channel"
],
"consumes": [
"mesh-controller.condition-raised",
"mesh-controller.condition-changed",
"mesh-controller.condition-cleared",
"mesh-controller.plan-moved",
"intake.choice",
"intake.link",
"intake.failed",
"intake.standing"
],
"emits": [
"refused"
],
"invokes": [
"seat:mesh-controller.conditions",
"seat:mesh-controller.root-free",
"seat:issue-tracker.tracking"
],
"state": [
"open",
"sent",
{
"name": "asks",
"ttl-seconds": 2592000
},
"identities",
"walks"
],
"own-secrets": {
"broker": "${dir:state}/broker"
},
"secrets-owner": "messenger",
"tools": [
"messenger_status",
"messenger_recent",
"messenger_test",
"messenger_preview",
"messenger_check",
"messenger_identities",
"messenger_unlink"
],
"config": {
"time-zone": {
"type": "string",
"description": "The time zone every time a message says is said in, an IANA name such as Europe/Brussels; empty is this machine's own zone.",
"trusted": true,
"default": ""
},
"desktop-machines": {
"type": "list",
"description": "The machines whose desktop showed the operator's messages, by node name. Nothing in this module reads it since the desk channel took the desktop over; it is taken so the file stays as a layer that still sets it makes it, until that layer drops it.",
"trusted": true,
"default": []
},
"only-what-needs-me": {
"type": "list",
"description": "The kinds of channel set to say only what needs the operator: a walk that delivered with nothing held and nothing open is not told there (ADR 0308 §4); empty is none.",
"trusted": true,
"default": []
}
},
"resources": [
{
"id": "account",
"type": "user",
"name": "messenger",
"shell": "/usr/bin/nologin",
"home": "/var/lib/messenger"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"owner": "messenger",
"unknown": "program"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"takes-config": ["time-zone", "desktop-machines", "only-what-needs-me"],
"merge": "json",
"template": "files/settings.json",
"owner": "messenger"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/messenger",
"binary": "messenger",
"loads": [
"messenger"
],
"env": {
"MESH_MESSENGER_SETTINGS": "${dir:state}/settings.json",
"MESH_MESSENGER_STATE": "${dir:state}"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,188 @@
{
"module": "minio",
"version": "1",
"upgrade": {
"policy": "record",
"why": "holds the photos themselves (irreplaceable, kept by photos) for its consumers: a person takes each build, after a backup (hq ADR 0236)"
},
"provides": [
{
"name": "s3-bucket",
"scope": "mesh",
"identity": {
"max": 20,
"in": "an S3 access key"
}
}
],
"requires": [
"route"
],
"contributes": {
"route": {
"api": {
"label": "files-api",
"endpoint": "s3"
},
"console": {
"label": "files",
"endpoint": "console"
}
}
},
"capabilities": [
"container-runtime"
],
"emits": [
"bucket.created",
"bucket.removed"
],
"listens": [
{
"name": "s3",
"port": 9000,
"protocol": "tcp",
"from": "mesh",
"why": "the S3 endpoint"
},
{
"name": "console",
"port": 9001,
"protocol": "tcp",
"from": "mesh",
"why": "the admin console"
}
],
"serves": {
"s3-bucket": {
"scheme": "http",
"region": "eu-west",
"port": 9000,
"bucket": "${consumer:as:dns}"
}
},
"receives": {
"s3-bucket": "${dir:grants}/mesh.json"
},
"grants": {
"s3-bucket": "${dir:grants}"
},
"own-secrets": {
"root": "${dir:state}/root.secret"
},
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "every consumer's bucket and its objects"
}
],
"consumers": {
"s3-bucket": {
"class": "valuable",
"in": "data",
"why": "a consumer's objects are the only copy of what it stored; a consumer that keeps something irreplaceable here says so (kept-by)"
}
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "root-env",
"type": "file",
"path": "${dir:state}/root.env",
"mode": "0600",
"template": "files/root.env"
},
{
"id": "data",
"type": "directory",
"path": "/var/lib/minio-store",
"mode": "0700",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "minio-net"
},
{
"id": "server",
"type": "container",
"name": "minio",
"image": "docker.io/pgsty/minio@sha256:b6bfe7239bfc83fb90d31612d9704d86039dd714f7904b3f1ad68f211e602372",
"network": "minio-net",
"args": [
"server",
"/data",
"--console-address",
":9001"
],
"env-file": [
"${dir:state}/root.env"
],
"ports": [
"9000",
"9001"
],
"volumes": [
"/var/lib/minio-store:/data",
"${dir:state}/root.secret:/run/secrets/root:ro"
],
"env": {
"MINIO_ROOT_PASSWORD_FILE": "/run/secrets/root",
"MINIO_REGION": "eu-west"
}
},
{
"id": "client",
"type": "package",
"package": "minio-client"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js",
"provisioner/index.js"
],
"loads": [
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_MINIO_ENDPOINT": "http://127.0.0.1:${port:9000}",
"MESH_MINIO_ROOT_USER": "meshroot",
"MESH_MINIO_ROOT_PASSWORD_FILE": "${dir:state}/root.secret",
"MESH_MINIO_REGION": "eu-west",
"MESH_MINIO_MC_BIN": "mcli",
"MESH_MINIO_MC_CONFIG": "${dir:state}/mc",
"MESH_RECEIVES": "${dir:grants}/mesh.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,107 @@
{
"module": "model-usage",
"version": "1",
"slug": "usage",
"capabilities": [
"container-runtime"
],
"requires": [
"postgres-database"
],
"contributes": {
"postgres-database": {
"name": "model_usage"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"consumes": [
"*.usage.*"
],
"data": {
"own": [
{
"id": "state",
"path": "${dir:state}",
"class": "cache",
"why": "the mesh's own files for it; its records are in its database"
},
{
"id": "spool",
"path": "${dir:spool}",
"class": "valuable",
"why": "usage events the store could not take yet; after the bus gives one up, the only copy"
}
]
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "database-url",
"type": "file",
"path": "${dir:state}/database.url",
"mode": "0600",
"template": "files/database.url"
},
{
"id": "spool",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "prepare",
"type": "process",
"name": "model-usage-prepare",
"artifact": "code",
"run": [
"node",
"prepare/index.js"
],
"run-once": true,
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url"
},
"restart-on": [
"database-url"
]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"prepare/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"DATABASE_URL_FILE": "${dir:state}/database.url",
"USAGE_SPOOL": "${dir:spool}"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,170 @@
{
"module": "mongodb",
"version": "1",
"upgrade": {
"policy": "record",
"why": "a provider whose restart drops every consumer on its machine, and which holds the photos' albums (irreplaceable, kept by photos): a person takes each build, after a backup (hq ADR 0236)"
},
"provides": [
{
"name": "mongodb-database",
"scope": "mesh",
"identity": {
"max": 63,
"in": "a MongoDB database name"
}
}
],
"capabilities": [
"container-runtime"
],
"emits": [
"database.provisioned",
"database.deprovisioned"
],
"consumes": [
"mongodb.database.provisioned",
"mongodb.database.deprovisioned"
],
"listens": [
{
"name": "database",
"port": 27017,
"protocol": "tcp",
"from": "mesh",
"why": "modules on any machine that were granted a database"
}
],
"serves": {
"mongodb-database": {
"port": 27017
}
},
"receives": {
"mongodb-database": "${dir:grants}/mesh.json"
},
"grants": {
"mongodb-database": "${dir:grants}"
},
"own-secrets": {
"root": "${dir:state}/root.secret"
},
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"backup": {
"dump": "docker exec mongodb-server sh -c 'printf \"password: %s\\n\" \"$(cat /run/secrets/root)\" > /tmp/.backup.yaml && mongodump --quiet --config /tmp/.backup.yaml --username root --authenticationDatabase admin --archive; s=$?; rm -f /tmp/.backup.yaml; exit $s' > ${dir:dumps}/all.archive.partial && mv ${dir:dumps}/all.archive.partial ${dir:dumps}/all.archive",
"into": "dumps"
},
"why": "every consumer's database; copied by the dump, not as live files"
},
{
"id": "dumps",
"path": "${dir:dumps}",
"class": "rebuildable",
"why": "last night's dump, made again every night"
}
],
"consumers": {
"mongodb-database": {
"class": "valuable",
"in": "data",
"why": "a consumer's documents are the only copy of what it wrote; a consumer that keeps something irreplaceable here says so (kept-by)"
}
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "dumps",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "mongodb"
},
{
"id": "server-root",
"type": "file",
"path": "${dir:state}/server-root.secret",
"mode": "0400",
"owner": "999:999",
"template": "files/server-root.secret"
},
{
"id": "server",
"type": "container",
"name": "mongodb-server",
"image": "mongo@sha256:e3fa459b4f4b72f3257c67a23c145e250b8b5700f033860392c68539b998bbe3",
"health": {
"kind": "tcp",
"endpoint": "database"
},
"network": "mongodb",
"env": {
"MONGO_INITDB_ROOT_USERNAME": "root",
"MONGO_INITDB_ROOT_PASSWORD_FILE": "/run/secrets/root"
},
"ports": [
"27017"
],
"volumes": [
"${dir:data}:/data/db",
"${dir:state}/server-root.secret:/run/secrets/root:ro"
]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"loads": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_PROVISION_MONGODB": "mongodb://root@127.0.0.1:${port:27017}/admin?authSource=admin",
"MESH_PROVISION_PASSWORD_FILE": "${dir:state}/root.secret",
"MESH_RECEIVES": "${dir:grants}/mesh.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,194 @@
{
"module": "mosquitto",
"version": "1",
"slug": "mosq",
"provides": [
{
"name": "mqtt-topic",
"scope": "mesh",
"identity": {
"in": "a Mosquitto client and topic prefix"
}
}
],
"capabilities": [
"container-runtime"
],
"emits": [
"topic.provisioned",
"topic.deprovisioned"
],
"consumes": [
"mosquitto.topic.provisioned",
"mosquitto.topic.deprovisioned"
],
"serves": {
"mqtt-topic": {
"scheme": "mqtt",
"port": 1883
}
},
"receives": {
"mqtt-topic": "${dir:grants}/mesh.json"
},
"grants": {
"mqtt-topic": "${dir:grants}"
},
"own-secrets": {
"admin": {
"path": "${dir:mesh-state}/admin",
"taken": "at-start"
}
},
"listens": [
{
"name": "mqtt",
"port": 1883,
"protocol": "tcp",
"from": "mesh",
"why": "modules on any machine that were granted a topic namespace"
},
{
"name": "mqtt-websockets",
"port": 8081,
"protocol": "tcp",
"from": "mesh",
"why": "the same broker over MQTT-on-WebSockets, for browser clients"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "rebuildable",
"why": "retained messages and sessions; devices publish them again"
}
],
"consumers": {
"mqtt-topic": {
"class": "rebuildable",
"in": "data",
"why": "retained messages are published again by the devices"
}
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "1883:1883",
"unknown": "program"
},
{
"id": "server-conf",
"type": "file",
"path": "${dir:state}/mosquitto.conf",
"mode": "0600",
"owner": "1883:1883",
"template": "files/mosquitto.conf"
},
{
"id": "net",
"type": "network",
"name": "mosquitto"
},
{
"id": "bootstrap-env",
"type": "file",
"path": "${dir:state}/bootstrap.env",
"mode": "0600",
"template": "files/bootstrap.env"
},
{
"id": "bootstrap",
"type": "process",
"name": "mosquitto-bootstrap",
"artifact": "code",
"run": [
"node",
"bootstrap/index.js"
],
"run-once": true,
"env-file": [
"${dir:state}/bootstrap.env"
],
"restart-on": [
"bootstrap-env",
"needs-admin"
]
},
{
"id": "server",
"type": "container",
"name": "mosquitto",
"image": "eclipse-mosquitto@sha256:38c0da4f2ef84284d47b3b3eeea1cb3bdeabe81ee10caf0cd5c5ff61ee3ea408",
"health": {
"kind": "tcp",
"endpoint": "mqtt"
},
"network": "mosquitto",
"ports": [
"1883",
"8081"
],
"volumes": [
"${dir:data}:/mosquitto/data",
"${dir:state}/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro"
]
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"provisioner/index.js",
"bootstrap/index.js"
],
"loads": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_RECEIVES": "${dir:grants}/mesh.json",
"MESH_PROVISION_MQTT": "127.0.0.1:${port:1883}",
"MESH_PROVISION_ADMIN_USER": "mesh-admin",
"MESH_PROVISION_PASSWORD_FILE": "${dir:mesh-state}/admin",
"MESH_MQTT_CTRL_CONTAINER": "mosquitto"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,160 @@
{
"module": "mounts",
"version": "1",
"requires": [
"nfs-share"
],
"reads": [
"nfs-server.exports"
],
"invokes": [
"seat:mesh-controller.data"
],
"capabilities": [
"package-manager",
"service-manager"
],
"claims": [
{
"name": "node-mounts",
"scope": "node",
"serves": [
"list",
"test",
"mount",
"unmount",
"adopt"
]
}
],
"tools": [
"mounts_list",
"mounts_exports",
"mounts_health"
],
"state": [
{
"name": "shares",
"per-machine": true
}
],
"config": {
"shares": {
"type": "string",
"description": "The shares of another machine this machine mounts: space-separated name=mountpoint, each optionally :ro, or none (novox/hq ADR 0263 rule 5).",
"trusted": true,
"default": "none"
},
"sources": {
"type": "string",
"description": "The occasional sources this machine mounts: space-separated name=smb://[<user>@]<host>/<share>@<mountpoint> or name=disk:<uuid>@<mountpoint>, each optionally :ro, or none (novox/hq ADR 0263 rule 6); an SMB source's username is in its entry, its password the secret smb-password-<name> (novox/hq ADR 0283).",
"trusted": true,
"default": "none"
}
},
"own-secrets": {
"smb-password-*": {
"path": "${dir:state}/smb-password-*.secret",
"issued-by": "outside"
}
},
"resources": [
{
"id": "nfs-utils",
"type": "package",
"package": "nfs-utils"
},
{
"id": "cifs-utils",
"type": "package",
"package": "cifs-utils"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config-dir",
"type": "directory",
"path": "/etc/mesh-mounts",
"mode": "0755",
"unknown": "program"
},
{
"id": "config",
"type": "file",
"path": "/etc/mesh-mounts/mounts.conf",
"mode": "0644",
"template": "files/mounts.conf"
},
{
"id": "bus-dir-parent",
"type": "directory",
"path": "/var/lib/mesh-mounts",
"mode": "0755",
"unknown": "program"
},
{
"id": "bus-dir",
"type": "directory",
"path": "/var/lib/mesh-mounts/from-bus",
"mode": "0755",
"owner": "${machine:account}",
"unknown": "program"
},
{
"id": "apply",
"type": "process",
"name": "mesh-mounts-apply",
"artifact": "tools-go",
"run": [
"./mounts",
"apply"
],
"health": {
"kind": "unit"
}
},
{
"id": "watch",
"type": "process",
"name": "mesh-mounts-watch",
"artifact": "tools-go",
"run": [
"./mounts",
"watch"
],
"health": {
"kind": "tool",
"tool": "mounts_health",
"interval": "60s",
"timeout": "10s",
"looks": 2,
"grace": "90s"
}
}
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/mounts",
"binary": "mounts",
"loads": [
"mounts"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,174 @@
{
"module": "mssql",
"version": "1",
"upgrade": {
"policy": "record",
"why": "a provider whose restart drops every consumer on its machine, and whose new version may upgrade its databases in place: a person takes each build, after a backup (hq ADR 0236)"
},
"provides": [
{
"name": "mssql-database",
"scope": "mesh",
"identity": {
"max": 128,
"in": "a SQL Server login and database name"
}
}
],
"capabilities": [
"container-runtime"
],
"emits": [
"database.provisioned",
"database.deprovisioned"
],
"consumes": [
"mssql.database.provisioned",
"mssql.database.deprovisioned"
],
"listens": [
{
"name": "database",
"port": 1433,
"protocol": "tcp",
"from": "mesh",
"why": "modules on any machine that were granted a database, and the people who were given its address; the machine port is the assignment's to pin"
}
],
"serves": {
"mssql-database": {}
},
"receives": {
"mssql-database": "${dir:grants}/mesh.json"
},
"grants": {
"mssql-database": "${dir:grants}"
},
"own-secrets": {
"sa": "${dir:state}/sa.secret",
"reader": "${dir:state}/reader.secret"
},
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"backup": {
"dump": "{ cat ${dir:state}/sa.secret; echo; cat ${dir:state}/backup.sql; } | docker exec -i mssql sh -c 'read -r p; SQLCMDPASSWORD=\"$p\" exec /opt/mssql-tools18/bin/sqlcmd -C -b -S localhost -U sa -i /dev/stdin'",
"into": "dumps"
},
"why": "every consumer's database; copied by the dump, not as live files"
},
{
"id": "dumps",
"path": "${dir:dumps}",
"class": "rebuildable",
"why": "last night's dump, made again every night"
}
],
"consumers": {
"mssql-database": {
"class": "valuable",
"in": "data",
"why": "a consumer's rows are the only copy of what it wrote"
}
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "sa-env",
"type": "file",
"path": "${dir:state}/sa.env",
"mode": "0600",
"template": "files/sa.env"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "10001:0",
"unknown": "program"
},
{
"id": "dumps",
"type": "directory",
"path": "${dir:data}/backup",
"mode": "0700",
"owner": "10001:0",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "mssql"
},
{
"id": "server",
"type": "container",
"name": "mssql",
"image": "mcr.microsoft.com/mssql/server@sha256:4402d880dd4c34bfa7d8705e56a86cd6c88da80a1f6bbbe741f999e76264a090",
"network": "mssql",
"env-file": [
"${dir:state}/sa.env"
],
"ports": [
"1433"
],
"volumes": [
"${dir:data}:/var/opt/mssql"
],
"secrets-in-environment": "the image documents only MSSQL_SA_PASSWORD, no _FILE and no configuration field; not convertible without a wrapper entrypoint"
},
{
"id": "backup-sql",
"type": "file",
"path": "${dir:state}/backup.sql",
"mode": "0600",
"template": "files/backup.sql"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"loads": [
"index.js",
"tools/index.js",
"provisioner/index.js"
],
"env": {
"MESH_PROVISION_MSSQL": "mssql://sa@127.0.0.1:${port:1433}/master",
"MESH_PROVISION_PASSWORD_FILE": "${dir:state}/sa.secret",
"MESH_RECEIVES": "${dir:grants}/mesh.json",
"MESH_MSSQL_READER_PASSWORD_FILE": "${dir:state}/reader.secret"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,173 @@
{
"module": "n8n",
"version": "1",
"capabilities": [
"container-runtime"
],
"requires": [
"postgres-database",
"route"
],
"contributes": {
"postgres-database": {
"name": "n8n"
},
"route": {
"label": "n8n",
"endpoint": "web"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret"
},
"accesses": [
{
"id": "media",
"mode": "read-write"
}
],
"listens": [
{
"name": "web",
"port": 5678,
"protocol": "tcp",
"from": "mesh",
"why": "the n8n editor, its REST API and the webhook endpoints workflows are triggered through; a public name is the route's"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "the instance's encryption key, settings and binary data; workflows are in the database"
},
{
"id": "cache",
"path": "${dir:cache}",
"class": "cache",
"why": "scratch space"
}
]
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "1000:1000",
"unknown": "program"
},
{
"id": "cache",
"type": "directory",
"mode": "0700",
"owner": "999:999",
"unknown": "program"
},
{
"id": "database-secret",
"type": "file",
"path": "${dir:state}/n8n-database.secret",
"mode": "0400",
"owner": "1000:1000",
"template": "files/n8n-database.secret"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "net",
"type": "network",
"name": "n8n"
},
{
"id": "server",
"type": "container",
"health": {
"kind": "http",
"endpoint": "web",
"path": "/healthz/readiness",
"status": 200,
"needs": "postgres-database"
},
"name": "n8n",
"artifact": "server",
"network": "n8n",
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"5678"
],
"volumes": [
"${dir:data}:/home/node/.n8n",
"${dir:state}/n8n-database.secret:/run/secrets/database:ro",
"${access:media}:/media-library"
]
},
{
"id": "cache-server",
"type": "container",
"name": "n8n-redis",
"image": "redis@sha256:8a1efc5f479551822b47424ccae982026b633f28818eab0387348120a61e10e2",
"network": "n8n",
"args": [
"redis-server",
"--appendonly",
"yes"
],
"volumes": [
"${dir:cache}:/data"
]
},
{
"id": "browser",
"type": "container",
"name": "n8n-selenium",
"image": "selenium/standalone-chrome@sha256:9ae1c78e9b2ca9fe4b22e57873b5ee34aeb8e814e3122293eef4c3abe4c5f448",
"network": "n8n",
"env": {
"SE_ENABLE_TRACING": "false",
"SE_NODE_MAX_SESSIONS": "5",
"SE_NODE_OVERRIDE_MAX_SESSIONS": "true"
}
}
],
"build": {
"on": [
{
"arg": "N8N_BASE",
"image": "n8nio/n8n@sha256:4846eb2f4b874ab04cde7fc1e249d2ddaec66e9aea64439beb2972cfea88e3c0"
}
],
"artifacts": [
{
"name": "server",
"kind": "image",
"from": "Dockerfile"
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,171 @@
{
"module": "nats",
"version": "1",
"upgrade": {
"policy": "record",
"why": "the bus: replaced only as a planned step a person starts (`bus upgrade`), its streams snapshotted first and checked after (hq ADR 0236); the controller holds this whatever is said here"
},
"provides": [
{
"name": "mesh-bus",
"scope": "mesh"
}
],
"claims": [
{
"name": "mesh-broker",
"scope": "mesh"
}
],
"bus-users": "/var/lib/nats-module/conf/accounts.conf",
"own-secrets": {
"broker": "${dir:mesh-state}/broker"
},
"capabilities": [
"container-runtime"
],
"emits": [],
"consumes": [],
"listens": [
{
"name": "bus",
"port": 4222,
"protocol": "tcp",
"from": "mesh",
"why": "the mesh bus — every link the mesh has, over TLS, reached across the overlay"
}
],
"tools": [
"nats_server",
"nats_connections",
"nats_closed_connections",
"nats_subscriptions",
"nats_streams",
"nats_backlog",
"nats_buckets",
"nats_users",
"nats_user_can"
],
"guards": [
8222
],
"data": {
"own": [
{
"id": "jetstream",
"path": "${dir:jetstream-data}",
"class": "valuable",
"active": "1d",
"backup": {
"dump": "docker exec -i mesh-broker-nats mesh-nats-snapshot snapshot < ${dir:mesh-state}/broker > ${dir:snapshots}/bus.tar.partial && mv ${dir:snapshots}/bus.tar.partial ${dir:snapshots}/bus.tar || { rm -f ${dir:snapshots}/bus.tar.partial; exit 1; }",
"into": "snapshots"
},
"why": "the bus's streams and key-value buckets: the hand-act log, conditions, every module's state; written all the time, so copied by the server's own snapshot of each stream (novox/hq ADR 0235), never as live files"
},
{
"id": "snapshots",
"path": "${dir:snapshots}",
"class": "rebuildable",
"why": "last night's snapshot of every stream with its manifest, made again every night"
}
]
},
"resources": [
{
"id": "jetstream-data",
"type": "directory",
"path": "/var/lib/mesh-broker-nats",
"mode": "0700",
"unknown": "program"
},
{
"id": "conf-dir",
"type": "directory",
"path": "/var/lib/nats-module/conf",
"mode": "0700",
"unknown": "program"
},
{
"id": "snapshots",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "server-conf",
"type": "file",
"path": "/var/lib/nats-module/conf/nats.conf",
"template": "files/nats.conf",
"mode": "0644"
},
{
"id": "server",
"type": "container",
"name": "mesh-broker-nats",
"ports": [
"4222:4222",
"127.0.0.1:8222:8222"
],
"volumes": [
"/var/lib/mesh-broker-nats:/data",
"/var/lib/nats-module/conf:/etc/nats:ro",
"${access:tls}:/tls:ro"
],
"artifact": "server"
}
],
"accesses": [
{
"id": "tls",
"path": "/var/lib/mesh-broker-tls",
"mode": "read"
}
],
"build": {
"on": [
{
"arg": "NATS_BASE",
"image": "nats@sha256:e4bf19f15fd3218814a4e3c9e0064e1334bd8aa20d5984b9f1a0afd084f8cc00"
},
{
"arg": "GO_BASE",
"image": "golang@sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c"
}
],
"artifacts": [
{
"name": "server",
"kind": "image",
"from": "Dockerfile"
},
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/nats-tools",
"binary": "nats-tools",
"loads": [
"nats-tools"
],
"env": {
"MESH_NATS_MONITOR": "http://127.0.0.1:8222",
"MESH_NATS_CONTAINER": "mesh-broker-nats",
"MESH_NATS_USERS_FILE": "/etc/nats/accounts.conf"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,57 @@
{
"module": "netcheck",
"version": "1",
"emits": [
"tunnel.endpoint-changed",
"tunnel.handshake-stale",
"tunnel.handshake-fresh"
],
"tools": [
"netcheck_tunnel",
"netcheck_tcp",
"netcheck_dns",
"netcheck_http",
"netcheck_listening"
],
"replaces": {
"netcheck_listening": [
"ss -lunt",
"ss -ltn",
"netstat -lnt"
],
"netcheck_dns": [
"dig",
"nslookup"
],
"netcheck_tunnel": [
"wg show",
"wg show mesh0 dump"
]
},
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/netcheck",
"binary": "netcheck",
"loads": [
"netcheck"
]
},
{
"name": "tools-typescript",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
],
"loads": [
"tools/index.js"
]
}
]
}
}
@@ -0,0 +1,71 @@
{
"module": "networkmanager",
"version": "1",
"upgrade": {
"policy": "record",
"why": "the machine's network: a build that breaks it can cut the machine off from the bus, and then neither the gate's rollback nor a push reaches it (hq ADR 0236)"
},
"slug": "nm",
"requires": [
"wildcard-resolution"
],
"capabilities": [
"package-manager",
"service-manager",
"uplink-networkmanager"
],
"claims": [
{
"name": "node-uplink",
"scope": "node"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/uplink-tools",
"binary": "uplink-tools",
"loads": [
"uplink-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
},
"facts": {
"resolvers": {
"path": "/etc/resolv.conf",
"template": "# Managed by the mesh, and written by the module holding this machine's uplink:\n# the program that manages the machine's network would otherwise rewrite this\n# file on every change of network, so its holder is the one that writes it\n# (novox/hq ADR 0117, ADR 0223). Replaced on every push; edit nothing here.\n#\n# Every resolver of the mesh, by address, and nothing else (novox/hq ADR 0223) \u2014\n# this machine's own first when it holds one, then the others by name. Each\n# answers the mesh's names from the same roster and forwards every other name, so\n# whichever answers first gives the one answer. There is no public resolver here:\n# a C library that asks every listed server at once and takes the first reply \u2014\n# musl, so every Alpine container \u2014 took a public resolver's \"no such name\" for\n# a mesh name and failed. A machine that reaches none of these has no names until\n# it does. Containers copy these lines from their machine.\n{{range index .Holders \"mesh-dns-resolver\"}}nameserver {{.Address}}\n{{end}}options timeout:1 attempts:2 edns0\n"
}
},
"resources": [
{
"id": "package",
"type": "package",
"package": "networkmanager"
},
{
"id": "config",
"type": "file",
"path": "/etc/NetworkManager/conf.d/50-mesh.conf",
"mode": "0644",
"template": "files/50-mesh.conf"
},
{
"id": "service",
"type": "service",
"unit": "NetworkManager.service",
"reload-on": [
"config"
]
}
]
}
@@ -0,0 +1,38 @@
{
"module": "nextcloud-client",
"version": "1",
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"tools": [
"nextcloud_status",
"nextcloud_log",
"nextcloud_restart",
"nextcloud_check"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "nextcloud-client"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/nextcloud-client-tools",
"binary": "nextcloud-client-tools",
"loads": [
"nextcloud-client-tools"
]
}
]
}
}
@@ -0,0 +1,168 @@
{
"module": "nextcloud",
"version": "1",
"slug": "ncloud",
"requires": [
"postgres-database",
"s3-bucket",
"route"
],
"contributes": {
"postgres-database": {
"name": "nextcloud"
},
"route": {
"label": "drive",
"endpoint": "web"
}
},
"binds": {
"postgres-database": "${dir:state}/database.json",
"s3-bucket": "${dir:state}/store.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "${dir:state}/database.secret",
"s3-bucket": "${dir:state}/store.secret"
},
"emits": [
"user.created",
"share.created"
],
"own-secrets": {
"admin": "${dir:state}/admin.secret"
},
"capabilities": [
"container-runtime"
],
"listens": [
{
"name": "web",
"port": 80,
"protocol": "tcp",
"from": "mesh",
"why": "files and sync, over http; a public name is a route grant later"
}
],
"data": {
"own": [
{
"id": "html",
"path": "${dir:html}",
"class": "valuable",
"why": "the instance's configuration, its secret and installed apps; the files are in the object store"
}
]
},
"config": {
"container": {
"type": "string",
"description": "The name of the container the module's tools run Nextcloud's occ in; empty is nextcloud.",
"trusted": true,
"default": ""
},
"url": {
"type": "string",
"description": "The address the module's tools reach Nextcloud's sharing API at, as a URL; empty is this machine's Nextcloud on its port.",
"trusted": true,
"default": ""
},
"user": {
"type": "string",
"description": "The Nextcloud account the module's tools act as; empty is admin.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "html",
"type": "directory",
"mode": "0750",
"owner": "33:33",
"unknown": "program"
},
{
"id": "server",
"type": "container",
"health": {
"kind": "http",
"endpoint": "web",
"path": "/status.php",
"status": 200,
"body": "\"installed\":true",
"needs": "postgres-database"
},
"name": "nextcloud",
"image": "nextcloud@sha256:fb966733647ea03f0446b0c22eac9733c8eb616d37b960caca9d4c3010e14a08",
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"80"
],
"volumes": [
"${dir:html}:/var/www/html"
],
"secrets-in-environment": "the image honours POSTGRES_PASSWORD_FILE and NEXTCLOUD_ADMIN_PASSWORD_FILE (entrypoint file_env); OBJECTSTORE_S3_SECRET has none and needs a generated config fragment; convertible, awaiting a bed"
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json",
"takes-config": ["container", "url", "user"],
"merge": "json"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"MESH_NEXTCLOUD_URL": "http://127.0.0.1:${port:80}",
"MESH_NEXTCLOUD_CONFIG_FILE": "${dir:mesh-state}/config.json",
"MESH_NEXTCLOUD_ADMIN_USER": "mesh-admin",
"MESH_NEXTCLOUD_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,191 @@
{
"module": "nfs-server",
"version": "1",
"upgrade": {
"policy": "record",
"why": "the folders other machines mount: a build that breaks the exports leaves every client's mount hanging or refused, and the gate on this one machine does not see the clients (hq ADR 0236, ADR 0263)"
},
"capabilities": [
"package-manager",
"service-manager"
],
"provides": [
{
"name": "nfs-share",
"scope": "mesh",
"identity": false
}
],
"data": {
"consumers": {
"nfs-share": {
"class": "none",
"why": "the shared folders are the operator's data (hq ADR 0051): what a client writes lands in them, and they are protected where the operator declares them, never by this module, which keeps nothing of a consumer's"
}
}
},
"claims": [
{
"name": "node-nfs-server",
"scope": "node",
"serves": [
"exports",
"clients",
"test",
"reload",
"adopt"
]
}
],
"state": [
{
"name": "exports",
"ttl-seconds": 120,
"per-machine": true
}
],
"reads": [
"mounts.shares"
],
"invokes": [
"seat:mesh-controller.seats",
"seat:mesh-controller.data"
],
"config": {
"shares": {
"type": "string",
"description": "The folders this machine exports, as space-separated name=path; the operator's, with no default (novox/hq ADR 0263).",
"trusted": true,
"required": true
},
"grants": {
"type": "string",
"description": "Which nodes may mount which share, and how: share=node:rw|ro[,node:rw|ro], entries separated by spaces, or none to export to no node whatever a node wants (novox/hq ADR 0263).",
"trusted": true,
"default": "none"
}
},
"facts": {
"machines": {
"path": "/etc/nfs-server/machines",
"template": "# Written by the mesh (module nfs-server, novox/hq ADR 0263): every machine of the mesh and its private\n# address, from which the module takes a node's address. Replaced on every push.\n{{range .Machines}}{{.Name}} {{.Address}}\n{{end}}"
}
},
"tools": [
"nfs_health"
],
"listens": [
{
"name": "nfs",
"port": 2049,
"protocol": "tcp",
"from": "mesh",
"fixed": true,
"why": "the shares, to the mesh's machines only (hq ADR 0263): NFS version 4 alone, which needs no other port, and never the home network, where a device that is not a node could claim any user id"
}
],
"resources": [
{
"id": "package",
"type": "package",
"package": "nfs-utils"
},
{
"id": "nfs-conf",
"type": "file",
"path": "/etc/nfs.conf.d/50-mesh.conf",
"mode": "0644",
"template": "files/50-mesh.conf"
},
{
"id": "run-dir",
"type": "directory",
"path": "/run/nfs-server",
"mode": "0755",
"unknown": "program"
},
{
"id": "server",
"type": "service",
"unit": "nfs-server.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"nfs-conf"
],
"health": {
"kind": "unit"
}
},
{
"id": "wants-dir-parent",
"type": "directory",
"path": "/var/lib/nfs-server",
"mode": "0755",
"unknown": "program"
},
{
"id": "wants-dir",
"type": "directory",
"path": "/var/lib/nfs-server/from-bus",
"mode": "0755",
"owner": "${machine:account}",
"unknown": "program"
},
{
"id": "exports",
"type": "process",
"name": "nfs-server-exports",
"artifact": "tools",
"run": [
"./nfs-server",
"exports"
],
"restart-on": [
"config"
],
"health": {
"kind": "tool",
"tool": "nfs_health",
"interval": "60s",
"timeout": "10s",
"looks": 2,
"grace": "90s"
}
},
{
"id": "config-dir",
"type": "directory",
"path": "/etc/nfs-server",
"mode": "0755",
"unknown": "program"
},
{
"id": "config",
"type": "file",
"path": "/etc/nfs-server/shares.conf",
"mode": "0644",
"template": "files/shares.conf"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/nfs-server",
"binary": "nfs-server",
"loads": [
"nfs-server"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,91 @@
{
"module": "nftables",
"version": "1",
"upgrade": {
"policy": "record",
"why": "the machine's packet filter: a build that breaks it can cut the machine off from the bus, and then neither the gate's rollback nor a push reaches it (hq ADR 0236)"
},
"capabilities": [
"firewall"
],
"claims": [
{
"name": "node-packet-filter",
"scope": "node",
"serves": [
"rules",
"reload",
"remove"
]
}
],
"filtering": {
"into": "/etc/nftables.conf"
},
"resources": [
{
"id": "package",
"type": "package",
"package": "nftables"
},
{
"id": "legacy-tools",
"type": "package",
"package": "iptables"
},
{
"id": "unit",
"type": "file",
"path": "/etc/systemd/system/mesh-filter.service",
"template": "files/mesh-filter.service",
"mode": "0644"
},
{
"id": "stock-unit-stop",
"type": "file",
"path": "/etc/systemd/system/nftables.service.d/mesh.conf",
"template": "files/mesh.conf",
"mode": "0644"
},
{
"id": "load",
"type": "service",
"unit": "mesh-filter.service",
"state": "running",
"boot": "enabled",
"restart-on": [
"unit",
"stock-unit-stop"
],
"reload-on": [
"filtering"
]
},
{
"id": "front-end",
"type": "package",
"package": "ufw",
"absent": true
}
],
"tools": [
"firewall_rules"
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,37 @@
{
"module": "nm-applet",
"version": "1",
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"tools": [
"nm_applet_status",
"nm_applet_restart",
"nm_applet_check"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "network-manager-applet"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/nm-applet-tools",
"binary": "nm-applet-tools",
"loads": [
"nm-applet-tools"
]
}
]
}
}
@@ -0,0 +1,55 @@
{
"module": "node-env",
"version": "1",
"moved": true,
"claims": [
{
"name": "node-environment",
"scope": "node"
}
],
"resources": [
{
"id": "mesh-config-dir",
"type": "directory",
"path": "${machine:account-home}/.config/mesh",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out",
"knows": ["forge.credentials"]
},
{
"id": "environment-d",
"type": "directory",
"path": "${machine:account-home}/.config/environment.d",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out"
},
{
"id": "posix",
"type": "file",
"path": "${machine:account-home}/.config/mesh/environment.sh",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/environment.sh"
},
{
"id": "systemd",
"type": "file",
"path": "${machine:account-home}/.config/environment.d/50-mesh.conf",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/50-mesh.conf"
}
],
"build": {
"artifacts": [
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,297 @@
{
"module": "nodered",
"version": "1",
"emits": [
"flows.deployed"
],
"own-secrets": {
"admin": {
"path": "${dir:mesh-state}/admin",
"taken": "at-start"
},
"api-token": {
"path": "${dir:mesh-state}/api-token",
"taken": "at-start"
}
},
"capabilities": [
"container-runtime"
],
"listens": [
{
"name": "web",
"port": 1880,
"protocol": "tcp",
"from": "mesh",
"why": "the flow editor and the endpoints flows expose"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "valuable",
"why": "flows and their credentials"
}
]
},
"config": {
"flow-file": {
"type": "string",
"description": "Node-RED's flowFile setting: the file in the user directory the flows are kept in.",
"trusted": true,
"default": "flows.json"
},
"flow-file-pretty": {
"type": "boolean",
"description": "Node-RED's flowFilePretty setting: whether the flows file is written indented.",
"trusted": true,
"default": true
},
"diagnostics": {
"type": "object",
"description": "Node-RED's diagnostics setting: whether its diagnostics report is on, and shown in the editor.",
"trusted": true,
"default": {
"enabled": true,
"ui": true
}
},
"runtime-state": {
"type": "object",
"description": "Node-RED's runtimeState setting: whether flows may be started and stopped from the editor.",
"trusted": true,
"default": {
"enabled": false,
"ui": false
}
},
"logging": {
"type": "object",
"description": "Node-RED's logging setting: the console log's level, and whether metrics and audit events are logged.",
"trusted": true,
"default": {
"console": {
"level": "info",
"metrics": false,
"audit": false
}
}
},
"export-global-context-keys": {
"type": "boolean",
"description": "Node-RED's exportGlobalContextKeys setting: whether a function node may list the global context's keys.",
"trusted": true,
"default": false
},
"external-modules": {
"type": "object",
"description": "Node-RED's externalModules setting: which modules the editor may install, and from where.",
"trusted": true,
"default": {}
},
"editor-theme": {
"type": "object",
"description": "Node-RED's editorTheme setting: the editor's look and features, projects among them.",
"trusted": true,
"default": {
"projects": {
"enabled": false
}
}
},
"function-external-modules": {
"type": "boolean",
"description": "Node-RED's functionExternalModules setting: whether a function node may load modules of its own.",
"trusted": true,
"default": true
},
"debug-max-length": {
"type": "number",
"description": "Node-RED's debugMaxLength setting: the most characters a debug message shows, a count.",
"trusted": true,
"default": 1000
},
"mqtt-reconnect-time": {
"type": "number",
"description": "Node-RED's mqttReconnectTime setting: how long an MQTT node waits before reconnecting, in milliseconds.",
"trusted": true,
"default": 15000
},
"serial-reconnect-time": {
"type": "number",
"description": "Node-RED's serialReconnectTime setting: how long a serial node waits before reconnecting, in milliseconds.",
"trusted": true,
"default": 15000
},
"mqtt": {
"type": "object",
"description": "The broker nodes the module's MQTT step keeps pointed at the mesh's broker, as {\"brokers\": [their ids]}; empty, none.",
"trusted": true,
"default": {}
},
"time-zone": {
"type": "string",
"description": "The time zone the flows schedule and format in, an IANA name such as Europe/Brussels; unset, the container's UTC.",
"trusted": true,
"default": ""
}
},
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh",
"unknown": "program"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"owner": "1000:1000",
"unknown": "program"
},
{
"id": "written",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "settings-code",
"type": "file",
"path": "${dir:state}/settings.js",
"mode": "0600",
"owner": "1000:1000",
"template": "files/settings.js"
},
{
"id": "settings",
"type": "file",
"path": "${dir:state}/settings.json",
"mode": "0600",
"owner": "1000:1000",
"merge": "json",
"takes-config": [{"key": "flow-file", "as": "flowFile"}, {"key": "flow-file-pretty", "as": "flowFilePretty"}, "diagnostics", {"key": "runtime-state", "as": "runtimeState"}, "logging", {"key": "export-global-context-keys", "as": "exportGlobalContextKeys"}, {"key": "external-modules", "as": "externalModules"}, {"key": "editor-theme", "as": "editorTheme"}, {"key": "function-external-modules", "as": "functionExternalModules"}, {"key": "debug-max-length", "as": "debugMaxLength"}, {"key": "mqtt-reconnect-time", "as": "mqttReconnectTime"}, {"key": "serial-reconnect-time", "as": "serialReconnectTime"}, "mqtt", {"key": "time-zone", "as": "timeZone"}],
"template": "files/settings.json"
},
{
"id": "server",
"type": "container",
"name": "nodered",
"image": "nodered/node-red@sha256:a649dd711d55490151a2c39a8e48ad0c44325488fbc0e66315f2d2e19e5e1ace",
"health": {
"kind": "runtime"
},
"env": {
"TZ": "Etc/UTC"
},
"ports": [
"1880"
],
"args": [
"--settings",
"/data/settings.js"
],
"volumes": [
"${dir:data}:/data",
"${dir:state}/settings.js:/data/settings.js:ro",
"${dir:state}/settings.json:/data/settings.json:ro"
],
"restart-on": [
"settings-code",
"settings"
]
},
{
"id": "runtime-config",
"type": "file",
"path": "${dir:mesh-state}/config.json",
"mode": "0600",
"template": "files/config.json"
},
{
"id": "mqtt-env",
"type": "file",
"path": "${dir:state}/mqtt.env",
"mode": "0600",
"template": "files/mqtt.env"
},
{
"id": "mqtt",
"type": "process",
"name": "nodered-mqtt",
"artifact": "code",
"run": [
"node",
"mqtt/index.js"
],
"run-once": true,
"env-file": [
"${dir:state}/mqtt.env"
],
"restart-on": [
"mqtt-env",
"bound-mqtt-topic",
"secret-mqtt-topic",
"settings"
]
}
],
"requires": [
"mqtt-topic",
"route"
],
"contributes": {
"mqtt-topic": {
"topics": [
"#"
]
},
"route": {
"label": "nodered",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json",
"mqtt-topic": "${dir:state}/mqtt-topic.json"
},
"secrets": {
"mqtt-topic": "${dir:state}/mqtt-topic.secret"
},
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"tools/index.js",
"mqtt/index.js"
],
"loads": [
"tools/index.js"
],
"env": {
"MESH_NODERED_URL": "http://127.0.0.1:${port:1880}",
"MESH_NODERED_CONFIG_FILE": "${dir:mesh-state}/config.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,62 @@
{
"module": "ollama",
"version": "1",
"capabilities": [
"container-runtime"
],
"provides": [
{
"name": "model-access",
"scope": "node"
}
],
"listens": [
{
"name": "api",
"port": 11434,
"protocol": "tcp",
"from": "machine",
"why": "consumers on this machine reaching the local model server's OpenAI-compatible API"
}
],
"serves": {
"model-access": {
"port": 11434,
"model": "llama3.2"
}
},
"data": {
"own": [
{
"id": "models",
"path": "${dir:state}",
"class": "rebuildable",
"backup": "none",
"measure": "shallow",
"why": "models, downloaded again, and too large to copy every night"
}
]
},
"resources": [
{
"id": "state",
"type": "directory",
"path": "/services/ollama",
"mode": "0700",
"unknown": "program"
},
{
"id": "server",
"type": "container",
"name": "ollama",
"image": "ollama/ollama@sha256:32931b46719f673c05fdbaa81ccb26da18ea4a1c57590a754874ab28ba269eb2",
"network": "host",
"env": {
"OLLAMA_HOST": "0.0.0.0:11434"
},
"volumes": [
"/services/ollama:/root/.ollama"
]
}
]
}
@@ -0,0 +1,173 @@
{
"module": "only-office",
"version": "1",
"slug": "office",
"capabilities": [
"container-runtime"
],
"requires": [
"route"
],
"contributes": {
"route": {
"label": "office",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json"
},
"own-secrets": {
"jwt": "${dir:state}/jwt.secret"
},
"listens": [
{
"name": "web",
"port": 9070,
"protocol": "tcp",
"from": "mesh",
"why": "the document server over http; its public name is a route grant, and route-proxy reaches it on this published port"
}
],
"data": {
"own": [
{
"id": "data",
"path": "${dir:data}",
"class": "rebuildable",
"why": "documents being edited; the documents themselves are the file store's"
},
{
"id": "lib",
"path": "${dir:lib}",
"class": "rebuildable",
"why": "the document server's working files"
},
{
"id": "db",
"path": "${dir:db}",
"class": "rebuildable",
"why": "the document server's own database of editing sessions"
},
{
"id": "fonts",
"path": "${dir:fonts}",
"class": "rebuildable",
"why": "fonts, installed again"
},
{
"id": "logs",
"path": "${dir:logs}",
"class": "cache",
"why": "logs"
},
{
"id": "rabbitmq",
"path": "${dir:rabbitmq}",
"class": "cache",
"why": "its queue's working set"
},
{
"id": "redis",
"path": "${dir:redis}",
"class": "cache",
"why": "its cache"
}
]
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "server-env",
"type": "file",
"path": "${dir:state}/server.env",
"mode": "0600",
"template": "files/server.env"
},
{
"id": "logs",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "data",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "lib",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "db",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "rabbitmq",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "redis",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "fonts",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "only-office"
},
{
"id": "server",
"type": "container",
"name": "only-office",
"image": "onlyoffice/documentserver@sha256:3ab6ebc7c605e5a32b7ae3ff19daed4925090245acc8100ce2230bd766c88212",
"network": "only-office",
"env-file": [
"${dir:state}/server.env"
],
"ports": [
"9070:80"
],
"volumes": [
"${dir:logs}:/var/log/onlyoffice",
"${dir:data}:/var/www/onlyoffice/Data",
"${dir:lib}:/var/lib/onlyoffice",
"${dir:db}:/var/lib/postgresql",
"${dir:rabbitmq}:/var/lib/rabbitmq",
"${dir:redis}:/var/lib/redis",
"${dir:fonts}:/usr/share/fonts/truetype/custom"
],
"secrets-in-environment": "run-document-server.sh regenerates JWT_SECRET from the environment on every start and overwrites local.json; not convertible"
}
],
"build": {
"artifacts": [
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,61 @@
{
"module": "openai-consumer",
"version": "1",
"slug": "openai",
"capabilities": [
"container-runtime"
],
"requires": [
"model-access"
],
"binds": {
"model-access": "${dir:state}/model.json"
},
"secrets": {
"model-access": "${dir:state}/api-key"
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "config",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "apply",
"type": "process",
"name": "openai-consumer-apply",
"artifact": "code",
"run": [
"node",
"apply/index.js"
],
"schedule": "*/5 * * * *",
"env": {
"MESH_MODEL_ACCESS_SECRET_FILE": "${dir:state}/api-key",
"MESH_MODEL_ACCESS_BIND_FILE": "${dir:state}/model.json",
"MESH_OPENAI_ENV_FILE": "${dir:state}/config/openai.env",
"MESH_OPENAI_CREDENTIALS_FILE": "${dir:state}/config/auth.json"
}
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"apply/index.js"
]
}
]
}
}
@@ -0,0 +1,52 @@
{
"module": "openrazer",
"version": "1",
"capabilities": [
"package-manager"
],
"tools": [
"openrazer_status",
"openrazer_restart",
"openrazer_check"
],
"resources": [
{
"id": "driver",
"type": "package",
"package": "openrazer-driver-dkms"
},
{
"id": "daemon",
"type": "package",
"package": "openrazer-daemon"
},
{
"id": "library",
"type": "package",
"package": "python-openrazer"
},
{
"id": "account",
"type": "user",
"name": "${machine:account}",
"groups": [
"openrazer"
]
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/openrazer-tools",
"binary": "openrazer-tools",
"loads": [
"openrazer-tools"
]
}
]
}
}
@@ -0,0 +1,96 @@
{
"module": "pacman",
"version": "1",
"capabilities": [
"package-manager",
"service-manager"
],
"claims": [
{
"name": "node-package-manager",
"scope": "node"
}
],
"tools": [
"pacman_search",
"pacman_info",
"pacman_installed",
"pacman_owns",
"pacman_files",
"pacman_updates",
"pacman_upgrade",
"pacman_orphans",
"pacman_remove_orphans",
"pacman_cache",
"pacman_history",
"pacman_mirrors",
"pacman_foreign",
"pacman_news",
"pacman_config"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "pacman"
},
{
"id": "config",
"type": "file",
"path": "/etc/pacman.conf",
"mode": "0644",
"template": "files/pacman.conf"
},
{
"id": "contrib",
"type": "package",
"package": "pacman-contrib"
},
{
"id": "reflector",
"type": "package",
"package": "reflector"
},
{
"id": "mirrors",
"type": "file",
"path": "/etc/xdg/reflector/reflector.conf",
"mode": "0644",
"template": "files/reflector.conf"
},
{
"id": "mirror-refresh",
"type": "service",
"unit": "reflector.timer",
"state": "running",
"boot": "enabled"
},
{
"id": "cache-cleaning",
"type": "service",
"unit": "paccache.timer",
"state": "running",
"boot": "enabled"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/pacman-tools",
"binary": "pacman-tools",
"loads": [
"pacman-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,56 @@
{
"module": "photos-eef",
"version": "1",
"slug": "eef",
"capabilities": [
"container-runtime"
],
"requires": [
"route"
],
"contributes": {
"route": {
"label": "eef",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json"
},
"listens": [
{
"name": "web",
"port": 4012,
"protocol": "tcp",
"from": "mesh",
"why": "the eef photos client site over http; its public name is a route grant, and route-proxy reaches it on this published port"
}
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "photos-eef"
},
{
"id": "client",
"type": "container",
"name": "photos-eef",
"image": "registry-api.novox.be/novox/photos-client@sha256:f87d63ee7bfb44c9f9748b99be6ba6dc0daf955a1d463699e9e7e3009693c0ab",
"network": "photos-eef",
"ports": [
"4012:80"
],
"names-on-purpose": {
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
}
}
]
}
@@ -0,0 +1,56 @@
{
"module": "photos-filip",
"version": "1",
"slug": "filip",
"capabilities": [
"container-runtime"
],
"requires": [
"route"
],
"contributes": {
"route": {
"label": "filip",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json"
},
"listens": [
{
"name": "web",
"port": 4013,
"protocol": "tcp",
"from": "mesh",
"why": "the filip photos client site over http; its public name is a route grant, and route-proxy reaches it on this published port"
}
],
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "net",
"type": "network",
"name": "photos-filip"
},
{
"id": "client",
"type": "container",
"name": "photos-filip",
"image": "registry-api.novox.be/novox/photos-client@sha256:f87d63ee7bfb44c9f9748b99be6ba6dc0daf955a1d463699e9e7e3009693c0ab",
"network": "photos-filip",
"ports": [
"4013:80"
],
"names-on-purpose": {
"registry-api.novox.be": "built outside the mesh, from the application's own repository, and pulled from the registry that built it; moves when that repository is a build source on the git seat (novox/hq ADR 0155, issue 122)"
}
}
]
}
@@ -0,0 +1,90 @@
{
"module": "picom",
"version": "1",
"capabilities": [
"package-manager"
],
"requires": [
"x11-display"
],
"claims": [
{
"name": "node-compositor",
"scope": "node"
}
],
"config": {
"backend": {
"type": "string",
"description": "How picom draws: glx with the graphics card, which has served every machine so far, or xrender on the CPU where glx leaves a window unpainted or stale on the machine's driver (novox/hq research 037, issue 345); xr_glx_hybrid and egl are picom's other backends.",
"enum": [
"glx",
"xrender",
"xr_glx_hybrid",
"egl"
],
"trusted": true,
"default": "glx"
},
"use-damage": {
"type": "boolean",
"description": "Whether picom repaints only what changed (true, picom's own default) or the whole screen each frame (false), which costs work and cures a window left stale or unpainted on some drivers (novox/hq issue 345).",
"trusted": true,
"default": true
}
},
"tools": [
"picom_restart",
"picom_rules",
"picom_window_opacity",
"picom_toggle"
],
"resources": [
{
"id": "package",
"type": "package",
"package": "picom"
},
{
"id": "window-properties",
"type": "package",
"package": "xorg-xprop"
},
{
"id": "configuration-dir",
"type": "directory",
"path": "${machine:account-home}/.config/picom",
"owner": "${machine:account}",
"mode": "0755",
"unknown": "move-out"
},
{
"id": "configuration",
"type": "file",
"path": "${machine:account-home}/.config/picom/picom.conf",
"owner": "${machine:account}",
"mode": "0644",
"template": "files/picom.conf"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/picom-tools",
"binary": "picom-tools",
"loads": [
"picom-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,40 @@
{
"module": "polychromatic",
"version": "1",
"moved": true,
"requires": [
"x11-display"
],
"tools": [
"polychromatic_status",
"polychromatic_restart",
"polychromatic_check"
],
"items": [
{
"collection": "contribution:node-display-session:config",
"name": "display-session",
"template": "files/display-session"
}
],
"build": {
"artifacts": [
{
"name": "tools",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/polychromatic-tools",
"binary": "polychromatic-tools",
"loads": [
"polychromatic-tools"
]
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}
@@ -0,0 +1,191 @@
{
"module": "postgres",
"version": "1",
"moved": true,
"upgrade": {
"policy": "record",
"why": "a provider whose restart drops every consumer on its machine, and whose new major version changes its data's format: a person takes each build, after a backup (hq ADR 0236)"
},
"provides": [
{
"name": "postgres-database",
"scope": "mesh",
"identity": {
"max": 63,
"in": "a PostgreSQL role and database name"
}
}
],
"claims": [
{
"name": "mesh-store",
"scope": "mesh",
"serves": [
"databases",
"query"
]
}
],
"capabilities": [
"container-runtime"
],
"emits": [
"database.provisioned",
"database.deprovisioned"
],
"consumes": [
"postgres.database.provisioned",
"postgres.database.deprovisioned"
],
"listens": [
{
"name": "database",
"port": 5432,
"protocol": "tcp",
"from": "mesh",
"why": "modules on any machine that were granted a database"
}
],
"guards": [
5432
],
"serves": {
"postgres-database": {
"port": 5432
}
},
"receives": {
"postgres-database": "${dir:grants}/mesh.json"
},
"grants": {
"postgres-database": "${dir:grants}"
},
"own-secrets": {
"superuser": "${dir:state}/superuser.secret",
"reader": "${dir:state}/reader.secret"
},
"data": {
"own": [
{
"id": "store",
"path": "${dir:store-data}",
"class": "valuable",
"backup": {
"dump": "docker exec -u postgres postgres sh -c 'cd /var/lib/postgresql/data/dumps && for db in $(psql -Atc \"select datname from pg_database where oid >= 16384 order by 1\"); do pg_dump -Fc -f \"$db.dump.partial\" \"$db\" && mv \"$db.dump.partial\" \"$db.dump\" || exit 1; done'",
"into": "dumps"
},
"why": "every consumer's database; copied by the dump below, since a running store's files are not a consistent copy"
},
{
"id": "dumps",
"path": "${dir:dumps}",
"class": "rebuildable",
"why": "last night's dump of the store, made again every night"
}
],
"consumers": {
"postgres-database": {
"class": "valuable",
"in": "store",
"why": "a consumer's rows are the only copy of what it wrote"
}
}
},
"resources": [
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": ".",
"unknown": "program"
},
{
"id": "grants",
"type": "directory",
"mode": "0700",
"unknown": "program"
},
{
"id": "consumers",
"type": "file",
"path": "${dir:state}/consumers.json",
"mode": "0600",
"template": "files/consumers.json"
},
{
"id": "store-data",
"type": "directory",
"path": "/var/lib/mesh-store",
"mode": "0700",
"owner": "999:70",
"unknown": "program"
},
{
"id": "dumps",
"type": "directory",
"path": "${dir:store-data}/dumps",
"mode": "0700",
"owner": "999:70",
"unknown": "program"
},
{
"id": "server",
"type": "container",
"name": "postgres",
"image": "pgvector/pgvector@sha256:cf134a767f474095eeba57e0117be8e568e011a63f33fbf252f14c9b760f8e6f",
"health": {
"kind": "tcp",
"endpoint": "database"
},
"env": {
"POSTGRES_PASSWORD_FILE": "/run/secrets/superuser",
"PGDATA": "/var/lib/postgresql/data/pgdata"
},
"ports": [
"5432:5432"
],
"volumes": [
"/var/lib/mesh-store:/var/lib/postgresql/data",
"${dir:state}/superuser.secret:/run/secrets/superuser:ro"
]
},
{
"id": "client",
"type": "package",
"package": "postgresql-libs"
}
],
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/postgres-provider",
"binary": "postgres-provider",
"loads": [
"postgres-provider"
],
"env": {
"MESH_PROVISION_POSTGRES": "postgres://postgres@127.0.0.1:${port:5432}/postgres?sslmode=disable",
"MESH_PROVISION_PASSWORD_FILE": "${dir:state}/superuser.secret",
"MESH_RECEIVES": "${dir:grants}/mesh.json",
"MESH_POSTGRES_READER_PASSWORD_FILE": "${dir:state}/reader.secret",
"MESH_CONSUMERS_FILE": "${dir:state}/consumers.json"
}
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
},
"state": [
"bound"
],
"reads": [
"mesh-controller.assignments"
]
}
@@ -0,0 +1,408 @@
{
"module": "power",
"version": "1",
"moved": true,
"templates": "templates",
"capabilities": [
"package-manager",
"service-manager"
],
"claims": [
{
"name": "node-power",
"scope": "node"
}
],
"emits": [
"booted",
"sleeping",
"woke",
"shutting-down",
"on-mains",
"on-battery",
"battery-low"
],
"state": [
{
"name": "draw",
"ttl-seconds": 30,
"per-machine": true
}
],
"tools": [
"power_state",
"power_hooks",
"power_history",
"power_run",
"power_check"
],
"config": {
"handle-power-key": {
"type": "string",
"description": "What logind does when the power key is pressed: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
"enum": [
"ignore",
"poweroff",
"reboot",
"halt",
"kexec",
"suspend",
"hibernate",
"hybrid-sleep",
"suspend-then-hibernate",
"lock",
"factory-reset",
"sleep"
],
"trusted": true,
"required": true
},
"handle-lid-switch": {
"type": "string",
"description": "What logind does when the lid is closed on battery: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
"enum": [
"ignore",
"poweroff",
"reboot",
"halt",
"kexec",
"suspend",
"hibernate",
"hybrid-sleep",
"suspend-then-hibernate",
"lock",
"factory-reset",
"sleep"
],
"trusted": true,
"required": true
},
"handle-lid-switch-external-power": {
"type": "string",
"description": "What logind does when the lid is closed on external power: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
"enum": [
"ignore",
"poweroff",
"reboot",
"halt",
"kexec",
"suspend",
"hibernate",
"hybrid-sleep",
"suspend-then-hibernate",
"lock",
"factory-reset",
"sleep"
],
"trusted": true,
"required": true
},
"handle-lid-switch-docked": {
"type": "string",
"description": "What logind does when the lid is closed while docked or with another screen attached: one of logind's actions, such as suspend, ignore or poweroff (logind.conf(5)); the operator's choice for this machine, with no default.",
"enum": [
"ignore",
"poweroff",
"reboot",
"halt",
"kexec",
"suspend",
"hibernate",
"hybrid-sleep",
"suspend-then-hibernate",
"lock",
"factory-reset",
"sleep"
],
"trusted": true,
"required": true
}
},
"resources": [
{
"id": "polkit",
"type": "package",
"package": "polkit"
},
{
"id": "scripts",
"type": "archive",
"path": "/usr/local/lib/mesh-power",
"artifact": "scripts",
"unknown": "program"
},
{
"id": "config-dir",
"type": "directory",
"path": "/etc/mesh-power",
"mode": "0755",
"unknown": "program"
},
{
"id": "moments-dir",
"type": "directory",
"path": "/etc/mesh-power/moments",
"mode": "0755",
"unknown": "program"
},
{
"id": "moment-after-boot",
"type": "file",
"path": "/etc/mesh-power/moments/after-boot",
"mode": "0644",
"template": "templates/mesh-power/moments/after-boot"
},
{
"id": "moment-before-sleep",
"type": "file",
"path": "/etc/mesh-power/moments/before-sleep",
"mode": "0644",
"template": "templates/mesh-power/moments/before-sleep"
},
{
"id": "moment-after-wake",
"type": "file",
"path": "/etc/mesh-power/moments/after-wake",
"mode": "0644",
"template": "templates/mesh-power/moments/after-wake"
},
{
"id": "moment-before-shutdown",
"type": "file",
"path": "/etc/mesh-power/moments/before-shutdown",
"mode": "0644",
"template": "templates/mesh-power/moments/before-shutdown"
},
{
"id": "moment-on-mains",
"type": "file",
"path": "/etc/mesh-power/moments/on-mains",
"mode": "0644",
"template": "templates/mesh-power/moments/on-mains"
},
{
"id": "moment-on-battery",
"type": "file",
"path": "/etc/mesh-power/moments/on-battery",
"mode": "0644",
"template": "templates/mesh-power/moments/on-battery"
},
{
"id": "logind-drop-ins",
"type": "directory",
"path": "/etc/systemd/logind.conf.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "logind-power",
"type": "file",
"path": "/etc/systemd/logind.conf.d/power.conf",
"mode": "0644",
"template": "templates/systemd/logind.conf.d/power.conf"
},
{
"id": "logind",
"type": "service",
"unit": "systemd-logind.service",
"reload-on": [
"logind-power"
]
},
{
"id": "after-boot-unit",
"type": "file",
"path": "/etc/systemd/system/mesh-power-after-boot.service",
"mode": "0644",
"template": "templates/systemd/system/mesh-power-after-boot.service"
},
{
"id": "before-shutdown-unit",
"type": "file",
"path": "/etc/systemd/system/mesh-power-before-shutdown.service",
"mode": "0644",
"template": "templates/systemd/system/mesh-power-before-shutdown.service"
},
{
"id": "before-sleep-unit",
"type": "file",
"path": "/etc/systemd/system/mesh-power-before-sleep.service",
"mode": "0644",
"template": "templates/systemd/system/mesh-power-before-sleep.service"
},
{
"id": "after-wake-unit",
"type": "file",
"path": "/etc/systemd/system/mesh-power-after-wake.service",
"mode": "0644",
"template": "templates/systemd/system/mesh-power-after-wake.service"
},
{
"id": "supply-unit",
"type": "file",
"path": "/etc/systemd/system/mesh-power-supply.service",
"mode": "0644",
"template": "templates/systemd/system/mesh-power-supply.service"
},
{
"id": "sleep-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/sleep.target.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "sleep-wants",
"type": "file",
"path": "/etc/systemd/system/sleep.target.d/mesh-power.conf",
"mode": "0644",
"template": "templates/systemd/system/sleep.target.d/mesh-power.conf"
},
{
"id": "suspend-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/suspend.target.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "suspend-wants",
"type": "file",
"path": "/etc/systemd/system/suspend.target.d/mesh-power.conf",
"mode": "0644",
"template": "templates/systemd/system/suspend.target.d/mesh-power.conf"
},
{
"id": "hibernate-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/hibernate.target.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "hibernate-wants",
"type": "file",
"path": "/etc/systemd/system/hibernate.target.d/mesh-power.conf",
"mode": "0644",
"template": "templates/systemd/system/hibernate.target.d/mesh-power.conf"
},
{
"id": "hybrid-sleep-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/hybrid-sleep.target.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "hybrid-sleep-wants",
"type": "file",
"path": "/etc/systemd/system/hybrid-sleep.target.d/mesh-power.conf",
"mode": "0644",
"template": "templates/systemd/system/hybrid-sleep.target.d/mesh-power.conf"
},
{
"id": "suspend-then-hibernate-drop-ins",
"type": "directory",
"path": "/etc/systemd/system/suspend-then-hibernate.target.d",
"mode": "0755",
"unknown": "program"
},
{
"id": "suspend-then-hibernate-wants",
"type": "file",
"path": "/etc/systemd/system/suspend-then-hibernate.target.d/mesh-power.conf",
"mode": "0644",
"template": "templates/systemd/system/suspend-then-hibernate.target.d/mesh-power.conf"
},
{
"id": "udev-rule",
"type": "file",
"path": "/etc/udev/rules.d/90-mesh-power.rules",
"mode": "0644",
"template": "templates/udev/rules.d/90-mesh-power.rules"
},
{
"id": "after-boot",
"type": "service",
"unit": "mesh-power-after-boot.service",
"state": "running",
"boot": "enabled"
},
{
"id": "before-shutdown",
"type": "service",
"unit": "mesh-power-before-shutdown.service",
"state": "running",
"boot": "enabled"
},
{
"id": "draw-dir",
"type": "directory",
"path": "/run/mesh-power",
"mode": "0755",
"unknown": "program"
},
{
"id": "draw",
"type": "process",
"name": "mesh-power-draw",
"artifact": "tools-go",
"run": [
"./power",
"draw"
],
"health": {
"kind": "unit"
}
}
],
"build": {
"artifacts": [
{
"name": "tools-go",
"kind": "bundle",
"language": "go",
"system": "arch",
"from": "cmd/power",
"binary": "power",
"loads": [
"power"
]
},
{
"name": "scripts",
"kind": "archive",
"from": "files"
},
{
"name": "templates",
"kind": "archive",
"from": "templates"
}
]
},
"items": [
{
"collection": "contribution:node-bar:block",
"name": "battery",
"if-capability": "battery",
"attributes": {
"bar": "bottom",
"place": "status",
"order": "40"
},
"template": "templates/bar-battery"
},
{
"collection": "contribution:node-bar:block",
"name": "power-draw",
"if-capability": "power-meter",
"attributes": {
"bar": "bottom",
"place": "status",
"order": "45"
},
"template": "templates/bar-power-draw"
}
]
}
@@ -0,0 +1,49 @@
{
"module": "powerlevel10k",
"version": "1",
"moved": true,
"resources": [
{
"id": "theme",
"type": "archive",
"path": "${machine:account-home}/.local/share/powerlevel10k",
"owner": "${machine:account}",
"artifact": "theme",
"unknown": "move-out",
"knows": ["powerlevel9k.zsh-theme.zwc", "powerlevel10k.zsh-theme.zwc", "internal/p10k.zsh.zwc", "internal/icons.zsh.zwc", "internal/configure.zsh.zwc", "internal/worker.zsh.zwc", "internal/parser.zsh.zwc", "gitstatus/gitstatus.plugin.zsh.zwc", "gitstatus/install.zwc"]
},
{
"id": "configuration",
"type": "archive",
"path": "${machine:account-home}/.config/powerlevel10k",
"owner": "${machine:account}",
"artifact": "configuration",
"unknown": "move-out"
}
],
"items": [
{
"collection": "shell:zsh:normal",
"template": "files/zsh-normal"
}
],
"build": {
"artifacts": [
{
"name": "theme",
"kind": "archive",
"from": "theme"
},
{
"name": "configuration",
"kind": "archive",
"from": "config"
},
{
"name": "files",
"kind": "archive",
"from": "files"
}
]
}
}

Some files were not shown because too many files have changed in this diff Show More