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.
knowfoolery/docs/4_work_plan/1.2-shared-backend-packages.md

8.7 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

  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

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