Session 7j: Soccer intelligence - 9 leagues, 11 signals, 6 traps, poller, prefetch, 131 new tests (1173 total)
This commit is contained in:
@@ -60,6 +60,7 @@ Mounted in `src/app.js`. Auth column meanings:
|
||||
| GET | /api/health | public | n/a | `app.js` (inline) |
|
||||
| GET | /api/odds/nba | public | 10mb | `routes/odds.js` |
|
||||
| GET | /api/odds/ncaab | public | 10mb | `routes/odds.js` |
|
||||
| GET | /api/odds/soccer/:league | public | 10mb | `routes/odds.js` (Session 7j) |
|
||||
| POST | /api/analyze/prop | public + 10/min IP | 10mb | `routes/analyze.js` (cached 60s) |
|
||||
| POST | /api/analyze/batch | public + 10/min IP | 10mb | `routes/analyze.js` (cached 60s) |
|
||||
| POST | /api/scan/parlay | user | 10mb | `routes/scan.js` |
|
||||
@@ -190,6 +191,14 @@ back). Updated this session in Section 1 of Session 7c.
|
||||
| `PINNACLE_API_BASE` | ✓ commented (legacy) |
|
||||
| `ODDS_API_KEY` | ✓ commented (legacy) |
|
||||
|
||||
### Soccer / World Cup 2026 (Session 7j)
|
||||
| Var | Required | Default | Used By | Doc? |
|
||||
| ------------------------- | -------- | ------------------------------------------------ | ------------------------------------------------------- | ---- |
|
||||
| `FOOTBALL_DATA_API_KEY` | no | (none) | `footballDataAdapter`, `soccer-data-prefetch` | ✓ |
|
||||
| `SOCCER_LEAGUES` | no | `WC` | `poller/soccer.js`, `soccer-data-prefetch` | ✓ |
|
||||
| `WORLDCUP_API_URL` | no | `https://worldcup2026-api.up.railway.app/api/...` | `poller/soccer.js` | ✓ |
|
||||
| `RAPID_API_KEY` | no | (none) | reserved for `soccer-data-prefetch` referee enrichment | ✓ |
|
||||
|
||||
### Engine 2
|
||||
| Var | Doc? |
|
||||
| ---------------------------- | ---- |
|
||||
@@ -235,6 +244,11 @@ back). Updated this session in Section 1 of Session 7c.
|
||||
| `VYNDR_API_URL` | `http://localhost:3001` | ✓ commented |
|
||||
| `OFF_HOURS_POLL_MS` | hardcoded 5min | not env |
|
||||
|
||||
PM2 ecosystem (Session 7j) — four poller processes per container:
|
||||
- `poller-nba`, `poller-wnba`, `poller-mlb` (box-score resolution path via `poller/poller.js`)
|
||||
- `poller-soccer` (fixture indexing via `poller/soccer.js` — different
|
||||
data sources and cache shape; honors `SOCCER_LEAGUES` env)
|
||||
|
||||
### Backup + Ops
|
||||
| Var | Doc? |
|
||||
| ------------------------- | ---- |
|
||||
@@ -347,6 +361,10 @@ Source: `grep -rn "cacheSet\|cacheGet\|redis\.set"`.
|
||||
| Resend (email) | `web/src/services/email.ts` | `RESEND_API_KEY`, `RESEND_FROM_EMAIL` | n/a | transactional email |
|
||||
| NexaPay | `web/src/services/nexapay.ts` | `NEXAPAY_*` | n/a | checkout fallback |
|
||||
| PostHog | `web/src/lib/analytics.ts` | `NEXT_PUBLIC_POSTHOG_KEY/HOST` | n/a | browser analytics |
|
||||
| football-data.org | `footballDataAdapter.js` | `FOOTBALL_DATA_API_KEY` | 10/min (8 enforced) | poller-soccer, prefetch |
|
||||
| Stripe | `services/stripeService.js` | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRICE_*` | n/a | checkout + webhook |
|
||||
| The Odds API | `services/oddsService.js` | `ODDS_API_KEY` | quota tracked | per-sport odds endpoints |
|
||||
| worldcup2026 OSS | `poller/soccer.js` | `WORLDCUP_API_URL` | none (free) | WC fixture poll |
|
||||
|
||||
---
|
||||
|
||||
@@ -484,6 +502,19 @@ No circular imports detected.
|
||||
Full removal blocks on ARCH-1 Step 6 — the legacy book adapters
|
||||
retire together with the legacy grading path.
|
||||
|
||||
- **[ARCH-3] Soccer pipeline added as a parallel branch.** Severity:
|
||||
Info. Status: **SHIPPED in Session 7j.** Soccer routes off
|
||||
`computeFeaturesForProp` to `soccerFeatureExtractor` when
|
||||
`sport ∈ {'soccer','football'}`; trap detection branches on the same
|
||||
in `getTrapScore`; reasoning branches in `buildConcreteReasoning`.
|
||||
Engine1 is sport-agnostic (passes unknown feature keys through).
|
||||
Data flow: `poller/soccer.js` writes per-team `nextmatch` /
|
||||
`lastfixture` pointers; `scripts/soccer-data-prefetch.js` writes
|
||||
per-player + per-team-defense aggregates. The feature extractor
|
||||
reads ONLY from cache — no external HTTP on the user request path.
|
||||
Day-1 gap: xG fields (`xg_per_90`, `xg_delta`) are null until the
|
||||
soccerdata-Python bridge ships; engine handles the nulls gracefully.
|
||||
|
||||
### SEC — Security
|
||||
|
||||
- **[SEC-1] `/api/analyze/batch` has no auth or rate limit.** Severity:
|
||||
|
||||
Reference in New Issue
Block a user