// Node.js 22+. Install: npm install pg standardwebhooks // Run webhook-inbox.sql in your application's database first. // DATABASE_URL and WEBHOOK_SECRET must be set in your server environment. import http from 'node:http'; import pg from 'pg'; import { Webhook } from 'standardwebhooks'; if (!process.env.DATABASE_URL || !process.env.WEBHOOK_SECRET) throw new Error('Database and signing secret required'); const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL, connectionTimeoutMillis: 3000, statement_timeout: 5000 }); const verifier = new Webhook(process.env.WEBHOOK_SECRET); const server = http.createServer(async (request, response) => { const reply = status => { response.writeHead(status); response.end(); }; if (request.method !== 'POST' || request.url !== '/webhook') return reply(404); try { const parts = []; let size = 0; for await (const part of request) { size += part.length; if (size > 262144) return reply(413); parts.push(part); } const raw = Buffer.concat(parts).toString('utf8'); let event; try { event = verifier.verify(raw, request.headers); } catch { return reply(401); } const id = request.headers['webhook-id']; if (typeof id !== 'string' || id.length > 200 || !event || typeof event !== 'object' || typeof event.type !== 'string') return reply(400); await pool.query( 'INSERT INTO email_webhook_inbox(source,event_id,payload) VALUES($1,$2,$3::jsonb) ON CONFLICT DO NOTHING', ['postrune-endpoint-1', id, JSON.stringify(event)], ); // Success only after the durable write. Duplicates get the same response. reply(204); } catch { reply(503); // Provider may retry; never acknowledge an uncommitted event. } }); server.requestTimeout = 5000; server.headersTimeout = 5000; // Set WEBHOOK_PORT=0 to choose an available local port for a test run. const port = Number(process.env.WEBHOOK_PORT ?? 3028); server.listen(port, '127.0.0.1', () => console.log(`Local webhook inbox: http://127.0.0.1:${server.address().port}`));