From 1ea50aa6abde53b609ba3963d3c7593cf080faf2 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Tue, 6 Oct 2026 21:39:48 -0400 Subject: [PATCH] feat(matrix): appservice marc-agent pour un token E2EE sur @marc Stub HTTP + registration synapse + login unique. Registration sous /var/lib/matrix-marc-agent-as (StateDirectory) : sous /var/lib/hermes/.matrix (0700) synapse ne pouvait pas la lire, et ReadWritePaths sur un dossier absent faisait echouer l'unite en 226/NAMESPACE, ce qui bloquait le switch. --- services/default.nix | 1 + services/matrix-marc-agent/default.nix | 149 +++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 services/matrix-marc-agent/default.nix diff --git a/services/default.nix b/services/default.nix index 9754129..286dd9c 100644 --- a/services/default.nix +++ b/services/default.nix @@ -26,6 +26,7 @@ ./matrix-discord ./matrix-meta ./matrix-linkedin + ./matrix-marc-agent # ./matrix-telegram # attendre api_id/api_hash de my.telegram.org ./navidrome ./jellyfin diff --git a/services/matrix-marc-agent/default.nix b/services/matrix-marc-agent/default.nix new file mode 100644 index 0000000..bebda78 --- /dev/null +++ b/services/matrix-marc-agent/default.nix @@ -0,0 +1,149 @@ +# services/matrix-marc-agent/default.nix +# Appservice minimal pour que l'agent hermes obtienne, UNE SEULE FOIS, un token +# Matrix LIE A UN APPAREIL sur le compte de @marc. C'est le seul moyen de +# publier des cles E2EE et donc de lire/ecrire dans les salons chiffres +# (ponts WhatsApp/Signal/Discord/Instagram/Messenger/LinkedIn + DM chiffres). +# Contexte complet : skill hermes-matrix-access et +# /var/lib/hermes/workspace/matrix-marc/README.md (outil marcmsg qui consomme +# le token produit ici). +# +# Effet de bord assume (valide avec marc) : tant que cette registration est +# chargee par synapse, TOUS les evenements des salons ou @marc est membre sont +# pousses vers notre stub (namespace users non exclusif, large par construction). +# Le stub ne fait que repondre 200 a tout, sans rien dechiffrer ni journaliser : +# aucune charge utile n'est conservee ici. +{pkgs, ...}: let + # Registration hors de /var/lib/hermes : synapse (groupe hermes) doit pouvoir + # la lire, or /var/lib/hermes/.matrix est en 0700 (non traversable par le + # groupe). StateDirectory cree le dossier avant le namespace : avec + # ReadWritePaths sur un dossier absent, l'unite echouait en 226/NAMESPACE. + dataDir = "/var/lib/matrix-marc-agent-as"; + appservicePort = 29340; + registrationFile = "${dataDir}/registration.yaml"; + + tokenDir = "/var/lib/hermes/.matrix/marc-agent"; + tokenFile = "${tokenDir}/token"; + + stubServer = pkgs.writeText "matrix-marc-agent-stub.py" '' + import http.server + import socketserver + + PORT = ${toString appservicePort} + + class Handler(http.server.BaseHTTPRequestHandler): + def _ok(self): + body = b"{}" + self.send_response(200) + self.send_header("Content-Type", "application/json") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def _drain(self): + length = int(self.headers.get("Content-Length", 0) or 0) + if length: + self.rfile.read(length) + + def do_GET(self): + self._ok() + + def do_PUT(self): + self._drain() + self._ok() + + def do_POST(self): + self._drain() + self._ok() + + def log_message(self, fmt, *args): + pass + + class Server(socketserver.ThreadingTCPServer): + allow_reuse_address = True + + with Server(("127.0.0.1", PORT), Handler) as httpd: + httpd.serve_forever() + ''; +in { + systemd.services.matrix-marc-agent-as = { + description = "Stub appservice HTTP (encaisse les pushs synapse pour la registration marc-agent)"; + wantedBy = ["multi-user.target"]; + before = ["matrix-synapse.service"]; + preStart = '' + if [ ! -f '${registrationFile}' ]; then + AS_TOKEN=$(${pkgs.openssl}/bin/openssl rand -hex 32) + HS_TOKEN=$(${pkgs.openssl}/bin/openssl rand -hex 32) + umask 0137 + cat > '${registrationFile}' < '${tokenFile}' + chmod 400 '${tokenFile}' + ''; + }; + + services.matrix-synapse.settings.app_service_config_files = [registrationFile]; + systemd.services.matrix-synapse.serviceConfig.SupplementaryGroups = ["hermes"]; + systemd.services.matrix-synapse.after = ["matrix-marc-agent-as.service"]; + systemd.services.matrix-synapse.wants = ["matrix-marc-agent-as.service"]; +}