Reverts the Hibernate-related changes introduced during PR review:
- Remove nullable = false from OfficialBotAccount.token (caused PropertyValueException
at first persist() since token is assigned after id is generated)
- Restore double persist() pattern: first persist() gets generated UUID, then token
is generated using that id and entity is persisted again with dirty tracking
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pre-assigning bot.id on a @GeneratedValue entity causes Hibernate 6 to treat
it as detached, throwing PersistentObjectException on persist(). Fix: persist
with null id (Hibernate assigns UUID immediately in-memory), then set token on
the now-managed entity — dirty tracking commits the token at transaction flush.
No second persist() call needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Restore @RolesAllowed("Admin") on official bot creation (security regression)
- Pre-assign UUID before first persist in createOfficialBotAccount/syncOfficialBots
to eliminate two-persist fragility (token-less entity on second-write failure)
- Add nullable = false to OfficialBotAccount.token column
- Replace JSON string interpolation in publishBotGameStart with objectMapper
- Replace specific hprof PID filename in .gitignore with *.hprof wildcard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace null with Option in GameResultStreamListener, PairingRepository,
ParticipantRepository, TournamentService
- Replace isInstanceOf checks with pattern matching in GameResultStreamListener
- Wrap var in SwissPairingService resolveConflicts with scalafix:off
- Apply spotlessScalaApply formatting across tournament and official-bots modules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add token field to OfficialBotAccount and generate a non-expiring bot
JWT on creation so official bots can authenticate
- Expose token in POST /api/account/official-bots response and open the
endpoint to any authenticated user
- Bridge TournamentService to Redis: publish gameStart events to
nowchess:bot:<name>:events after each pairing so OfficialBotService
picks up games automatically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the full tournament lifecycle: create, join, withdraw, start,
round progression, and finish with Buchholz tiebreak standings.
- REST resource covering all 11 endpoints from the OpenAPI spec
- Swiss pairing algorithm with bye support
- Per-bot NDJSON stream with targeted gameStart events (color field)
- Game result ingestion via Redis writeback stream
- H2-backed integration tests for resource and pairing service
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>