--- phase: 01-tournament-engine plan: 01 subsystem: infra tags: [go, nats, jetstream, libsql, websocket, chi, jwt, embed, sveltekit] # Dependency graph requires: [] provides: - Go binary scaffold with cmd/leaf entry point - Embedded NATS JetStream with AUDIT and STATE streams - LibSQL database with WAL mode and migration runner - WebSocket hub with JWT auth and tournament-scoped broadcasting - chi HTTP server with middleware (auth, CORS, body limits, timeouts) - SvelteKit SPA stub served via go:embed with fallback routing - Health endpoint reporting all subsystem status - Integration test suite (9 tests) affects: [01-tournament-engine] # Tech tracking tech-stack: added: - go-libsql v0.0.0-20251219133454 (pinned commit, no tagged releases) - nats-server v2.12.4 (embedded, JetStream sync=always) - nats.go v1.49.0 (client + jetstream package) - coder/websocket v1.8.14 - go-chi/chi v5.2.5 - golang-jwt/jwt v5.3.1 patterns: - Embedded NATS with DontListen=true, in-process client connection - WebSocket JWT auth via query parameter (not header) - Tournament-scoped broadcasting via client subscription - UUID validation before NATS subject construction (injection prevention) - go:embed SPA with fallback routing for client-side routing - Reverse-order graceful shutdown on signal key-files: created: - cmd/leaf/main.go - cmd/leaf/main_test.go - internal/nats/embedded.go - internal/nats/publisher.go - internal/server/server.go - internal/server/ws/hub.go - internal/server/middleware/auth.go - internal/server/middleware/role.go - internal/server/middleware/bodylimit.go - internal/store/db.go - internal/store/migrate.go - frontend/embed.go - frontend/build/index.html - Makefile - go.mod - go.sum modified: [] key-decisions: - "NATS JetStreamSyncInterval=0 (sync_interval: always) for single-node durability per Jepsen 2025" - "WebSocket JWT via query parameter rather than header (browser WebSocket API limitation)" - "Ephemeral JWT signing key (generated on startup) — will be persisted in a later plan" - "NATS server requires Go 1.24+ — upgraded from Go 1.23 (auto-resolved by go get)" - "Tournament validator is a stub (accepts all) — will validate against DB in auth plan" patterns-established: - "Embedded infrastructure: all services start in-process, no external dependencies" - "Tournament-scoped state: all broadcasting and events keyed by tournament ID" - "UUID validation on all NATS subject construction (security)" - "Integration tests with httptest.NewServer and t.TempDir() for isolation" requirements-completed: [ARCH-01, ARCH-04, ARCH-05, ARCH-06, ARCH-07] # Metrics duration: 15min completed: 2026-03-01 --- # Phase 1 Plan 01: Project Scaffold + Core Infrastructure Summary **Go binary embedding NATS JetStream (sync=always), LibSQL (WAL), WebSocket hub (JWT auth), chi HTTP server, and SvelteKit SPA via go:embed — all verified with 9 integration tests** ## Performance - **Duration:** 15 min - **Started:** 2026-03-01T02:27:38Z - **Completed:** 2026-03-01T02:42:58Z - **Tasks:** 2 - **Files modified:** 48 ## Accomplishments - Single Go binary compiles and runs with all infrastructure embedded — no external services required - NATS JetStream with mandatory sync_interval=always for single-node durability (Jepsen 2025 finding) - WebSocket hub authenticates via JWT query param, broadcasts tournament-scoped messages, drops slow consumers - Health endpoint reports status of all subsystems (database, NATS, WebSocket) - Full directory structure matching research recommendations with 30+ package stubs ## Task Commits Each task was committed atomically: 1. **Task A1: Initialize Go module and dependency tree** - `af13732` (feat) 2. **Task A2: Implement core infrastructure** - `16caa12` (feat) ## Files Created/Modified - `cmd/leaf/main.go` - Entry point: flags, startup orchestration, signal handling, graceful shutdown - `cmd/leaf/main_test.go` - 9 integration tests covering all verification criteria - `internal/nats/embedded.go` - Embedded NATS server with JetStream, AUDIT + STATE streams - `internal/nats/publisher.go` - Tournament-scoped publisher with UUID validation - `internal/server/server.go` - chi HTTP server with middleware, health endpoint, SPA handler - `internal/server/ws/hub.go` - WebSocket hub with JWT auth, tournament scoping, broadcasting - `internal/server/middleware/auth.go` - JWT validation middleware (Bearer header + raw token) - `internal/server/middleware/role.go` - Role-based access control (admin > floor > viewer) - `internal/server/middleware/bodylimit.go` - MaxBytesReader middleware (1MB default) - `internal/store/db.go` - LibSQL open with WAL, foreign keys, busy timeout - `internal/store/migrate.go` - Embedded SQL migration runner with dev-only migrations - `frontend/embed.go` - go:embed handler with SPA fallback routing - `frontend/build/index.html` - Stub HTML with Catppuccin Mocha dark theme colors - `Makefile` - build, run, run-dev, test, frontend, all, clean targets - `go.mod` / `go.sum` - Module definition with all dependencies pinned ## Decisions Made - NATS server v2.12.4 requires Go 1.24+ — upgraded automatically from 1.23 - WebSocket JWT passed via query parameter (browser WebSocket API does not support custom headers) - JWT signing key is ephemeral (random per startup) — will be persisted to disk in auth plan - Tournament validator stub accepts all — real validation deferred to auth/tournament plans - Added `run-dev` Makefile target for development mode with seed data ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] Store package auto-populated by linter** - **Found during:** Task A1 (directory structure creation) - **Issue:** The db.go and migrate.go files were auto-populated with full implementations including migration runner, replacing my stub package declarations - **Fix:** Kept the auto-populated implementations (correct and useful), removed my redundant migrations.go stub - **Files modified:** internal/store/db.go, internal/store/migrate.go - **Verification:** go build and go vet pass - **Committed in:** af13732 (Task A1 commit) **2. [Rule 3 - Blocking] Go 1.24 required by NATS server v2.12.4** - **Found during:** Task A2 (dependency installation) - **Issue:** nats-server v2.12.4 requires go >= 1.24.0, but go.mod specified 1.23.6 - **Fix:** go toolchain auto-resolved by upgrading go directive to 1.24.0 in go.mod - **Files modified:** go.mod - **Verification:** go build succeeds, all tests pass - **Committed in:** 16caa12 (Task A2 commit) --- **Total deviations:** 2 auto-fixed (2 blocking) **Impact on plan:** Both auto-fixes were necessary for compilation. No scope creep. ## Issues Encountered - Go 1.23.6 installed on system but NATS v2.12.4 required Go 1.24+ — resolved automatically by Go toolchain management - Port 8080 remained bound after manual server test — cleaned up with lsof before re-test ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - Infrastructure scaffold complete — ready for database schema (Plan 02), auth (Plan 03), and all subsequent plans - All subsystems verified operational via integration tests - Tournament-scoped architecture established from day one (MULTI-01) ## Self-Check: PASSED All 16 created files verified present. Both commit hashes (af13732, 16caa12) found in git log. SUMMARY.md exists at expected path. --- *Phase: 01-tournament-engine* *Completed: 2026-03-01*