From 35748219ab8b409f564c8a5c52d5e7fc39ecbc22 Mon Sep 17 00:00:00 2001 From: lorentz Date: Wed, 18 Mar 2026 10:54:27 +0000 Subject: [PATCH] Fix scheduled sync: add cron endpoint, systemd timer, bypass auth middleware - Add /api/cron/sync route secured by x-cron-secret header - Bypass NextAuth middleware for /api/cron/* routes - Add CRON_SECRET to .env - Fix FK violation: pass undefined instead of 'system' for triggered_by - Systemd timer (ondeck-sync.timer) runs daily at 2 AM via curl --- ondeck/src/app/api/cron/sync/route.ts | 18 ++++++++++++++++++ ondeck/src/middleware.ts | 5 +++++ 2 files changed, 23 insertions(+) create mode 100644 ondeck/src/app/api/cron/sync/route.ts diff --git a/ondeck/src/app/api/cron/sync/route.ts b/ondeck/src/app/api/cron/sync/route.ts new file mode 100644 index 0000000..3f69fe6 --- /dev/null +++ b/ondeck/src/app/api/cron/sync/route.ts @@ -0,0 +1,18 @@ +import { NextRequest, NextResponse } from 'next/server' +import { runSync } from '@/lib/sync/sync-engine' + +export async function POST(request: NextRequest) { + const secret = request.headers.get('x-cron-secret') + if (!secret || secret !== process.env.CRON_SECRET) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + try { + const result = await runSync(undefined, true) + return NextResponse.json({ success: result.success, stats: result.stats, error: result.error }) + } catch (error) { + const message = error instanceof Error ? error.message : String(error) + console.error('Cron sync error:', error) + return NextResponse.json({ error: message }, { status: 500 }) + } +} diff --git a/ondeck/src/middleware.ts b/ondeck/src/middleware.ts index c65f5a6..d49db64 100644 --- a/ondeck/src/middleware.ts +++ b/ondeck/src/middleware.ts @@ -42,6 +42,11 @@ export default withAuth( return true } + // Allow cron endpoints (secured by x-cron-secret header instead) + if (path.startsWith('/api/cron/')) { + return true + } + // Require authentication for all other paths return !!token },