import assert from "node:assert/strict"; import { createHmac } from "node:crypto"; import { mkdtemp, rm } from "node:fs/promises"; import { createServer } from "node:http"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { AgentStore } from "../../adapters/database/store.js"; import { type HttpRequestLog, handleHttp, observeHttpRequest, } from "../../application/controller/server.js"; test("signed webhooks are durably admitted before acknowledgment", async () => { const root = await mkdtemp(join(tmpdir(), "agent-http-")); const store = new AgentStore(join(root, "agent.db")); const server = createServer((request, response) => { handleHttp(request, response, { store, webhookSecret: "test-secret", repositoryId: 9, repositoryFullName: "owner/repo", }).catch((error) => { response.writeHead(500); response.end(String(error)); }); }); try { await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve), ); const address = server.address(); assert.ok(address && typeof address === "object"); const body = JSON.stringify({ action: "created", comment: { body: "/agent plan" }, repository: { id: 9, full_name: "owner/repo" }, }); const signature = createHmac("sha256", "test-secret") .update(body) .digest("hex"); const response = await fetch( `http://127.0.0.1:${address.port}/webhooks/gitea`, { method: "POST", headers: { "content-type": "application/json", "x-gitea-signature": signature, "x-gitea-delivery": "delivery-http-1", "x-gitea-event": "issue_comment", "x-gitea-event-type": "issue_comment", }, body, }, ); assert.equal(response.status, 204); assert.equal(store.leaseDelivery()?.id, "delivery-http-1"); } finally { await new Promise((resolve) => server.close(() => resolve())); store.close(); await rm(root, { recursive: true, force: true }); } }); test("invalid webhook signatures are rejected without persistence", async () => { const root = await mkdtemp(join(tmpdir(), "agent-http-auth-")); const store = new AgentStore(join(root, "agent.db")); const requests: HttpRequestLog[] = []; const server = createServer((request, response) => { observeHttpRequest(request, response, (entry) => requests.push(entry)); handleHttp(request, response, { store, webhookSecret: "test-secret", repositoryId: 9, repositoryFullName: "owner/repo", }).catch(() => { response.writeHead(500); response.end(); }); }); try { await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve), ); const address = server.address(); assert.ok(address && typeof address === "object"); const response = await fetch( `http://127.0.0.1:${address.port}/webhooks/gitea`, { method: "POST", headers: { "content-type": "application/json", "x-gitea-signature": "0".repeat(64), "x-gitea-delivery": "delivery-http-2", "x-gitea-event": "issues", "x-gitea-event-type": "issue_label", }, body: JSON.stringify({ repository: { id: 9, full_name: "owner/repo" }, }), }, ); assert.equal(response.status, 401); assert.equal(store.leaseDelivery(), undefined); assert.equal(requests.length, 1); assert.deepEqual( { method: requests[0]?.method, path: requests[0]?.path, statusCode: requests[0]?.statusCode, completed: requests[0]?.completed, }, { method: "POST", path: "/webhooks/gitea", statusCode: 401, completed: true, }, ); assert.ok((requests[0]?.durationMs ?? -1) >= 0); const readiness = await fetch( `http://127.0.0.1:${address.port}/readyz`, ); assert.equal(readiness.status, 200); assert.equal(requests.length, 1); } finally { await new Promise((resolve) => server.close(() => resolve())); store.close(); await rm(root, { recursive: true, force: true }); } });