---
id: w1/m5/t003
title: Push webhook shipped in w2 (deploy-from-chat) — verify vs m5 acceptance, close
worker: worker1
status: done
estimate: 15m
depends_on: []
---

## Objective

The deploy-on-push HMAC webhook this task originally scoped was shipped by w2's deploy-from-chat work (2026-07-08): `lego/backend/internal/apps/webhook.go`, `POST /v1/webhooks/git`, keyed by `BEX_WEBHOOK_SECRET` — in bex-api, as an API surface, exactly where it belongs (the operator is mechanism-only). What remains is verifying the shipped implementation against **m5's** acceptance bar, filing gaps if any, and closing this task as covered.

## Context

- Shipped surface: `lego/backend/internal/apps/webhook.go` + `deploy_test.go`; documented in docs/ADR017-deploy-from-chat.md and docs/ADR006-bex-api.md (`BEX_WEBHOOK_SECRET` unset ⇒ webhook 503).
- m5's acceptance bar: signed push to `App.branch` bumps the revision; invalid HMAC rejected; `autoDeploy: false` apps not bumped; pushes to non-tracked branches ignored.
- Single-writer rule: with the store on (`BEX_CP_DB_URI`), the bump must survive a projector resync (written through the row, not a bare CR patch the projector reverts).

## Steps

1. Read `webhook.go` + `deploy_test.go`; check each m5 acceptance item is implemented and tested.
2. Check the store-on bump path honors the single-writer rule.
3. File any gap as an inbox note (or extend t005's coverage scope); mark this task done with a one-line closure note.

## Acceptance criteria

- [ ] Each m5 acceptance item verified against the shipped code/tests, with gaps filed — or an explicit "fully covered by w2" closure.

## Out of scope

- The build itself (t001); re-implementing anything the w2 work already covers.
