Public: anyone can read this; the crew can change it.
A repository's webhook routes leave api.ts for src/http/api/hooks.ts #7044
Check · Review · Land · Live done — Landed and live in production.
The repository's webhook routes now live in a new file, `src/http/api/hooks.ts`, which exports `hookRoutes(router)`. They are `GET` and `POST /api/v1/repos/:owner/:name/hooks` and `DELETE …/hooks/:id`, and their behaviour is unchanged. `apiRoutes` calls `hookRoutes(router)` in the exact spot where the block was, so the change to `src/http/api.ts` is one removal, one call and one import. The import…
shipped production is serving it deploy 7cfd21c
The repository's webhook routes now live in a new file, src/http/api/hooks.ts, which exports hookRoutes(router). They are GET and POST /api/v1/repos/:owner/:name/hooks and DELETE …/hooks/:id, and their behaviour is unchanged. apiRoutes calls hookRoutes(router) in the exact spot where the block was, so the change to src/http/api.ts is one removal, one call and one import. The imports it no longer uses are gone too (createWebhook, deleteWebhook, listWebhooks). src/http/api.ts has no /hooks route left; the only match is the new import line.
The handlers moved word for word:
- The list is still admin-scoped and still answers 404 to anyone who cannot administer the repository.
- The secret is returned once, when the hook is created, and in no other answer.
The new file follows the same pattern as src/http/api/labels.ts. It uses the existing loadRepo, pageOf and pageParams from api.ts and canAdmin from core/repos.ts. Nothing was copied and no helper had to be newly exported.
Checks: bun x tsc --noEmit is clean. These test files pass, none of them edited: test/webhooks.test.ts, test/mcp-hooks.test.ts, test/webhook-ownership.test.ts, test/mcp-size.test.ts, test/parity.test.ts, test/list-pages.test.ts, test/repo-reads-timing.test.ts, test/openapi-oa-crew.test.ts, and the other suites that touch /hooks (231 tests run: 229 pass, 2 skipped, 0 fail). Nothing under src/web/ changed, so the design lint does not apply.
To try it: GET /api/v1/repos/:owner/:name/hooks with an admin token lists the hooks, without secrets. POST the same path with { "url": … }: the answer includes the secret, this one time only.
🤖 Generated with Claude Code
Clean, behaviour-preserving move of the three webhook routes into src/http/api/hooks.ts, following the labels.ts/forges.ts pattern. The handlers are unchanged: admin scope is still required on all three, the list still answers 404 to anyone who is not a repo admin, and create/delete still go through requireRepoAdmin in actions/repos.ts. The secret is still returned only on create. No new helpers had to be exported, and the dead imports are gone from api.ts. Preview: anonymous GET and DELETE on /hooks answer 401, an anonymous POST is refused (400), and / answers 200. No new behaviour means no new tests are needed; the existing webhook suites cover these routes. Approved.
The repository's webhook routes now live in a new file,
src/http/api/hooks.ts, which exportshookRoutes(router). They areGETandPOST /api/v1/repos/:owner/:name/hooksandDELETE …/hooks/:id, and their behaviour is unchanged.apiRoutescallshookRoutes(router)in the exact spot where the block was, so the change tosrc/http/api.tsis one removal, one call and one import. The imports it no longer uses are gone too (createWebhook,deleteWebhook,listWebhooks).src/http/api.tshas no/hooksroute left; the only match is the new import line.The handlers moved word for word:
The new file follows the same pattern as
src/http/api/labels.ts. It uses the existingloadRepo,pageOfandpageParamsfromapi.tsandcanAdminfromcore/repos.ts. Nothing was copied and no helper had to be newly exported.Checks:
bun x tsc --noEmitis clean. These test files pass, none of them edited:test/webhooks.test.ts,test/mcp-hooks.test.ts,test/webhook-ownership.test.ts,test/mcp-size.test.ts,test/parity.test.ts,test/list-pages.test.ts,test/repo-reads-timing.test.ts,test/openapi-oa-crew.test.ts, and the other suites that touch/hooks(231 tests run: 229 pass, 2 skipped, 0 fail). Nothing undersrc/web/changed, so the design lint does not apply.To try it:
GET /api/v1/repos/:owner/:name/hookswith an admin token lists the hooks, without secrets.POSTthe same path with{ "url": … }: the answer includes the secret, this one time only.🤖 Generated with Claude Code
Closes #6333