2026 OpenClaw MeshMac: Matrix Webhook for Shared Build Status on Multi-Node Remote Mac
Published April 1, 2026
Meshmac Team
Teams on a MeshMac pool need one Matrix room for CI state regardless of which Mac runs the build. Here is a minimal path: gateway tokens, webhook or appservice setup, signing, a CI field map, and an FAQ when events vanish—so multi-node observers share one timeline.
Why Matrix Notifications Fail Across Mesh Nodes
- Split-brain senders post from different users or aliases, creating duplicate or contradictory lines.
- Token sprawl puts full Matrix sessions inside CI images, breaking least privilege when a runner leaks.
- Unverified HTTP invites forged payloads; align with our webhook hardening guide.
Use one ingress gateway and the shared queue pattern from multi-node deploy and task queue sync, then emit Matrix events only from that choke point.
Webhook-Only Bot Versus Appservice
Start with a webhook bridge; move to an appservice when you need ghost users or richer transactions.
| Pattern | Best for | Trade-off |
|---|---|---|
| Incoming HTTP to bridge | Fastest greenfield on a single homeserver | Limited schema control; you must validate JSON yourself before the bridge emits m.room.message |
| Registered appservice | Stable multi-room routing and ghost users | More moving parts: registration yaml, token pairs, and Synapse reload discipline |
Gateway Installation and Tokens
Run the gateway on a stable host reachable from Synapse and CI egress. Set OPENCLAW_CONFIG_ROOT, mount config read-only, and store Matrix secrets outside Git. Create a build bot user, join the team room once, save its access token as 0440 for the gateway user only—workers stay tokenless on the queue. Restart the gateway after token rotation so every MeshMac node picks up the same notify path. See IM alerts and token rotation for cadence.
- Homeserver URL must match verified TLS; pin fingerprints if self-hosted.
- Room id should be the full id, not only an alias.
- Correlation id flows CI → OpenClaw → Matrix body for log joins.
Matrix Webhook and Appservice Configuration Steps
- Expose
/hooks/matrix/build-status(or similar) behind TLS at the proxy. - Register via the integration manager or
app_service_config_filespointing at your yaml. - Set
id,url,as_token,hs_token, and namespaces such asbuildbot_. - Reload Synapse, curl a signed sample POST, confirm
m.room.message. - Document in the topic that every worker adds
mesh_node_idfor multi-node clarity.
Message Signing or Least-Privilege Verification
Verify every POST: HMAC-SHA256 over raw bytes with constant-time compare, or a bearer secret plus CI egress IP allowlists if the vendor cannot sign. Reject timestamps older than five minutes.
Scope the Matrix token to send in one room only—no invites or admin. Redact Authorization headers in logs and perform verification only on the gateway, not on each Mac.
CI Status Field Mapping Table
Normalize CI JSON before rendering Matrix markdown or plain text.
| CI source field | Gateway key | Matrix message use |
|---|---|---|
| workflow name or pipeline name | workflow | Bold first line so readers recognize which automation fired |
| status or conclusion | state | Map to queued, running, succeeded, or failed with emoji guardrails your team agrees on |
| head branch or ref | branch | Second line for release versus feature visibility |
| head sha or commit id | commit | Short seven character prefix linked to the provider run URL |
| html_url or web_url | run_url | Clickable markdown link for deep debugging on the mesh node logs |
| runner name or custom mesh label | mesh_node_id | Footer line that disambiguates multi-node pools without opening SSH sessions |
Troubleshooting FAQ: When Messages Never Arrive
- CI two hundred but no room event
- Check membership, bridge logs for empty bodies, and null conclusions in templates; retry with a tiny test workflow.
- Appservice signature errors
- Diff hs_token in Synapse versus disk yaml, strip secret newlines, curl from the homeserver host to rule out TLS middleboxes.
- Only some nodes notify
- Runners skipped the shared gateway—unify the webhook URL env and restrict egress to the approved ingress.
- Duplicate lines per run
- Dedupe with run id plus state keys stored seventy-two hours in Redis or SQLite before emitting Matrix text.
Summary
Send Matrix only from the gateway, verify HTTP callers, map CI fields once, and surface mesh_node_id for pool visibility. Visit the homepage, blog, and help center for next steps.