Release: Scouting API, roster refactor, and bug fixes #61

Merged
cal merged 46 commits from next-release into main 2026-03-09 14:12:42 +00:00
Owner

Summary

New Features

  • Scouting API — Added scout_opportunities and scout_claims tables and endpoints (#44)
  • Roster refactor — Replaced 26 FK columns with RosterSlot junction table (#29)

Bug Fixes

  • Security: Use constant-time comparison for bearer token validation (#8)
  • Security: Remove plaintext bearer token from warning logs (#7)
  • Performance: Batch BattingCard/BattingCardRatings lookups in lineup builder (#18)
  • Performance: Batch-fetch PitchingCardRatings instead of per-row queries (#19)
  • Performance: Replace 467 manual db.close() calls with middleware (#30)
  • Data: Fix inverted TESTING env check and leading space in .env (#23)
  • Data: Respect is_ai=False in get_teams filter (#22)
  • Data: Remove duplicate ranking_max filter in get_teams (#21)
  • Data: Compute CSV after appending data row in get_one_player (#12)
  • Data: Guard against None rating objects in pitcher sorting (#13)
  • Data: Use Field(default_factory) for offense_col random default (#24)
  • Data: Remove dead roster fields from CSV in v1_cards_get_one (#25)
  • API: Consolidate redundant double-query in get_one_play (#14)
  • API: Remove broken live_update_batting stub endpoint (#10)
  • API: Add type annotations to untyped path parameters (#27)
  • API: Remove debug print(req.scope) from get_docs route (#31)

Cleanup

  • Replace broad except Exception blocks with DoesNotExist (#15)
  • Centralize logging config in main.py — remove basicConfig from 32 files (#26)
  • Document SQLite synchronous=0 pragma in db_engine.py (#20)

CI/CD

  • Use docker-tags composite action for multi-channel release support

Resolved Issues

Closes #7, #8, #10, #12, #13, #14, #15, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #29, #30, #31, #44

## Summary ### New Features - **Scouting API** — Added `scout_opportunities` and `scout_claims` tables and endpoints (#44) - **Roster refactor** — Replaced 26 FK columns with `RosterSlot` junction table (#29) ### Bug Fixes - **Security**: Use constant-time comparison for bearer token validation (#8) - **Security**: Remove plaintext bearer token from warning logs (#7) - **Performance**: Batch BattingCard/BattingCardRatings lookups in lineup builder (#18) - **Performance**: Batch-fetch PitchingCardRatings instead of per-row queries (#19) - **Performance**: Replace 467 manual `db.close()` calls with middleware (#30) - **Data**: Fix inverted `TESTING` env check and leading space in `.env` (#23) - **Data**: Respect `is_ai=False` in `get_teams` filter (#22) - **Data**: Remove duplicate `ranking_max` filter in `get_teams` (#21) - **Data**: Compute CSV after appending data row in `get_one_player` (#12) - **Data**: Guard against None rating objects in pitcher sorting (#13) - **Data**: Use `Field(default_factory)` for `offense_col` random default (#24) - **Data**: Remove dead roster fields from CSV in `v1_cards_get_one` (#25) - **API**: Consolidate redundant double-query in `get_one_play` (#14) - **API**: Remove broken `live_update_batting` stub endpoint (#10) - **API**: Add type annotations to untyped path parameters (#27) - **API**: Remove debug `print(req.scope)` from get_docs route (#31) ### Cleanup - Replace broad `except Exception` blocks with `DoesNotExist` (#15) - Centralize logging config in `main.py` — remove `basicConfig` from 32 files (#26) - Document SQLite `synchronous=0` pragma in `db_engine.py` (#20) ### CI/CD - Use `docker-tags` composite action for multi-channel release support ## Resolved Issues Closes #7, #8, #10, #12, #13, #14, #15, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #29, #30, #31, #44
cal added 46 commits 2026-03-09 14:12:18 +00:00
fix: remove debug print(req.scope) from get_docs route (#31)
All checks were successful
Build Docker Image / build (pull_request) Successful in 9m50s
65ad72c299
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #32
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`all_teams.where(Team.is_ai)` always filtered for AI teams regardless
of the caller's intent. Match the existing has_guide pattern and use
explicit boolean comparison so False is handled correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #41
- Change `== 'False'` to `== 'True'` so TESTING=True routes to dev URL
- Fix leading space on TESTING=TRUE in .env so the var is actually set
- Update .env comment to match corrected logic

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #40
Card model has no roster1/2/3 fields. Accessing them would raise
AttributeError at runtime. Removed the non-existent columns from
the CSV header and data row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #35
Pydantic evaluates bare `random.randint(1, 3)` once at class definition
time, so every PlayerModel instance shared the same value. Replaced with
`pydantic.Field(default_factory=...)` so a new random value is generated
per instance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #38
Add db_session_middleware to main.py that opens the connection at the
start of each request and closes it in a try/finally block, ensuring
connections are always returned even on uncaught exceptions.

Remove all individual db.close() calls from 30 router files in
app/routers_v2/ — the middleware now handles all code paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed 55 unused imports across 26 router files. Most were `db` imports
left over after the db.close() removal in the previous commit, plus
additional stale imports (scipy.stats, chunked, copy, base64, Html2Image,
pandas.DataFrame, pydantic.validator, etc.) that were already unused.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #33
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #42
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #43
Replace two get_or_none calls per row in sort_pitchers and sort_starters
with a single batched SELECT for all card IDs, reducing N*2 queries to 1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #44
Moved logging.basicConfig() to app/main.py as the single source of truth.
Removed duplicate (no-op) calls from app/db_engine.py, app/dependencies.py,
and all 30 router files in app/routers_v2/. Removed the now-unused LOG_DATA
dict and date/log_level locals from dependencies.py and db_engine.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #46
Add explanatory comment clarifying that synchronous=OFF is a dev-only
trade-off (production uses PostgreSQL), and describing the crash-corruption
risk and how WAL mode partially mitigates it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #49
Add None checks for vlval/vrval in get_total_ops inside sort_pitchers()
and sort_starters(). Returns float("inf") when ratings are missing so
pitchers without ratings sort to the end rather than raising AttributeError.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #50
return_val was assigned from DataFrame(data_list).to_csv() before the
player data row was appended to data_list, so the CSV response contained
only the header row. Moved the to_csv() call to after the append.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #51
Reuse the result of get_or_none instead of discarding it and calling
get_by_id again, eliminating one unnecessary round-trip per request.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #52
Replace all logging.warning(f'Bad Token: {token}') calls with
logging.warning('Bad Token: [REDACTED]') across 30 router files.
Full bearer tokens were being written to log files on auth failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #55
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #56
Support the Discord bot's new scouting feature where players can scout
cards from other teams' opened packs. Stores opportunities with expiry
timestamps and tracks which teams claim which cards.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Creates scout_opportunity and scout_claim tables with foreign keys,
unique constraint on (opportunity, team), and expires_at index.
Already applied to dev database.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reviewed-on: #59
Replace per-player get_or_none() calls in get_bratings() with two bulk
SELECT queries before the position loop, keyed by player_id and card+hand.
This reduces DB round trips from O(3N) to O(2) for all lineup difficulties.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace 71 broad `except Exception` blocks in 19 router files with the
specific `peewee.DoesNotExist` exception. GET endpoints that call
`Model.get_by_id()` now only catch the expected DoesNotExist error,
allowing real DB failures (connection errors, etc.) to propagate as
500s rather than being masked as 404s.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The endpoint iterated over `files.vl_basic` (a string, not parsed CSV),
causing it to loop over individual characters. The body contained only
`pass` with TODO comments and no running stats logic. Removed the
endpoint entirely along with the dead commented-out csv helper code.
The `BattingFiles` model is retained as it is still used by
`live_update_pitching`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove card_1..card_26 FK columns from Roster ORM model
- Add RosterSlot model with (roster, slot, card) and a unique index on (roster, slot)
- Activate get_cards() helper on Roster using the new junction table
- Register RosterSlot in create_tables for SQLite dev environments
- Add migrations/migrate_roster_junction_table.py to backfill existing data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ci: Use docker-tags composite action for multi-channel release support
All checks were successful
Build Docker Image / build (push) Successful in 3m9s
10983138a9
Adds next-release branch trigger and replaces separate dev/production
build steps with the shared docker-tags action for tag resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reviewed-on: #45
Reviewed-on: #48
Reviewed-on: #54
Merge pull request 'fix: refactor Roster from 26 FK columns to RosterSlot junction table (#29)' (#58) from ai/paper-dynasty-database#29 into next-release
Some checks failed
Build Docker Image / build (push) Successful in 3m28s
Build Docker Image / build (pull_request) Has been cancelled
7295e77c96
Reviewed-on: #58
cal merged commit 7b8b7b9c01 into main 2026-03-09 14:12:42 +00:00
Sign in to join this conversation.
No description provided.