# 1.2 Shared Backend Packages - Detailed Implementation Plan (Aligned to Current Codebase) ## Overview | Attribute | Value | |-----------|-------| | **Priority** | HIGH | | **Duration** | 3-4 days | | **Dependencies** | Phase 1.1 complete (Go workspace, linting) | | **Team Size** | 1-2 developers | ## Objectives 1. Build and finalize shared domain primitives (errors, events, types, value objects) 2. Provide infra helpers (auth, DB, observability, utils, security) 3. Replace placeholder implementations with production-ready behavior 4. Ensure unit test coverage and stable public APIs --- ## Target Package Structure (Current) ``` backend/shared/ ├── domain/ │ ├── errors/ │ ├── events/ │ ├── types/ │ └── valueobjects/ └── infra/ ├── auth/ │ ├── zitadel/ │ └── rbac/ ├── database/ │ ├── postgres/ │ └── redis/ ├── observability/ │ ├── logging/ │ ├── metrics/ │ └── tracing/ ├── security/ └── utils/ ├── httputil/ └── validation/ ``` --- ## Task Breakdown ### Task 1: Domain Errors **Files:** - `backend/shared/domain/errors/errors.go` - `backend/shared/domain/errors/codes.go` **Keep:** - `DomainError` with `Code`, `Message`, `Err` - `Wrap`, `New`, `Unwrap` - Error code constants **Add or confirm:** - Stable error code list - `errors.Is` compatibility as implemented - HTTP mapping documented via `infra/utils/httputil/errors.go` **Acceptance criteria:** - Error codes are stable and exhaustive for current domains - Errors wrap and compare predictably - HTTP mapping is documented and tested in httputil --- ### Task 2: Domain Events **Files:** - `backend/shared/domain/events/event.go` - `backend/shared/domain/events/contracts.go` **Keep:** - `Event` interface with `EventType`, `OccurredAt`, `AggregateID`, `AggregateType` - `EventBus` with `Publish` and `Subscribe` - Event type constants for game, user, question, leaderboard - `NewBaseEvent` helper **Acceptance criteria:** - Event interfaces match current definitions - Event types are enumerated and documented --- ### Task 3: Domain Types **Files:** - `backend/shared/domain/types/id.go` - `backend/shared/domain/types/pagination.go` - `backend/shared/domain/types/enums.go` **Keep:** - UUID `ID` type and validation - Pagination helpers and bounds - Shared enums: session status, difficulty, roles, completion types **Add or confirm:** - Pagination normalization logic documented **Acceptance criteria:** - IDs validate UUID format - Pagination bounds are enforced - Enums are centralized and reused --- ### Task 4: Value Objects **Files:** - `backend/shared/domain/valueobjects/player_name.go` - `backend/shared/domain/valueobjects/score.go` **Keep:** - PlayerName validation and normalization - Score and Attempt utilities **Decision:** - Do not introduce `time_window.go` in this phase (not referenced in codebase) **Acceptance criteria:** - Player name validation is deterministic - Score helpers are documented and tested --- ### Task 5: Auth (Zitadel + RBAC) **Files:** - `backend/shared/infra/auth/zitadel/client.go` - `backend/shared/infra/auth/zitadel/middleware.go` - `backend/shared/infra/auth/rbac/roles.go` **Goal:** Replace placeholder JWT validation with real Zitadel token validation. **Implementation details:** - Add dependency: `github.com/golang-jwt/jwt/v5` - Add dependency: `github.com/MicahParks/keyfunc/v3` for JWKS discovery + refresh - Use OIDC discovery at `{BaseURL}/.well-known/openid-configuration` - Implement `ValidateToken`: 1. Fetch discovery document and `jwks_uri` 2. Parse JWT with JWKS 3. Validate signature, `iss`, `aud`, expiry 4. Extract claims into `AuthClaims` 5. Set `MFAVerified` based on `amr` containing `mfa` or `otp` - Implement `RefreshToken` and `RevokeToken` using discovery endpoints - Keep `JWTMiddleware` behavior and tests (fake validator pattern) - Keep RBAC helpers unchanged **Acceptance criteria:** - JWT validation works with real JWKS - Issuer and audience checks enforced - Admin endpoints require `admin` role and MFA verified - Unit tests for token validation and MFA logic --- ### Task 6: Database Clients (Postgres + Redis) **Files:** - `backend/shared/infra/database/postgres/client.go` - `backend/shared/infra/database/redis/client.go` **Postgres implementation:** - Keep shared package minimal: config/env parsing and connection string helpers - Implement `ConfigFromEnv` using `os.Getenv` with defaults - Add lightweight `HealthCheck` helper for connectivity validation - Do **not** introduce a shared runtime Postgres data client - Each service initializes and manages Ent directly for Postgres access **Redis implementation:** - Add dependency: `github.com/redis/go-redis/v9` - Replace placeholder client with wrapper around `*redis.Client` - Implement `Set`, `Get`, `Delete`, `Exists`, `Incr`, `Expire` - Implement `ConfigFromEnv` using `os.Getenv` with defaults **Acceptance criteria:** - Postgres helper is minimal and does not duplicate Ent responsibilities - Postgres and Redis health checks are real and return errors on failure - Redis CRUD methods implemented and tested --- ### Task 7: Observability **Files:** - `backend/shared/infra/observability/logging/logger.go` - `backend/shared/infra/observability/tracing/tracer.go` - `backend/shared/infra/observability/metrics/prometheus.go` **Logging:** - Keep zerolog wrapper and document config options **Tracing implementation:** - Add dependencies: - `go.opentelemetry.io/otel` - `go.opentelemetry.io/otel/sdk/trace` - `go.opentelemetry.io/otel/exporters/jaeger` - `go.opentelemetry.io/otel/sdk/resource` - Implement `NewTracer`: 1. Build Jaeger exporter with `JaegerEndpoint` 2. Configure sampler with `SampleRate` 3. Set global tracer provider and resource attributes - Implement `Shutdown` - Update `StartSpan` to return real spans - Implement `ConfigFromEnv` **Metrics:** - Keep existing metrics definitions - Add helper to expose `/metrics` using `promhttp.Handler()` in new `metrics/http.go` - Implement `ConfigFromEnv` **Acceptance criteria:** - Tracing works with Jaeger collector endpoint - Metrics are registerable and exposable via HTTP - Tests cover tracer init and metrics handler creation --- ### Task 8: Infra Utils **Files:** - `backend/shared/infra/utils/httputil/response.go` - `backend/shared/infra/utils/httputil/errors.go` - `backend/shared/infra/utils/httputil/pagination.go` - `backend/shared/infra/utils/validation/validator.go` **Keep:** - Response envelope and pagination helpers - Error mapping to HTTP status - Validator with custom tags **Add or confirm:** - `MapError` covers all domain codes - Validation errors return `CodeValidationFailed` **Acceptance criteria:** - HTTP helpers are consistent across services - Validation errors are readable and standardized --- ### Task 9: Infra Security **Files:** - `backend/shared/infra/security/sanitize.go` **Keep:** - Sanitize helpers for player name, answer, question text, theme **Add or confirm:** - Document allowed patterns and length limits - Tests cover dangerous pattern detection **Acceptance criteria:** - Sanitization functions are deterministic - Edge cases are tested --- ## Public API or Interface Changes - `infra/auth/zitadel.Client.ValidateToken` becomes fully implemented with JWKS validation - `infra/auth/zitadel.Client.RefreshToken` and `RevokeToken` implemented - `infra/database/postgres` remains a minimal helper package (config/env + health check) - `infra/database/redis.Client` wraps `*redis.Client` - `infra/observability/tracing.Tracer` uses OpenTelemetry and returns real spans - New helper in metrics: `metrics.Handler()` or `metrics.PrometheusHandler()` --- ## Test Plan Add or extend unit tests for: 1. JWT validation with JWKS (mocked discovery) 2. MFA detection via `amr` claim 3. Postgres config parsing and health check error behavior 4. Redis CRUD behavior (use `miniredis` or mocked client) 5. Tracing initialization and shutdown behavior 6. Metrics handler creation Existing unit tests should remain valid and may be expanded. --- ## Verification Checklist ```bash cd backend/shared go test ./... golangci-lint run ./... ``` --- ## Estimated Time Breakdown | Task | Duration | Cumulative | |------|----------|------------| | Domain errors | 2-3 hours | 3 hours | | Domain events | 2-3 hours | 6 hours | | Domain types | 2-3 hours | 9 hours | | Value objects | 2-3 hours | 12 hours | | Auth (Zitadel + RBAC) | 6-8 hours | 20 hours | | Database (Postgres + Redis) | 6-8 hours | 28 hours | | Observability | 6-8 hours | 36 hours | | Utils | 3-4 hours | 40 hours | | Security | 2-3 hours | 43 hours | | Tests/Docs/Review | 4-6 hours | 49 hours | --- ## Next Steps After Completion - Proceed to Phase 2.1: Question Bank Service - Use shared packages in service implementations