brackt/app
chrisp 273742f02e
Some checks failed
🚀 Deploy / 🧪 Test (push) Failing after 2m45s
🚀 Deploy / ʦ🔍 Typecheck & Lint (push) Successful in 1m27s
🚀 Deploy / 🐳 Build (push) Has been skipped
🚀 Deploy / 🚀 Deploy (push) Has been skipped
Phase A: external HTTP cron jobs for snapshots, standings sync, and simulation (#79)
## Summary

- Removes the last in-process \`setInterval\` (\`server/snapshots.ts\` 24h loop) and replaces it with an external HTTP cron job via Forgejo Actions
- Adds automated standings sync + conditional simulation: syncs every 2h, only simulates when standings actually changed (detected by comparing \`gamesPlayed\`/\`leagueRank\` before upsert)
- Adds \`GET /healthz\` for Docker healthcheck (Phase B prerequisite)

## What's new

| Endpoint | Triggered by | What it does |
|---|---|---|
| \`POST /admin/jobs/run-daily-snapshots\` | Forgejo schedule \`5 0 * * *\` | Creates daily fantasy standings snapshots for all active/draft seasons |
| \`POST /admin/jobs/sync-and-simulate\` | Forgejo schedule \`0 */2 * * *\` | Syncs standings from external APIs; runs simulation only if standings changed |
| \`GET /healthz\` | Docker / Traefik | Returns 200 \`{ok:true}\` when DB reachable, 503 otherwise |

Both cron endpoints are protected by \`X-Cron-Secret\` header (set \`CRON_SECRET\` in Forgejo repo secrets + production env).

## Schema changes (migration 0118)

Two new nullable columns on \`sports_seasons\`:
- \`standings_last_changed_at\` — written by \`syncStandings()\` when data actually changes
- \`last_simulated_at\` — written by the cron job after a successful simulation run

## Deployment notes

1. Add \`CRON_SECRET\` to Forgejo repo secrets (generate with \`openssl rand -hex 32\`)
2. Add same value to production environment
3. Migration runs automatically via the \`migrate\` container on deploy

## Test plan

- [ ] \`curl -X POST https://brackt.com/admin/jobs/run-daily-snapshots -H "X-Cron-Secret: ..."\` → 200 \`{total, succeeded, errors}\`
- [ ] \`curl -X POST https://brackt.com/admin/jobs/sync-and-simulate -H "X-Cron-Secret: ..."\` → 200 with \`synced\`/\`unchanged\`/\`simulated\` breakdown
- [ ] \`curl https://brackt.com/healthz\` → 200 \`{ok:true}\`
- [ ] Verify Forgejo workflow runs appear in Actions tab after merge
- [ ] Kill web process mid-day; confirm external cron still fires (no in-process dependency)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Chris Parsons <chrisparsons1127@gmail.com>
Reviewed-on: #79
2026-06-08 07:42:14 +00:00
..
components Fix QP standings: filter to drafted/points-earning participants with correct global ranks 2026-06-06 09:38:47 -07:00
contexts
hooks Fix three timer-pause gaps found in code review 2026-06-06 08:52:04 -07:00
lib Phase A: external HTTP cron jobs for snapshots, standings sync, and simulation (#79) 2026-06-08 07:42:14 +00:00
models Fix draft timer: broadcasts, increments, reconnect sync, overnight pause (#72) 2026-06-06 05:57:46 +00:00
routes Phase A: external HTTP cron jobs for snapshots, standings sync, and simulation (#79) 2026-06-08 07:42:14 +00:00
services Phase A: external HTTP cron jobs for snapshots, standings sync, and simulation (#79) 2026-06-08 07:42:14 +00:00
test Add auto-start draft at scheduled time (#437) (#438) 2026-05-16 23:37:29 -07:00
types
utils claude/sports-templates-conversion-ILWAM (#71) 2026-06-04 21:31:49 +00:00
welcome
app.css Add electric flash + fade animation for draft picks, fixes #381 (#407) 2026-05-10 23:17:29 -07:00
entry.client.tsx
entry.server.tsx
root.tsx fix: resolve all 48 WCAG 2.2 AA accessibility issues (#439) 2026-05-17 20:11:38 -07:00
routes.ts Phase A: external HTTP cron jobs for snapshots, standings sync, and simulation (#79) 2026-06-08 07:42:14 +00:00