Submatter/.convoys/owner-cockpit-v02/brief-1-forge-webhook-receiver.md
Randall Stillwell 6f139d6af2 feat(owner-cockpit): forge webhooks + artifacts + copilot (Epic 8/11/12)
- Forge webhook POST /api/webhooks/forge HMAC sha256 verify, marker echodo-convoy → pr_review→merged as automation
- Completion artifacts table 0017, deterministic summary template, gallery /artifacts
- Ops copilot tRPC copilot + context tools (fleet, convoy, backlog) + panel + Draft Task → backlog.createTask
- Doc-writer SOPs: webhook rotation, copilot prompt, published flow examples
- Allow pr_review→merged as automation for webhook

Convoy: .convoys/owner-cockpit-v02

Co-authored-by: orchestrator
2026-08-25 17:49:38 -05:00

1.7 KiB

brief convoy role title status priority slice_dependencies recommended_model model_tier
1 owner-cockpit-v02 role-implementer Forge webhook receiver — GitHub/Forgejo → pr_review→merged ready P0
qwen-coder local

Brief 1 — Task-forge-webhook-receiver.md (Epic 8)

Goal

POST /api/webhooks/forge verifies signature via FORGE_WEBHOOK_SECRET, finds echodo-convoy: <uuid> marker in PR body (from apps/worker/src/git/pr.ts), transitions pr_review→merged via transitionConvoy packages/shared/src/convoy-lifecycle/state-machine.ts:90 as automation, writes convoy_events.

Files

  • apps/web/app/api/webhooks/forge/route.ts NEW — parse X-Hub-Signature-256 (GitHub) or X-Forgejo-Signature (Forgejo) HMAC sha256 FORGE_WEBHOOK_SECRET, handle pull_request: closed & merged=true + pr.body marker regex /echodo-convoy:\s*([0-9a-f-]{36})/, lookup convoy by id, validate status===pr_review, call transitionConvoy(db, {workspaceId, convoyId, toStatus:merged, actor:automation, reason: pr#N merged}). Return 200 + ok even if no convoy (don't leak). Rate-limit per IP.
  • apps/web/server/lib/forge/adapters.ts — reuse ForgeAdapter if needed for verify.
  • docs/operations/live-e2e-checklist.md — add webhook step.

Acceptance

  • Forgejo/GitHub payload with body: "… echodo-convoy: <id> …" + valid HMAC transitions pr_review→merged; invalid signature 401; no marker 200 no-op.
  • Existing pnpm lint && pnpm type-check pass.

Prompt

You are role-implementer brief 1. Read packages/shared/src/convoy-lifecycle/state-machine.ts, apps/web/server/lib/forge/adapters.ts, apps/worker/src/git/pr.ts, docs/convoy-lifecycle.md. Keep verify constant-time, workspace-scoped.

Depends

None.