MF-3: Per-forge webhook ingress + signature verification #294
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#294
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?
As a platform engineer, I want webhook deliveries from Forgejo, GitHub, and GitLab routed into the same domain dispatch pipeline (normalised at the HTTP boundary) so that the rest of the service stays forge-agnostic and signature verification is uniformly enforced.
Acceptance criteria
Routes
/webhooks/forgejo,/webhooks/github,/webhooks/gitlab./webhooksstays as a Forgejo alias — zero-cost, indefinite.204(no-op), never500.Signature verification (per forge)
webhook_secret, headerX-Forgejo-Signature(current behaviour preserved).X-Hub-Signature-256: sha256=<hex>(prefix stripped before compare).X-Gitlab-Tokenheader. Documented in code + docs as plaintext (not HMAC); per-forge secrets MUST be unique per repo to limit blast radius.403.Normaliser
apps/server/src/http/webhook-normalize.tswith pure functions:normalizeGitHubPayload(event, body) → ForgeEventnormalizeGitLabPayload(event, body) → ForgeEventnormalizeForgejoPayload(event, body) → ForgeEvent(either refactor the existing dispatch or call through the shared shape).Shared event union
ForgeEventdiscriminated union exported frompackages/sharedcovering every event the Forgejo dispatch currently handles:issues.assigned,issues.labeled,issues.closed,pull_request.opened,pull_request.closed,pull_request_review.request,pull_request_review.approved,pull_request_review.changes_requested,issue_comment.created,action_run.*/workflow_run.*(CI status).ForgeEvent.Unhandled— still204, never lost.Tests
webhook-normalize.test.ts: each forge's real-world payload (captured fixture, trimmed of PII) normalises to the sameForgeEventfor equivalent actions.403.204.Out of scope
switch (event)to the normalisedForgeEventunion in one go. Can be a follow-up once the union is stable; keep today's Forgejo handlers as-is, just call the normaliser for parity.References
specs/multi-forge.md§ MF-3.apps/server/src/http/webhook.ts— current Forgejo-only entry.apps/server/src/http/webhook-handlers.ts— event handlers that receive the normalised events.Dependencies