- New DB tables: shape_import_runs, shape_import_logs (raw SQL applied)
- src/lib/shape-import/run-import.ts: importable core logic extracted from CLI script
- POST /api/admin/shape-import: starts run async, returns runId immediately
- GET /api/admin/shape-import: lists last 20 runs
- GET /api/admin/shape-import/[id]: polls log lines and run status
- /admin/shape-import page: drive ID config, dry run / execute (with confirmation),
live log panel (2s poll), stats summary, run history with log replay
- Admin index: added SHAPE Historical Import card
- Notes moved to collapsible panel just below header
- Auto-expanded if client has notes, collapsed if empty
- Shows preview snippet when collapsed
- Claims Advocate, Designations, Team Members, Related Companies
consolidated into new 'Assignment' tab
- Removed 4 standalone cards from main scroll area
This was the 4th location missing the filter — the API endpoint had no
suppression at all, so old/dead tasks showed when admins viewed other users' tasks.
Prisma NOT:[condA, condB] means exclude only if BOTH match, and OR at the
same level overrode the NOT entirely. Restructured to:
- NOT (single object) for dead policy exclusion
- OR for group expiry check (null group OR recent renewal)
- AND > OR for recent-or-terminal filter
Fixed in all 3 locations: tasks page, client tasks API, client detail SSR.
- Update page title, metadata, sign-in header, nav bar brand name
- Update dev account emails from ondeck.local to horizon.local
- Update comments in permissions.ts and types/index.ts
- Update NEXTAUTH_URL to https://horizon.seubert.cloud
- Update systemd timer service URL and log path
- 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