Webhook receiver: Plane deliveries trigger a tick (PAD-7)

agentd webhook-serve (agentd/webhook.py, stdlib): verifies X-Plane-Signature
(HMAC-SHA256 hex of the body, constant-time; 401 on missing/bad), routes by
data.project to a configured tenant (others 202), coalesces deliveries within
3 s into one tick, runs one more tick when deliveries arrive during a tick,
and retries every 15 s for up to 2 min while the lock is held (tick command
exit 75: flock -E 75 in the cron scripts, cli tick on Busy). Ticks run in a
systemd scope so restarting the receiver never kills one. Log:
<log_dir>/webhook.log; GET /healthz.

Config: webhook section (key names only, PLANE_WEBHOOK_SECRET scrubbed from
child envs like the Plane tokens), notify: {kind: none} as a no-op hook
called on every state move; the unused per-project webhook_secret_key is
gone (Plane webhooks are workspace-level). systemd unit for the LXC and
tools/plane-webhook.py to create/rotate the Plane webhook as the workspace
admin (secret straight into the Vault, never printed).
This commit is contained in:
jj.wang
2026-10-21 13:24:04 +00:00
parent 72681db46b
commit 6dc7e72ac8
14 changed files with 651 additions and 9 deletions
+5 -2
View File
@@ -148,6 +148,8 @@ class Config:
self.executors = data["executors"]
self.projects = data["projects"]
self.agentd = data.get("agentd", {})
self.webhook = data.get("webhook", {})
self.notify = data.get("notify") or {"kind": "none"}
@property
def state_dir(self):
@@ -176,9 +178,10 @@ class Config:
return os.environ.get(self.token_env(terminal))
def secret_keys(self):
"""Every env var name that carries a secret (Plane tokens, webhook secrets): never handed to executors."""
"""Every env var name that carries a secret (Plane tokens, the webhook secret): never handed to children."""
keys = {t["token_key"] for t in self.terminals.values()}
keys |= {p["webhook_secret_key"] for p in self.projects.values() if p.get("webhook_secret_key")}
if self.webhook.get("secret_key"):
keys.add(self.webhook["secret_key"])
return keys
def scrubbed_env(self):