Files
junhong_cmp_fiber/specs/001-fiber-middleware-integration/plan.md

383 lines
17 KiB
Markdown

# Implementation Plan: Fiber Middleware Integration with Configuration Management
**Branch**: `001-fiber-middleware-integration` | **Date**: 2025-11-10 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/001-fiber-middleware-integration/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
## Summary
Integrate essential Fiber middleware (logger, recover, requestid, keyauth, limiter) with unified response structure, Viper configuration hot reload, and Zap+Lumberjack logging. This establishes the foundational middleware layer for the 君鸿卡管系统, ensuring proper authentication, logging, error recovery, and request tracing capabilities following Go idiomatic patterns.
## Technical Context
**Language/Version**: Go 1.25.1
**Primary Dependencies**:
- Fiber v2.52.9 (HTTP framework)
- Sonic v1.14.2 (JSON encoding/decoding - already integrated)
- Viper (configuration with hot reload)
- Zap (structured logging)
- Lumberjack.v2 (log rotation)
- Redis client (for keyauth token validation)
**Storage**:
- Redis (for authentication token validation - token as key, user ID as value with TTL)
- Log files (app.log for application logs, access.log for HTTP access logs)
**Testing**:
- Go standard testing framework (`testing` package)
- Table-driven tests for middleware logic
- Integration tests for API endpoints with middleware
- Mock Redis for keyauth testing
**Target Platform**: Linux server (production), macOS (development)
**Project Type**: Single backend web service (Go web application)
**Performance Goals**:
- API response time P95 < 200ms, P99 < 500ms
- Middleware overhead < 5ms per request
- Configuration hot reload detection within 5 seconds
- Log rotation without blocking requests
**Constraints**:
- No external authentication service (Redis-only token validation)
- Fail-closed authentication (Redis unavailable = HTTP 503)
- Zero downtime for configuration changes (hot reload)
- Separate log files with independent retention policies
**Scale/Scope**:
- Foundation for multi-module card management system
- ~10 initial API endpoints (will grow)
- Expected 1000+ req/s capacity
- 24/7 production availability requirement
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
**Tech Stack Adherence**:
- [x] Feature uses Fiber + Viper + Zap + Lumberjack.v2 + sonic JSON + Redis
- [x] No native calls bypass framework (no `net/http` direct use)
- [x] All HTTP operations use Fiber framework
- [x] All async tasks use Asynq (N/A for this feature - no async tasks)
- [x] Uses Go official toolchain: `go fmt`, `go vet`, `golangci-lint`
- [x] Uses Go Modules for dependency management (already initialized)
**Code Quality Standards**:
- [x] Follows Handler → Service → Store → Model architecture (keyauth validation follows this)
- [x] Handler layer only handles HTTP, no business logic
- [x] Service layer contains business logic with cross-module support
- [x] Store layer manages all data access with transaction support
- [x] Uses dependency injection via struct fields (not constructor patterns)
- [x] Unified error codes in `pkg/errors/` (will define auth error codes: 1001-1004)
- [x] Unified API responses via `pkg/response/` (core requirement: {code, data, msg})
- [x] All constants defined in `pkg/constants/` (Redis keys, error messages)
- [x] All Redis keys managed via key generation functions (no hardcoded strings)
- [x] All exported functions/types have Go-style doc comments
- [x] Code formatted with `gofmt`
- [x] Follows Effective Go and Go Code Review Comments
**Go Idiomatic Design**:
- [x] Package structure is flat (max 2-3 levels), organized by feature
- Structure: `pkg/config/`, `pkg/logger/`, `pkg/response/`, `pkg/errors/`, `pkg/constants/`
- Middleware: `internal/middleware/` (flat, no deep nesting)
- [x] Interfaces are small (1-3 methods), defined at use site
- TokenValidator interface (2 methods: ValidateToken, IsAvailable)
- [x] No Java-style patterns: no I-prefix, no Impl-suffix, no getters/setters
- [x] Error handling is explicit (return errors, no panic/recover abuse)
- Recover middleware captures panics only, normal errors use error returns
- [x] Uses composition over inheritance
- [x] Uses goroutines and channels for config hot reload watcher
- [x] Uses `context.Context` for cancellation and timeouts
- [x] Naming follows Go conventions: short receivers, consistent abbreviations (URL, ID, HTTP)
- [x] No Hungarian notation or type prefixes
- [x] Simple constructors (New/NewXxx), no Builder pattern unless necessary
**Testing Standards**:
- [x] Unit tests for all core business logic (token validation, config loading)
- [x] Integration tests for all API endpoints with middleware chain
- [x] Tests use Go standard testing framework
- [x] Test files named `*_test.go` in same directory
- [x] Test functions use `Test` prefix, benchmarks use `Benchmark` prefix
- [x] Table-driven tests for multiple test cases (especially middleware scenarios)
- [x] Test helpers marked with `t.Helper()`
- [x] Tests are independent (mock Redis, no external dependencies)
- [x] Target coverage: 70%+ overall, 90%+ for core business (auth, config)
**User Experience Consistency**:
- [x] All APIs use unified JSON response format: `{code, data, msg}`
- [x] Error responses include clear error codes and bilingual messages
- 1001: Missing authentication token (缺失认证令牌)
- 1002: Invalid or expired token (令牌无效或已过期)
- 1003: Too many requests (请求过于频繁)
- 1004: Authentication service unavailable (认证服务不可用)
- [x] RESTful design principles followed
- [x] Unified pagination parameters (N/A for this feature)
- [x] Time fields use ISO 8601 format (RFC3339) - in log timestamps
- [x] Currency amounts use integers (N/A for this feature)
**Performance Requirements**:
- [x] API response time (P95) < 200ms, (P99) < 500ms
- Middleware overhead budgeted at < 5ms per request
- [x] Batch operations use bulk queries/inserts (N/A for this feature)
- [x] All database queries have appropriate indexes (N/A - Redis only)
- [x] List queries implement pagination (N/A for this feature)
- [x] Non-realtime operations use async tasks (N/A - all operations are realtime)
- [x] Database and Redis connection pools properly configured
- Redis: PoolSize=10, MinIdleConns=5
- [x] Uses goroutines/channels for concurrency (config watcher)
- [x] Uses `context.Context` for timeout control (Redis operations)
- [x] Uses `sync.Pool` for frequently allocated objects (if needed for performance)
## Project Structure
### Documentation (this feature)
```text
specs/001-fiber-middleware-integration/
├── plan.md # This file (/speckit.plan command output)
├── research.md # Phase 0 output (/speckit.plan command)
├── data-model.md # Phase 1 output (/speckit.plan command)
├── quickstart.md # Phase 1 output (/speckit.plan command)
├── contracts/ # Phase 1 output (/speckit.plan command)
│ └── api.yaml # OpenAPI spec for unified response format
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
```
### Source Code (repository root)
```text
junhong_cmp_fiber/
├── cmd/
│ ├── api/
│ │ └── main.go # HTTP server entry point (updated)
│ └── worker/
│ └── main.go # Worker process (no changes for this feature)
├── internal/
│ └── middleware/ # Fiber middleware implementations
│ ├── auth.go # keyauth middleware integration
│ ├── ratelimit.go # limiter middleware integration (commented)
│ └── recover.go # Custom recover middleware with Zap logging
├── pkg/
│ ├── config/
│ │ ├── config.go # Viper configuration management
│ │ ├── loader.go # Config loading and validation
│ │ └── watcher.go # Hot reload implementation
│ │
│ ├── logger/
│ │ ├── logger.go # Zap logger initialization
│ │ ├── rotation.go # Lumberjack integration
│ │ └── middleware.go # Fiber logger middleware adapter
│ │
│ ├── response/
│ │ ├── response.go # Unified response structure and helpers
│ │ └── codes.go # Response code constants
│ │
│ ├── errors/
│ │ ├── errors.go # Custom error types
│ │ └── codes.go # Error code constants (1001-1004)
│ │
│ ├── constants/
│ │ ├── constants.go # Business constants
│ │ └── redis.go # Redis key generation functions
│ │
│ └── validator/
│ └── token.go # Token validation service (Redis interaction)
├── configs/
│ ├── config.yaml # Default configuration
│ ├── config.dev.yaml # Development environment
│ ├── config.staging.yaml # Staging environment
│ └── config.prod.yaml # Production environment
├── logs/ # Log output directory (gitignored)
│ ├── app.log # Application logs
│ └── access.log # HTTP access logs
└── tests/
├── integration/
│ ├── middleware_test.go # Integration tests for middleware chain
│ └── auth_test.go # Auth flow integration tests
└── unit/
├── config_test.go # Config loading and validation tests
├── logger_test.go # Logger tests
├── response_test.go # Response format tests
└── validator_test.go # Token validation tests
```
**Structure Decision**: Single project structure (Option 1) as this is a backend-only Go web service. The project follows Go's standard layout with `cmd/` for entry points, `internal/` for private application code, and `pkg/` for reusable packages. Configuration files are centralized in `configs/` with environment-specific overrides. This structure aligns with Go best practices and the constitution's flat package organization principle.
## Complexity Tracking
> **Fill ONLY if Constitution Check has violations that must be justified**
*No violations detected. All requirements align with constitution principles.*
## Phase 0: Research & Discovery
**Status**: Starting research phase
**Research Tasks**:
1. Viper configuration hot reload best practices and implementation patterns
2. Zap + Lumberjack integration patterns for dual log files (app.log, access.log)
3. Fiber middleware execution order and error handling patterns
4. Fiber keyauth middleware customization for Redis token validation
5. Fiber limiter middleware configuration options and IP extraction
6. Redis client selection and connection pool configuration for Go
7. UUID v4 generation in Go (standard library vs third-party)
8. Graceful shutdown patterns for config watchers and HTTP server
**Unknowns to Resolve**:
- Best Redis client library for Go (go-redis vs redigo)
- Optimal Viper hot reload implementation (polling vs fsnotify)
- How to properly separate Fiber logger middleware output to access.log
- How to inject custom Zap logger into Fiber recover middleware
- Request ID propagation through Fiber context
- Testing strategies for middleware integration tests
**Output**: `research.md` with decisions and rationale
---
## Phase 1: Design & Contracts
**Prerequisites**: Phase 0 research complete
**Design Artifacts**:
1. **data-model.md**: Entity definitions
- Configuration structure (server, redis, logging, middleware settings)
- AuthToken entity (Redis key-value structure)
- Request Context structure (request ID, user ID, metadata)
- Log Entry structure (JSON fields for app.log and access.log)
- Rate Limit State (IP-based tracking structure)
2. **contracts/api.yaml**: OpenAPI specification
- Unified response format schema
- Error response schemas (1001-1004)
- Common headers (X-Request-ID, token)
- Example endpoints demonstrating middleware integration
3. **quickstart.md**: Developer setup guide
- Environment setup (Go, Redis)
- Configuration file setup (config.yaml)
- Running the server
- Testing middleware (curl examples)
- Enabling/disabling rate limiter
**Output**: data-model.md, contracts/api.yaml, quickstart.md
---
## Phase 2: Task Generation
**Status**: To be completed by `/speckit.tasks` command (NOT part of `/speckit.plan`)
This phase will generate `tasks.md` with implementation steps ordered by dependencies.
---
## Notes & Decisions
### Key Design Decisions (from spec clarifications):
1. **Log Separation**: Application logs (app.log) and HTTP access logs (access.log) in separate files with independent rotation and retention policies
2. **Token Storage**: Simple Redis key-value (token → user ID) with Redis TTL for expiration
3. **Auth Failure Mode**: Fail closed when Redis unavailable (HTTP 503, no fallback)
4. **Rate Limiting**: Per-IP address with configurable requests/time window, disabled by default
5. **Request ID Format**: UUID v4 for distributed tracing compatibility
6. **Config Hot Reload**: 5-second detection window, atomic updates, invalid config = keep previous
### Technical Choices (to be validated in Phase 0):
- Use `github.com/go-redis/redis/v8` for Redis client (widely adopted, good performance)
- Use `github.com/fsnotify/fsnotify` (Viper's native watcher) for hot reload
- Use `github.com/google/uuid` (already in go.mod) for UUID v4 generation
- Separate Zap logger instances for app.log and access.log
- Middleware order: recover → requestid → logger → keyauth → limiter → handler
### Risk Mitigation:
- **Risk**: Configuration hot reload causes in-flight request issues
- **Mitigation**: Use atomic pointer swap for config updates, don't affect in-flight requests
- **Risk**: Log rotation blocks request processing
- **Mitigation**: Lumberjack handles rotation atomically, Zap is non-blocking
- **Risk**: Redis connection pool exhaustion under load
- **Mitigation**: Proper pool sizing (10 connections), timeout configuration, circuit breaker consideration
- **Risk**: Rate limiter memory leak with many unique IPs
- **Mitigation**: Use Fiber's built-in limiter with storage backend (memory or Redis), TTL cleanup
---
## Phase 1 Constitution Re-Check
**Status**: ✅ PASSED - All design artifacts comply with constitution
**Verification Results**:
1. **Go Idiomatic Design**
- ✅ Flat package structure: `pkg/config/`, `pkg/logger/`, `pkg/response/`, `pkg/errors/`
- ✅ Small interfaces: TokenValidator (2 methods only)
- ✅ No Java patterns: No IService, no Impl suffix, no getters/setters
- ✅ Simple structs with direct field access (Config, Response, LogEntry)
- ✅ Explicit error handling with custom error types
- ✅ Composition: Config composed of sub-configs, no inheritance
2. **Tech Stack Compliance**
- ✅ Fiber for all HTTP operations (middleware, routing)
- ✅ Viper for configuration with hot reload
- ✅ Zap + Lumberjack for logging
- ✅ go-redis/redis/v8 for Redis client
- ✅ google/uuid for request ID generation
- ✅ No `net/http`, `database/sql`, or `encoding/json` direct usage
3. **Architecture Alignment**
- ✅ Clear separation: Middleware → Handler → Service (TokenValidator) → Store (Redis)
- ✅ Dependency injection via struct fields
- ✅ Unified response format in `pkg/response/`
- ✅ Error codes centralized in `pkg/errors/`
- ✅ Constants and Redis key functions in `pkg/constants/`
4. **Performance Requirements**
- ✅ Middleware overhead budgeted at <5ms per request
- ✅ Redis connection pool configured (10 connections, 5 idle)
- ✅ Goroutines for config watcher (non-blocking)
- ✅ Context timeouts for Redis operations (50ms)
- ✅ Lumberjack non-blocking log rotation
5. **Testing Strategy**
- ✅ Table-driven tests planned (Go idiomatic)
- ✅ Mock Redis for unit tests
- ✅ Integration tests with testcontainers
- ✅ Target coverage defined (70%+ overall, 90%+ core)
**Design Quality Metrics**:
- Zero Java-style anti-patterns detected
- All error handling explicit (no panic/recover abuse)
- Configuration validation implemented
- Graceful shutdown pattern defined
- Security: Fail-closed auth, explicit timeout handling
**Conclusion**: Design is ready for implementation. All artifacts (research.md, data-model.md, contracts/api.yaml, quickstart.md) align with constitution principles. No violations or exceptions required.
---
## Next Steps
1. ✅ Plan created and constitution check passed
2. ✅ Execute Phase 0 research (research.md)
3. ✅ Execute Phase 1 design (data-model.md, contracts/, quickstart.md)
4. ✅ Update agent context with new technologies
5. ✅ Phase 1 Constitution re-check passed
6. ⏳ Run `/speckit.tasks` to generate implementation tasks
7. ⏳ Run `/speckit.implement` to execute tasks
**Command**: `/speckit.plan` complete. All design artifacts generated and validated.
**Ready for**: `/speckit.tasks` command to generate actionable implementation tasks.