# Configuration And Contract Examples The examples below are illustrative. Replace `localhost`, port numbers, IDs, and timestamps with values that match the deployment under inspection. ## Example `.env` A minimum-viable `LOBBY_*` set for a local run against a single Redis container plus a PostgreSQL container with the `lobby` schema and the `lobbyservice` role provisioned. The full list with defaults lives in `../README.md` §Configuration. ```bash LOBBY_REDIS_MASTER_ADDR=127.0.0.1:6379 LOBBY_REDIS_PASSWORD=local LOBBY_POSTGRES_PRIMARY_DSN=postgres://lobbyservice:lobbyservice@127.0.0.1:5432/galaxy?search_path=lobby&sslmode=disable LOBBY_USER_SERVICE_BASE_URL=http://127.0.0.1:8083 LOBBY_GM_BASE_URL=http://127.0.0.1:8096 LOBBY_PUBLIC_HTTP_ADDR=:8094 LOBBY_INTERNAL_HTTP_ADDR=:8095 LOBBY_LOG_LEVEL=info LOBBY_SHUTDOWN_TIMEOUT=30s LOBBY_RACE_NAME_DIRECTORY_BACKEND=postgres LOBBY_ENROLLMENT_AUTOMATION_INTERVAL=30s LOBBY_RACE_NAME_EXPIRATION_INTERVAL=1h OTEL_SERVICE_NAME=galaxy-lobby OTEL_TRACES_EXPORTER=none OTEL_METRICS_EXPORTER=none LOBBY_OTEL_STDOUT_TRACES_ENABLED=false LOBBY_OTEL_STDOUT_METRICS_ENABLED=false ``` ## Public HTTP Examples The public listener trusts the `X-User-ID` header injected by Edge Gateway. Direct calls during development can supply the header manually. ### Submit an application to a public game ```bash curl -s -X POST \ -H 'Content-Type: application/json' \ -H 'X-User-ID: user-01HZ...' \ http://localhost:8094/api/v1/lobby/games/game-01HZ.../applications \ -d '{"race_name":"Aurora"}' ``` Response (`200 OK`): ```json { "application_id": "application-01HZ...", "game_id": "game-01HZ...", "user_id": "user-01HZ...", "status": "submitted", "created_at": 1714081234567 } ``` ### List my open invites ```bash curl -s \ -H 'X-User-ID: user-01HZ...' \ 'http://localhost:8094/api/v1/lobby/my/invites?page_size=50' ``` ### Register a race name from a pending entry ```bash curl -s -X POST \ -H 'Content-Type: application/json' \ -H 'X-User-ID: user-01HZ...' \ http://localhost:8094/api/v1/lobby/race-names/register \ -d '{"race_name":"Aurora"}' ``` A `422` response with `error.code="race_name_pending_window_expired"` indicates the 30-day window has elapsed and the user must enter a new game to re-establish eligibility. ## Internal HTTP Examples The internal listener admits the admin actor without `X-User-ID` and serves GM-facing read paths. ### Create a public game (admin) ```bash curl -s -X POST \ -H 'Content-Type: application/json' \ http://localhost:8095/api/v1/lobby/games \ -d '{ "game_name": "Spring Tournament", "game_type": "public", "min_players": 4, "max_players": 12, "start_gap_hours": 24, "start_gap_players": 4, "enrollment_ends_at": 1716673200, "turn_schedule": "0 18 * * *", "target_engine_version": "1.4.0" }' ``` ### Read a game record (Game Master) ```bash curl -s http://localhost:8095/api/v1/internal/games/game-01HZ... ``` ### List memberships for a running game (Game Master) ```bash curl -s http://localhost:8095/api/v1/internal/games/game-01HZ.../memberships ``` ## Storage Inspection Examples ### Inspect a game record (PostgreSQL) ```bash psql "$LOBBY_POSTGRES_PRIMARY_DSN" -c \ "SELECT * FROM lobby.games WHERE game_id = 'game-01HZ...'" ``` The columns mirror the fields documented in `../README.md` §Game Record Model. ### Inspect open enrollment games (sorted by created_at) ```bash psql "$LOBBY_POSTGRES_PRIMARY_DSN" -c \ "SELECT game_id, game_name, created_at FROM lobby.games WHERE status = 'enrollment_open' ORDER BY created_at DESC" ``` ### Inspect a Race Name Directory binding ```bash psql "$LOBBY_POSTGRES_PRIMARY_DSN" -c \ "SELECT canonical_key, game_id, holder_user_id, race_name, binding_kind, source_game_id, eligible_until_ms, registered_at_ms FROM lobby.race_names WHERE race_name = 'Aurora'" ``` ## Redis Examples ### Publish a runtime job result (Runtime Manager simulation) Runtime Manager would normally publish this. The shape matches the consumer in `internal/worker/runtimejobresult/consumer.go`. ```bash redis-cli XADD runtime:job_results '*' \ job_id 'runtime-job-01HZ...' \ game_id 'game-01HZ...' \ outcome 'success' \ container_id 'container-7f...' \ engine_endpoint '127.0.0.1:9100' \ bound_at_ms 1714081239876 ``` ### Publish a Game Master runtime snapshot update ```bash redis-cli XADD gm:lobby_events '*' \ kind 'runtime_snapshot_update' \ game_id 'game-01HZ...' \ current_turn '12' \ runtime_status 'healthy' \ engine_health_summary 'ok' \ player_turn_stats '[{"user_id":"user-01HZ...","planets":4,"population":900,"ships_built":17}]' ``` ### Publish a game-finished event ```bash redis-cli XADD gm:lobby_events '*' \ kind 'game_finished' \ game_id 'game-01HZ...' \ finished_at_ms 1714123456789 ``` ## Notification Intent Format Lobby produces every notification through `pkg/notificationintent` and appends to `notification:intents` with plain `XADD`. A representative intent for `lobby.application.submitted`: ```bash redis-cli XADD notification:intents '*' \ envelope '{ "type": "lobby.application.submitted", "producer": "lobby", "idempotency_key": "lobby.application.submitted:application-01HZ...", "audience": {"kind": "admin_email", "email_address_kind": "lobby_application_submitted"}, "payload": { "game_id": "game-01HZ...", "game_name": "Spring Tournament", "applicant_user_id": "user-01HZ...", "applicant_name": "Aurora" } }' ``` The exact field set per type is documented in `../../notification/README.md` and frozen by the AsyncAPI spec under `../../notification/api/intents-asyncapi.yaml`.