Session 32: Grades pipeline + NFL/NHL wiring + rate limiting + audit cleanup (1718 tests)
- gradeSlateService writes grades:{sport} cache (closes content pipeline →
dataLevel full); fire-and-forget from oddsService.recordDownstream, gated
by shouldGradeSlate (off in test, GRADE_SLATE_ON_FETCH override)
- NFL/NHL wired: oddsService SPORT_KEYS/SPORT_MARKETS (correct the-odds-api
keys americanfootball_nfl/icehockey_nhl), proplineAdapter MARKETS, NHL
MARKET_MAP keys to avoid silent-zero
- rate limiting mounted on 8 public cached routers (odds/parlay 30/min,
rest 60/min)
- jsonlLogger writes to temp under test (no more dirtied tracked artifact);
5MB pipeline test given 20s timeout
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,37 @@ Player props now have abundance, not rationing.
|
||||
- **Game-level odds** — Tank01 (unchanged). Tank01 PLAYER PROPS = empty,
|
||||
do not wire.
|
||||
|
||||
## Grades Content Pipeline (Session 32)
|
||||
Closes the content pipeline: `contentTemplateService` reads a `grades:{sport}`
|
||||
cache "when present" but nothing wrote it, so slate/POTD never reached
|
||||
`dataLevel: 'full'`.
|
||||
- **Writer** — `gradeSlateService.gradeAndCacheSlate(sport, props, opts)`
|
||||
dedupes props to unique player+stat+line (cap 25, concurrency 5), grades
|
||||
BOTH sides via `analyzeViaEngine1` (engine1 is direction-aware — keeps the
|
||||
higher-confidence side), sorts by confidence desc, writes
|
||||
`grades:{sport}` = `{ grades, updated_at, source }` (TTL 2h). The legacy
|
||||
grade shape already matches `normalizeGrade` — no remap needed.
|
||||
- **Trigger** — fire-and-forget inside `oddsService.recordDownstream` (runs
|
||||
on a fresh odds fetch / cache MISS, NOT on cache hits). Does NOT hold the
|
||||
odds HTTP response. Gated by `shouldGradeSlate()`: ON by default, OFF when
|
||||
`NODE_ENV==='test'` (its feature-compute fan-out would pollute call-count
|
||||
assertions), override with `GRADE_SLATE_ON_FETCH=1`/`0`. `0` is the
|
||||
operator kill-switch if the per-prop feature-compute cost needs shedding.
|
||||
|
||||
## NFL/NHL Props (Session 32)
|
||||
NFL + NHL wired end-to-end. **the-odds-api keys are `americanfootball_nfl`
|
||||
and `icehockey_nhl`** (full-name prefix like `basketball_nba`) — NOT
|
||||
`football_nfl`/`hockey_nhl` (those are PropLine's keys in `proplineAdapter`).
|
||||
`oddsService.SPORT_KEYS` + `SPORT_MARKETS` carry both; `proplineAdapter.MARKETS`
|
||||
filled. NHL keys (`player_shots_on_goal`, `goalie_saves`) added to
|
||||
`MARKET_MAP` so NHL props don't silently normalize to zero in-season.
|
||||
|
||||
## Public Route Rate Limiting (Session 32)
|
||||
`middleware/rateLimit` (`createRateLimit`, in-memory per-IP, independent
|
||||
bucket per call site) now mounts via `router.use` at the top of every public
|
||||
cached router: odds + parlay = 30/min, schedule/gamelines/streaks/hotlist/
|
||||
content/lines/books = 60/min. `/api/analyze` keeps its own 10/min.
|
||||
|
||||
## Frontend ↔ Backend Wiring (Session 25 — non-obvious)
|
||||
A new Express route under `/api/*` is NOT reachable from the browser until
|
||||
a matching **Next.js proxy route** exists at `web/src/app/api/.../route.ts`
|
||||
|
||||
Reference in New Issue
Block a user