Added detailed implementation plan for step '1.2 Shared Backend Packages'
parent
ed99d88d92
commit
78e9720c25
@ -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
|
||||
Loading…
Reference in New Issue