-- Create webhooks table for project webhook subscriptions CREATE TABLE IF NOT EXISTS webhooks ( id TEXT PRIMARY KEY, project_id TEXT NOT NULL, url TEXT NOT NULL, secret TEXT, -- HMAC-SHA256 signing secret (optional but recommended) events TEXT NOT NULL, -- JSON array of event types to subscribe enabled BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Index for efficient lookup by project CREATE INDEX IF NOT EXISTS idx_webhooks_project_id ON webhooks(project_id); -- Index for finding enabled webhooks (most queries will filter by enabled) CREATE INDEX IF NOT EXISTS idx_webhooks_enabled ON webhooks(enabled) WHERE enabled = true; -- GIN index for efficient JSONB containment queries on events column -- Required for: WHERE events::jsonb ? 'event_type' CREATE INDEX IF NOT EXISTS idx_webhooks_events_gin ON webhooks USING GIN ((events::jsonb)); -- Create webhook_deliveries table for delivery tracking CREATE TABLE IF NOT EXISTS webhook_deliveries ( id TEXT PRIMARY KEY, webhook_id TEXT NOT NULL REFERENCES webhooks(id) ON DELETE CASCADE, event_type TEXT NOT NULL, payload TEXT NOT NULL, -- JSON payload that was sent response_status INT, response_body TEXT, delivered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), success BOOLEAN NOT NULL DEFAULT false, retry_count INT NOT NULL DEFAULT 0, error_message TEXT -- Capture error details for failed deliveries ); -- Index for listing deliveries by webhook CREATE INDEX IF NOT EXISTS idx_webhook_deliveries_webhook_id ON webhook_deliveries(webhook_id, delivered_at DESC); -- Index for monitoring failed deliveries CREATE INDEX IF NOT EXISTS idx_webhook_deliveries_success ON webhook_deliveries(success, delivered_at DESC) WHERE success = false; -- Index for cleanup of old deliveries CREATE INDEX IF NOT EXISTS idx_webhook_deliveries_delivered_at ON webhook_deliveries(delivered_at); COMMENT ON TABLE webhooks IS 'Webhook subscriptions for project events'; COMMENT ON COLUMN webhooks.project_id IS 'Project ID that this webhook is subscribed to'; COMMENT ON COLUMN webhooks.url IS 'URL to POST webhook payloads to'; COMMENT ON COLUMN webhooks.secret IS 'Secret for HMAC-SHA256 signing (X-Webhook-Signature header)'; COMMENT ON COLUMN webhooks.events IS 'JSON array of event types: command.started, command.completed, command.failed, pod.ready, pod.failed'; COMMENT ON COLUMN webhooks.enabled IS 'Whether this webhook is active'; COMMENT ON TABLE webhook_deliveries IS 'Webhook delivery history and retry tracking'; COMMENT ON COLUMN webhook_deliveries.webhook_id IS 'Reference to the webhook configuration'; COMMENT ON COLUMN webhook_deliveries.event_type IS 'Type of event that triggered this delivery'; COMMENT ON COLUMN webhook_deliveries.payload IS 'JSON payload that was sent to the webhook URL'; COMMENT ON COLUMN webhook_deliveries.response_status IS 'HTTP status code from the webhook endpoint'; COMMENT ON COLUMN webhook_deliveries.response_body IS 'Response body from the webhook endpoint (truncated)'; COMMENT ON COLUMN webhook_deliveries.success IS 'Whether the delivery was successful (2xx response)'; COMMENT ON COLUMN webhook_deliveries.retry_count IS 'Number of retry attempts for this delivery'; COMMENT ON COLUMN webhook_deliveries.error_message IS 'Error details if delivery failed';