Files
mopac-pmo/archive/TASK-20260828-1975-events-receiver.md

1.8 KiB

TASK: mopac events — webhook receiver (build phase 2b, V1 scope)

Objective

Implement mopac events in /home/reachableceo/projects/meta/MOPAC/harness per DESIGN.md ("Events are V1 scope" section — READ FIRST). A Go HTTP webhook receiver that makes Redmine/Discourse/Gitea able to punch the harness: replies, ticket updates, PR approvals -> harness knows and acts.

Constraints

  • ALL DEV IN DOCKER (hard rule): no host toolchains. Pull digest-pinned golang:1.26(-alpine) builder; bind-mount the repo; build/vet/test inside the container. If a Makefile/dev.sh wrapper helps, add it, but every compile/test path routes through docker run.
  • Go stdlib net/http only (no frameworks); no new deps without need.
  • Receivers: /hooks/redmine, /hooks/discourse, /hooks/gitea.
    • Verify secrets: Gitea HMAC-SHA256 header; Discourse secret header; Redmine shared-secret header; reject unsigned/unverified with 401.
    • Normalize each into one internal Event struct (source, kind, actor, subject/topic/PR id, payload digest, received-at).
    • Persist events (append-only JSONL + dedup by provider event id) under a state dir from config; NEVER log secret/header values.
    • Event -> action mapping per DESIGN (turn dispatch is a stub call into the conductor interface for now; wiring comes after skeleton lands).
  • Config: webhook secrets via env refs (os.environ/VAR pattern), port + state dir in harness.toml; sensible defaults.
  • Table-driven tests for signature verification + normalization + dedup.
  • Run it: brief docker run smoke on a high LAN port (e.g. 4100) with a curl-equivalent POST (python urllib — curl is banned on host) using a test secret; show 401 without secret, 200 + JSONL record with.
  • Commit incrementally to main; push. REPORT to inbox-pmo lists what works, what's stubbed, exact container commands used.