# Configuration and Contract Examples Example values that complement `../README.md` ยง4 and the OpenAPI contract. ## Local `.env` ```dotenv # HTTP and gRPC listeners BACKEND_HTTP_LISTEN_ADDR=:8080 BACKEND_GRPC_PUSH_LISTEN_ADDR=:8081 # Postgres BACKEND_POSTGRES_DSN=postgres://galaxy:galaxy@localhost:5432/galaxy_backend?sslmode=disable&search_path=backend # SMTP relay (mailpit by default for dev) BACKEND_SMTP_HOST=localhost BACKEND_SMTP_PORT=1025 BACKEND_SMTP_FROM=galaxy-backend@galaxy.test BACKEND_SMTP_TLS_MODE=none # Docker BACKEND_DOCKER_HOST=unix:///var/run/docker.sock BACKEND_DOCKER_NETWORK=galaxy-dev # Game engine BACKEND_GAME_STATE_ROOT=/var/lib/galaxy-game # Admin bootstrap BACKEND_ADMIN_BOOTSTRAP_USER=bootstrap BACKEND_ADMIN_BOOTSTRAP_PASSWORD=change-me-immediately # GeoLite2 BACKEND_GEOIP_DB_PATH=/var/lib/galaxy/geoip.mmdb # Telemetry (stdout for dev) BACKEND_OTEL_TRACES_EXPORTER=stdout BACKEND_OTEL_METRICS_EXPORTER=stdout ``` The above is enough for `go run ./backend/cmd/backend` to boot locally. Required-but-empty admin variables can be set to `bootstrap` and any non-empty password; rotate immediately after first sign-in. ## Public REST examples ### `POST /api/v1/public/auth/send-email-code` ```http POST /api/v1/public/auth/send-email-code HTTP/1.1 Host: backend.internal Content-Type: application/json Accept-Language: en-US {"email": "pilot@example.com"} ``` ```http HTTP/1.1 200 OK Content-Type: application/json {"challenge_id": "9c8c47f0-3a9a-4f1d-8b7d-2bfca6c6a431"} ``` The `Accept-Language` header is captured as `preferred_language` for the new account; the body schema rejects unknown fields, so locale must travel through the header. ### `POST /api/v1/public/auth/confirm-email-code` ```http POST /api/v1/public/auth/confirm-email-code HTTP/1.1 Host: backend.internal Content-Type: application/json { "challenge_id": "9c8c47f0-3a9a-4f1d-8b7d-2bfca6c6a431", "code": "123456", "client_public_key": "", "time_zone": "Europe/Berlin" } ``` ```http HTTP/1.1 200 OK Content-Type: application/json {"device_session_id": "5e7ae3e6-3f4f-4d59-9b9b-2f2c3d2e0a91"} ``` ## Internal REST examples (gateway-only) ```http GET /api/v1/internal/sessions/5e7ae3e6-3f4f-4d59-9b9b-2f2c3d2e0a91 HTTP/1.1 Host: backend.internal ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "device_session_id": "5e7ae3e6-...", "user_id": "f3a17a32-...", "client_public_key": "", "status": "active" } ``` ```http POST /api/v1/internal/sessions/5e7ae3e6-.../revoke HTTP/1.1 Host: backend.internal ``` ## Admin REST examples ```http GET /api/v1/admin/mail/deliveries?page=1&page_size=10 HTTP/1.1 Host: backend.internal Authorization: Basic ``` ```http HTTP/1.1 200 OK Content-Type: application/json { "items": [ { "delivery_id": "...", "template_id": "auth.login_code", "status": "sent", "attempts": 1, "next_attempt_at": null, "created_at": "2026-05-05T06:34:46Z" } ], "total": 1 } ``` Resend on a `sent` row returns `409 Conflict`: ```http POST /api/v1/admin/mail/deliveries/{id}/resend HTTP/1.1 Authorization: Basic ... ``` ```http HTTP/1.1 409 Conflict Content-Type: application/json {"error": {"code": "conflict", "message": "delivery already sent"}} ``` ## Standard error envelope Every error response across the four route groups uses: ```json {"error": {"code": "", "message": ""}} ``` The closed set of `code` values lives in `components/schemas/ErrorBody` of `../openapi.yaml`.