From 78e9720c25fbdab9fbc513a279383c10f220036f Mon Sep 17 00:00:00 2001 From: oabrivard Date: Thu, 5 Feb 2026 22:11:18 +0100 Subject: [PATCH] Added detailed implementation plan for step '1.2 Shared Backend Packages' --- .../1.2-shared-backend-packages.md | 322 ++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 docs/4_work_plan/1.2-shared-backend-packages.md diff --git a/docs/4_work_plan/1.2-shared-backend-packages.md b/docs/4_work_plan/1.2-shared-backend-packages.md new file mode 100644 index 0000000..21af302 --- /dev/null +++ b/docs/4_work_plan/1.2-shared-backend-packages.md @@ -0,0 +1,322 @@ +# 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:** +- Add dependency: `github.com/jackc/pgx/v5/pgxpool` +- Replace placeholder client with wrapper around `*pgxpool.Pool` +- Implement `NewClient(ctx, cfg)` with config validation +- Implement `Ping`, `Close`, `HealthCheck` +- Implement `ConfigFromEnv` using `os.Getenv` with defaults + +**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:** +- Clients connect successfully via `ConfigFromEnv` +- 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.Client` wraps `*pgxpool.Pool` +- `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 validation and connection errors +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