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>
Replace synchronous account→core game-creation HTTP call and plain
pub/sub bot game-start events with Redis Streams using consumer groups,
XACK, retry, and a Dead Letter Queue for at-least-once delivery and
observability.
- account: GameCreationStreamClient publishes game-creation requests and
correlates responses via a per-instance consumer group (NCS-91)
- core: GameCreationStreamListener consumes requests, calls
GameCreationService, publishes response events, retries, and routes
exhausted/unparseable events to the DLQ (NCS-91, NCS-93, NCS-94)
- official-bots: bot game-start events migrated from pub/sub to Streams
with consumer group, XACK, retry, and DLQ (NCS-92)
- account EventPublisher dual-writes to the stream and legacy pub/sub
channel for backward compatibility
- all flows use the typed EventEnvelope (eventId/type/payload/timestamp/
correlationId) with DLQ error context (eventType, error, attempt)
- register new DTOs and EventEnvelope/EventType for native reflection
Closes NCS-91, NCS-92, NCS-93, NCS-94
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Janis Eccarius <eccariusjanis@gmail.com>
Reviewed-on: #62
- Add EventEnvelope case class (eventId, type, payload, timestamp, correlationId)
- Add EventType enum with all known event types
- Update account EventPublisher to use EventEnvelope instead of raw string interpolation
- Add EventEnvelope/EventType to account NativeReflectionConfig
- Add Jackson Scala and JSR310 modules to api dependencies
- Add api module dependency to account module
- Add NativeReflectionConfig rule to CLAUDE.md
Closes NCS-90
https://knockoutwhist.youtrack.cloud/issue/NCS-90
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reviewed-on: #61
Two bugs in move notation causing PGN import failures in LiChess:
1. Disambiguation: when two pieces of same type can reach same square,
SAN requires file/rank/full-square prefix (e.g. "Ndf3" not "Nf3").
Added disambiguate() in PgnExporter and disambiguatePiece() in
GameEngine, both querying allLegalMoves to find competing pieces.
2. Check/checkmate suffix: "+" and "#" were never appended.
PgnExporter now threads ctxAfter through moveToAlgebraic and
calls DefaultRules.isCheck/isCheckmate. GameEngine passes
PostMoveStatus to translateMoveToNotation for the same result.
Also removes dead notation code in executeMoveBody (result was never
used — not passed to MoveExecutedEvent).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Janis Eccarius <eccariusjanis@gmail.com>
Reviewed-on: #56
Default Agroal pool (max-size=20) exhausted under concurrent logins due to
bcrypt latency per request. Fixes NCS-87.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Track whether subscribeGame is being called and completing successfully
to diagnose empty game-writeback messages.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
When instance stream drops, immediately force delete the K8s pod (grace period 0). No waiting for health check or pod watch events.
Reduces failover latency and ensures stale pods don't linger.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Scale up: only if resource constrained (CPU/memory)
Scale down: only if NOT resource constrained AND game load low
Remove: triggering scale-up on unexpected instance failures
Keep: health monitoring (mark dead, delete pod, failover games) but no scaling
Prevents cascade scaling from transient health check failures.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>