You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.8 KiB
8.8 KiB
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
- Build and finalize shared domain primitives (errors, events, types, value objects)
- Provide infra helpers (auth, DB, observability, utils, security)
- Replace placeholder implementations with production-ready behavior
- 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.gobackend/shared/domain/errors/codes.go
Keep:
DomainErrorwithCode,Message,ErrWrap,New,Unwrap- Error code constants
Add or confirm:
- Stable error code list
errors.Iscompatibility 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.gobackend/shared/domain/events/contracts.go
Keep:
Eventinterface withEventType,OccurredAt,AggregateID,AggregateTypeEventBuswithPublishandSubscribe- Event type constants for game, user, question, leaderboard
NewBaseEventhelper
Acceptance criteria:
- Event interfaces match current definitions
- Event types are enumerated and documented
Task 3: Domain Types
Files:
backend/shared/domain/types/id.gobackend/shared/domain/types/pagination.gobackend/shared/domain/types/enums.go
Keep:
- UUID
IDtype 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.gobackend/shared/domain/valueobjects/score.go
Keep:
- PlayerName validation and normalization
- Score and Attempt utilities
Decision:
- Do not introduce
time_window.goin 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.gobackend/shared/infra/auth/zitadel/middleware.gobackend/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/v3for JWKS discovery + refresh - Use OIDC discovery at
{BaseURL}/.well-known/openid-configuration - Implement
ValidateToken:- Fetch discovery document and
jwks_uri - Parse JWT with JWKS
- Validate signature,
iss,aud, expiry - Extract claims into
AuthClaims - Set
MFAVerifiedbased onamrcontainingmfaorotp
- Fetch discovery document and
- Implement
RefreshTokenandRevokeTokenusing discovery endpoints - Keep
JWTMiddlewarebehavior 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
adminrole and MFA verified - Unit tests for token validation and MFA logic
Task 6: Database Clients (Postgres + Redis)
Files:
backend/shared/infra/database/postgres/client.gobackend/shared/infra/database/redis/client.go
Postgres implementation:
- Keep shared package minimal: config/env parsing and connection string helpers
- Implement
ConfigFromEnvusingos.Getenvwith defaults - Add lightweight
HealthCheckhelper 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
ConfigFromEnvusingos.Getenvwith 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.gobackend/shared/infra/observability/tracing/tracer.gobackend/shared/infra/observability/metrics/prometheus.go
Logging:
- Keep zerolog wrapper and document config options
Tracing implementation:
- Add dependencies:
go.opentelemetry.io/otelgo.opentelemetry.io/otel/sdk/tracego.opentelemetry.io/otel/exporters/jaegergo.opentelemetry.io/otel/sdk/resource
- Implement
NewTracer:- Build Jaeger exporter with
JaegerEndpoint - Configure sampler with
SampleRate - Set global tracer provider and resource attributes
- Build Jaeger exporter with
- Implement
Shutdown - Update
StartSpanto return real spans - Implement
ConfigFromEnv
Metrics:
- Keep existing metrics definitions
- Add helper to expose
/metricsusingpromhttp.Handler()in newmetrics/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.gobackend/shared/infra/utils/httputil/errors.gobackend/shared/infra/utils/httputil/pagination.gobackend/shared/infra/utils/validation/validator.go
Keep:
- Response envelope and pagination helpers
- Error mapping to HTTP status
- Validator with custom tags
Add or confirm:
MapErrorcovers 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.ValidateTokenbecomes fully implemented with JWKS validationinfra/auth/zitadel.Client.RefreshTokenandRevokeTokenimplementedinfra/database/postgresremains a minimal helper package (config/env + health check)infra/database/redis.Clientwraps*redis.Clientinfra/observability/tracing.Traceruses OpenTelemetry and returns real spans- New helper in metrics:
metrics.Handler()ormetrics.PrometheusHandler()
Test Plan
Add or extend unit tests for:
- JWT validation with JWKS (mocked discovery)
- MFA detection via
amrclaim - Postgres config parsing and health check error behavior
- Redis CRUD behavior (use
miniredisor mocked client) - Tracing initialization and shutdown behavior
- Metrics handler creation
Existing unit tests should remain valid and may be expanded.
Verification Checklist
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