From f4fc5b3be8f7fd524b9c40ec71eb863f55247771 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 3 Sep 2026 22:53:07 +0200 Subject: [PATCH] =?UTF-8?q?umami:=20the=20reference=20module=20=E2=80=94?= =?UTF-8?q?=20a=20provider=20as=20well=20as=20a=20consumer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit umami was only half a module: it required postgres but did not provide what it exists to offer. It now provides the mesh 'analytics' interface (ADR 0045) — a webapp requires analytics and umami's provisioner creates its site and returns the grant — mirroring the postgres provider pattern (serves/receives/grants + a provisioner container that adapts umami's API to the mesh contract). Also: split the listen (one port, two surfaces — the mesh-gated dashboard and the public collection endpoint browsers POST to, hence from:anywhere), and an admin own-secret for the provisioner to drive umami's API. Parses against internal/catalogue. Still to build: the provisioner image (mesh-provision-umami-analytics — the adapter, real code like postgres-provisioner; placeholder digest for now) and umami's tools/client in the module (ADR 0044), which need the sdk harness. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF --- modules/umami/module.json | 70 ++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/modules/umami/module.json b/modules/umami/module.json index aa341e7..b4b5d19 100644 --- a/modules/umami/module.json +++ b/modules/umami/module.json @@ -1,6 +1,10 @@ { "module": "umami", "version": "1", + "capabilities": [ + "container-runtime" + ], + "requires": [ "postgres-database" ], @@ -15,20 +19,37 @@ "secrets": { "postgres-database": "/var/lib/umami/database.secret" }, - "own-secrets": { - "app-secret": "/var/lib/umami/app.secret" - }, - "capabilities": [ - "container-runtime" + + "provides": [ + { + "name": "analytics", + "scope": "mesh" + } ], + "serves": { + "analytics": {} + }, + "receives": { + "analytics": "/var/lib/umami/grants/mesh.json" + }, + "grants": { + "analytics": "/var/lib/umami/grants" + }, + + "own-secrets": { + "app-secret": "/var/lib/umami/app.secret", + "admin": "/var/lib/umami/admin.secret" + }, + "listens": [ { "port": 3000, "protocol": "tcp", - "from": "mesh", - "why": "the analytics pages and the collection endpoint" + "from": "anywhere", + "why": "one port serves two surfaces: the dashboard (the proxy gates it to the mesh) and the public collection endpoint that the browsers of every tracked site POST to — so the port itself must be reachable from anywhere" } ], + "resources": [ { "id": "state", @@ -36,24 +57,57 @@ "path": "/var/lib/umami", "mode": "0700" }, + { + "id": "grants", + "type": "directory", + "path": "/var/lib/umami/grants", + "mode": "0700" + }, { "id": "server-env", "type": "file", "path": "/var/lib/umami/server.env", "mode": "0600", - "content": "DATABASE_URL=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/umami\nAPP_SECRET=${secret:app-secret}\n" + "content": "DATABASE_URL=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/umami\nDATABASE_TYPE=postgresql\nAPP_SECRET=${secret:app-secret}\n" + }, + { + "id": "provisioner-env", + "type": "file", + "path": "/var/lib/umami/provisioner.env", + "mode": "0600", + "content": "MESH_PROVISION_UMAMI_URL=http://umami:3000\nGRANTS=/var/lib/umami/grants\n" + }, + { + "id": "net", + "type": "network", + "name": "umami" }, { "id": "server", "type": "container", "name": "umami", "image": "ghcr.io/umami-software/umami@sha256:fa32d116cf20cad52cbc3fad9a63b46e7fa02299d8f967168eb453d49c476b4a", + "network": "umami", "env-file": [ "/var/lib/umami/server.env" ], "ports": [ "3000" ] + }, + { + "id": "provisioner", + "type": "container", + "name": "mesh-provision-umami-analytics", + "image": "mesh-provision-umami-analytics@sha256:0000000000000000000000000000000000000000000000000000000000000000", + "network": "umami", + "env-file": [ + "/var/lib/umami/provisioner.env" + ], + "volumes": [ + "/var/lib/umami/grants:/var/lib/umami/grants", + "/var/lib/umami/admin.secret:/run/secrets/admin:ro" + ] } ] }