org-subscriber daemon drops all Mark/org_mode webhooks with 401 — hook 102 has no secret while daemon requires HMAC #38
Labels
No labels
blocked:needs-decision
bug
chore
cron
design
in-progress
infra
milestone
module-o
needs-decompose
needs-research
ops-task
pm
quickfix
security/medium
triage-approved
vikunja
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/org_mode#38
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Every Mark/org_mode event sent to the org-subscriber daemon is rejected with 401 Unauthorized. The daemon webhook endpoint requires an HMAC secret, but Forgejo hook id 102 on Mark/org_mode has no secret configured. Zero Mark/org_mode events reach the daemon — issue close/label events (e.g. the org_mode#29 close on 2026-08-21) are silently dropped.
Pre-existing (known pitfall, verified 2026-08-07) — NOT a regression from the #29 fix, but it breaks the event substrate the Module O swarm bridge (org_mode#29) is supposed to run on.
Reproduction
~/.hermes/scripts/forgejo-api.sh GET /repos/Mark/org_mode/hooks→ hook id 102, active, urlhttp://unstable.tail018ac4.ts.net:9090/webhooks/forgejo, config keys = [content_type, url] only — no secret.grep -n -B2 -A3 secret /home/b/Projects/org_mode/config/daemon.unstable.yaml→secret: "2173fe56e5a7a10a6d6e090c454693720bf1c3e3e62eac031054a85d5ba92df6"set for path/webhooks/forgejo.ssh unstable journalctl --user -u org-subscriber -n 300 --no-pager→POST /webhooks/forgejo ... 401 Unauthorizedimmediately after the event. Verified live 2026-08-21 22:54–22:58: continuous 200/401 pairs, only osint-hub (secret-bearing) hooks return 200.Actual behavior
Expected behavior
Fix candidates (agent-reachable)
secretin daemon.unstable.yaml (needs explicit permission — out of reporter scope).Kanban origin: card t_99b7d377 (post-deploy probe of Mark/org_mode#29).
#38 fix verification: webhook secret sync 2026-08-27Z
webhook delivery test 03:38Z
post-fix live trigger
post-dns-fix live trigger
Resolution (2026-08-27 ~03:52Z)
Closed-loop breaker was a two-layer bug, not just the missing secret:
Secret mismatch (described in #38 body). Forgejo hook 102 had no
config.secret; daemondaemon.unstable.yamlhadsecret: 2173fe56...ba92df6for/webhooks/forgejo. PATCH/repos/Mark/org_mode/hooks/102set the matching secret.DNS resolution failure (not described in #38 body, but visible in
hook_taskdelivery log). Forgejo containerresolv.confpoints at1.1.1.1/8.8.8.8(public DNS), sounstable.tail018ac4.ts.net(Tailscale MagicDNS) did not resolve. Every hook_task delivery for hook 102 from 2026-08-26 ~05:09Z onward returneddial tcp: lookup unstable.tail018ac4.ts.net on 1.1.1.1:53: no such host— before any HMAC check ran. So the symptom (#38 said "every Mark/org_mode event is rejected with 401 Unauthorized") was actually a TCP-layer failure masquerading as an auth failure: Forgejo never even reached the daemon to be 401-rejected.Fix applied
PATCH
/repos/Mark/org_mode/hooks/102with:config.secret = 2173fe56e5a7a10a6d6e090c454693720bf1c3e3e62eac031054a85d5ba92df6config.url = http://100.123.237.4:9090/webhooks/forgejo(bypasses MagicDNS by using the tailnet IPv4 directly)Verification
Live trigger (issue_comment #52841 on Mark/org_mode#38) at 03:52:43Z:
journalctl --user -u org-subscriber:server.webhooks.router: Webhook received: source=forgejo event=issue_comment.created actor=Mark repo=Mark/org_modeINFO: 100.123.237.4:45848 - "POST /webhooks/forgejo HTTP/1.1" 200 OKhook_taskrow 13685:is_succeed=1, status=200, body={"status":"ok","event_type":"issue_comment.created"...}Side findings (not blocking this issue)
resolv.conf=1.1.1.1,8.8.8.8) is unsuitable for any internal tailnet webhook target. If a future hook needs DNS, either set the URL to a literal tailnet IP (as done here), or change the container's DNS to100.100.100.100(Tailscale MagicDNS resolver) — but that needs a container restart and a daemon-reload for resolv.conf to take effect.forgejo_tailscaleconmon (PID 2018666) is runningpodman start -aagainst a non-existent container. Worth a separate cleanup ticket; not a closed-loop blocker.Closes the closed-loop breaker for org_mode: every labeled event on Mark/org_mode now reaches the daemon, the daemon action_chain runs, downstream PM/kanban/E/N/O modules can rely on the event substrate.