/** * @ai-summary Resend inbound webhook + user-facing pending association routes * @ai-context Public webhook (no JWT) + authenticated CRUD for pending vehicle associations */ import { FastifyPluginAsync } from 'fastify'; import { EmailIngestionController } from './email-ingestion.controller'; /** Public webhook route - no JWT auth, uses Svix signature verification */ export const emailIngestionWebhookRoutes: FastifyPluginAsync = async (fastify) => { const controller = new EmailIngestionController(); // POST /api/webhooks/resend/inbound - PUBLIC endpoint (no JWT auth) // Resend authenticates via webhook signature verification (Svix) // rawBody MUST be enabled for signature verification to work fastify.post( '/webhooks/resend/inbound', { config: { rawBody: true, }, }, controller.handleInboundWebhook.bind(controller) ); }; /** Authenticated user-facing routes for pending vehicle associations */ export const emailIngestionRoutes: FastifyPluginAsync = async (fastify) => { const controller = new EmailIngestionController(); // GET /api/email-ingestion/pending - List pending associations for authenticated user fastify.get('/email-ingestion/pending', { preHandler: [fastify.authenticate], handler: controller.getPendingAssociations.bind(controller), }); // GET /api/email-ingestion/pending/count - Get count of pending associations fastify.get('/email-ingestion/pending/count', { preHandler: [fastify.authenticate], handler: controller.getPendingAssociationCount.bind(controller), }); // POST /api/email-ingestion/pending/:id/resolve - Resolve by selecting vehicle fastify.post<{ Params: { id: string }; Body: { vehicleId: string } }>( '/email-ingestion/pending/:id/resolve', { preHandler: [fastify.authenticate], handler: controller.resolveAssociation.bind(controller), } ); // DELETE /api/email-ingestion/pending/:id - Dismiss/discard a pending association fastify.delete<{ Params: { id: string } }>( '/email-ingestion/pending/:id', { preHandler: [fastify.authenticate], handler: controller.dismissAssociation.bind(controller), } ); };