Files
mesh-catalog/modules/gitea/module.json
T
mesh-tools 652b00b25b
mesh/merge-gate checking again: the gate refused `unknown` because the controller judged with a node-engine validator pinned before mesh-host #117; mesh-co…
mesh/repo-check checking again: the gate refused `unknown` because the controller judged with a node-engine validator pinned before mesh-host #117; mesh-co…
mesh/delivery-group group feat/owned-paths checking: 0 of 2 member(s) ready
mesh/delivery superseded: a newer head of the same pull request
Say on every directory how it treats files it does not know, and check it (issue 1024, ADR 0422)
Every directory and archive resource carries `unknown`: move-out for a home folder whose program writes nothing there (the node-engine, delivered in mesh-host #117, moves the rest to ~/.local/state/mesh-moved/<module>/ with a list), module for ~/.ssh and ~/.claude, program elsewhere; `knows` keeps what a program or the operator relies on (powerlevel10k's compiled files, i3's scripts and the asus/g14 drop-ins, dunst's slack rule, betterbird's records, node-env's forge credential, issue 1033). Two shared folders are no longer declared. Each module's README says it. checks/owned holds every manifest to it; checks/sshdir stays while main's merge check runs it (issue 1035). Tests that pin a manifest follow the new key only. Reviewed in three rounds.
2026-10-17 16:23:03 +00:00

515 lines
14 KiB
JSON

{
"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": {}
},
"ready-authors": {
"type": "string",
"description": "the forge accounts whose comment \"ready at <full head sha>\" marks a pull request ready for mesh-delivery to merge, separated by spaces: the account the forge's tools act as (novox/hq ADR 0365), the admin account for marks made before the tools acted as their own, and the operator's (novox/hq issue 722). A comment by any other account is ignored and said in the forge's log. Trusted: who may have a change merged is the operator's word",
"trusted": true,
"default": "mesh-tools mesh-admin jschoubben"
}
},
"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": "ready-authors",
"type": "file",
"path": "${dir:mesh-state}/ready-authors",
"mode": "0600",
"trusted": true,
"template": "files/ready-authors"
},
{
"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": "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"
]
}
],
"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_READY_AUTHORS_FILE": "${dir:mesh-state}/ready-authors",
"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": "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"
]
}