docs: add implementation plan, ADRs, and task tracking system
- Add comprehensive 8-phase implementation plan (docs/plan.md) - Add 28 Architecture Decision Records (docs/adr/) covering all phases - Add task tracking system with 283+ task files (docs/stories/) - Add task generator script for automated task file creation - Add reference playbooks and requirements documentation This commit establishes the complete planning foundation for the Go Platform implementation, documenting all architectural decisions and providing detailed task breakdown for Phases 0-8.
This commit is contained in:
95
.cursor/rules/golang.md
Normal file
95
.cursor/rules/golang.md
Normal file
@@ -0,0 +1,95 @@
|
||||
You are an expert in Go, microservices architecture, and clean backend development practices. Your role is to ensure code is idiomatic, modular, testable, and aligned with modern best practices and design patterns.
|
||||
|
||||
### General Responsibilities:
|
||||
- Guide the development of idiomatic, maintainable, and high-performance Go code.
|
||||
- Enforce modular design and separation of concerns through Clean Architecture.
|
||||
- Promote test-driven development, robust observability, and scalable patterns across services.
|
||||
|
||||
### Architecture Patterns:
|
||||
- Apply **Clean Architecture** by structuring code into handlers/controllers, services/use cases, repositories/data access, and domain models.
|
||||
- Use **domain-driven design** principles where applicable.
|
||||
- Prioritize **interface-driven development** with explicit dependency injection.
|
||||
- Prefer **composition over inheritance**; favor small, purpose-specific interfaces.
|
||||
- Ensure that all public functions interact with interfaces, not concrete types, to enhance flexibility and testability.
|
||||
|
||||
### Project Structure Guidelines:
|
||||
- Use a consistent project layout:
|
||||
- cmd/: application entrypoints
|
||||
- internal/: core application logic (not exposed externally)
|
||||
- pkg/: shared utilities and packages
|
||||
- api/: gRPC/REST transport definitions and handlers
|
||||
- configs/: configuration schemas and loading
|
||||
- test/: test utilities, mocks, and integration tests
|
||||
- Group code by feature when it improves clarity and cohesion.
|
||||
- Keep logic decoupled from framework-specific code.
|
||||
|
||||
### Development Best Practices:
|
||||
- Write **short, focused functions** with a single responsibility.
|
||||
- Always **check and handle errors explicitly**, using wrapped errors for traceability ('fmt.Errorf("context: %w", err)').
|
||||
- Avoid **global state**; use constructor functions to inject dependencies.
|
||||
- Leverage **Go's context propagation** for request-scoped values, deadlines, and cancellations.
|
||||
- Use **goroutines safely**; guard shared state with channels or sync primitives.
|
||||
- **Defer closing resources** and handle them carefully to avoid leaks.
|
||||
|
||||
### Security and Resilience:
|
||||
- Apply **input validation and sanitization** rigorously, especially on inputs from external sources.
|
||||
- Use secure defaults for **JWT, cookies**, and configuration settings.
|
||||
- Isolate sensitive operations with clear **permission boundaries**.
|
||||
- Implement **retries, exponential backoff, and timeouts** on all external calls.
|
||||
- Use **circuit breakers and rate limiting** for service protection.
|
||||
- Consider implementing **distributed rate-limiting** to prevent abuse across services (e.g., using Redis).
|
||||
|
||||
### Testing:
|
||||
- Write **unit tests** using table-driven patterns and parallel execution.
|
||||
- **Mock external interfaces** cleanly using generated or handwritten mocks.
|
||||
- Separate **fast unit tests** from slower integration and E2E tests.
|
||||
- Ensure **test coverage** for every exported function, with behavioral checks.
|
||||
- Use tools like 'go test -cover' to ensure adequate test coverage.
|
||||
|
||||
### Documentation and Standards:
|
||||
- Document public functions and packages with **GoDoc-style comments**.
|
||||
- Provide concise **READMEs** for services and libraries.
|
||||
- Maintain a 'CONTRIBUTING.md' and 'ARCHITECTURE.md' to guide team practices.
|
||||
- Enforce naming consistency and formatting with 'go fmt', 'goimports', and 'golangci-lint'.
|
||||
|
||||
### Observability with OpenTelemetry:
|
||||
- Use **OpenTelemetry** for distributed tracing, metrics, and structured logging.
|
||||
- Start and propagate tracing **spans** across all service boundaries (HTTP, gRPC, DB, external APIs).
|
||||
- Always attach 'context.Context' to spans, logs, and metric exports.
|
||||
- Use **otel.Tracer** for creating spans and **otel.Meter** for collecting metrics.
|
||||
- Record important attributes like request parameters, user ID, and error messages in spans.
|
||||
- Use **log correlation** by injecting trace IDs into structured logs.
|
||||
- Export data to **OpenTelemetry Collector**, **Jaeger**, or **Prometheus**.
|
||||
|
||||
### Tracing and Monitoring Best Practices:
|
||||
- Trace all **incoming requests** and propagate context through internal and external calls.
|
||||
- Use **middleware** to instrument HTTP and gRPC endpoints automatically.
|
||||
- Annotate slow, critical, or error-prone paths with **custom spans**.
|
||||
- Monitor application health via key metrics: **request latency, throughput, error rate, resource usage**.
|
||||
- Define **SLIs** (e.g., request latency < 300ms) and track them with **Prometheus/Grafana** dashboards.
|
||||
- Alert on key conditions (e.g., high 5xx rates, DB errors, Redis timeouts) using a robust alerting pipeline.
|
||||
- Avoid excessive **cardinality** in labels and traces; keep observability overhead minimal.
|
||||
- Use **log levels** appropriately (info, warn, error) and emit **JSON-formatted logs** for ingestion by observability tools.
|
||||
- Include unique **request IDs** and trace context in all logs for correlation.
|
||||
|
||||
### Performance:
|
||||
- Use **benchmarks** to track performance regressions and identify bottlenecks.
|
||||
- Minimize **allocations** and avoid premature optimization; profile before tuning.
|
||||
- Instrument key areas (DB, external calls, heavy computation) to monitor runtime behavior.
|
||||
|
||||
### Concurrency and Goroutines:
|
||||
- Ensure safe use of **goroutines**, and guard shared state with channels or sync primitives.
|
||||
- Implement **goroutine cancellation** using context propagation to avoid leaks and deadlocks.
|
||||
|
||||
### Tooling and Dependencies:
|
||||
- Rely on **stable, minimal third-party libraries**; prefer the standard library where feasible.
|
||||
- Use **Go modules** for dependency management and reproducibility.
|
||||
- Version-lock dependencies for deterministic builds.
|
||||
- Integrate **linting, testing, and security checks** in CI pipelines.
|
||||
|
||||
### Key Conventions:
|
||||
1. Prioritize **readability, simplicity, and maintainability**.
|
||||
2. Design for **change**: isolate business logic and minimize framework lock-in.
|
||||
3. Emphasize clear **boundaries** and **dependency inversion**.
|
||||
4. Ensure all behavior is **observable, testable, and documented**.
|
||||
5. **Automate workflows** for testing, building, and deployment.
|
||||
37
docs/adr/0001-go-module-path.md
Normal file
37
docs/adr/0001-go-module-path.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# ADR-0001: Go Module Path
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The project needs a Go module path that uniquely identifies the platform. This path will be used:
|
||||
- In `go.mod` file
|
||||
- For importing packages within the project
|
||||
- For module dependencies
|
||||
- For future module publishing
|
||||
|
||||
## Decision
|
||||
Use `git.dcentral.systems/toolz/goplt` as the Go module path.
|
||||
|
||||
**Rationale:**
|
||||
- Matches the organization's Git hosting structure
|
||||
- Follows Go module naming conventions
|
||||
- Clearly identifies the project as a Go platform tool
|
||||
- Prevents naming conflicts with other modules
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Clear, descriptive module path
|
||||
- Aligns with organization's infrastructure
|
||||
- Easy to identify in dependency graphs
|
||||
|
||||
### Negative
|
||||
- Requires access to `git.dcentral.systems` for module resolution
|
||||
- May need to configure GOPRIVATE/GONOPROXY if using private registry
|
||||
|
||||
### Implementation Notes
|
||||
- Initialize module: `go mod init git.dcentral.systems/toolz/goplt`
|
||||
- Update all import paths in code to use this module path
|
||||
- Configure `.git/config` or Go environment variables if needed for private module access
|
||||
|
||||
39
docs/adr/0002-go-version.md
Normal file
39
docs/adr/0002-go-version.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# ADR-0002: Go Version
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
Go releases new versions regularly with new features, performance improvements, and security fixes. We need to choose a Go version that:
|
||||
- Provides necessary features for the platform
|
||||
- Has good ecosystem support
|
||||
- Is stable and production-ready
|
||||
- Supports required tooling (plugins, etc.)
|
||||
|
||||
## Decision
|
||||
Use **Go 1.24.3** as the minimum required version for the platform.
|
||||
|
||||
**Rationale:**
|
||||
- Latest stable version available
|
||||
- Provides all required features for the platform
|
||||
- Ensures compatibility with modern Go tooling
|
||||
- Supports all planned features (modules, plugins, generics)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Access to latest Go features and performance improvements
|
||||
- Better security with latest patches
|
||||
- Modern tooling support
|
||||
|
||||
### Negative
|
||||
- Requires developers to have Go 1.24.3+ installed
|
||||
- CI/CD must use compatible Go version
|
||||
- May limit compatibility with some older dependencies (if any)
|
||||
|
||||
### Implementation Notes
|
||||
- Specify in `go.mod`: `go 1.24`
|
||||
- Document in `README.md` and CI configuration
|
||||
- Update `.github/workflows/ci.yml` to use `actions/setup-go@v5` with version `1.24.3`
|
||||
- Add version check script if needed
|
||||
|
||||
49
docs/adr/0003-dependency-injection-framework.md
Normal file
49
docs/adr/0003-dependency-injection-framework.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# ADR-0003: Dependency Injection Framework
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform requires dependency injection to:
|
||||
- Manage service lifecycle
|
||||
- Wire dependencies between components
|
||||
- Support module system initialization
|
||||
- Handle graceful shutdown
|
||||
- Provide testability through dependency substitution
|
||||
|
||||
Options considered:
|
||||
1. **uber-go/fx** - Runtime dependency injection with lifecycle management
|
||||
2. **uber-go/dig** - Compile-time dependency injection
|
||||
3. **Manual constructor injection** - No framework, explicit wiring
|
||||
|
||||
## Decision
|
||||
Use **uber-go/fx** (v1.23.0+) as the dependency injection framework.
|
||||
|
||||
**Rationale:**
|
||||
- Provides lifecycle management (OnStart/OnStop hooks) crucial for services
|
||||
- Supports module-based architecture through fx.Option composition
|
||||
- Runtime dependency resolution with compile-time type safety
|
||||
- Excellent for modular monolith architecture
|
||||
- Well-documented and actively maintained
|
||||
- Used by major Go projects (Uber, etc.)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Clean lifecycle management for services
|
||||
- Easy module composition via fx.Option
|
||||
- Graceful shutdown handling built-in
|
||||
- Test-friendly with fx.Options for test overrides
|
||||
|
||||
### Negative
|
||||
- Runtime reflection overhead (minimal)
|
||||
- Learning curve for developers unfamiliar with fx
|
||||
- Slightly more complex error messages on dependency resolution failures
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `go get go.uber.org/fx@v1.23.0`
|
||||
- Create `internal/di/container.go` with fx.New()
|
||||
- Use fx.Provide() for service registration
|
||||
- Use fx.Invoke() for initialization tasks
|
||||
- Leverage fx.Lifecycle for service startup/shutdown
|
||||
|
||||
50
docs/adr/0004-configuration-management.md
Normal file
50
docs/adr/0004-configuration-management.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# ADR-0004: Configuration Management Library
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs a configuration system that:
|
||||
- Supports hierarchical configuration (defaults → files → env → secrets)
|
||||
- Handles multiple formats (YAML, JSON, env vars)
|
||||
- Provides type-safe access to configuration values
|
||||
- Supports environment-specific overrides
|
||||
- Can integrate with secret managers (future)
|
||||
|
||||
Options considered:
|
||||
1. **spf13/viper** - Comprehensive configuration management
|
||||
2. **envconfig** - Environment variable only
|
||||
3. **koanf** - Lightweight configuration library
|
||||
4. **Standard library + manual parsing** - No external dependency
|
||||
|
||||
## Decision
|
||||
Use **spf13/viper** (v1.18.0+) with **spf13/cobra** (v1.8.0+) for configuration management.
|
||||
|
||||
**Rationale:**
|
||||
- Industry standard for Go configuration management
|
||||
- Supports multiple sources (files, env vars, flags)
|
||||
- Hierarchical configuration with precedence rules
|
||||
- Easy integration with Cobra for CLI commands
|
||||
- Well-documented and widely used
|
||||
- Supports future secret manager integration
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Flexible configuration loading from multiple sources
|
||||
- Easy to add new configuration sources
|
||||
- Type-safe access methods
|
||||
- Environment variable support via automatic env binding
|
||||
|
||||
### Negative
|
||||
- Additional dependency
|
||||
- Viper can be verbose for simple use cases
|
||||
- Some learning curve for advanced features
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `go get github.com/spf13/viper@v1.18.0` and `github.com/spf13/cobra@v1.8.0`
|
||||
- Create `pkg/config/config.go` interface to abstract Viper
|
||||
- Implement `internal/config/viper_config.go` as concrete implementation
|
||||
- Load order: `default.yaml` → `development.yaml`/`production.yaml` → env vars → secrets (future)
|
||||
- Use typed getters (GetString, GetInt, GetBool) for type safety
|
||||
|
||||
50
docs/adr/0005-logging-framework.md
Normal file
50
docs/adr/0005-logging-framework.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# ADR-0005: Logging Framework
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform requires structured logging that:
|
||||
- Supports multiple log levels
|
||||
- Provides structured output (JSON for production)
|
||||
- Allows adding contextual fields
|
||||
- Performs well under load
|
||||
- Integrates with observability tools
|
||||
|
||||
Options considered:
|
||||
1. **go.uber.org/zap** - High-performance structured logging
|
||||
2. **rs/zerolog** - Zero-allocation logger
|
||||
3. **sirupsen/logrus** - Structured logger (maintenance mode)
|
||||
4. **Standard library log** - Basic logging (insufficient)
|
||||
|
||||
## Decision
|
||||
Use **go.uber.org/zap** (v1.26.0+) as the logging framework.
|
||||
|
||||
**Rationale:**
|
||||
- Industry standard for high-performance Go applications
|
||||
- Excellent structured logging with field support
|
||||
- Very low overhead (designed for high-throughput systems)
|
||||
- JSON output for production, human-readable for development
|
||||
- Strong ecosystem integration
|
||||
- Actively maintained by Uber
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- High performance (low latency, high throughput)
|
||||
- Rich structured logging with fields
|
||||
- Easy integration with observability tools
|
||||
- Configurable output formats (JSON/console)
|
||||
|
||||
### Negative
|
||||
- Slightly more verbose API than standard library
|
||||
- Requires wrapping for common use cases (we'll abstract via interface)
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `go get go.uber.org/zap@v1.26.0`
|
||||
- Create `pkg/logger/logger.go` interface to abstract zap
|
||||
- Implement `internal/logger/zap_logger.go` as concrete implementation
|
||||
- Use JSON encoder for production, console encoder for development
|
||||
- Support request-scoped fields via context
|
||||
- Export global logger via `pkg/logger` package
|
||||
|
||||
50
docs/adr/0006-http-framework.md
Normal file
50
docs/adr/0006-http-framework.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# ADR-0006: HTTP Framework
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs an HTTP framework for:
|
||||
- REST API endpoints
|
||||
- Middleware support (auth, logging, metrics)
|
||||
- Request/response handling
|
||||
- Route registration from modules
|
||||
- Integration with observability tools
|
||||
|
||||
Options considered:
|
||||
1. **gin-gonic/gin** - Fast, feature-rich HTTP web framework
|
||||
2. **gorilla/mux** - Lightweight router
|
||||
3. **go-chi/chi** - Lightweight, idiomatic router
|
||||
4. **net/http** (standard library) - No external dependency
|
||||
|
||||
## Decision
|
||||
Use **gin-gonic/gin** (v1.9.1+) as the HTTP framework.
|
||||
|
||||
**Rationale:**
|
||||
- Fast performance (comparable to net/http)
|
||||
- Rich middleware ecosystem
|
||||
- Excellent for REST APIs
|
||||
- Easy route grouping (useful for modules)
|
||||
- Good OpenTelemetry integration support
|
||||
- Widely used and well-documented
|
||||
- Recommended in playbook-golang.md
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- High performance
|
||||
- Easy middleware chaining
|
||||
- Route grouping supports module architecture
|
||||
- Good ecosystem support
|
||||
|
||||
### Negative
|
||||
- Additional dependency (though lightweight)
|
||||
- Slight learning curve for developers unfamiliar with Gin
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `go get github.com/gin-gonic/gin@v1.9.1`
|
||||
- Create router in `internal/server/server.go`
|
||||
- Use route groups for module isolation: `r.Group("/api/v1/blog")`
|
||||
- Add middleware stack: logging, recovery, metrics, auth (later)
|
||||
- Support graceful shutdown via fx lifecycle
|
||||
|
||||
82
docs/adr/0007-project-directory-structure.md
Normal file
82
docs/adr/0007-project-directory-structure.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# ADR-0007: Project Directory Structure
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The project needs a clear, scalable directory structure that:
|
||||
- Follows Go best practices
|
||||
- Separates public interfaces from implementations
|
||||
- Supports modular architecture
|
||||
- Is maintainable and discoverable
|
||||
- Aligns with Go community standards
|
||||
|
||||
## Decision
|
||||
Adopt a **standard Go project layout** with **internal/** and **pkg/** separation:
|
||||
|
||||
```
|
||||
goplt/
|
||||
├── cmd/
|
||||
│ └── platform/ # Application entry point
|
||||
├── internal/ # Private implementation code
|
||||
│ ├── di/ # Dependency injection
|
||||
│ ├── registry/ # Module registry
|
||||
│ ├── pluginloader/ # Plugin loader (optional)
|
||||
│ ├── config/ # Config implementation
|
||||
│ ├── logger/ # Logger implementation
|
||||
│ └── infra/ # Infrastructure adapters
|
||||
├── pkg/ # Public interfaces (exported)
|
||||
│ ├── config/ # ConfigProvider interface
|
||||
│ ├── logger/ # Logger interface
|
||||
│ ├── module/ # IModule interface
|
||||
│ ├── auth/ # Auth interfaces (Phase 2)
|
||||
│ ├── perm/ # Permission DSL (Phase 2)
|
||||
│ └── infra/ # Infrastructure interfaces
|
||||
├── modules/ # Feature modules
|
||||
│ └── blog/ # Sample module (Phase 4)
|
||||
├── config/ # Configuration files
|
||||
│ ├── default.yaml
|
||||
│ ├── development.yaml
|
||||
│ └── production.yaml
|
||||
├── api/ # OpenAPI specs
|
||||
├── scripts/ # Build/test scripts
|
||||
├── docs/ # Documentation
|
||||
│ └── adr/ # Architecture Decision Records
|
||||
├── ops/ # Operations (Grafana dashboards, etc.)
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ └── ci.yml
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
├── docker-compose.test.yml
|
||||
└── go.mod
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- `internal/` prevents external packages from importing implementation details
|
||||
- `pkg/` exposes only interfaces that modules need
|
||||
- `cmd/` follows Go standard for application entry points
|
||||
- `modules/` clearly separates feature modules
|
||||
- `config/` centralizes configuration files
|
||||
- Separates concerns and supports clean architecture
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Clear separation of concerns
|
||||
- Prevents circular dependencies
|
||||
- Easy to navigate and understand
|
||||
- Aligns with Go community standards
|
||||
- Supports modular architecture
|
||||
|
||||
### Negative
|
||||
- Slightly more directories than minimal structure
|
||||
- Requires discipline to maintain boundaries
|
||||
|
||||
### Implementation Notes
|
||||
- Initialize with `go mod init git.dcentral.systems/toolz/goplt`
|
||||
- Create all directories upfront in Phase 0
|
||||
- Document structure in `README.md`
|
||||
- Enforce boundaries via `internal/` package visibility
|
||||
- Use `go build ./...` to verify structure
|
||||
|
||||
57
docs/adr/0008-error-handling-strategy.md
Normal file
57
docs/adr/0008-error-handling-strategy.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# ADR-0008: Error Handling Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
Go's error handling philosophy requires explicit error checking. We need a consistent approach for:
|
||||
- Error creation and wrapping
|
||||
- Error propagation
|
||||
- Error classification (domain vs infrastructure)
|
||||
- Error reporting (logging, monitoring)
|
||||
- HTTP error responses
|
||||
|
||||
## Decision
|
||||
Adopt a **wrapped error pattern** with **structured error types**:
|
||||
|
||||
1. **Error Wrapping**: Use `fmt.Errorf("context: %w", err)` for error wrapping
|
||||
2. **Error Types**: Define custom error types for domain errors
|
||||
3. **Error Classification**: Distinguish between:
|
||||
- Domain errors (business logic failures)
|
||||
- Infrastructure errors (external system failures)
|
||||
- Validation errors (input validation failures)
|
||||
4. **Error Context**: Always wrap errors with context about where they occurred
|
||||
|
||||
**Rationale:**
|
||||
- Follows Go 1.13+ error wrapping best practices
|
||||
- Enables error inspection with `errors.Is()` and `errors.As()`
|
||||
- Maintains error chains for debugging
|
||||
- Allows structured error handling
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Full error traceability through call stack
|
||||
- Can inspect and handle specific error types
|
||||
- Better debugging with error context
|
||||
- Aligns with Go best practices
|
||||
|
||||
### Negative
|
||||
- Requires discipline to wrap errors consistently
|
||||
- Can be verbose in some cases
|
||||
|
||||
### Implementation Notes
|
||||
- Always wrap errors: `return nil, fmt.Errorf("failed to load config: %w", err)`
|
||||
- Create error types for domain errors:
|
||||
```go
|
||||
type ConfigError struct {
|
||||
Key string
|
||||
Cause error
|
||||
}
|
||||
func (e *ConfigError) Error() string { ... }
|
||||
func (e *ConfigError) Unwrap() error { return e.Cause }
|
||||
```
|
||||
- Use `errors.Is()` and `errors.As()` for error checking
|
||||
- Log errors with context before returning
|
||||
- Map domain errors to HTTP status codes in handlers
|
||||
|
||||
56
docs/adr/0009-context-key-types.md
Normal file
56
docs/adr/0009-context-key-types.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# ADR-0009: Context Key Types
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform will use `context.Context` to propagate request-scoped values such as:
|
||||
- User ID (from authentication)
|
||||
- Request ID (for tracing)
|
||||
- Tenant ID (for multi-tenancy)
|
||||
- Logger instance (with request-scoped fields)
|
||||
|
||||
Go best practices recommend using typed keys instead of string keys to avoid collisions.
|
||||
|
||||
## Decision
|
||||
Use **typed context keys** for all context values:
|
||||
|
||||
```go
|
||||
type contextKey string
|
||||
|
||||
const (
|
||||
userIDKey contextKey = "user_id"
|
||||
requestIDKey contextKey = "request_id"
|
||||
tenantIDKey contextKey = "tenant_id"
|
||||
loggerKey contextKey = "logger"
|
||||
)
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- Prevents key collisions between packages
|
||||
- Type-safe access to context values
|
||||
- Aligns with Go best practices (see `context.WithValue` documentation)
|
||||
- Makes context usage explicit and discoverable
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Type-safe context access
|
||||
- Prevents accidental key collisions
|
||||
- Clear intent in code
|
||||
- Better IDE support
|
||||
|
||||
### Negative
|
||||
- Slightly more verbose than string keys
|
||||
- Requires defining keys upfront
|
||||
|
||||
### Implementation Notes
|
||||
- Create `pkg/context/keys.go` with all context key definitions
|
||||
- Provide helper functions for setting/getting values:
|
||||
```go
|
||||
func WithUserID(ctx context.Context, userID string) context.Context
|
||||
func UserIDFromContext(ctx context.Context) (string, bool)
|
||||
```
|
||||
- Use in middleware and services
|
||||
- Document all context keys and their usage
|
||||
|
||||
50
docs/adr/0010-ci-cd-platform.md
Normal file
50
docs/adr/0010-ci-cd-platform.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# ADR-0010: CI/CD Platform
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs a CI/CD system for:
|
||||
- Automated testing on pull requests
|
||||
- Code quality checks (linting, formatting)
|
||||
- Building binaries and Docker images
|
||||
- Publishing artifacts
|
||||
- Running integration tests
|
||||
|
||||
Options considered:
|
||||
1. **GitHub Actions** - Native GitHub integration
|
||||
2. **GitLab CI** - If using GitLab
|
||||
3. **Jenkins** - Self-hosted option
|
||||
4. **CircleCI** - Cloud-based CI/CD
|
||||
|
||||
## Decision
|
||||
Use **GitHub Actions** for CI/CD pipeline.
|
||||
|
||||
**Rationale:**
|
||||
- Native integration with GitHub repositories
|
||||
- Free for public repos, reasonable for private
|
||||
- Rich ecosystem of actions
|
||||
- Easy to configure with YAML
|
||||
- Good documentation and community support
|
||||
- Recommended in playbook-golang.md
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Easy setup and configuration
|
||||
- Good GitHub integration
|
||||
- Large action marketplace
|
||||
- Free for public repositories
|
||||
|
||||
### Negative
|
||||
- Tied to GitHub (if migrating Git hosts, need to migrate CI)
|
||||
- Limited customization compared to self-hosted solutions
|
||||
|
||||
### Implementation Notes
|
||||
- Create `.github/workflows/ci.yml`
|
||||
- Use `actions/setup-go@v5` for Go setup
|
||||
- Configure caching for Go modules
|
||||
- Run: linting, unit tests, integration tests, build
|
||||
- Use `actions/cache@v4` for module caching
|
||||
- Add build matrix if needed for multiple Go versions (future)
|
||||
|
||||
53
docs/adr/0011-code-generation-tools.md
Normal file
53
docs/adr/0011-code-generation-tools.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# ADR-0011: Code Generation Tools
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform will use code generation for:
|
||||
- Permission constants from module manifests
|
||||
- Ent ORM code generation
|
||||
- Mock generation for testing
|
||||
- OpenAPI client/server code (future)
|
||||
|
||||
We need to decide on tooling and workflow.
|
||||
|
||||
## Decision
|
||||
Use **standard Go generation tools** with `go generate`:
|
||||
|
||||
1. **Ent ORM**: `entgo.io/ent/cmd/ent` for schema code generation
|
||||
2. **Mocks**: `github.com/vektra/mockery/v2` or `github.com/golang/mock/mockgen`
|
||||
3. **Permissions**: Custom `scripts/generate-permissions.go`
|
||||
4. **OpenAPI**: `github.com/deepmap/oapi-codegen` (future)
|
||||
|
||||
**Workflow:**
|
||||
- Use `//go:generate` directives in source files
|
||||
- Run `go generate ./...` before commits
|
||||
- Document in `Makefile` with `make generate` target
|
||||
- CI should verify generated code is up-to-date
|
||||
|
||||
**Rationale:**
|
||||
- Standard Go tooling, well-supported
|
||||
- `go generate` is the idiomatic way to run code generation
|
||||
- Easy to integrate into CI/CD
|
||||
- Reduces manual code maintenance
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Automated code generation reduces errors
|
||||
- Consistent code style
|
||||
- Easy to maintain
|
||||
- Standard Go workflow
|
||||
|
||||
### Negative
|
||||
- Requires developers to run generation before commits
|
||||
- Generated code must be committed (or verified in CI)
|
||||
- Slight learning curve for new developers
|
||||
|
||||
### Implementation Notes
|
||||
- Add `//go:generate` directives where needed
|
||||
- Create `Makefile` target: `make generate`
|
||||
- Add CI step to verify generated code: `go generate ./... && git diff --exit-code`
|
||||
- Document in `CONTRIBUTING.md`
|
||||
|
||||
62
docs/adr/0012-logger-interface-design.md
Normal file
62
docs/adr/0012-logger-interface-design.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# ADR-0012: Logger Interface Design
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
We're using zap for logging, but want to abstract it behind an interface for:
|
||||
- Testability (mock logger in tests)
|
||||
- Flexibility (could swap implementations)
|
||||
- Module compatibility (modules use interface, not concrete type)
|
||||
|
||||
We need to decide on the interface design.
|
||||
|
||||
## Decision
|
||||
Create a **simple logger interface** that matches zap's API pattern but uses generic types:
|
||||
|
||||
```go
|
||||
type Field interface {
|
||||
// Field represents a key-value pair for structured logging
|
||||
}
|
||||
|
||||
type Logger interface {
|
||||
Debug(msg string, fields ...Field)
|
||||
Info(msg string, fields ...Field)
|
||||
Warn(msg string, fields ...Field)
|
||||
Error(msg string, fields ...Field)
|
||||
With(fields ...Field) Logger
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation:**
|
||||
- Use `zap.Field` as the Field type (no abstraction needed for now)
|
||||
- Provide helper functions in `pkg/logger` for creating fields:
|
||||
```go
|
||||
func String(key, value string) Field
|
||||
func Int(key string, value int) Field
|
||||
func Error(err error) Field
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- Simple interface that modules can depend on
|
||||
- Matches zap's usage patterns
|
||||
- Easy to test with mock implementations
|
||||
- Allows future swap if needed (though unlikely)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Clean abstraction for modules
|
||||
- Testable with mocks
|
||||
- Simple API for modules to use
|
||||
|
||||
### Negative
|
||||
- Slight indirection overhead
|
||||
- Need to maintain interface compatibility
|
||||
|
||||
### Implementation Notes
|
||||
- Define interface in `pkg/logger/logger.go`
|
||||
- Implement in `internal/logger/zap_logger.go`
|
||||
- Export helper functions in `pkg/logger/fields.go`
|
||||
- Modules import `pkg/logger`, not `internal/logger`
|
||||
|
||||
54
docs/adr/0013-database-orm.md
Normal file
54
docs/adr/0013-database-orm.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# ADR-0013: Database ORM Selection
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs a database ORM/library that:
|
||||
- Supports PostgreSQL (primary database)
|
||||
- Provides type-safe query building
|
||||
- Supports code generation (reduces boilerplate)
|
||||
- Handles migrations
|
||||
- Supports relationships (many-to-many, etc.)
|
||||
- Integrates with Ent (code generation)
|
||||
|
||||
Options considered:
|
||||
1. **entgo.io/ent** - Code-generated, type-safe ORM
|
||||
2. **gorm.io/gorm** - Feature-rich ORM with reflection
|
||||
3. **sqlx** - Lightweight wrapper around database/sql
|
||||
4. **Standard library database/sql** - No ORM, raw SQL
|
||||
|
||||
## Decision
|
||||
Use **entgo.io/ent** as the primary ORM for the platform.
|
||||
|
||||
**Rationale:**
|
||||
- Code generation provides compile-time type safety
|
||||
- Excellent schema definition and migration support
|
||||
- Strong relationship modeling
|
||||
- Good performance (no reflection at runtime)
|
||||
- Active development and good documentation
|
||||
- Recommended in playbook-golang.md
|
||||
- Easy to integrate with OpenTelemetry
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Type-safe queries eliminate runtime errors
|
||||
- Schema changes are explicit and versioned
|
||||
- Code generation reduces boilerplate
|
||||
- Good migration support
|
||||
- Strong relationship support
|
||||
|
||||
### Negative
|
||||
- Requires code generation step (`go generate`)
|
||||
- Learning curve for developers unfamiliar with Ent
|
||||
- Less flexible than raw SQL for complex queries
|
||||
- Generated code must be committed or verified in CI
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `go get entgo.io/ent/cmd/ent`
|
||||
- Initialize schema: `go run entgo.io/ent/cmd/ent init User Role Permission`
|
||||
- Use `//go:generate` directives for code generation
|
||||
- Run migrations on startup via `client.Schema.Create()`
|
||||
- Create wrapper in `internal/infra/database/client.go` for DI injection
|
||||
|
||||
52
docs/adr/0014-health-check-implementation.md
Normal file
52
docs/adr/0014-health-check-implementation.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# ADR-0014: Health Check Implementation
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs health check endpoints for:
|
||||
- Kubernetes liveness probes (`/healthz`)
|
||||
- Kubernetes readiness probes (`/ready`)
|
||||
- Monitoring and alerting
|
||||
- Load balancer health checks
|
||||
|
||||
Health checks should be:
|
||||
- Fast and lightweight
|
||||
- Check critical dependencies (database, cache, etc.)
|
||||
- Provide clear status indicators
|
||||
|
||||
## Decision
|
||||
Implement **custom health check registry** with composable checkers:
|
||||
|
||||
1. **Liveness endpoint** (`/healthz`): Always returns 200 if process is running
|
||||
2. **Readiness endpoint** (`/ready`): Checks all registered health checkers
|
||||
3. **Health check interface**: `type HealthChecker interface { Check(ctx context.Context) error }`
|
||||
4. **Registry pattern**: Modules can register additional health checkers
|
||||
|
||||
**Rationale:**
|
||||
- Custom implementation gives full control
|
||||
- Composable design allows modules to add checks
|
||||
- Simple interface is easy to test
|
||||
- No external dependency for basic functionality
|
||||
- Can extend with Prometheus metrics later
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Lightweight and fast
|
||||
- Extensible by modules
|
||||
- Easy to test
|
||||
- Clear separation of liveness vs readiness
|
||||
|
||||
### Negative
|
||||
- Need to implement ourselves (though simple)
|
||||
- Must maintain the registry
|
||||
|
||||
### Implementation Notes
|
||||
- Create `pkg/health/health.go` interface
|
||||
- Implement `internal/health/registry.go` with checker map
|
||||
- Register core checkers: database, cache (if enabled)
|
||||
- Add endpoints to HTTP router
|
||||
- Return JSON response: `{"status": "ok", "checks": {...}}`
|
||||
- Consider timeout (e.g., 5 seconds) for readiness checks
|
||||
|
||||
55
docs/adr/0015-error-bus-implementation.md
Normal file
55
docs/adr/0015-error-bus-implementation.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# ADR-0015: Error Bus Implementation
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs a centralized error handling mechanism for:
|
||||
- Capturing panics and errors
|
||||
- Logging errors consistently
|
||||
- Sending errors to external services (Sentry, etc.)
|
||||
- Avoiding error handling duplication
|
||||
|
||||
Options considered:
|
||||
1. **Channel-based in-process bus** - Simple, Go-idiomatic
|
||||
2. **Event bus integration** - Use existing event bus
|
||||
3. **Direct logging** - No bus, direct integration
|
||||
4. **External service integration** - Direct to Sentry
|
||||
|
||||
## Decision
|
||||
Implement a **channel-based error bus** with pluggable sinks:
|
||||
|
||||
1. **Error bus interface**: `type ErrorPublisher interface { Publish(err error) }`
|
||||
2. **Channel-based implementation**: Background goroutine consumes errors from channel
|
||||
3. **Pluggable sinks**: Logger (always), Sentry (optional, Phase 6)
|
||||
4. **Panic recovery middleware**: Automatically publishes panics to error bus
|
||||
|
||||
**Rationale:**
|
||||
- Simple, idiomatic Go pattern
|
||||
- Non-blocking error publishing (buffered channel)
|
||||
- Decouples error capture from error handling
|
||||
- Easy to add new sinks (Sentry, logging, metrics)
|
||||
- Can be extended to use event bus later if needed
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Centralized error handling
|
||||
- Non-blocking (doesn't slow down request path)
|
||||
- Easy to extend with new sinks
|
||||
- Consistent error handling across the platform
|
||||
|
||||
### Negative
|
||||
- Additional goroutine overhead (minimal)
|
||||
- Must ensure error bus doesn't become bottleneck
|
||||
|
||||
### Implementation Notes
|
||||
- Create `pkg/errorbus/errorbus.go` interface
|
||||
- Implement `internal/errorbus/channel_bus.go`:
|
||||
- Buffered channel (e.g., size 100)
|
||||
- Background goroutine consumes errors
|
||||
- Multiple sinks (logger, optional Sentry)
|
||||
- Add panic recovery middleware that publishes to bus
|
||||
- Register in DI container as singleton
|
||||
- Monitor channel size to detect error storms
|
||||
|
||||
56
docs/adr/0016-opentelemetry-observability.md
Normal file
56
docs/adr/0016-opentelemetry-observability.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# ADR-0016: OpenTelemetry Observability Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs distributed tracing and observability for:
|
||||
- Request tracing across services/modules
|
||||
- Performance monitoring
|
||||
- Debugging production issues
|
||||
- Integration with observability tools (Jaeger, Grafana, etc.)
|
||||
|
||||
Options considered:
|
||||
1. **OpenTelemetry** - Industry standard, vendor-neutral
|
||||
2. **Zipkin** - Older standard, less ecosystem support
|
||||
3. **Custom tracing** - Build our own
|
||||
4. **No tracing** - Only logs and metrics
|
||||
|
||||
## Decision
|
||||
Use **OpenTelemetry (OTEL)** for all observability:
|
||||
|
||||
1. **Tracing**: Distributed tracing with spans
|
||||
2. **Metrics**: Prometheus-compatible metrics
|
||||
3. **Logs**: Structured logs with trace correlation
|
||||
4. **Export**: OTLP collector for production, stdout for development
|
||||
|
||||
**Rationale:**
|
||||
- Industry standard, vendor-neutral
|
||||
- Excellent Go SDK support
|
||||
- Integrates with major observability tools
|
||||
- Supports metrics, traces, and logs
|
||||
- Recommended in playbook-golang.md
|
||||
- Future-proof (not locked to specific vendor)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Vendor-neutral (can switch backends)
|
||||
- Rich ecosystem and tooling
|
||||
- Excellent Go SDK
|
||||
- Supports all observability signals
|
||||
|
||||
### Negative
|
||||
- Learning curve for OpenTelemetry concepts
|
||||
- Slight overhead (minimal with sampling)
|
||||
- Requires OTLP collector or compatible backend
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `go.opentelemetry.io/otel` and contrib packages
|
||||
- Initialize TracerProvider in `internal/observability/tracer.go`
|
||||
- Use HTTP instrumentation middleware: `otelhttp.NewHandler()`
|
||||
- Add database instrumentation via Ent interceptor
|
||||
- Export to stdout for development, OTLP for production
|
||||
- Include trace ID in structured logs
|
||||
- Configure sampling for production (e.g., 10% or adaptive)
|
||||
|
||||
55
docs/adr/0017-jwt-token-strategy.md
Normal file
55
docs/adr/0017-jwt-token-strategy.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# ADR-0017: JWT Token Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs authentication tokens that:
|
||||
- Are stateless (no server-side session storage)
|
||||
- Support role and permission claims
|
||||
- Can be revoked (challenge)
|
||||
- Have appropriate lifetimes
|
||||
- Support multi-tenancy (tenant ID in claims)
|
||||
|
||||
Token strategies considered:
|
||||
1. **Short-lived access tokens + long-lived refresh tokens** - Industry standard
|
||||
2. **Single long-lived tokens** - Simple but insecure
|
||||
3. **Short-lived tokens only** - Secure but poor UX
|
||||
4. **Session-based** - Stateful, requires storage
|
||||
|
||||
## Decision
|
||||
Use **short-lived access tokens + long-lived refresh tokens**:
|
||||
|
||||
1. **Access tokens**: 15 minutes lifetime, contain user ID, roles, tenant ID
|
||||
2. **Refresh tokens**: 7 days lifetime, stored in database (for revocation)
|
||||
3. **Token format**: JWT with claims: `sub` (user ID), `roles`, `tenant_id`, `exp`
|
||||
4. **Revocation**: Refresh tokens stored in DB, can be revoked/deleted
|
||||
|
||||
**Rationale:**
|
||||
- Industry best practice (OAuth2/OIDC pattern)
|
||||
- Good balance of security and UX
|
||||
- Access tokens can't be revoked (short lifetime mitigates risk)
|
||||
- Refresh tokens can be revoked (stored in DB)
|
||||
- Supports stateless authentication for most requests
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Secure (short access token lifetime)
|
||||
- Good UX (refresh tokens prevent frequent re-login)
|
||||
- Stateless for most requests (access tokens)
|
||||
- Supports revocation (refresh tokens)
|
||||
|
||||
### Negative
|
||||
- Requires refresh token storage (DB table)
|
||||
- More complex than single token
|
||||
- Need to handle token refresh flow
|
||||
|
||||
### Implementation Notes
|
||||
- Use `github.com/golang-jwt/jwt/v5` for JWT handling
|
||||
- Store refresh tokens in `refresh_tokens` table (user_id, token_hash, expires_at)
|
||||
- Generate access tokens with HS256 or RS256 signing
|
||||
- Include roles in token claims (not just role IDs)
|
||||
- Validate token signature and expiration on each request
|
||||
- Refresh endpoint validates refresh token and issues new access token
|
||||
|
||||
53
docs/adr/0018-password-hashing.md
Normal file
53
docs/adr/0018-password-hashing.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# ADR-0018: Password Hashing Algorithm
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs to securely store user passwords. Requirements:
|
||||
- Resist brute-force attacks
|
||||
- Resist rainbow table attacks
|
||||
- Future-proof against advances in computing
|
||||
- Reasonable performance (not too slow)
|
||||
|
||||
Options considered:
|
||||
1. **bcrypt** - Battle-tested, widely used
|
||||
2. **argon2id** - Modern, memory-hard, recommended by OWASP
|
||||
3. **scrypt** - Memory-hard, good alternative
|
||||
4. **PBKDF2** - Older standard, less secure
|
||||
|
||||
## Decision
|
||||
Use **argon2id** for password hashing with recommended parameters:
|
||||
|
||||
- **Algorithm**: argon2id (variant)
|
||||
- **Memory**: 64 MB (65536 KB)
|
||||
- **Iterations**: 3 (time cost)
|
||||
- **Parallelism**: 4 (number of threads)
|
||||
- **Salt length**: 16 bytes (random, unique per password)
|
||||
|
||||
**Rationale:**
|
||||
- Recommended by OWASP for new applications
|
||||
- Memory-hard algorithm (resistant to GPU/ASIC attacks)
|
||||
- Good balance of security and performance
|
||||
- Future-proof design
|
||||
- Standard library support in Go 1.23+
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Strong security guarantees
|
||||
- Memory-hard (resistant to hardware attacks)
|
||||
- OWASP recommended
|
||||
- Standard library support
|
||||
|
||||
### Negative
|
||||
- Slightly slower than bcrypt (acceptable trade-off)
|
||||
- Requires tuning parameters for production
|
||||
|
||||
### Implementation Notes
|
||||
- Use `golang.org/x/crypto/argon2` package
|
||||
- Store hash in format: `$argon2id$v=19$m=65536,t=3,p=4$salt$hash`
|
||||
- Use `crypto/rand` for salt generation
|
||||
- Verify passwords with `argon2.CompareHashAndPassword()`
|
||||
- Consider increasing parameters for high-security environments
|
||||
|
||||
57
docs/adr/0019-permission-dsl-format.md
Normal file
57
docs/adr/0019-permission-dsl-format.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# ADR-0019: Permission DSL Format
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs a permission system that:
|
||||
- Is extensible by modules
|
||||
- Prevents typos and errors (compile-time safety)
|
||||
- Supports hierarchical permissions
|
||||
- Is easy to understand and use
|
||||
|
||||
Permission formats considered:
|
||||
1. **String format**: `"module.resource.action"` - Simple, flexible
|
||||
2. **Enum/Constants**: Type-safe but less flexible
|
||||
3. **Hierarchical tree**: Complex but powerful
|
||||
4. **Bitmask**: Efficient but hard to read
|
||||
|
||||
## Decision
|
||||
Use **string-based permission format** with **code-generated constants**:
|
||||
|
||||
1. **Format**: `"{module}.{resource}.{action}"`
|
||||
- Examples: `blog.post.create`, `user.read`, `system.health.check`
|
||||
2. **Code generation**: Generate constants from `module.yaml` files
|
||||
3. **Type safety**: `type Permission string` with generated constants
|
||||
4. **Validation**: Compile-time constants prevent typos
|
||||
|
||||
**Rationale:**
|
||||
- Simple and readable
|
||||
- Easy to extend (modules define in manifest)
|
||||
- Code generation provides compile-time safety
|
||||
- Flexible (modules can define any format)
|
||||
- Hierarchical structure is intuitive
|
||||
- Easy to parse and match
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Simple and intuitive format
|
||||
- Compile-time safety via code generation
|
||||
- Easy to extend by modules
|
||||
- Human-readable
|
||||
- Flexible for various permission models
|
||||
|
||||
### Negative
|
||||
- String comparisons (minimal performance impact)
|
||||
- Requires code generation step
|
||||
- Potential for permission string conflicts (mitigated by module prefix)
|
||||
|
||||
### Implementation Notes
|
||||
- Define `type Permission string` in `pkg/perm/perm.go`
|
||||
- Create code generator: `scripts/generate-permissions.go`
|
||||
- Scan `modules/*/module.yaml` for permissions
|
||||
- Generate constants in `pkg/perm/generated.go`
|
||||
- Use `//go:generate` directive
|
||||
- Validate format: `^[a-z0-9]+(\.[a-z0-9]+)*$` (lowercase, dots)
|
||||
|
||||
63
docs/adr/0020-audit-logging-storage.md
Normal file
63
docs/adr/0020-audit-logging-storage.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# ADR-0020: Audit Logging Storage
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs to audit all security-relevant actions:
|
||||
- User logins and authentication attempts
|
||||
- Permission changes
|
||||
- Data modifications
|
||||
- Administrative actions
|
||||
|
||||
Audit logs must be:
|
||||
- Immutable (append-only)
|
||||
- Queryable
|
||||
- Performant (don't slow down operations)
|
||||
- Compliant with audit requirements
|
||||
|
||||
Storage options considered:
|
||||
1. **PostgreSQL table** - Simple, queryable, transactional
|
||||
2. **Elasticsearch** - Excellent for searching, but additional dependency
|
||||
3. **File-based logs** - Simple but hard to query
|
||||
4. **External audit service** - Overkill for initial version
|
||||
|
||||
## Decision
|
||||
Store audit logs in **PostgreSQL append-only table** with JSON metadata:
|
||||
|
||||
1. **Table structure**: `audit_logs` with columns:
|
||||
- `id`, `actor_id`, `action`, `target_id`, `metadata` (JSONB), `timestamp`
|
||||
2. **Append-only**: No UPDATE or DELETE operations
|
||||
3. **JSON metadata**: Flexible storage for additional context
|
||||
4. **Indexing**: Index on `actor_id`, `action`, `timestamp` for queries
|
||||
|
||||
**Rationale:**
|
||||
- Simple (no additional infrastructure)
|
||||
- Queryable via SQL
|
||||
- Transactional (consistent with other data)
|
||||
- JSONB provides flexibility for metadata
|
||||
- Can migrate to Elasticsearch later if needed
|
||||
- Good performance for typical audit volumes
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Simple implementation
|
||||
- Queryable via SQL
|
||||
- No additional infrastructure
|
||||
- Transactional consistency
|
||||
- Can archive old logs if needed
|
||||
|
||||
### Negative
|
||||
- Adds load to primary database
|
||||
- May need archiving strategy for large volumes
|
||||
- Less powerful search than Elasticsearch
|
||||
|
||||
### Implementation Notes
|
||||
- Create `audit_logs` table via Ent schema
|
||||
- Use JSONB for metadata column (PostgreSQL-specific)
|
||||
- Add indexes: `(actor_id, timestamp)`, `(action, timestamp)`
|
||||
- Implement async logging (optional, via channel) for high throughput
|
||||
- Consider partitioning by date for large volumes
|
||||
- Add retention policy (e.g., archive after 1 year)
|
||||
|
||||
54
docs/adr/0021-module-loading-strategy.md
Normal file
54
docs/adr/0021-module-loading-strategy.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# ADR-0021: Module Loading Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs to support pluggable modules. Two approaches:
|
||||
1. **Static registration** - Modules compiled into binary
|
||||
2. **Dynamic plugin loading** - Load `.so` files at runtime
|
||||
|
||||
Each has trade-offs for development, CI, and production.
|
||||
|
||||
## Decision
|
||||
Support **both approaches** with **static registration as primary**:
|
||||
|
||||
1. **Static registration (primary)**:
|
||||
- Modules register via `init()` function
|
||||
- Imported via `import _ "module/pkg"` in main
|
||||
- Works everywhere (Windows, Linux, macOS)
|
||||
- Compile-time type safety
|
||||
|
||||
2. **Dynamic plugin loading (optional)**:
|
||||
- Support via Go `plugin` package
|
||||
- Load `.so` files from `./plugins/` directory
|
||||
- Only for production scenarios requiring hot-swap
|
||||
- Linux/macOS only (Go plugin limitation)
|
||||
|
||||
**Rationale:**
|
||||
- Static registration is simpler and more reliable
|
||||
- Works in CI/CD (no plugin compilation needed)
|
||||
- Compile-time safety catches errors early
|
||||
- Dynamic loading provides flexibility for specific use cases
|
||||
- Modules can choose their approach
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Flexible: static for most cases, dynamic when needed
|
||||
- Static registration works everywhere
|
||||
- Compile-time safety with static
|
||||
- Hot-swap capability with dynamic (Linux/macOS)
|
||||
|
||||
### Negative
|
||||
- Two code paths to maintain
|
||||
- Dynamic plugins have version compatibility constraints
|
||||
- Plugin debugging is harder
|
||||
|
||||
### Implementation Notes
|
||||
- Implement static registry in `internal/registry/registry.go`
|
||||
- Modules register via: `registry.Register(Module)` in `init()`
|
||||
- Implement plugin loader in `internal/pluginloader/plugin_loader.go` (optional)
|
||||
- Document when to use each approach
|
||||
- Validate plugin version compatibility if using dynamic loading
|
||||
|
||||
56
docs/adr/0022-cache-implementation.md
Normal file
56
docs/adr/0022-cache-implementation.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# ADR-0022: Cache Implementation
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs caching for:
|
||||
- Performance optimization (reduce database load)
|
||||
- Frequently accessed data (user permissions, roles)
|
||||
- Session data (optional)
|
||||
- Query results
|
||||
|
||||
Options considered:
|
||||
1. **Redis** - Industry standard, feature-rich
|
||||
2. **In-memory cache** - Simple, no external dependency
|
||||
3. **Memcached** - Simple, but less features than Redis
|
||||
4. **No cache** - Simplest, but poor performance at scale
|
||||
|
||||
## Decision
|
||||
Use **Redis** as the primary cache with **in-memory fallback**:
|
||||
|
||||
1. **Primary**: Redis for production
|
||||
2. **Fallback**: In-memory cache for development/testing
|
||||
3. **Interface abstraction**: `Cache` interface allows swapping implementations
|
||||
4. **Use cases**: Permission lookups, role assignments, query caching
|
||||
|
||||
**Rationale:**
|
||||
- Industry standard, widely supported
|
||||
- Rich feature set (TTL, pub/sub, etc.)
|
||||
- Can be shared across instances (multi-instance deployments)
|
||||
- Good performance
|
||||
- Easy to abstract behind interface
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- High performance
|
||||
- Shared across instances
|
||||
- Rich feature set
|
||||
- Easy to scale horizontally
|
||||
- Abstraction allows swapping implementations
|
||||
|
||||
### Negative
|
||||
- Additional infrastructure dependency
|
||||
- Network latency (minimal with proper setup)
|
||||
- Need to handle Redis failures gracefully
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `github.com/redis/go-redis/v9`
|
||||
- Create `pkg/infra/cache/cache.go` interface
|
||||
- Implement `internal/infra/cache/redis_cache.go`
|
||||
- Implement `internal/infra/cache/memory_cache.go` for fallback
|
||||
- Use connection pooling
|
||||
- Handle Redis failures gracefully (fallback or error)
|
||||
- Configure TTLs appropriately (e.g., 5 minutes for permissions)
|
||||
|
||||
59
docs/adr/0023-event-bus-implementation.md
Normal file
59
docs/adr/0023-event-bus-implementation.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# ADR-0023: Event Bus Implementation
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs an event bus for:
|
||||
- Module-to-module communication
|
||||
- Decoupled event publishing
|
||||
- Event sourcing (optional, future)
|
||||
- Integration with external systems
|
||||
|
||||
Options considered:
|
||||
1. **In-process channel-based bus** - Simple, for development/testing
|
||||
2. **Kafka** - Production-grade, scalable
|
||||
3. **RabbitMQ** - Alternative message broker
|
||||
4. **Redis pub/sub** - Simple but less reliable
|
||||
|
||||
## Decision
|
||||
Support **dual implementation** with **in-process primary, Kafka for production**:
|
||||
|
||||
1. **In-process bus (default)**:
|
||||
- Channel-based implementation
|
||||
- Used for development, testing, small deployments
|
||||
- Simple, no external dependencies
|
||||
|
||||
2. **Kafka bus (production)**:
|
||||
- Full Kafka integration via `segmentio/kafka-go`
|
||||
- Producer/consumer groups
|
||||
- Configurable via environment (switch implementation)
|
||||
|
||||
**Rationale:**
|
||||
- In-process bus is simple for development
|
||||
- Kafka provides production-grade reliability and scalability
|
||||
- Interface abstraction allows swapping
|
||||
- Modules don't need to know which implementation
|
||||
- Can start simple and scale up
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Simple for development (no Kafka needed)
|
||||
- Scalable for production (Kafka)
|
||||
- Flexible (can choose implementation)
|
||||
- Modules are decoupled from implementation
|
||||
|
||||
### Negative
|
||||
- Two implementations to maintain
|
||||
- Need to ensure interface covers both use cases
|
||||
- Kafka adds infrastructure complexity
|
||||
|
||||
### Implementation Notes
|
||||
- Create `pkg/eventbus/eventbus.go` interface
|
||||
- Implement `internal/infra/bus/inprocess_bus.go` (channel-based)
|
||||
- Implement `internal/infra/bus/kafka_bus.go` (Kafka)
|
||||
- Select implementation via config
|
||||
- Support both sync and async event publishing
|
||||
- Handle errors gracefully (retry, dead letter queue)
|
||||
|
||||
56
docs/adr/0024-job-scheduler.md
Normal file
56
docs/adr/0024-job-scheduler.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# ADR-0024: Background Job Scheduler
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs background job processing for:
|
||||
- Periodic tasks (cron jobs)
|
||||
- Asynchronous processing
|
||||
- Long-running operations
|
||||
- Retry logic for failed jobs
|
||||
|
||||
Options considered:
|
||||
1. **asynq (Redis-based)** - Simple, feature-rich
|
||||
2. **cron + custom queue** - Build our own
|
||||
3. **Kafka consumers** - Use event bus
|
||||
4. **External service** - AWS SQS, etc.
|
||||
|
||||
## Decision
|
||||
Use **asynq** (Redis-backed) for job scheduling:
|
||||
|
||||
1. **Cron jobs**: `github.com/robfig/cron/v3` for periodic tasks
|
||||
2. **Job queue**: `github.com/hibiken/asynq` for async jobs
|
||||
3. **Storage**: Redis (shared with cache)
|
||||
4. **Features**: Retries, backoff, job status tracking
|
||||
|
||||
**Rationale:**
|
||||
- Simple, Redis-backed (no new infrastructure)
|
||||
- Good Go library support
|
||||
- Built-in retry and backoff
|
||||
- Job status tracking
|
||||
- Easy to integrate
|
||||
- Can scale horizontally (multiple workers)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Simple (uses existing Redis)
|
||||
- Feature-rich (retries, backoff)
|
||||
- Good performance
|
||||
- Easy to scale
|
||||
- Job status tracking
|
||||
|
||||
### Negative
|
||||
- Tied to Redis (but we're already using it)
|
||||
- Requires Redis to be available
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `github.com/hibiken/asynq` and `github.com/robfig/cron/v3`
|
||||
- Create `pkg/scheduler/scheduler.go` interface
|
||||
- Implement `internal/infra/scheduler/asynq_scheduler.go`
|
||||
- Register jobs in `internal/infra/scheduler/job_registry.go`
|
||||
- Start worker in fx lifecycle
|
||||
- Configure retry policies (exponential backoff)
|
||||
- Add job monitoring endpoint
|
||||
|
||||
49
docs/adr/0025-multitenancy-model.md
Normal file
49
docs/adr/0025-multitenancy-model.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# ADR-0025: Multi-tenancy Model
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform may need multi-tenancy support for SaaS deployments. Options:
|
||||
1. **Shared database with tenant_id column** - Single DB, row-level isolation
|
||||
2. **Schema-per-tenant** - Single DB, separate schemas
|
||||
3. **Database-per-tenant** - Separate databases
|
||||
|
||||
Each has trade-offs for isolation, performance, and operational complexity.
|
||||
|
||||
## Decision
|
||||
Use **shared database with tenant_id column** (optional feature):
|
||||
|
||||
1. **Model**: Single PostgreSQL database with `tenant_id` column on tenant-scoped tables
|
||||
2. **Isolation**: Row-level via Ent interceptors (automatic filtering)
|
||||
3. **Tenant resolution**: From header (`X-Tenant-ID`), subdomain, or JWT claim
|
||||
4. **Optional**: Can be disabled for single-tenant deployments
|
||||
|
||||
**Rationale:**
|
||||
- Simplest operational model (single database)
|
||||
- Good performance (can index tenant_id)
|
||||
- Easy to implement (Ent interceptors)
|
||||
- Can migrate to schema-per-tenant later if needed
|
||||
- Flexible (can support both single and multi-tenant)
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Simple operations (single database)
|
||||
- Good performance with proper indexing
|
||||
- Easy to implement
|
||||
- Flexible (optional feature)
|
||||
|
||||
### Negative
|
||||
- Requires careful query design (ensure tenant_id filtering)
|
||||
- Data isolation at application level (not database level)
|
||||
- Potential for data leakage if bugs occur
|
||||
|
||||
### Implementation Notes
|
||||
- Make tenant_id optional (nullable) for single-tenant mode
|
||||
- Add Ent interceptor to automatically filter by tenant_id
|
||||
- Resolve tenant from context via middleware
|
||||
- Add tenant_id to JWT claims
|
||||
- Document tenant isolation guarantees
|
||||
- Consider adding tenant_id to all tenant-scoped tables
|
||||
|
||||
54
docs/adr/0026-error-reporting-service.md
Normal file
54
docs/adr/0026-error-reporting-service.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# ADR-0026: Error Reporting Service
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs error reporting for:
|
||||
- Production error tracking
|
||||
- Stack trace collection
|
||||
- Error aggregation and analysis
|
||||
- Integration with monitoring
|
||||
|
||||
Options considered:
|
||||
1. **Sentry** - Popular, feature-rich
|
||||
2. **Rollbar** - Alternative error tracking
|
||||
3. **Custom solution** - Build our own
|
||||
4. **Logs only** - No external service
|
||||
|
||||
## Decision
|
||||
Use **Sentry** for error reporting (optional, configurable):
|
||||
|
||||
1. **Integration**: Via error bus sink
|
||||
2. **Configuration**: Sentry DSN from config
|
||||
3. **Context**: Include user ID, trace ID, module name
|
||||
4. **Optional**: Can be disabled for development
|
||||
|
||||
**Rationale:**
|
||||
- Industry standard error tracking
|
||||
- Excellent Go SDK
|
||||
- Rich features (release tracking, grouping, etc.)
|
||||
- Good free tier
|
||||
- Easy to integrate
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Excellent error tracking
|
||||
- Rich context and grouping
|
||||
- Easy integration
|
||||
- Good free tier
|
||||
|
||||
### Negative
|
||||
- External dependency
|
||||
- Additional cost at scale
|
||||
- Privacy considerations (data sent to Sentry)
|
||||
|
||||
### Implementation Notes
|
||||
- Install: `github.com/getsentry/sentry-go`
|
||||
- Create Sentry sink for error bus
|
||||
- Configure via environment variable
|
||||
- Include context: user ID, trace ID, module name
|
||||
- Set up release tracking
|
||||
- Configure sampling for high-volume deployments
|
||||
|
||||
54
docs/adr/0027-rate-limiting-strategy.md
Normal file
54
docs/adr/0027-rate-limiting-strategy.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# ADR-0027: Rate Limiting Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs rate limiting to:
|
||||
- Prevent abuse and DoS attacks
|
||||
- Protect against brute-force attacks
|
||||
- Ensure fair resource usage
|
||||
- Comply with API usage policies
|
||||
|
||||
Rate limiting strategies:
|
||||
1. **Per-user rate limiting** - Based on authenticated user
|
||||
2. **Per-IP rate limiting** - Based on client IP
|
||||
3. **Fixed rate limiting** - Global limits
|
||||
4. **Distributed rate limiting** - Shared state across instances
|
||||
|
||||
## Decision
|
||||
Implement **multi-level rate limiting**:
|
||||
|
||||
1. **Per-user rate limiting**: For authenticated requests (e.g., 100 req/min)
|
||||
2. **Per-IP rate limiting**: For all requests (e.g., 1000 req/min)
|
||||
3. **Storage**: Redis for distributed rate limiting
|
||||
4. **Algorithm**: Token bucket or sliding window
|
||||
|
||||
**Rationale:**
|
||||
- Multi-level provides defense in depth
|
||||
- Per-user prevents abuse by authenticated users
|
||||
- Per-IP protects against unauthenticated abuse
|
||||
- Redis enables distributed rate limiting (multi-instance)
|
||||
- Token bucket provides smooth rate limiting
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Multi-layer protection
|
||||
- Works with multiple instances
|
||||
- Configurable per endpoint
|
||||
- Standard approach
|
||||
|
||||
### Negative
|
||||
- Requires Redis (or shared state)
|
||||
- Additional latency (minimal)
|
||||
- Need to handle Redis failures gracefully
|
||||
|
||||
### Implementation Notes
|
||||
- Use `github.com/ulule/limiter/v3` library
|
||||
- Configure limits in config file
|
||||
- Store rate limit state in Redis
|
||||
- Return `X-RateLimit-*` headers
|
||||
- Handle Redis failures gracefully (fail open or closed based on config)
|
||||
- Configure different limits for different endpoints
|
||||
|
||||
67
docs/adr/0028-testing-strategy.md
Normal file
67
docs/adr/0028-testing-strategy.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# ADR-0028: Testing Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The platform needs a comprehensive testing strategy:
|
||||
- Unit tests for individual components
|
||||
- Integration tests for full flows
|
||||
- Contract tests for API compatibility
|
||||
- Load tests for performance
|
||||
|
||||
Testing tools and approaches vary in complexity and coverage.
|
||||
|
||||
## Decision
|
||||
Adopt a **multi-layered testing approach**:
|
||||
|
||||
1. **Unit tests**:
|
||||
- Tool: Standard `testing` package + `testify`
|
||||
- Coverage: >80% for core modules
|
||||
- Mocks: `mockery` or `mockgen`
|
||||
- Fast execution (< 1 second)
|
||||
|
||||
2. **Integration tests**:
|
||||
- Tool: `testcontainers-go` for Docker-based services
|
||||
- Coverage: End-to-end flows (auth, modules, etc.)
|
||||
- Infrastructure: PostgreSQL, Redis, Kafka via testcontainers
|
||||
- Tagged: `//go:build integration`
|
||||
|
||||
3. **Contract tests**:
|
||||
- Tool: OpenAPI validator (`kin-openapi`)
|
||||
- Coverage: API request/response validation
|
||||
- Optional: Pact for service contracts
|
||||
|
||||
4. **Load tests**:
|
||||
- Tool: k6 or vegeta
|
||||
- Coverage: Critical endpoints (auth, API)
|
||||
- Performance benchmarks
|
||||
|
||||
**Rationale:**
|
||||
- Comprehensive coverage across layers
|
||||
- Fast feedback with unit tests
|
||||
- Realistic testing with integration tests
|
||||
- API compatibility with contract tests
|
||||
- Performance validation with load tests
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- High confidence in code quality
|
||||
- Fast unit tests for quick feedback
|
||||
- Realistic integration tests
|
||||
- API compatibility guaranteed
|
||||
|
||||
### Negative
|
||||
- Integration tests are slower
|
||||
- Requires Docker for testcontainers
|
||||
- More complex CI setup
|
||||
|
||||
### Implementation Notes
|
||||
- Use `testify` for assertions: `require` and `assert`
|
||||
- Generate mocks with `mockery` or `mockgen`
|
||||
- Create test helpers in `internal/testutil/`
|
||||
- Use test tags: `go test -tags=integration ./...`
|
||||
- Run integration tests in separate CI job
|
||||
- Document testing approach in `CONTRIBUTING.md`
|
||||
|
||||
86
docs/adr/README.md
Normal file
86
docs/adr/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Architecture Decision Records (ADRs)
|
||||
|
||||
This directory contains Architecture Decision Records (ADRs) for the Go Platform project.
|
||||
|
||||
## What are ADRs?
|
||||
|
||||
ADRs document important architectural decisions made during the project. They help:
|
||||
- Track why decisions were made
|
||||
- Understand the context and constraints
|
||||
- Review decisions when requirements change
|
||||
- Onboard new team members
|
||||
|
||||
## ADR Format
|
||||
|
||||
Each ADR follows this structure:
|
||||
- **Status**: Proposed | Accepted | Rejected | Superseded
|
||||
- **Context**: The situation that led to the decision
|
||||
- **Decision**: What was decided
|
||||
- **Consequences**: Positive and negative impacts
|
||||
|
||||
## ADR Index
|
||||
|
||||
### Phase 0: Project Setup & Foundation
|
||||
|
||||
- [ADR-0001: Go Module Path](./0001-go-module-path.md) - Module path: `git.dcentral.systems/toolz/goplt`
|
||||
- [ADR-0002: Go Version](./0002-go-version.md) - Go 1.24.3
|
||||
- [ADR-0003: Dependency Injection Framework](./0003-dependency-injection-framework.md) - uber-go/fx
|
||||
- [ADR-0004: Configuration Management](./0004-configuration-management.md) - spf13/viper + cobra
|
||||
- [ADR-0005: Logging Framework](./0005-logging-framework.md) - go.uber.org/zap
|
||||
- [ADR-0006: HTTP Framework](./0006-http-framework.md) - gin-gonic/gin
|
||||
- [ADR-0007: Project Directory Structure](./0007-project-directory-structure.md) - Standard Go layout with internal/pkg separation
|
||||
- [ADR-0008: Error Handling Strategy](./0008-error-handling-strategy.md) - Wrapped errors with typed errors
|
||||
- [ADR-0009: Context Key Types](./0009-context-key-types.md) - Typed context keys
|
||||
- [ADR-0010: CI/CD Platform](./0010-ci-cd-platform.md) - GitHub Actions
|
||||
- [ADR-0011: Code Generation Tools](./0011-code-generation-tools.md) - go generate workflow
|
||||
- [ADR-0012: Logger Interface Design](./0012-logger-interface-design.md) - Logger interface abstraction
|
||||
|
||||
### Phase 1: Core Kernel & Infrastructure
|
||||
|
||||
- [ADR-0013: Database ORM Selection](./0013-database-orm.md) - entgo.io/ent
|
||||
- [ADR-0014: Health Check Implementation](./0014-health-check-implementation.md) - Custom health check registry
|
||||
- [ADR-0015: Error Bus Implementation](./0015-error-bus-implementation.md) - Channel-based error bus with pluggable sinks
|
||||
- [ADR-0016: OpenTelemetry Observability Strategy](./0016-opentelemetry-observability.md) - OpenTelemetry for tracing, metrics, logs
|
||||
|
||||
### Phase 2: Authentication & Authorization
|
||||
|
||||
- [ADR-0017: JWT Token Strategy](./0017-jwt-token-strategy.md) - Short-lived access tokens + long-lived refresh tokens
|
||||
- [ADR-0018: Password Hashing Algorithm](./0018-password-hashing.md) - argon2id
|
||||
- [ADR-0019: Permission DSL Format](./0019-permission-dsl-format.md) - String-based format with code generation
|
||||
- [ADR-0020: Audit Logging Storage](./0020-audit-logging-storage.md) - PostgreSQL append-only table with JSONB metadata
|
||||
|
||||
### Phase 3: Module Framework
|
||||
|
||||
- [ADR-0021: Module Loading Strategy](./0021-module-loading-strategy.md) - Static registration (primary) + dynamic plugin loading (optional)
|
||||
|
||||
### Phase 5: Infrastructure Adapters
|
||||
|
||||
- [ADR-0022: Cache Implementation](./0022-cache-implementation.md) - Redis with in-memory fallback
|
||||
- [ADR-0023: Event Bus Implementation](./0023-event-bus-implementation.md) - In-process bus (default) + Kafka (production)
|
||||
- [ADR-0024: Background Job Scheduler](./0024-job-scheduler.md) - asynq (Redis-backed) + cron
|
||||
- [ADR-0025: Multi-tenancy Model](./0025-multitenancy-model.md) - Shared database with tenant_id column (optional)
|
||||
|
||||
### Phase 6: Observability & Production Readiness
|
||||
|
||||
- [ADR-0026: Error Reporting Service](./0026-error-reporting-service.md) - Sentry (optional, configurable)
|
||||
- [ADR-0027: Rate Limiting Strategy](./0027-rate-limiting-strategy.md) - Multi-level (per-user + per-IP) with Redis
|
||||
|
||||
### Phase 7: Testing, Documentation & CI/CD
|
||||
|
||||
- [ADR-0028: Testing Strategy](./0028-testing-strategy.md) - Multi-layered (unit, integration, contract, load)
|
||||
|
||||
## Adding New ADRs
|
||||
|
||||
When making a new architectural decision:
|
||||
|
||||
1. Create a new file: `XXXX-short-title.md` (next sequential number)
|
||||
2. Follow the ADR template
|
||||
3. Update this README with the new entry
|
||||
4. Set status to "Proposed" initially
|
||||
5. Update to "Accepted" after review/approval
|
||||
|
||||
## References
|
||||
|
||||
- [ADR Template](https://adr.github.io/madr/)
|
||||
- [Documenting Architecture Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions)
|
||||
|
||||
1485
docs/plan.md
Normal file
1485
docs/plan.md
Normal file
File diff suppressed because it is too large
Load Diff
620
docs/playbook.md
Normal file
620
docs/playbook.md
Normal file
@@ -0,0 +1,620 @@
|
||||
# Go‑Platform Boilerplate Play‑book
|
||||
**“Plug‑in‑friendly SaaS/Enterprise Platform – Go Edition”**
|
||||
|
||||
## 1️⃣ ARCHITECTURAL IMPERATIVES (Go‑flavoured)
|
||||
|
||||
| Principle | Go‑specific rationale | Enforcement Technique |
|
||||
|-----------|-----------------------|------------------------|
|
||||
| **Clean / Hexagonal Architecture** | Go’s package‑level visibility (`internal/`) naturally creates a *boundary* between core and plug‑ins. | Keep all **domain** code in `internal/domain`, expose only **interfaces** in `pkg/`. |
|
||||
| **Dependency Injection (DI) via Constructors** | Go avoids reflection‑heavy containers; compile‑time wiring is preferred. | Use **uber‑go/fx** (runtime graph) *or* **uber‑go/dig** for optional runtime DI. For a lighter weight solution, use plain **constructor injection** with a small **registry**. |
|
||||
| **Modular Monolith → Micro‑service‑ready** | A single binary is cheap in Go; later you can extract modules into separate services without breaking APIs. | Each module lives in its own Go **module** (`go.mod`) under `./modules/*`. The core loads them via the **Go plugin** system *or* static registration (preferred for CI stability). |
|
||||
| **Plugin‑first design** | Go’s `plugin` package allows runtime loading of compiled `.so` files (Linux/macOS). | Provide an **IModule** interface and a **loader** that discovers `*.so` files (or compiled‑in modules for CI). |
|
||||
| **API‑First (OpenAPI + gin/gorilla)** | Guarantees language‑agnostic contracts. | Generate server stubs from an `openapi.yaml` stored in `api/`. |
|
||||
| **Security‑by‑Design** | Go’s static typing makes it easy to keep auth data out of the request flow. | Central middleware for JWT verification + context‑based user propagation. |
|
||||
| **Observability (OpenTelemetry)** | The Go ecosystem ships first‑class OTEL SDK. | Instrument HTTP, DB, queues, and custom events automatically. |
|
||||
| **Configuration‑as‑Code** | Viper + Cobra give hierarchical config and flag parsing. | Load defaults → file → env → secret manager (AWS Secrets Manager / Vault). |
|
||||
| **Testing & CI** | `go test` is fast; Testcontainers via **testcontainers-go** can spin up DB, Redis, Kafka. | CI pipeline runs unit, integration, and contract tests on each PR. |
|
||||
| **Semantic Versioning & Compatibility** | Go modules already enforce version constraints. | Core declares **minimal required versions** in `go.mod` and uses `replace` for local dev. |
|
||||
|
||||
---
|
||||
|
||||
## 2️⃣ CORE KERNEL (What every Go‑platform must ship)
|
||||
|
||||
| Module | Public Interfaces (exported from `pkg/`) | Recommended Packages | Brief Implementation Sketch |
|
||||
|--------|-------------------------------------------|----------------------|------------------------------|
|
||||
| **Config** | `type ConfigProvider interface { Get(key string) any; Unmarshal(v any) error }` | `github.com/spf13/viper` | Load defaults (`config/default.yaml`), then env overrides, then optional secret‑store. |
|
||||
| **Logger** | `type Logger interface { Debug(msg string, fields ...Field); Info(...); Error(...); With(fields ...Field) Logger }` | `go.uber.org/zap` (or `zerolog`) | Global logger is created in `cmd/main.go`; exported via `pkg/logger`. |
|
||||
| **DI / Service Registry** | `type Container interface { Provide(constructor any) error; Invoke(fn any) error }` | `go.uber.org/dig` (or `fx` for lifecycle) | Core creates a `dig.New()` container, registers core services, then calls `container.Invoke(app.Start)`. |
|
||||
| **Health & Metrics** | `type HealthChecker interface { Check(ctx context.Context) error }` | `github.com/prometheus/client_golang/prometheus`, `github.com/heptiolabs/healthcheck` | Expose `/healthz`, `/ready`, `/metrics`. |
|
||||
| **Error Bus** | `type ErrorPublisher interface { Publish(err error) }` | Simple channel‐based implementation + optional Sentry (`github.com/getsentry/sentry-go`) | Core registers a singleton `ErrorBus`. |
|
||||
| **Auth (JWT + OIDC)** | `type Authenticator interface { GenerateToken(userID string, roles []string) (string, error); VerifyToken(token string) (*TokenClaims, error) }` | `github.com/golang-jwt/jwt/v5`, `github.com/coreos/go-oidc` | Token claims embed `sub`, `roles`, `tenant_id`. Middleware adds `User` to `context.Context`. |
|
||||
| **Authorization (RBAC/ABAC)** | `type Authorizer interface { Authorize(ctx context.Context, perm Permission) error }` | Custom DSL, `github.com/casbin/casbin/v2` (optional) | Permission format: `"module.resource.action"`; core ships a simple in‑memory resolver and a `casbin` adapter. |
|
||||
| **Audit** | `type Auditor interface { Record(ctx context.Context, act AuditAction) error }` | Write to append‑only table (Postgres) or Elastic via `olivere/elastic` | Audits include `actorID`, `action`, `targetID`, `metadata`. |
|
||||
| **Event Bus** | `type EventBus interface { Publish(ctx context.Context, ev Event) error; Subscribe(topic string, handler EventHandler) }` | `github.com/segmentio/kafka-go` (for production) + in‑process fallback | Core ships an **in‑process bus** used by tests and a **Kafka bus** for real deployments. |
|
||||
| **Persistence (Repository)** | `type UserRepo interface { FindByID(id string) (*User, error); Create(u *User) error; … }` | `entgo.io/ent` (code‑gen ORM) **or** `gorm.io/gorm` | Core provides an `EntClient` wrapper that implements all core repos. |
|
||||
| **Scheduler / Background Jobs** | `type Scheduler interface { Cron(spec string, job JobFunc) error; Enqueue(q string, payload any) error }` | `github.com/robfig/cron/v3`, `github.com/hibiken/asynq` (Redis‑backed) | Expose a `JobRegistry` where modules can register periodic jobs. |
|
||||
| **Notification** | `type Notifier interface { Send(ctx context.Context, n Notification) error }` | `github.com/go-mail/mail` (SMTP), `github.com/aws/aws-sdk-go-v2/service/ses`, `github.com/IBM/sarama` (for push) | Core supplies an `EmailNotifier` and a `WebhookNotifier`. |
|
||||
| **Multitenancy (optional)** | `type TenantResolver interface { Resolve(ctx context.Context) (tenantID string, err error) }` | Header/ sub‑domain parser + JWT claim scanner | Tenant ID is stored in request context and automatically added to SQL queries via Ent’s `Client` interceptor. |
|
||||
|
||||
All *public* interfaces live under `pkg/` so that plug‑ins can import them without pulling in implementation details. The concrete implementations stay in `internal/` (or separate go.mod modules) and are **registered with the container** during bootstrap.
|
||||
|
||||
---
|
||||
|
||||
## 3️⃣ MODULE (PLUGIN) FRAMEWORK
|
||||
|
||||
### 3.1 Interface that every module must implement
|
||||
|
||||
```go
|
||||
// pkg/module/module.go
|
||||
package module
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// IModule is the contract a feature plug‑in must fulfil.
|
||||
type IModule interface {
|
||||
// Name returns a unique, human‑readable identifier.
|
||||
Name() string
|
||||
// Init registers the module's services, routes, jobs, and permissions.
|
||||
// The fx.Options returned are merged into the app's lifecycle.
|
||||
Init() fx.Option
|
||||
// Migrations returns a slice of Ent migration functions (or raw SQL) that
|
||||
// the core will run when the platform starts.
|
||||
Migrations() []func(*ent.Client) error
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Registration Mechanics
|
||||
|
||||
Two ways to get a module into the platform:
|
||||
|
||||
| Approach | When to use | Pros | Cons |
|
||||
|----------|-------------|------|------|
|
||||
| **Static registration** – each module imports `core` and calls `module.Register(MyBlogModule{})` in its own `init()` | Development, CI (no `.so` needed) | Simpler, works on Windows; compile‑time type safety | Requires recompiling the binary for new modules |
|
||||
| **Runtime `plugin` loading** – compile each module as a `go build -buildmode=plugin -o blog.so ./modules/blog` | Production SaaS where clients drop new modules, or separate micro‑service extraction | Hot‑swap without rebuild | Only works on Linux/macOS; plugins must be compiled with same Go version & same `go.mod` replace graph; debugging harder |
|
||||
|
||||
**Static registration example**
|
||||
|
||||
```go
|
||||
// internal/registry/registry.go
|
||||
package registry
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"github.com/yourorg/platform/pkg/module"
|
||||
)
|
||||
|
||||
var (
|
||||
mu sync.Mutex
|
||||
modules = make(map[string]module.IModule)
|
||||
)
|
||||
|
||||
func Register(m module.IModule) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if _, ok := modules[m.Name()]; ok {
|
||||
panic("module already registered: " + m.Name())
|
||||
}
|
||||
modules[m.Name()] = m
|
||||
}
|
||||
|
||||
func All() []module.IModule {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
out := make([]module.IModule, 0, len(modules))
|
||||
for _, m := range modules {
|
||||
out = append(out, m)
|
||||
}
|
||||
return out
|
||||
}
|
||||
```
|
||||
|
||||
**Plugin loader skeleton**
|
||||
|
||||
```go
|
||||
// internal/pluginloader/loader.go
|
||||
package pluginloader
|
||||
|
||||
import (
|
||||
"plugin"
|
||||
"github.com/yourorg/platform/pkg/module"
|
||||
)
|
||||
|
||||
func Load(path string) (module.IModule, error) {
|
||||
p, err := plugin.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sym, err := p.Lookup("Module")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mod, ok := sym.(module.IModule)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid module type")
|
||||
}
|
||||
return mod, nil
|
||||
}
|
||||
```
|
||||
|
||||
> **Tip:** Ship a tiny CLI (`platformctl modules list`) that scans `./plugins/*.so`, loads each via `Load`, and prints `Name()`. This is a great sanity check for ops.
|
||||
|
||||
### 3.3 Permissions DSL (compile‑time safety)
|
||||
|
||||
```go
|
||||
// pkg/perm/perm.go
|
||||
package perm
|
||||
|
||||
type Permission string
|
||||
|
||||
func (p Permission) String() string { return string(p) }
|
||||
|
||||
var (
|
||||
// Core permissions
|
||||
SystemHealthCheck Permission = "system.health.check"
|
||||
|
||||
// Blog module – generated by a small go:generate script
|
||||
BlogPostCreate Permission = "blog.post.create"
|
||||
BlogPostRead Permission = "blog.post.read"
|
||||
BlogPostUpdate Permission = "blog.post.update"
|
||||
BlogPostDelete Permission = "blog.post.delete"
|
||||
)
|
||||
```
|
||||
|
||||
A **code‑gen** tool (`go generate ./...`) can scan each module’s `module.yaml` for declared actions and emit a single `perm.go` file, guaranteeing no duplicate strings.
|
||||
|
||||
---
|
||||
|
||||
## 4️⃣ SAMPLE FEATURE MODULE – **Blog**
|
||||
|
||||
```
|
||||
modules/
|
||||
└─ blog/
|
||||
├─ go.mod # (module github.com/yourorg/blog)
|
||||
├─ module.yaml
|
||||
├─ internal/
|
||||
│ ├─ api/
|
||||
│ │ └─ handler.go
|
||||
│ ├─ domain/
|
||||
│ │ ├─ post.go
|
||||
│ │ └─ post_repo.go
|
||||
│ └─ service/
|
||||
│ └─ post_service.go
|
||||
└─ pkg/
|
||||
└─ module.go
|
||||
```
|
||||
|
||||
### 4.1 `module.yaml`
|
||||
|
||||
```yaml
|
||||
name: blog
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- core >= 1.3.0
|
||||
permissions:
|
||||
- blog.post.create
|
||||
- blog.post.read
|
||||
- blog.post.update
|
||||
- blog.post.delete
|
||||
routes:
|
||||
- method: POST
|
||||
path: /api/v1/blog/posts
|
||||
permission: blog.post.create
|
||||
- method: GET
|
||||
path: /api/v1/blog/posts/:id
|
||||
permission: blog.post.read
|
||||
```
|
||||
|
||||
### 4.2 Go implementation
|
||||
|
||||
```go
|
||||
// pkg/module.go
|
||||
package blog
|
||||
|
||||
import (
|
||||
"github.com/yourorg/platform/pkg/module"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
type BlogModule struct{}
|
||||
|
||||
func (b BlogModule) Name() string { return "blog" }
|
||||
|
||||
func (b BlogModule) Init() fx.Option {
|
||||
return fx.Options(
|
||||
// Register repository implementation
|
||||
fx.Provide(NewPostRepo),
|
||||
|
||||
// Register service layer
|
||||
fx.Provide(NewPostService),
|
||||
|
||||
// Register HTTP handlers (using Gin)
|
||||
fx.Invoke(RegisterHandlers),
|
||||
|
||||
// Register permissions (optional – just for documentation)
|
||||
fx.Invoke(RegisterPermissions),
|
||||
)
|
||||
}
|
||||
|
||||
func (b BlogModule) Migrations() []func(*ent.Client) error {
|
||||
// Ent migration generated in internal/ent/migrate
|
||||
return []func(*ent.Client) error{
|
||||
func(c *ent.Client) error { return c.Schema.Create(context.Background()) },
|
||||
}
|
||||
}
|
||||
|
||||
// Export a variable for the plugin loader
|
||||
var Module BlogModule
|
||||
```
|
||||
|
||||
**Handler registration (Gin example)**
|
||||
|
||||
```go
|
||||
// internal/api/handler.go
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yourorg/blog/internal/service"
|
||||
"github.com/yourorg/platform/pkg/perm"
|
||||
"github.com/yourorg/platform/pkg/auth"
|
||||
)
|
||||
|
||||
func RegisterHandlers(r *gin.Engine, svc *service.PostService, authz auth.Authorizer) {
|
||||
grp := r.Group("/api/v1/blog")
|
||||
grp.Use(auth.AuthMiddleware()) // verifies JWT, injects user in context
|
||||
|
||||
// POST /posts
|
||||
grp.POST("/posts", func(c *gin.Context) {
|
||||
if err := authz.Authorize(c.Request.Context(), perm.BlogPostCreate); err != nil {
|
||||
c.JSON(403, gin.H{"error": "forbidden"})
|
||||
return
|
||||
}
|
||||
// decode request, call svc.Create, return 201…
|
||||
})
|
||||
// GET /posts/:id (similar)
|
||||
}
|
||||
```
|
||||
|
||||
**Repository using Ent**
|
||||
|
||||
```go
|
||||
// internal/domain/post_repo.go
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/yourorg/platform/internal/ent"
|
||||
"github.com/yourorg/platform/internal/ent/post"
|
||||
)
|
||||
|
||||
type PostRepo struct{ client *ent.Client }
|
||||
|
||||
func NewPostRepo(client *ent.Client) *PostRepo { return &PostRepo{client} }
|
||||
|
||||
func (r *PostRepo) Create(ctx context.Context, p *Post) (*Post, error) {
|
||||
entPost, err := r.client.Post.
|
||||
Create().
|
||||
SetTitle(p.Title).
|
||||
SetContent(p.Content).
|
||||
SetAuthorID(p.AuthorID).
|
||||
Save(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fromEnt(entPost), nil
|
||||
}
|
||||
```
|
||||
|
||||
> **Result:** Adding a new feature is just a matter of creating a new folder under `modules/`, implementing `module.IModule`, registering routes, permissions and migrations. The core automatically wires everything together.
|
||||
|
||||
---
|
||||
|
||||
## 5️⃣ INFRASTRUCTURE ADAPTERS (swap‑able, per‑environment)
|
||||
|
||||
| Concern | Implementation (Go) | Where it lives |
|
||||
|---------|---------------------|----------------|
|
||||
| **Database** | `entgo.io/ent` (code‑gen) | `internal/infra/ent/` |
|
||||
| **Cache** | `github.com/go-redis/redis/v9` | `internal/infra/cache/` |
|
||||
| **Message Queue** | `github.com/segmentio/kafka-go` (Kafka) **or** `github.com/hibiken/asynq` (Redis) | `internal/infra/bus/` |
|
||||
| **Blob Storage** | `github.com/aws/aws-sdk-go-v2/service/s3` (or GCS) | `internal/infra/blob/` |
|
||||
| **Email** | `github.com/go-mail/mail` (SMTP) | `internal/infra/email/` |
|
||||
| **SMS / Push** | Twilio SDK, Firebase Cloud Messaging | `internal/infra/notify/` |
|
||||
| **Secret Store** | AWS Secrets Manager (`aws-sdk-go-v2`) or HashiCorp Vault (`github.com/hashicorp/vault/api`) | `internal/infra/secret/` |
|
||||
|
||||
All adapters expose an **interface** in `pkg/infra/…` and are registered in the DI container as **singletons**.
|
||||
|
||||
---
|
||||
|
||||
## 6️⃣ OBSERVABILITY STACK
|
||||
|
||||
| Layer | Library | What it does |
|
||||
|-------|---------|--------------|
|
||||
| **Tracing** | `go.opentelemetry.io/otel`, `go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp` | Auto‑instrument HTTP, DB (Ent plugin), Kafka, Redis |
|
||||
| **Metrics** | `github.com/prometheus/client_golang/prometheus` | Counter/Histogram per request, DB latency, job execution |
|
||||
| **Logging** | `go.uber.org/zap` (structured JSON) | Global logger, request‑scoped fields (`request_id`, `user_id`, `tenant_id`) |
|
||||
| **Error Reporting** | `github.com/getsentry/sentry-go` (optional) | Capture panics & errors, link to trace ID |
|
||||
| **Dashboard** | Grafana + Prometheus + Loki (logs) | Provide ready‑made dashboards in `ops/` folder |
|
||||
|
||||
**Instrumentation example (HTTP)**
|
||||
|
||||
```go
|
||||
import (
|
||||
"net/http"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := gin.New()
|
||||
// Wrap the entire router with OTEL middleware
|
||||
wrapped := otelhttp.NewHandler(r, "http-server")
|
||||
http.ListenAndServe(":8080", wrapped)
|
||||
}
|
||||
```
|
||||
|
||||
**Metrics middleware**
|
||||
|
||||
```go
|
||||
func PromMetrics() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
c.Next()
|
||||
duration := time.Since(start).Seconds()
|
||||
method := c.Request.Method
|
||||
path := c.FullPath()
|
||||
status := fmt.Sprintf("%d", c.Writer.Status())
|
||||
requestDuration.WithLabelValues(method, path, status).Observe(duration)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7️⃣ CONFIGURATION & ENVIRONMENT
|
||||
|
||||
```
|
||||
config/
|
||||
├─ default.yaml # baseline values
|
||||
├─ development.yaml
|
||||
├─ production.yaml
|
||||
└─ secrets/ # git‑ignored, loaded via secret manager
|
||||
```
|
||||
|
||||
**Bootstrap**
|
||||
|
||||
```go
|
||||
func LoadConfig() (*Config, error) {
|
||||
v := viper.New()
|
||||
v.SetConfigName("default")
|
||||
v.AddConfigPath("./config")
|
||||
if err := v.ReadInConfig(); err != nil { return nil, err }
|
||||
|
||||
env := v.GetString("environment") // dev / prod / test
|
||||
v.SetConfigName(env)
|
||||
v.MergeInConfig() // overrides defaults
|
||||
|
||||
v.AutomaticEnv() // env vars win
|
||||
// optional: secret manager overlay
|
||||
return &Config{v}, nil
|
||||
}
|
||||
```
|
||||
|
||||
All services receive a `*Config` via DI.
|
||||
|
||||
---
|
||||
|
||||
## 8️⃣ CI / CD PIPELINE (GitHub Actions)
|
||||
|
||||
```yaml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GO111MODULE: on
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
- name: Cache Go modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||
- name: Install Tools
|
||||
run: |
|
||||
go install github.com/vektra/mockery/v2@latest
|
||||
go install github.com/golang/mock/mockgen@latest
|
||||
- name: Lint
|
||||
run: |
|
||||
go install golang.org/x/lint/golint@latest
|
||||
golint ./...
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
go test ./... -cover -race -short
|
||||
- name: Integration Tests (Docker Compose)
|
||||
run: |
|
||||
docker compose -f ./docker-compose.test.yml up -d
|
||||
go test ./... -tags=integration -count=1
|
||||
docker compose -f ./docker-compose.test.yml down
|
||||
- name: Build Binaries
|
||||
run: |
|
||||
go build -ldflags="-X main.version=${{ github.sha }}" -o bin/platform ./cmd/platform
|
||||
- name: Publish Docker Image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.ref == 'refs/heads/main' }}
|
||||
tags: ghcr.io/yourorg/platform:${{ github.sha }}
|
||||
```
|
||||
|
||||
**Key points**
|
||||
|
||||
* `go test ./... -tags=integration` runs tests that spin up Postgres, Redis, Kafka via **Testcontainers** (`github.com/testcontainers/testcontainers-go`).
|
||||
* Linting via `golint` or `staticcheck`.
|
||||
* Docker image built from the compiled binary (multi‑stage: `golang:1.22-alpine` → `scratch` or `distroless`).
|
||||
* Semantic‑release can be added on top (`semantic-release` action) to tag releases automatically.
|
||||
|
||||
---
|
||||
|
||||
## 9️⃣ TESTING STRATEGY
|
||||
|
||||
| Test type | Tools | Typical coverage |
|
||||
|-----------|-------|------------------|
|
||||
| **Unit** | `testing`, `github.com/stretchr/testify`, `github.com/golang/mock` | Individual services, repositories (use in‑memory DB or mocks). |
|
||||
| **Integration** | `testcontainers-go` for Postgres, Redis, Kafka; real Ent client | End‑to‑end request → DB → event bus flow. |
|
||||
| **Contract** | `pact-go` or **OpenAPI** validator middleware (`github.com/getkin/kin-openapi`) | Guarantees that modules do not break the published API. |
|
||||
| **Load / Stress** | `k6` or `vegeta` scripts in `perf/` | Verify that auth middleware adds < 2 ms latency per request. |
|
||||
| **Security** | `gosec`, `zap` for secret detection, OWASP ZAP for API scan | Detect hard‑coded secrets, SQL injection risk. |
|
||||
|
||||
**Example integration test skeleton**
|
||||
|
||||
```go
|
||||
func TestCreatePost_Integration(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
// Spin up a PostgreSQL container
|
||||
pg, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: testcontainers.ContainerRequest{
|
||||
Image: "postgres:15-alpine",
|
||||
Env: map[string]string{"POSTGRES_PASSWORD": "secret", "POSTGRES_DB": "test"},
|
||||
ExposedPorts: []string{"5432/tcp"},
|
||||
WaitingFor: wait.ForListeningPort("5432/tcp"),
|
||||
},
|
||||
Started: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
defer pg.Terminate(ctx)
|
||||
|
||||
// Build DSN from container host/port
|
||||
host, _ := pg.Endpoint(ctx)
|
||||
dsn := fmt.Sprintf("postgres://postgres:secret@%s/test?sslmode=disable", host)
|
||||
|
||||
// Initialize Ent client against that DSN
|
||||
client, err := ent.Open("postgres", dsn)
|
||||
require.NoError(t, err)
|
||||
defer client.Close()
|
||||
// Run schema migration
|
||||
err = client.Schema.Create(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Build the whole app using fx, injecting the test client
|
||||
app := fx.New(
|
||||
core.ProvideAll(),
|
||||
fx.Provide(func() *ent.Client { return client }),
|
||||
blog.Module.Init(),
|
||||
// ...
|
||||
)
|
||||
// Start the app, issue a HTTP POST request through httptest.Server,
|
||||
// assert 201 and DB row existence.
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10️⃣ COMMON PITFALLS & SOLUTIONS (Go‑centric)
|
||||
|
||||
| Pitfall | Symptom | Remedy |
|
||||
|---------|----------|--------|
|
||||
| **Circular imports** (core ↔ module) | `import cycle not allowed` build error | Keep **interfaces only** in `pkg/`. Core implements, modules depend on the interface only. |
|
||||
| **Too‑big binary** (all modules compiled in) | Long build times, memory pressure on CI | Use **Go plugins** for truly optional modules; keep core binary minimal. |
|
||||
| **Version mismatch with plugins** | Panic: `plugin was built with a different version of package X` | Enforce a **single `replace` directive** for core in each module’s `go.mod` (e.g., `replace github.com/yourorg/platform => ../../platform`). |
|
||||
| **Context leakage** (request data not passed) | Logs missing `user_id`, permission checks use zero‑value user | Always store user/tenant info in `context.Context` via middleware; provide helper `auth.FromContext(ctx)`. |
|
||||
| **Ent migrations out‑of‑sync** | Startup fails with “column does not exist” | Run `go generate ./...` (ent codegen) and `ent/migrate` automatically at boot **after all module migrations are collected**. |
|
||||
| **Hard‑coded permission strings** | Typos go unnoticed → 403 bugs | Use the **generated `perm` package** (see §4.1) and reference constants everywhere. |
|
||||
| **Blocking I/O in request path** | 500 ms latency spikes | Off‑load long‑running work to **asynq jobs** or **Kafka consumers**; keep request handlers thin. |
|
||||
| **Over‑exposed HTTP handlers** | Missing auth middleware → open endpoint | Wrap the router with a **global security middleware** that checks a whitelist and enforces `Authorizer` for everything else. |
|
||||
| **Memory leaks with goroutine workers** | Leak after many module reloads | Use **fx.Lifecycle** to start/stop background workers; always cancel contexts on `Stop`. |
|
||||
| **Testing with real DB slows CI** | Pipeline > 10 min | Use **testcontainers** in parallel jobs, cache Docker images, or use in‑memory SQLite for unit tests and only run DB‑heavy tests in a dedicated job. |
|
||||
|
||||
---
|
||||
|
||||
## 11️⃣ QUICK‑START STEPS (What to code first)
|
||||
|
||||
1. **Bootstrap repo**
|
||||
```bash
|
||||
mkdir platform && cd platform
|
||||
go mod init github.com/yourorg/platform
|
||||
mkdir cmd internal pkg config modules
|
||||
touch cmd/main.go
|
||||
```
|
||||
2. **Create core container** (`internal/di/container.go`) using `dig`. Register Config, Logger, DB, EventBus, Authenticator, Authorizer.
|
||||
3. **Add Auth middleware** (`pkg/auth/middleware.go`) that extracts JWT, validates claims, injects `User` into context.
|
||||
4. **Implement Permission DSL** (`pkg/perm/perm.go`) and a **simple in‑memory resolver** (`pkg/perm/resolver.go`).
|
||||
5. **Write `module` interface** (`pkg/module/module.go`) and a **static registry** (`internal/registry/registry.go`).
|
||||
6. **Add first plug‑in** – copy the **Blog** module skeleton from §4.
|
||||
`cd modules/blog && go mod init github.com/yourorg/blog && go run ../..` (build & test).
|
||||
7. **Wire everything in `cmd/main.go`** using `fx.New(...)`:
|
||||
```go
|
||||
app := fx.New(
|
||||
core.Module, // registers core services
|
||||
fx.Invoke(registry.RegisterAllModules), // loads static modules
|
||||
fx.Invoke(func(lc fx.Lifecycle, r *gin.Engine) {
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(context.Context) error {
|
||||
go r.Run(":8080")
|
||||
return nil
|
||||
},
|
||||
OnStop: func(ctx context.Context) error { return nil },
|
||||
})
|
||||
}),
|
||||
)
|
||||
app.Run()
|
||||
```
|
||||
8. **Run integration test** (`go test ./... -tags=integration`) to sanity‑check DB + routes.
|
||||
9. **Add CI workflow** (copy the `.github/workflows/ci.yml` from §8) and push.
|
||||
10. **Publish first Docker image** (`docker build -t ghcr.io/yourorg/platform:dev .`).
|
||||
|
||||
After step 10 you have a **complete, production‑grade scaffolding** that:
|
||||
|
||||
* authenticates users via JWT (with optional OIDC),
|
||||
* authorizes actions through a compile‑time‑checked permission DSL,
|
||||
* logs/metrics/traces out of the box,
|
||||
* lets any team drop a new `*.so` or static module under `modules/` to add resources,
|
||||
* ships with a working CI pipeline and a ready‑to‑run Docker image.
|
||||
|
||||
---
|
||||
|
||||
## 12️⃣ REFERENCE IMPLEMENTATION (public)
|
||||
|
||||
If you prefer to start from a **real open‑source baseline**, check out the following community projects that already adopt most of the ideas above:
|
||||
|
||||
| Repo | Highlights |
|
||||
|------|------------|
|
||||
| `github.com/go‑microservices/clean‑arch` | Clean‑architecture skeleton, fx DI, Ent ORM, JWT auth |
|
||||
| `github.com/ory/hydra` | Full OIDC provider (good for auth reference) |
|
||||
| `github.com/segmentio/kafka-go` examples | Event‑bus integration |
|
||||
| `github.com/ThreeDotsLabs/watermill` | Pub/sub abstraction usable as bus wrapper |
|
||||
| `github.com/hibiken/asynq` | Background job framework (Redis based) |
|
||||
|
||||
Fork one, strip the business logic, and rename the packages to match *your* `github.com/yourorg/platform` namespace.
|
||||
|
||||
---
|
||||
|
||||
## 13️⃣ FINAL CHECKLIST (before you ship)
|
||||
|
||||
- [ ] Core modules compiled & registered in `internal/di`.
|
||||
- [ ] `module.IModule` interface and static registry in place.
|
||||
- [ ] JWT auth + middleware + `User` context helper.
|
||||
- [ ] Permission constants generated & compiled in `pkg/perm`.
|
||||
- [ ] Ent schema + migration runner that aggregates all module migrations.
|
||||
- [ ] OpenTelemetry tracer/provider wired at process start.
|
||||
- [ ] Prometheus metrics endpoint (`/metrics`).
|
||||
- [ ] Health endpoints (`/healthz`, `/ready`).
|
||||
- [ ] Dockerfile (multi‑stage) and `docker-compose.yml` for dev.
|
||||
- [ ] GitHub Actions pipeline (CI) passes all tests.
|
||||
- [ ] Sample plug‑in (Blog) builds, loads, registers routes, and passes integration test.
|
||||
- [ ] Documentation: `README.md`, `docs/architecture.md`, `docs/extension-points.md`.
|
||||
|
||||
> **Congratulations!** You now have a **robust, extensible Go platform boilerplate** that can be the foundation for any SaaS, internal toolset, or micro‑service ecosystem you wish to build. Happy coding! 🚀
|
||||
319
docs/requirements.md
Normal file
319
docs/requirements.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# Requirements
|
||||
|
||||
## 1️⃣ HIGH‑LEVEL ARCHITECTURAL PRINCIPLES
|
||||
|
||||
| Principle | Why it matters for a modular platform | How to enforce it |
|
||||
|-----------|----------------------------------------|-------------------|
|
||||
| **Separation of Concerns (SoC)** | Keeps core services (auth, audit, config) independent from business modules. | Use **layered** or **hexagonal/clean‑architecture** boundaries. |
|
||||
| **Domain‑Driven Design (DDD) Bounded Contexts** | Allows each module to own its own model & rules while sharing a common identity kernel. | Define a **Core Context** (Identity, Security, Infrastructure) and **Feature Contexts** (Billing, CMS, Chat, …). |
|
||||
| **Modular Monolith → Micro‑service‑ready** | Start simple (single process) but keep each module in its own package so you can later split to services if needed. | Package each module as an **independent library** with its own **DI container‑module** and **routing**. |
|
||||
| **Plug‑in / Extension‑point model** | Enables customers or internal teams to drop new features without touching core code. | Export **well‑defined interfaces** (e.g., `IUserProvider`, `IPermissionResolver`, `IModuleInitializer`). |
|
||||
| **API‑First** | Guarantees that any UI (web, mobile, CLI) can be built on top of the same contract. | Publish **OpenAPI/GraphQL schema** as part of the build artefact. |
|
||||
| **Security‑by‑Design** | The platform will hold user credentials, roles and possibly PII. | Centralize **authentication**, **authorization**, **audit**, **rate‑limiting**, **CORS**, **CSP**, **secure defaults**. |
|
||||
| **Observability** | You need to know when a plug‑in crashes or misbehaves. | Provide **structured logging**, **metrics**, **tracing**, **health‑checks**, **central error bus**. |
|
||||
| **CI/CD‑Ready Boilerplate** | Keeps the framework maintainable and encourages best‑practice adoption. | Include **GitHub Actions / GitLab CI** pipelines that run lint, unit, integration, contract tests, and a publish step. |
|
||||
| **Configuration‑as‑Code** | Each module may need its own settings but you want a single source of truth. | Use a **hierarchical config system** (environment > file > secret store). |
|
||||
| **Multitenancy (optional)** | If you plan SaaS, the core must be ready to isolate data per tenant. | Provide **tenant‑aware repository abstractions** and **tenant‑scoped middlewares**. |
|
||||
| **Versioning & Compatibility** | Modules evolve; the core should never break existing plug‑ins. | Adopt **semantic versioning** + **backwards‑compatibility shim layer** (e.g., deprecation warnings). |
|
||||
|
||||
---
|
||||
|
||||
## 2️⃣ LAYERED / HEXAGONAL BLUEPRINT
|
||||
|
||||
```
|
||||
+---------------------------------------------------+
|
||||
| Presentation |
|
||||
| (REST/GraphQL/ gRPC Controllers, UI SDKs, CLI) |
|
||||
+-------------------+-------------------------------+
|
||||
| Application Services (Use‑cases) |
|
||||
| - orchestrate core & feature modules |
|
||||
| - enforce policies (RBAC, rate‑limit) |
|
||||
+-------------------+-------------------------------+
|
||||
| Domain (Business Logic) |
|
||||
| - Core Entities (User, Role, Permission) |
|
||||
| - Domain Services (PasswordPolicy, TokenMgr) |
|
||||
+-------------------+-------------------------------+
|
||||
| Infrastructure / Adapters |
|
||||
| - Persistence (ORM/NoSQL Repositories) |
|
||||
| - External services (Email, SMS, OIDC) |
|
||||
| - Event bus (Kafka/Rabbit, In‑process) |
|
||||
| - File storage, Cache, Search |
|
||||
+---------------------------------------------------+
|
||||
| Platform Core (Kernel) |
|
||||
| - DI container, Module loader, Config manager |
|
||||
| - Cross‑cutting concerns (Logging, Metrics) |
|
||||
| - Security subsystem (AuthN/AuthZ, Token Issuer)|
|
||||
+---------------------------------------------------+
|
||||
```
|
||||
|
||||
*All layers talk to each other **through interfaces** defined in the Core kernel. Feature modules implement those interfaces and register themselves at startup.*
|
||||
|
||||
---
|
||||
|
||||
## 3️⃣ REQUIRED BASE MODULES (THE “CORE KERNEL”)
|
||||
|
||||
| Module | Core responsibilities | Public API / Extension points |
|
||||
|--------|-----------------------|--------------------------------|
|
||||
| **Identity‑Management** | - User CRUD (local + federation) <br>- Password hashing, reset flow <br>- Email/Phone verification | `IUserRepository`, `IUserService`, `IExternalIdpProvider` |
|
||||
| **Roles & Permissions** | - Role hierarchy (role → permission set) <br>- Permission definitions (string, enum, policy) <br>- Dynamic permission evaluation (ABAC) | `IPermissionResolver`, `IRoleService` |
|
||||
| **Authentication** | - JWT / OAuth2 Access & Refresh tokens <br>- OpenID Connect Provider (optional) <br>- Session Management (stateless + optional stateful) | `IAuthService`, `ITokenProvider` |
|
||||
| **Authorization Middleware** | - Enforce RBAC/ABAC on each request <br>- Policy DSL (e.g., `hasPermission('project.read') && resource.ownerId == user.id`) | `IAuthorizationHandler` |
|
||||
| **Audit & Activity Log** | - Immutable log of security‑relevant actions <br>- Correlation IDs, actor, target, timestamp | `IAuditSink`, `IAuditService` |
|
||||
| **Configuration** | - Hierarchical sources (env, files, secret manager) <br>- Validation schema (JSON‑Schema / Yup / JSR‑380) | `IConfigProvider` |
|
||||
| **Health & Metrics** | - `/healthz`, `/ready`, `/metrics` endpoints <br>- Export to Prometheus, Grafana, CloudWatch | `IHealthCheck`, `IMetricsRegistry` |
|
||||
| **Error Handling** | - Centralized error objects, stack trace masking <br>- Automatic mapping to HTTP status <br>- Exception‑to‑event publishing | `IErrorMapper`, `IErrorBus` |
|
||||
| **Logging** | - Structured JSON logs (level, requestId, userId) <br>- pluggable sinks (stdout, file, ELK, Cloud Logging) | `ILoggerFactory` |
|
||||
| **Notification** | - Email, SMS, Push (FCM/APNs), Webhooks <br>- Queue‑backed delivery, retries | `INotificationService` |
|
||||
| **File / Blob Storage** | - Abstracted bucket API (upload, version, signed URLs) | `IBlobStore` |
|
||||
| **Scheduler / Background Jobs** | - Cron‑like tasks, queue workers, retry/back‑off policies | `IJobScheduler`, `IJobProcessor` |
|
||||
| **Internationalization (i18n)** | - Message catalog, locale negotiation, runtime translation | `I18nService` |
|
||||
| **API Gateway (optional)** | - Rate‑limit, request/response transformation, API‑key handling, request routing to modules | `IGatewayPlugin` |
|
||||
| **Multitenancy (optional)** | - Tenant identification (sub‑domain, header, JWT claim) <br>- Tenant‑scoped data isolation primitives | `ITenantResolver`, `ITenantContext` |
|
||||
|
||||
> **Tip:** Pack each module as a **separate NPM/ Maven / NuGet / Go module** with its own `package.json` / `pom.xml` etc. The platform’s **bootstrapper** loads every module that implements `IModuleInitializer` (or similar) and calls `ConfigureServices` / `RegisterRoutes`.
|
||||
|
||||
---
|
||||
|
||||
## 4️⃣ EXTENSION‑POINT DESIGN (HOW PLUG‑INS HOOK IN)
|
||||
|
||||
1. **Module Manifest** – a tiny JSON/YAML file (`module.yaml`) that declares:
|
||||
- Module name, version, dependencies (core ≥ 1.2.0, other modules)
|
||||
- Public routes (e.g., `/api/v1/blog/**`)
|
||||
- Required permissions (auto‑generated from source annotations)
|
||||
- UI assets (static folder, React component entry point)
|
||||
|
||||
2. **Bootstrap Interface**
|
||||
```ts
|
||||
export interface IModuleInitializer {
|
||||
/**
|
||||
* Called during platform start‑up.
|
||||
* Register services, routes, policies, background jobs.
|
||||
*/
|
||||
init(app: IApplicationBuilder, container: IServiceContainer): Promise<void>;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Dependency Injection (DI) Conventions**
|
||||
- Core registers **contracts** (`IUserRepository`, `IPermissionResolver`) as **singletons**.
|
||||
- Modules register **implementations** with a **named scope** (e.g., `UserRepository:Local`).
|
||||
- Override is possible via **module ordering** or explicit `container.override(...)`.
|
||||
|
||||
4. **Policy/Permission Extension**
|
||||
```ts
|
||||
// core lib
|
||||
export type Permission = `${string}.${string}`; // e.g., "blog.post.create"
|
||||
|
||||
// module
|
||||
export const BLOG_PERMS = {
|
||||
POST_CREATE: 'blog.post.create',
|
||||
POST_READ: 'blog.post.read',
|
||||
POST_UPDATE: 'blog.post.update',
|
||||
POST_DELETE: 'blog.post.delete',
|
||||
} as const;
|
||||
```
|
||||
|
||||
5. **Event Bus & Hooks**
|
||||
- Central **topic**: `platform.*` (user.created, role.assigned, tenant.created)
|
||||
- Modules can **publish** and **subscribe** via `IEventBus`.
|
||||
- Provide **synchronous guard hooks** (`beforeUserCreate`, `afterRoleDelete`) for validation & side‑effects.
|
||||
|
||||
6. **UI Plug‑in System**
|
||||
- Serve a **manifest** at `/modules` that front‑end bundles read to render navigation.
|
||||
- Encourage **Web Component / Module Federation** pattern for SPA integration.
|
||||
|
||||
---
|
||||
|
||||
## 5️⃣ SAMPLE REPOSITORY LAYOUT (language‑agnostic)
|
||||
|
||||
```
|
||||
/platform-root
|
||||
│
|
||||
├─ /core # ---- Kernel / Base modules ----
|
||||
│ ├─ /auth
|
||||
│ │ ├─ src/
|
||||
│ │ └─ package.json
|
||||
│ ├─ /identity
|
||||
│ ├─ /authorization
|
||||
│ ├─ /audit
|
||||
│ ├─ /config
|
||||
│ ├─ /logging
|
||||
│ ├─ /metrics
|
||||
│ └─ index.ts (exports all core APIs)
|
||||
│
|
||||
├─ /modules # ---- Feature plug‑ins ----
|
||||
│ ├─ /blog
|
||||
│ │ ├─ module.yaml # manifest
|
||||
│ │ ├─ src/
|
||||
│ │ │ ├─ BlogController.ts
|
||||
│ │ │ ├─ BlogService.ts
|
||||
│ │ │ └─ BlogModule.ts (implements IModuleInitializer)
|
||||
│ │ └─ package.json
|
||||
│ │
|
||||
│ ├─ /billing
|
||||
│ └─ /chat
|
||||
│
|
||||
├─ /infra # ---- Infrastructure adapters ----
|
||||
│ ├─ /orm (typeorm/hibernate/EFCore etc.)
|
||||
│ ├─ /cache (redis)
|
||||
│ ├─ /queue (rabbit/kafka)
|
||||
│ └─ /storage (s3/azure‑blob)
|
||||
│
|
||||
├─ /gateway (optional API‑gateway layer)
|
||||
│
|
||||
├─ /scripts # build / lint / test helpers
|
||||
│
|
||||
├─ /ci
|
||||
│ └─ github-actions.yml
|
||||
│
|
||||
├─ /docs
|
||||
│ └─ architecture.md
|
||||
│
|
||||
├─ package.json (or pom.xml / go.mod)
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
### How it boots
|
||||
|
||||
```ts
|
||||
// platform-root/src/main.ts
|
||||
import { createApp } from '@core/app';
|
||||
import { loadModules } from '@core/module-loader';
|
||||
import { CoreModule } from '@core';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await createApp();
|
||||
|
||||
// 1️⃣ Load core kernel (DI, config, logger)
|
||||
await app.register(CoreModule);
|
||||
|
||||
// 2️⃣ Dynamically discover all `module.yaml` under /modules
|
||||
const modules = await loadModules(__dirname + '/modules');
|
||||
|
||||
// 3️⃣ Initialise each module (order can be defined in manifest)
|
||||
for (const mod of modules) {
|
||||
await mod.instance.init(app.builder, app.container);
|
||||
}
|
||||
|
||||
// 4️⃣ Start HTTP / gRPC server
|
||||
await app.listen(process.env.PORT || 3000);
|
||||
}
|
||||
|
||||
bootstrap().catch(err => {
|
||||
console.error('❌ Platform failed to start', err);
|
||||
process.exit(1);
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6️⃣ KEY DECISIONS YOU MUST TAKE EARLY
|
||||
|
||||
| Decision | Options | Implications |
|
||||
|----------|---------|--------------|
|
||||
| **Language / Runtime** | Node.js (NestJS, Fastify), Java (Spring Boot), .NET (ASP.NET Core), Go (Gin/Fiber), Python (FastAPI) | Affects DI framework, module packaging, community libs for auth/OIDC, testing. |
|
||||
| **Persistence Strategy** | Relational (PostgreSQL, MySQL) + optional NoSQL (Mongo, Dynamo) | Choose an ORM/Repository pattern that can be swapped per module. |
|
||||
| **Auth Protocol** | JWT + Refresh, OAuth2 Authorization Server, OpenID Connect Provider, or integrate with external IdP (Keycloak, Auth0) | Influences token lifetimes, revocation strategy, multi‑tenant support. |
|
||||
| **Event Bus** | In‑process EventEmitter (for monolith) → Kafka/Rabbit for scaling | Must expose both sync and async hooks. |
|
||||
| **Module Packaging** | NPM packages (private registry) / Maven artifacts / Docker images (for micro‑service extraction) | Define a *semantic version* policy (core ≥ 1.0.0 never forces breaking changes on plug‑ins). |
|
||||
| **Multitenancy Model** | Single DB with tenant_id column (shared), Schema‑per‑tenant, or DB‑per‑tenant | Affects repository base class and migrations tooling. |
|
||||
| **Internationalisation** | i18next (frontend) + ICU messages in backend, or .NET Resource files | Choose a format that can be merged from modules at build time. |
|
||||
| **CI/CD** | GitHub Actions + Docker Buildx + semantic‑release | Automate publishing of core + modules to same artifact registry. |
|
||||
| **Testing Strategy** | Unit (Jest, JUnit, xUnit), Integration (Testcontainers), Contract (Pact) | Provide a **core testing harness** that loads a dummy module and asserts the contract of each extension point. |
|
||||
|
||||
---
|
||||
|
||||
## 7️⃣ COMMON PITFALLS & HOW TO AVOID THEM
|
||||
|
||||
| Pitfall | Symptoms | Fix / Guardrail |
|
||||
|---------|----------|-----------------|
|
||||
| **Tight coupling of modules to core implementation** | Module imports internal ORM classes, fails on core upgrade. | Expose **only interfaces** (`IUserRepository`) from core and keep the concrete implementation as a private package. |
|
||||
| **Hard‑coded permission strings** | Duplicate names across modules, typos cause silent authorisation bypass. | Provide a **Permission Builder DSL** (`Permission.define('blog.post', ['create', 'read'])`) that generates constants and registers them automatically. |
|
||||
| **Global state in modules** | Tests interfere with each other, memory leaks when hot‑reloading. | Enforce **stateless services**; keep per‑request scoped data (e.g., via DI context). |
|
||||
| **Schema migrations clash** | Two modules try to add the same column or foreign key. | Adopt a **central migration orchestrator** (e.g., Flyway/DBMate) that loads migration scripts from each module in alphabetical order. |
|
||||
| **Authorization checks omitted in new routes** | Security hole for new plug‑in routes. | Provide a **base controller class** that auto‑applies `Authorize` filter, or a compile‑time lint rule that checks every exported route for a permission annotation. |
|
||||
| **Vendor lock‑in to a particular IdP** | Hard to replace Keycloak later. | Keep **IdP adapters** behind a `IIdentityProvider` interface; ship at least two (local DB + OIDC). |
|
||||
| **Unbounded background jobs** | Queue overflow, OOM, duplicate processing. | Use a **job‑scheduler abstraction** that caps concurrency, persists state, and provides `@Retry` decorator. |
|
||||
| **Insufficient observability** | You can’t tell which module caused latency spikes. | Tag every log/metric with `module=<moduleName>` automatically via middleware. |
|
||||
| **Version drift between core and modules** | Module built against core 1.0 fails on core 1.5. | Publish a **core compatibility matrix** and enforce `peerDependencies` in package.json; CI should fail on mismatched ranges. |
|
||||
|
||||
---
|
||||
|
||||
## 8️⃣ QUICK START GUIDE (What to Build First)
|
||||
|
||||
1. **Create the Core Kernel**
|
||||
- Set up DI container, config loader, logger, health/metrics endpoint.
|
||||
- Scaffold `IUserRepository`, `IPermissionResolver`, `ITokenProvider`.
|
||||
|
||||
2. **Implement Identity & Auth**
|
||||
- Choose JWT + Refresh + optional OpenID Connect.
|
||||
- Add password hashing (bcrypt/argon2) and email verification flow.
|
||||
|
||||
3. **Add Role/Permission Engine**
|
||||
- Simple RBAC matrix with an extensible `Permission` type.
|
||||
- Provide a UI admin UI (or API only) to manage roles.
|
||||
|
||||
4. **Set Up Event Bus & Audit**
|
||||
- Publish `user.created`, `role.granted` events.
|
||||
- Store audit entries in an append‑only table (or log to Elastic).
|
||||
|
||||
5. **Build the Module Loader**
|
||||
- Scan `modules/*/module.yaml`, load via `require()`/classpath.
|
||||
- Register each `IModuleInitializer`.
|
||||
|
||||
6. **Create a Sample Feature Module** – e.g., **Blog**
|
||||
- Define its own entities (`Post`, `Comment`).
|
||||
- Register routes (`/api/v1/blog/posts`).
|
||||
- Declare required permissions (`blog.post.create`).
|
||||
|
||||
7. **Write Integration Tests**
|
||||
- Spin up an in‑memory DB (SQLite or H2).
|
||||
- Load core + blog module, assert that a user without `blog.post.create` receives 403.
|
||||
|
||||
8. **Add CI Pipeline**
|
||||
- Lint → Unit → Integration (Docker Compose with DB + Redis).
|
||||
- On tag, publish `core` and `blog` packages to your private registry.
|
||||
|
||||
9. **Document Extension Points**
|
||||
- Provide a **Developer Handbook** (README + `docs/extension-points.md`).
|
||||
|
||||
10. **Iterate** – add Notification, Scheduler, Multitenancy, API‑Gateway as needed.
|
||||
|
||||
---
|
||||
|
||||
## 9️⃣ TOOLS & LIBRARIES (starter suggestions per stack)
|
||||
|
||||
| Stack | Core | Auth | DI / Module | Event Bus | ORM | Validation | Testing |
|
||||
|-------|------|------|-------------|-----------|-----|------------|---------|
|
||||
| **Node (TypeScript)** | NestJS (or Fastify + `awilix`) | `@nestjs/passport`, `passport-jwt`, `openid-client` | NestJS dynamic modules or `@nestjs-modules/mailer` | `@nestjs/event-emitter` or `KafkaJS` | TypeORM / Prisma | `class-validator` + `class-transformer` | Jest + `supertest`, Testcontainers |
|
||||
| **Java** | Spring Boot | Spring Security + `spring-boot-starter-oauth2-resource-server` | Spring Boot `@Configuration` + `ImportBeanDefinitionRegistrar` | Spring Cloud Stream (Kafka) | JPA / Hibernate | Bean Validation (Hibernate Validator) | JUnit5 + Testcontainers |
|
||||
| **.NET 8** | ASP.NET Core | `Microsoft.AspNetCore.Authentication.JwtBearer` | `IHostedService` + `Scrutor` for module discovery | MassTransit (Rabbit/Kafka) | EF Core | FluentValidation | xUnit + DockerTestContainers |
|
||||
| **Go** | Echo / Fiber | `golang.org/x/oauth2` + `github.com/golang-jwt/jwt/v5` | `uber-go/fx` for DI, module registration | `segmentio/kafka-go` | GORM / Ent | `go-playground/validator` | Testify + Dockertest |
|
||||
| **Python** | FastAPI | `fastapi-users` / `Authlib` | `pluggy` (pytest plugins) or custom loader | `aiokafka` | SQLModel / Tortoise ORM | Pydantic | Pytest + pytest‑asyncio, Testcontainers |
|
||||
|
||||
Pick the stack you’re most comfortable with; the concepts stay identical.
|
||||
|
||||
---
|
||||
|
||||
## 🎉 TL;DR – What You Must Deliver
|
||||
|
||||
| Layer | Must‑have components | Why |
|
||||
|-------|----------------------|-----|
|
||||
| **Core Kernel** | Config, Logger, DI, Health, Metrics, Error Bus | Foundation for any module. |
|
||||
| **Security** | Auth (JWT/OIDC), Authorization (RBAC + ABAC), Audit | Guarantees secure, traceable access. |
|
||||
| **User & Role Management** | User CRUD, Password reset, Role ↔ Permission matrix | The “identity” piece everyone will reuse. |
|
||||
| **Extension System** | `IModuleInitializer`, `module.yaml`, EventBus, Permission DSL | Enables plug‑ins without touching core. |
|
||||
| **Infrastructure Adapters** | DB repo, Cache, Queue, Blob storage, Email/SMS | Keeps core agnostic to any concrete tech. |
|
||||
| **Observability** | Structured logs, Prometheus metrics, OpenTelemetry traces | You can monitor each module individually. |
|
||||
| **DevOps Boilerplate** | CI pipelines, Dockerfiles, Semantic‑release, Docs | Makes the framework production‑ready out‑of‑the‑box. |
|
||||
| **Sample Feature Module** | (e.g., Blog) to show how to add routes, permissions, DB entities | Provides a reference implementation for future developers. |
|
||||
|
||||
When you scaffold those pieces **once**, any downstream team can drop a new folder that follows the `module.yaml` contract, implement the initializer, add its own tables & APIs, and instantly get:
|
||||
|
||||
* secure authentication,
|
||||
* role‑based authorization,
|
||||
* logging/metrics,
|
||||
* unified config,
|
||||
* CI‑ready testing,
|
||||
* optional multi‑tenant isolation.
|
||||
|
||||
That’s the foundation of a **robust, future‑proof platform boilerplate**. Happy building! 🚀
|
||||
62
docs/stories/COMPLETE_TASK_LIST.md
Normal file
62
docs/stories/COMPLETE_TASK_LIST.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Complete Task List
|
||||
|
||||
This document provides a comprehensive list of all tasks across all phases. Each task has a corresponding detailed file in the phase-specific directories.
|
||||
|
||||
## Task Organization
|
||||
|
||||
Tasks are organized by phase and section. Each task file follows the naming convention: `{section}.{subtask}-{description}.md`
|
||||
|
||||
## Phase 0: Project Setup & Foundation
|
||||
|
||||
### 0.1 Repository Bootstrap
|
||||
- [0.1.1 - Initialize Go Module](./phase0/0.1.1-initialize-go-module.md)
|
||||
- [0.1.2 - Create Directory Structure](./phase0/0.1.2-create-directory-structure.md)
|
||||
- [0.1.3 - Add Gitignore](./phase0/0.1.3-add-gitignore.md)
|
||||
- [0.1.4 - Create Initial README](./phase0/0.1.4-create-initial-readme.md)
|
||||
|
||||
### 0.2 Configuration System
|
||||
- [0.2.1 - Install Configuration Dependencies](./phase0/0.2.1-install-config-dependencies.md)
|
||||
- [0.2.2 - Create Config Interface](./phase0/0.2.2-create-config-interface.md)
|
||||
- [0.2.3 - Implement Config Loader](./phase0/0.2.3-implement-config-loader.md)
|
||||
- [0.2.4 - Create Configuration Files](./phase0/0.2.4-create-configuration-files.md)
|
||||
|
||||
### 0.3 Logging Foundation
|
||||
- [0.3.1 - Install Logging Dependencies](./phase0/0.3.1-install-logging-dependencies.md)
|
||||
- See [Phase 0 README](./phase0/README.md) for remaining tasks
|
||||
|
||||
### 0.4 Basic CI/CD Pipeline
|
||||
- See [Phase 0 README](./phase0/README.md) for tasks
|
||||
|
||||
### 0.5 Dependency Injection Setup
|
||||
- See [Phase 0 README](./phase0/README.md) for tasks
|
||||
|
||||
## Phase 1-8 Tasks
|
||||
|
||||
Detailed task files for Phases 1-8 are being created. See individual phase README files:
|
||||
- [Phase 1 README](./phase1/README.md) - Core Kernel & Infrastructure
|
||||
- [Phase 2 README](./phase2/README.md) - Authentication & Authorization
|
||||
- [Phase 3 README](./phase3/README.md) - Module Framework
|
||||
- [Phase 4 README](./phase4/README.md) - Sample Feature Module (Blog)
|
||||
- [Phase 5 README](./phase5/README.md) - Infrastructure Adapters
|
||||
- [Phase 6 README](./phase6/README.md) - Observability & Production Readiness
|
||||
- [Phase 7 README](./phase7/README.md) - Testing, Documentation & CI/CD
|
||||
- [Phase 8 README](./phase8/README.md) - Advanced Features & Polish
|
||||
|
||||
## Task Status Tracking
|
||||
|
||||
To track task completion:
|
||||
1. Update the Status field in each task file
|
||||
2. Update checkboxes in the main plan.md
|
||||
3. Reference task IDs in commit messages: `[0.1.1] Initialize Go module`
|
||||
4. Link GitHub issues to tasks if using issue tracking
|
||||
|
||||
## Generating Missing Task Files
|
||||
|
||||
A script is available to generate task files from plan.md:
|
||||
```bash
|
||||
cd docs/tasks
|
||||
python3 generate_tasks.py
|
||||
```
|
||||
|
||||
Note: Manually review and refine generated task files as needed.
|
||||
|
||||
63
docs/stories/README.md
Normal file
63
docs/stories/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Implementation Tasks
|
||||
|
||||
This directory contains detailed task definitions for each phase of the Go Platform implementation.
|
||||
|
||||
## Task Organization
|
||||
|
||||
Tasks are organized by phase, with each major task section having its own detailed file:
|
||||
|
||||
### Phase 0: Project Setup & Foundation
|
||||
- [Phase 0 Tasks](./phase0/README.md) - All Phase 0 tasks
|
||||
|
||||
### Phase 1: Core Kernel & Infrastructure
|
||||
- [Phase 1 Tasks](./phase1/README.md) - All Phase 1 tasks
|
||||
|
||||
### Phase 2: Authentication & Authorization
|
||||
- [Phase 2 Tasks](./phase2/README.md) - All Phase 2 tasks
|
||||
|
||||
### Phase 3: Module Framework
|
||||
- [Phase 3 Tasks](./phase3/README.md) - All Phase 3 tasks
|
||||
|
||||
### Phase 4: Sample Feature Module (Blog)
|
||||
- [Phase 4 Tasks](./phase4/README.md) - All Phase 4 tasks
|
||||
|
||||
### Phase 5: Infrastructure Adapters
|
||||
- [Phase 5 Tasks](./phase5/README.md) - All Phase 5 tasks
|
||||
|
||||
### Phase 6: Observability & Production Readiness
|
||||
- [Phase 6 Tasks](./phase6/README.md) - All Phase 6 tasks
|
||||
|
||||
### Phase 7: Testing, Documentation & CI/CD
|
||||
- [Phase 7 Tasks](./phase7/README.md) - All Phase 7 tasks
|
||||
|
||||
### Phase 8: Advanced Features & Polish (Optional)
|
||||
- [Phase 8 Tasks](./phase8/README.md) - All Phase 8 tasks
|
||||
|
||||
## Task Status
|
||||
|
||||
Each task file includes:
|
||||
- **Task ID**: Unique identifier (e.g., `0.1.1`)
|
||||
- **Title**: Descriptive task name
|
||||
- **Phase**: Implementation phase
|
||||
- **Status**: Pending | In Progress | Completed | Blocked
|
||||
- **Priority**: High | Medium | Low
|
||||
- **Dependencies**: Tasks that must complete first
|
||||
- **Description**: Detailed requirements
|
||||
- **Acceptance Criteria**: How to verify completion
|
||||
- **Implementation Notes**: Technical details and references
|
||||
- **Related ADRs**: Links to relevant architecture decisions
|
||||
|
||||
## Task Tracking
|
||||
|
||||
Tasks can be tracked using:
|
||||
- GitHub Issues (linked from tasks)
|
||||
- Project boards
|
||||
- Task management tools
|
||||
- Direct commit messages referencing task IDs
|
||||
|
||||
## Task Naming Convention
|
||||
|
||||
Tasks follow the format: `{phase}.{section}.{subtask}`
|
||||
|
||||
Example: `0.1.1` = Phase 0, Section 1 (Repository Bootstrap), Subtask 1
|
||||
|
||||
54
docs/stories/TASK_TEMPLATE.md
Normal file
54
docs/stories/TASK_TEMPLATE.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Task Template
|
||||
|
||||
Use this template for creating new task files.
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: {phase}.{section}.{subtask}
|
||||
- **Title**: {Descriptive Task Name}
|
||||
- **Phase**: {Phase Number} - {Phase Name}
|
||||
- **Section**: {Section Number}.{Section Name}
|
||||
- **Status**: Pending | In Progress | Completed | Blocked
|
||||
- **Priority**: High | Medium | Low
|
||||
- **Estimated Time**: {time estimate}
|
||||
- **Dependencies**: {task IDs that must complete first}
|
||||
|
||||
## Description
|
||||
{Clear description of what needs to be done}
|
||||
|
||||
## Requirements
|
||||
- {Requirement 1}
|
||||
- {Requirement 2}
|
||||
- {Requirement 3}
|
||||
|
||||
## Implementation Steps
|
||||
1. {Step 1}
|
||||
2. {Step 2}
|
||||
3. {Step 3}
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] {Criterion 1}
|
||||
- [ ] {Criterion 2}
|
||||
- [ ] {Criterion 3}
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-XXXX: {ADR Title}](../../adr/XXXX-adr-title.md)
|
||||
|
||||
## Implementation Notes
|
||||
- {Note 1}
|
||||
- {Note 2}
|
||||
- {Note 3}
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
## Files to Create/Modify
|
||||
- `path/to/file.go` - {Description}
|
||||
- `path/to/file_test.go` - {Description}
|
||||
|
||||
## References
|
||||
- {Link to relevant documentation}
|
||||
- {Link to example code}
|
||||
|
||||
219
docs/stories/generate_tasks.py
Normal file
219
docs/stories/generate_tasks.py
Normal file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate task files from plan.md
|
||||
This script parses the plan.md file and creates detailed task files for each task.
|
||||
"""
|
||||
|
||||
import re
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
def parse_plan(plan_path):
|
||||
"""Parse plan.md and extract tasks"""
|
||||
with open(plan_path, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
tasks = []
|
||||
current_phase = None
|
||||
current_section = None
|
||||
subtask_num = 1
|
||||
|
||||
lines = content.split('\n')
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
line = lines[i].rstrip()
|
||||
|
||||
# Phase header
|
||||
phase_match = re.match(r'^## Phase (\d+):', line)
|
||||
if phase_match:
|
||||
current_phase = int(phase_match.group(1))
|
||||
subtask_num = 1 # Reset subtask counter for new phase
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# Section header (e.g., "#### 0.1 Repository Bootstrap")
|
||||
section_match = re.match(r'^#### (\d+\.\d+)', line)
|
||||
if section_match:
|
||||
current_section = section_match.group(1)
|
||||
subtask_num = 1 # Reset subtask counter for new section
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# Task item (checkbox) - must match exactly
|
||||
task_match = re.match(r'^- \[ \] (.+)', line)
|
||||
if task_match and current_phase is not None and current_section is not None:
|
||||
task_desc = task_match.group(1).strip()
|
||||
|
||||
# Handle tasks that end with colon (might have code block or list following)
|
||||
code_block = ""
|
||||
# Skip empty lines and code blocks
|
||||
if i + 1 < len(lines):
|
||||
next_line = lines[i + 1].strip()
|
||||
if next_line.startswith('```'):
|
||||
# Extract code block
|
||||
j = i + 2
|
||||
while j < len(lines) and not lines[j].strip().startswith('```'):
|
||||
code_block += lines[j] + '\n'
|
||||
j += 1
|
||||
i = j + 1
|
||||
elif next_line.startswith('- [ ]') or next_line.startswith('```'):
|
||||
# Next task or code block, don't skip
|
||||
i += 1
|
||||
else:
|
||||
i += 1
|
||||
else:
|
||||
i += 1
|
||||
|
||||
# Only add if we have valid phase and section
|
||||
if current_phase is not None and current_section is not None:
|
||||
tasks.append({
|
||||
'phase': current_phase,
|
||||
'section': current_section,
|
||||
'subtask': subtask_num,
|
||||
'description': task_desc,
|
||||
'code': code_block.strip()
|
||||
})
|
||||
subtask_num += 1
|
||||
continue
|
||||
|
||||
i += 1
|
||||
|
||||
return tasks
|
||||
|
||||
def create_task_file(task, output_dir):
|
||||
"""Create a task markdown file"""
|
||||
phase_dir = output_dir / f"phase{task['phase']}"
|
||||
phase_dir.mkdir(exist_ok=True)
|
||||
|
||||
task_id = f"{task['section']}.{task['subtask']}"
|
||||
# Create safe filename
|
||||
safe_desc = re.sub(r'[^\w\s-]', '', task['description'])[:50].strip().replace(' ', '-').lower()
|
||||
filename = f"{task_id}-{safe_desc}.md"
|
||||
filepath = phase_dir / filename
|
||||
|
||||
# Generate content
|
||||
content = f"""# Task {task_id}: {task['description']}
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: {task_id}
|
||||
- **Title**: {task['description']}
|
||||
- **Phase**: {task['phase']} - {get_phase_name(task['phase'])}
|
||||
- **Section**: {task['section']}
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
{task['description']}
|
||||
|
||||
## Requirements
|
||||
- {task['description']}
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task {task_id} is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
if task['code']:
|
||||
content += f"\n## Code Reference\n\n```go\n{task['code']}\n```\n"
|
||||
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(content)
|
||||
|
||||
return filepath
|
||||
|
||||
def get_phase_name(phase_num):
|
||||
"""Get phase name from number"""
|
||||
phases = {
|
||||
0: "Project Setup & Foundation",
|
||||
1: "Core Kernel & Infrastructure",
|
||||
2: "Authentication & Authorization",
|
||||
3: "Module Framework",
|
||||
4: "Sample Feature Module (Blog)",
|
||||
5: "Infrastructure Adapters",
|
||||
6: "Observability & Production Readiness",
|
||||
7: "Testing, Documentation & CI/CD",
|
||||
8: "Advanced Features & Polish"
|
||||
}
|
||||
return phases.get(phase_num, "Unknown")
|
||||
|
||||
def main():
|
||||
script_dir = Path(__file__).parent
|
||||
plan_path = script_dir.parent / "plan.md"
|
||||
output_dir = script_dir
|
||||
|
||||
if not plan_path.exists():
|
||||
print(f"Error: {plan_path} not found")
|
||||
return
|
||||
|
||||
print(f"Parsing {plan_path}...")
|
||||
try:
|
||||
tasks = parse_plan(plan_path)
|
||||
print(f"Found {len(tasks)} tasks")
|
||||
|
||||
if len(tasks) == 0:
|
||||
print("Warning: No tasks found. Check the plan.md format.")
|
||||
return
|
||||
|
||||
created = 0
|
||||
skipped = 0
|
||||
for task in tasks:
|
||||
try:
|
||||
task_id = f"{task['section']}.{task['subtask']}"
|
||||
|
||||
# Determine filepath before creating
|
||||
phase_dir = output_dir / f"phase{task['phase']}"
|
||||
phase_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Create safe filename
|
||||
safe_desc = re.sub(r'[^\w\s-]', '', task['description'])[:50].strip().replace(' ', '-').lower()
|
||||
filename = f"{task_id}-{safe_desc}.md"
|
||||
filepath = phase_dir / filename
|
||||
|
||||
# Check if file already exists (skip if so)
|
||||
if filepath.exists() and filepath.stat().st_size > 100:
|
||||
skipped += 1
|
||||
continue
|
||||
|
||||
# Create the file
|
||||
create_task_file(task, output_dir)
|
||||
created += 1
|
||||
if created % 10 == 0:
|
||||
print(f"Created {created} task files...")
|
||||
except Exception as e:
|
||||
print(f"Error creating task {task.get('section', '?')}.{task.get('subtask', '?')}: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
print(f"\nCreated {created} new task files")
|
||||
if skipped > 0:
|
||||
print(f"Skipped {skipped} existing task files")
|
||||
print(f"Total tasks processed: {len(tasks)}")
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# Task 0.1.1: Initialize Go Module
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.1
|
||||
- **Title**: Initialize Go Module
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1 Repository Bootstrap
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: None
|
||||
|
||||
## Description
|
||||
Initialize the Go module with the correct module path for the platform.
|
||||
|
||||
## Requirements
|
||||
- Use module path: `git.dcentral.systems/toolz/goplt`
|
||||
- Go version: 1.24.3
|
||||
- Ensure `go.mod` file is created correctly
|
||||
|
||||
## Implementation Steps
|
||||
1. Run `go mod init git.dcentral.systems/toolz/goplt` in the project root
|
||||
2. Verify `go.mod` file is created with correct module path
|
||||
3. Set Go version in `go.mod`: `go 1.24`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `go.mod` file exists in project root
|
||||
- [ ] Module path is `git.dcentral.systems/toolz/goplt`
|
||||
- [ ] Go version is set to `1.24`
|
||||
- [ ] `go mod verify` passes
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0001: Go Module Path](../../adr/0001-go-module-path.md)
|
||||
- [ADR-0002: Go Version](../../adr/0002-go-version.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Ensure the module path matches the organization's Git hosting structure
|
||||
- The module path will be used for all internal imports
|
||||
- Update any documentation that references placeholder module paths
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Verify module initialization
|
||||
go mod verify
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
47
docs/stories/phase0/0.1.1-initialize-go-module.md
Normal file
47
docs/stories/phase0/0.1.1-initialize-go-module.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Task 0.1.1: Initialize Go Module
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.1
|
||||
- **Title**: Initialize Go Module
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1 Repository Bootstrap
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: None
|
||||
|
||||
## Description
|
||||
Initialize the Go module with the correct module path for the platform.
|
||||
|
||||
## Requirements
|
||||
- Use module path: `git.dcentral.systems/toolz/goplt`
|
||||
- Go version: 1.24.3
|
||||
- Ensure `go.mod` file is created correctly
|
||||
|
||||
## Implementation Steps
|
||||
1. Run `go mod init git.dcentral.systems/toolz/goplt` in the project root
|
||||
2. Verify `go.mod` file is created with correct module path
|
||||
3. Set Go version in `go.mod`: `go 1.24`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `go.mod` file exists in project root
|
||||
- [ ] Module path is `git.dcentral.systems/toolz/goplt`
|
||||
- [ ] Go version is set to `1.24`
|
||||
- [ ] `go mod verify` passes
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0001: Go Module Path](../../adr/0001-go-module-path.md)
|
||||
- [ADR-0002: Go Version](../../adr/0002-go-version.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Ensure the module path matches the organization's Git hosting structure
|
||||
- The module path will be used for all internal imports
|
||||
- Update any documentation that references placeholder module paths
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Verify module initialization
|
||||
go mod verify
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
77
docs/stories/phase0/0.1.2-create-directory-structure.md
Normal file
77
docs/stories/phase0/0.1.2-create-directory-structure.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Task 0.1.2: Create directory structure:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.2
|
||||
- **Title**: Create directory structure:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create directory structure:
|
||||
|
||||
## Requirements
|
||||
- Create directory structure:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.1.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
platform/
|
||||
├── cmd/
|
||||
│ └── platform/ # Main entry point
|
||||
├── internal/ # Private implementation code
|
||||
│ ├── di/ # Dependency injection container
|
||||
│ ├── registry/ # Module registry
|
||||
│ ├── pluginloader/ # Plugin loader (optional)
|
||||
│ └── infra/ # Infrastructure adapters
|
||||
├── pkg/ # Public interfaces (exported)
|
||||
│ ├── config/ # ConfigProvider interface
|
||||
│ ├── logger/ # Logger interface
|
||||
│ ├── module/ # IModule interface
|
||||
│ ├── auth/ # Auth interfaces
|
||||
│ ├── perm/ # Permission DSL
|
||||
│ └── infra/ # Infrastructure interfaces
|
||||
├── modules/ # Feature modules
|
||||
│ └── blog/ # Sample Blog module (Phase 4)
|
||||
├── config/ # Configuration files
|
||||
│ ├── default.yaml
|
||||
│ ├── development.yaml
|
||||
│ └── production.yaml
|
||||
├── api/ # OpenAPI specs
|
||||
├── scripts/ # Build/test scripts
|
||||
├── docs/ # Documentation
|
||||
├── ops/ # Operations (Grafana dashboards, etc.)
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ └── ci.yml
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
├── docker-compose.test.yml
|
||||
└── go.mod
|
||||
```
|
||||
56
docs/stories/phase0/0.1.3-add-gitignore-for-go-projects.md
Normal file
56
docs/stories/phase0/0.1.3-add-gitignore-for-go-projects.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Task 0.1.3: Add Gitignore
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.3
|
||||
- **Title**: Add Gitignore
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1 Repository Bootstrap
|
||||
- **Status**: Pending
|
||||
- **Priority**: Medium
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Create a comprehensive `.gitignore` file for Go projects that excludes build artifacts, dependencies, IDE files, and sensitive data.
|
||||
|
||||
## Requirements
|
||||
- Ignore Go build artifacts
|
||||
- Ignore dependency caches
|
||||
- Ignore IDE-specific files
|
||||
- Ignore environment-specific files
|
||||
- Ignore secrets and sensitive data
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `.gitignore` in project root
|
||||
2. Add standard Go ignores:
|
||||
- `*.exe`, `*.exe~`, `*.dll`, `*.so`, `*.dylib`
|
||||
- `*.test`, `*.out`
|
||||
- `go.work`, `go.work.sum`
|
||||
3. Add IDE ignores:
|
||||
- `.vscode/`, `.idea/`, `*.swp`, `*.swo`
|
||||
4. Add environment ignores:
|
||||
- `.env`, `.env.local`, `config/secrets/`
|
||||
5. Add OS ignores:
|
||||
- `.DS_Store`, `Thumbs.db`
|
||||
6. Add build artifacts:
|
||||
- `bin/`, `dist/`, `tmp/`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `.gitignore` file exists
|
||||
- [ ] Common Go artifacts are ignored
|
||||
- [ ] IDE files are ignored
|
||||
- [ ] Sensitive files are ignored
|
||||
- [ ] Test with `git status` to verify
|
||||
|
||||
## Implementation Notes
|
||||
- Use standard Go `.gitignore` templates
|
||||
- Ensure `config/secrets/` is ignored (for secret files)
|
||||
- Consider adding `*.log` for log files
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Verify gitignore works
|
||||
git status
|
||||
# Should not show build artifacts or IDE files
|
||||
```
|
||||
|
||||
56
docs/stories/phase0/0.1.3-add-gitignore.md
Normal file
56
docs/stories/phase0/0.1.3-add-gitignore.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Task 0.1.3: Add Gitignore
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.3
|
||||
- **Title**: Add Gitignore
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1 Repository Bootstrap
|
||||
- **Status**: Pending
|
||||
- **Priority**: Medium
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Create a comprehensive `.gitignore` file for Go projects that excludes build artifacts, dependencies, IDE files, and sensitive data.
|
||||
|
||||
## Requirements
|
||||
- Ignore Go build artifacts
|
||||
- Ignore dependency caches
|
||||
- Ignore IDE-specific files
|
||||
- Ignore environment-specific files
|
||||
- Ignore secrets and sensitive data
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `.gitignore` in project root
|
||||
2. Add standard Go ignores:
|
||||
- `*.exe`, `*.exe~`, `*.dll`, `*.so`, `*.dylib`
|
||||
- `*.test`, `*.out`
|
||||
- `go.work`, `go.work.sum`
|
||||
3. Add IDE ignores:
|
||||
- `.vscode/`, `.idea/`, `*.swp`, `*.swo`
|
||||
4. Add environment ignores:
|
||||
- `.env`, `.env.local`, `config/secrets/`
|
||||
5. Add OS ignores:
|
||||
- `.DS_Store`, `Thumbs.db`
|
||||
6. Add build artifacts:
|
||||
- `bin/`, `dist/`, `tmp/`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `.gitignore` file exists
|
||||
- [ ] Common Go artifacts are ignored
|
||||
- [ ] IDE files are ignored
|
||||
- [ ] Sensitive files are ignored
|
||||
- [ ] Test with `git status` to verify
|
||||
|
||||
## Implementation Notes
|
||||
- Use standard Go `.gitignore` templates
|
||||
- Ensure `config/secrets/` is ignored (for secret files)
|
||||
- Consider adding `*.log` for log files
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Verify gitignore works
|
||||
git status
|
||||
# Should not show build artifacts or IDE files
|
||||
```
|
||||
|
||||
63
docs/stories/phase0/0.1.4-create-initial-readme.md
Normal file
63
docs/stories/phase0/0.1.4-create-initial-readme.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Task 0.1.4: Create Initial README
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.4
|
||||
- **Title**: Create Initial README
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1 Repository Bootstrap
|
||||
- **Status**: Pending
|
||||
- **Priority**: Medium
|
||||
- **Estimated Time**: 20 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Create an initial `README.md` file that provides an overview of the project, its purpose, architecture, and quick start instructions.
|
||||
|
||||
## Requirements
|
||||
- Project overview and description
|
||||
- Architecture overview
|
||||
- Quick start guide
|
||||
- Links to documentation
|
||||
- Build and run instructions
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `README.md` in project root
|
||||
2. Add project title and description
|
||||
3. Add architecture overview section
|
||||
4. Add quick start instructions
|
||||
5. Add links to documentation (`docs/`)
|
||||
6. Add build and run commands
|
||||
7. Add contribution guidelines (placeholder)
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `README.md` exists
|
||||
- [ ] Project overview is clear
|
||||
- [ ] Quick start instructions are present
|
||||
- [ ] Links to documentation work
|
||||
- [ ] Build instructions are accurate
|
||||
|
||||
## Implementation Notes
|
||||
- Keep README concise but informative
|
||||
- Update as project evolves
|
||||
- Include badges (build status, etc.) later
|
||||
- Reference ADRs for architecture decisions
|
||||
|
||||
## Content Structure
|
||||
```markdown
|
||||
# Go Platform (goplt)
|
||||
|
||||
[Description]
|
||||
|
||||
## Architecture
|
||||
[Overview]
|
||||
|
||||
## Quick Start
|
||||
[Instructions]
|
||||
|
||||
## Documentation
|
||||
[Links]
|
||||
|
||||
## Development
|
||||
[Setup instructions]
|
||||
```
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Task 0.1.4: Create Initial README
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.1.4
|
||||
- **Title**: Create Initial README
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.1 Repository Bootstrap
|
||||
- **Status**: Pending
|
||||
- **Priority**: Medium
|
||||
- **Estimated Time**: 20 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Create an initial `README.md` file that provides an overview of the project, its purpose, architecture, and quick start instructions.
|
||||
|
||||
## Requirements
|
||||
- Project overview and description
|
||||
- Architecture overview
|
||||
- Quick start guide
|
||||
- Links to documentation
|
||||
- Build and run instructions
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `README.md` in project root
|
||||
2. Add project title and description
|
||||
3. Add architecture overview section
|
||||
4. Add quick start instructions
|
||||
5. Add links to documentation (`docs/`)
|
||||
6. Add build and run commands
|
||||
7. Add contribution guidelines (placeholder)
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `README.md` exists
|
||||
- [ ] Project overview is clear
|
||||
- [ ] Quick start instructions are present
|
||||
- [ ] Links to documentation work
|
||||
- [ ] Build instructions are accurate
|
||||
|
||||
## Implementation Notes
|
||||
- Keep README concise but informative
|
||||
- Update as project evolves
|
||||
- Include badges (build status, etc.) later
|
||||
- Reference ADRs for architecture decisions
|
||||
|
||||
## Content Structure
|
||||
```markdown
|
||||
# Go Platform (goplt)
|
||||
|
||||
[Description]
|
||||
|
||||
## Architecture
|
||||
[Overview]
|
||||
|
||||
## Quick Start
|
||||
[Instructions]
|
||||
|
||||
## Documentation
|
||||
[Links]
|
||||
|
||||
## Development
|
||||
[Setup instructions]
|
||||
```
|
||||
|
||||
47
docs/stories/phase0/0.2.1-install-config-dependencies.md
Normal file
47
docs/stories/phase0/0.2.1-install-config-dependencies.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Task 0.2.1: Install Configuration Dependencies
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.1
|
||||
- **Title**: Install Configuration Dependencies
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Install Viper and Cobra packages for configuration management and CLI support.
|
||||
|
||||
## Requirements
|
||||
- Install `github.com/spf13/viper` v1.18.0+
|
||||
- Install `github.com/spf13/cobra` v1.8.0+
|
||||
- Add to `go.mod` with proper version constraints
|
||||
|
||||
## Implementation Steps
|
||||
1. Run `go get github.com/spf13/viper@v1.18.0`
|
||||
2. Run `go get github.com/spf13/cobra@v1.8.0`
|
||||
3. Run `go mod tidy` to update dependencies
|
||||
4. Verify packages in `go.mod`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Viper is listed in `go.mod`
|
||||
- [ ] Cobra is listed in `go.mod`
|
||||
- [ ] `go mod verify` passes
|
||||
- [ ] Dependencies are properly versioned
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Use specific versions for reproducibility
|
||||
- Consider using `go get -u` for latest patch versions
|
||||
- Document version choices in ADR
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
go mod verify
|
||||
go list -m github.com/spf13/viper
|
||||
go list -m github.com/spf13/cobra
|
||||
```
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# Task 0.2.1: Install Configuration Dependencies
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.1
|
||||
- **Title**: Install Configuration Dependencies
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Install Viper and Cobra packages for configuration management and CLI support.
|
||||
|
||||
## Requirements
|
||||
- Install `github.com/spf13/viper` v1.18.0+
|
||||
- Install `github.com/spf13/cobra` v1.8.0+
|
||||
- Add to `go.mod` with proper version constraints
|
||||
|
||||
## Implementation Steps
|
||||
1. Run `go get github.com/spf13/viper@v1.18.0`
|
||||
2. Run `go get github.com/spf13/cobra@v1.8.0`
|
||||
3. Run `go mod tidy` to update dependencies
|
||||
4. Verify packages in `go.mod`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Viper is listed in `go.mod`
|
||||
- [ ] Cobra is listed in `go.mod`
|
||||
- [ ] `go mod verify` passes
|
||||
- [ ] Dependencies are properly versioned
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Use specific versions for reproducibility
|
||||
- Consider using `go get -u` for latest patch versions
|
||||
- Document version choices in ADR
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
go mod verify
|
||||
go list -m github.com/spf13/viper
|
||||
go list -m github.com/spf13/cobra
|
||||
```
|
||||
|
||||
59
docs/stories/phase0/0.2.2-create-config-interface.md
Normal file
59
docs/stories/phase0/0.2.2-create-config-interface.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Task 0.2.2: Create Config Interface
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.2
|
||||
- **Title**: Create Config Interface
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 15 minutes
|
||||
- **Dependencies**: 0.2.1
|
||||
|
||||
## Description
|
||||
Create the `ConfigProvider` interface in `pkg/config/` to abstract configuration access. This interface will be used by all modules and services.
|
||||
|
||||
## Requirements
|
||||
- Define interface in `pkg/config/config.go`
|
||||
- Include methods for type-safe access
|
||||
- Support nested configuration keys
|
||||
- Support unmarshaling into structs
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `pkg/config/config.go`
|
||||
2. Define `ConfigProvider` interface:
|
||||
```go
|
||||
type ConfigProvider interface {
|
||||
Get(key string) any
|
||||
Unmarshal(v any) error
|
||||
GetString(key string) string
|
||||
GetInt(key string) int
|
||||
GetBool(key string) bool
|
||||
GetStringSlice(key string) []string
|
||||
}
|
||||
```
|
||||
3. Add package documentation
|
||||
4. Export interface for use by modules
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `pkg/config/config.go` exists
|
||||
- [ ] `ConfigProvider` interface is defined
|
||||
- [ ] Interface methods match requirements
|
||||
- [ ] Package documentation is present
|
||||
- [ ] Interface compiles without errors
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Interface should be minimal and focused
|
||||
- Additional methods can be added later if needed
|
||||
- Consider adding `GetDuration()` for time.Duration values
|
||||
- Consider adding `IsSet(key string) bool` to check if key exists
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
go build ./pkg/config
|
||||
go vet ./pkg/config
|
||||
```
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Task 0.2.2: Create Config Interface
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.2
|
||||
- **Title**: Create Config Interface
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 15 minutes
|
||||
- **Dependencies**: 0.2.1
|
||||
|
||||
## Description
|
||||
Create the `ConfigProvider` interface in `pkg/config/` to abstract configuration access. This interface will be used by all modules and services.
|
||||
|
||||
## Requirements
|
||||
- Define interface in `pkg/config/config.go`
|
||||
- Include methods for type-safe access
|
||||
- Support nested configuration keys
|
||||
- Support unmarshaling into structs
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `pkg/config/config.go`
|
||||
2. Define `ConfigProvider` interface:
|
||||
```go
|
||||
type ConfigProvider interface {
|
||||
Get(key string) any
|
||||
Unmarshal(v any) error
|
||||
GetString(key string) string
|
||||
GetInt(key string) int
|
||||
GetBool(key string) bool
|
||||
GetStringSlice(key string) []string
|
||||
}
|
||||
```
|
||||
3. Add package documentation
|
||||
4. Export interface for use by modules
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `pkg/config/config.go` exists
|
||||
- [ ] `ConfigProvider` interface is defined
|
||||
- [ ] Interface methods match requirements
|
||||
- [ ] Package documentation is present
|
||||
- [ ] Interface compiles without errors
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Interface should be minimal and focused
|
||||
- Additional methods can be added later if needed
|
||||
- Consider adding `GetDuration()` for time.Duration values
|
||||
- Consider adding `IsSet(key string) bool` to check if key exists
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
go build ./pkg/config
|
||||
go vet ./pkg/config
|
||||
```
|
||||
|
||||
60
docs/stories/phase0/0.2.3-implement-config-loader.md
Normal file
60
docs/stories/phase0/0.2.3-implement-config-loader.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Task 0.2.3: Implement Config Loader
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.3
|
||||
- **Title**: Implement Config Loader
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 30 minutes
|
||||
- **Dependencies**: 0.2.1, 0.2.2
|
||||
|
||||
## Description
|
||||
Implement the Viper-based configuration loader in `internal/config/` that implements the `ConfigProvider` interface. This loader will handle hierarchical configuration loading from files and environment variables.
|
||||
|
||||
## Requirements
|
||||
- Implement `ConfigProvider` interface using Viper
|
||||
- Load configuration in order: defaults → environment-specific → env vars
|
||||
- Support YAML configuration files
|
||||
- Support environment variable overrides
|
||||
- Provide placeholder for secret manager integration (Phase 6)
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `internal/config/config.go`:
|
||||
- Implement `ConfigProvider` interface
|
||||
- Wrap Viper instance
|
||||
- Implement all interface methods
|
||||
2. Create `internal/config/loader.go`:
|
||||
- `LoadConfig()` function
|
||||
- Load `config/default.yaml` as baseline
|
||||
- Merge environment-specific YAML (development/production)
|
||||
- Apply environment variable overrides
|
||||
- Set up automatic environment variable binding
|
||||
3. Add error handling for missing config files
|
||||
4. Add logging for configuration loading
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `internal/config/config.go` implements `ConfigProvider`
|
||||
- [ ] `internal/config/loader.go` has `LoadConfig()` function
|
||||
- [ ] Configuration loads from `config/default.yaml`
|
||||
- [ ] Environment-specific configs are merged correctly
|
||||
- [ ] Environment variables override file values
|
||||
- [ ] Errors are handled gracefully
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Use Viper's `SetConfigName()` and `AddConfigPath()`
|
||||
- Use `MergeInConfig()` for environment-specific files
|
||||
- Use `AutomaticEnv()` for environment variable binding
|
||||
- Set environment variable prefix (e.g., `GOPLT_`)
|
||||
- Use `SetEnvKeyReplacer()` to replace dots with underscores
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Test config loading
|
||||
go test ./internal/config -v
|
||||
```
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Task 0.2.3: Implement Config Loader
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.3
|
||||
- **Title**: Implement Config Loader
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 30 minutes
|
||||
- **Dependencies**: 0.2.1, 0.2.2
|
||||
|
||||
## Description
|
||||
Implement the Viper-based configuration loader in `internal/config/` that implements the `ConfigProvider` interface. This loader will handle hierarchical configuration loading from files and environment variables.
|
||||
|
||||
## Requirements
|
||||
- Implement `ConfigProvider` interface using Viper
|
||||
- Load configuration in order: defaults → environment-specific → env vars
|
||||
- Support YAML configuration files
|
||||
- Support environment variable overrides
|
||||
- Provide placeholder for secret manager integration (Phase 6)
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `internal/config/config.go`:
|
||||
- Implement `ConfigProvider` interface
|
||||
- Wrap Viper instance
|
||||
- Implement all interface methods
|
||||
2. Create `internal/config/loader.go`:
|
||||
- `LoadConfig()` function
|
||||
- Load `config/default.yaml` as baseline
|
||||
- Merge environment-specific YAML (development/production)
|
||||
- Apply environment variable overrides
|
||||
- Set up automatic environment variable binding
|
||||
3. Add error handling for missing config files
|
||||
4. Add logging for configuration loading
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `internal/config/config.go` implements `ConfigProvider`
|
||||
- [ ] `internal/config/loader.go` has `LoadConfig()` function
|
||||
- [ ] Configuration loads from `config/default.yaml`
|
||||
- [ ] Environment-specific configs are merged correctly
|
||||
- [ ] Environment variables override file values
|
||||
- [ ] Errors are handled gracefully
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Use Viper's `SetConfigName()` and `AddConfigPath()`
|
||||
- Use `MergeInConfig()` for environment-specific files
|
||||
- Use `AutomaticEnv()` for environment variable binding
|
||||
- Set environment variable prefix (e.g., `GOPLT_`)
|
||||
- Use `SetEnvKeyReplacer()` to replace dots with underscores
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Test config loading
|
||||
go test ./internal/config -v
|
||||
```
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# Task 0.2.4: Create Configuration Files
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.4
|
||||
- **Title**: Create Configuration Files
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 15 minutes
|
||||
- **Dependencies**: 0.1.2
|
||||
|
||||
## Description
|
||||
Create the baseline configuration YAML files that define the default configuration structure for the platform.
|
||||
|
||||
## Requirements
|
||||
- Create `config/default.yaml` with baseline values
|
||||
- Create `config/development.yaml` with development overrides
|
||||
- Create `config/production.yaml` with production overrides
|
||||
- Define configuration schema for all core services
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `config/default.yaml`:
|
||||
```yaml
|
||||
environment: development
|
||||
server:
|
||||
port: 8080
|
||||
host: "0.0.0.0"
|
||||
database:
|
||||
driver: "postgres"
|
||||
dsn: ""
|
||||
logging:
|
||||
level: "info"
|
||||
format: "json"
|
||||
```
|
||||
2. Create `config/development.yaml`:
|
||||
- Override logging level to "debug"
|
||||
- Add development-specific settings
|
||||
3. Create `config/production.yaml`:
|
||||
- Override logging level to "warn"
|
||||
- Add production-specific settings
|
||||
4. Document configuration options
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `config/default.yaml` exists with complete structure
|
||||
- [ ] `config/development.yaml` exists
|
||||
- [ ] `config/production.yaml` exists
|
||||
- [ ] All configuration files are valid YAML
|
||||
- [ ] Configuration structure is documented
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Use consistent indentation (2 spaces)
|
||||
- Add comments for unclear configuration options
|
||||
- Use environment variables for sensitive values (DSN, secrets)
|
||||
- Consider adding validation schema later
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Validate YAML syntax
|
||||
yamllint config/*.yaml
|
||||
# or
|
||||
python3 -c "import yaml; yaml.safe_load(open('config/default.yaml'))"
|
||||
```
|
||||
|
||||
67
docs/stories/phase0/0.2.4-create-configuration-files.md
Normal file
67
docs/stories/phase0/0.2.4-create-configuration-files.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# Task 0.2.4: Create Configuration Files
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.4
|
||||
- **Title**: Create Configuration Files
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2 Configuration System
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 15 minutes
|
||||
- **Dependencies**: 0.1.2
|
||||
|
||||
## Description
|
||||
Create the baseline configuration YAML files that define the default configuration structure for the platform.
|
||||
|
||||
## Requirements
|
||||
- Create `config/default.yaml` with baseline values
|
||||
- Create `config/development.yaml` with development overrides
|
||||
- Create `config/production.yaml` with production overrides
|
||||
- Define configuration schema for all core services
|
||||
|
||||
## Implementation Steps
|
||||
1. Create `config/default.yaml`:
|
||||
```yaml
|
||||
environment: development
|
||||
server:
|
||||
port: 8080
|
||||
host: "0.0.0.0"
|
||||
database:
|
||||
driver: "postgres"
|
||||
dsn: ""
|
||||
logging:
|
||||
level: "info"
|
||||
format: "json"
|
||||
```
|
||||
2. Create `config/development.yaml`:
|
||||
- Override logging level to "debug"
|
||||
- Add development-specific settings
|
||||
3. Create `config/production.yaml`:
|
||||
- Override logging level to "warn"
|
||||
- Add production-specific settings
|
||||
4. Document configuration options
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] `config/default.yaml` exists with complete structure
|
||||
- [ ] `config/development.yaml` exists
|
||||
- [ ] `config/production.yaml` exists
|
||||
- [ ] All configuration files are valid YAML
|
||||
- [ ] Configuration structure is documented
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0004: Configuration Management](../../adr/0004-configuration-management.md)
|
||||
|
||||
## Implementation Notes
|
||||
- Use consistent indentation (2 spaces)
|
||||
- Add comments for unclear configuration options
|
||||
- Use environment variables for sensitive values (DSN, secrets)
|
||||
- Consider adding validation schema later
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# Validate YAML syntax
|
||||
yamllint config/*.yaml
|
||||
# or
|
||||
python3 -c "import yaml; yaml.safe_load(open('config/default.yaml'))"
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 0.2.5: Add `internal/config/loader.go` with `LoadConfig()` function
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.2.5
|
||||
- **Title**: Add `internal/config/loader.go` with `LoadConfig()` function
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add `internal/config/loader.go` with `LoadConfig()` function
|
||||
|
||||
## Requirements
|
||||
- Add `internal/config/loader.go` with `LoadConfig()` function
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.2.5 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
33
docs/stories/phase0/0.3.1-install-gouberorgzap.md
Normal file
33
docs/stories/phase0/0.3.1-install-gouberorgzap.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Task 0.3.1: Install Logging Dependencies
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.3.1
|
||||
- **Title**: Install Logging Dependencies
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.3 Logging Foundation
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Install the Zap logging library for structured logging.
|
||||
|
||||
## Requirements
|
||||
- Install `go.uber.org/zap` v1.26.0+
|
||||
- Add to `go.mod` with proper version constraints
|
||||
|
||||
## Implementation Steps
|
||||
1. Run `go get go.uber.org/zap@v1.26.0`
|
||||
2. Run `go mod tidy`
|
||||
3. Verify package in `go.mod`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Zap is listed in `go.mod`
|
||||
- [ ] Version is v1.26.0 or later
|
||||
- [ ] `go mod verify` passes
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0005: Logging Framework](../../adr/0005-logging-framework.md)
|
||||
- [ADR-0012: Logger Interface Design](../../adr/0012-logger-interface-design.md)
|
||||
|
||||
33
docs/stories/phase0/0.3.1-install-logging-dependencies.md
Normal file
33
docs/stories/phase0/0.3.1-install-logging-dependencies.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Task 0.3.1: Install Logging Dependencies
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.3.1
|
||||
- **Title**: Install Logging Dependencies
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.3 Logging Foundation
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: 5 minutes
|
||||
- **Dependencies**: 0.1.1
|
||||
|
||||
## Description
|
||||
Install the Zap logging library for structured logging.
|
||||
|
||||
## Requirements
|
||||
- Install `go.uber.org/zap` v1.26.0+
|
||||
- Add to `go.mod` with proper version constraints
|
||||
|
||||
## Implementation Steps
|
||||
1. Run `go get go.uber.org/zap@v1.26.0`
|
||||
2. Run `go mod tidy`
|
||||
3. Verify package in `go.mod`
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Zap is listed in `go.mod`
|
||||
- [ ] Version is v1.26.0 or later
|
||||
- [ ] `go mod verify` passes
|
||||
|
||||
## Related ADRs
|
||||
- [ADR-0005: Logging Framework](../../adr/0005-logging-framework.md)
|
||||
- [ADR-0012: Logger Interface Design](../../adr/0012-logger-interface-design.md)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# Task 0.3.2: Create `pkg/logger/logger.go` interface:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.3.2
|
||||
- **Title**: Create `pkg/logger/logger.go` interface:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `pkg/logger/logger.go` interface:
|
||||
|
||||
## Requirements
|
||||
- Create `pkg/logger/logger.go` interface:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.3.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
type Logger interface {
|
||||
Debug(msg string, fields ...Field)
|
||||
Info(msg string, fields ...Field)
|
||||
Warn(msg string, fields ...Field)
|
||||
Error(msg string, fields ...Field)
|
||||
With(fields ...Field) Logger
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 0.3.3: Implement `internal/logger/zap_logger.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.3.3
|
||||
- **Title**: Implement `internal/logger/zap_logger.go`:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Implement `internal/logger/zap_logger.go`:
|
||||
|
||||
## Requirements
|
||||
- Implement `internal/logger/zap_logger.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.3.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 0.3.4: Add request ID middleware helper (Gin middleware)
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.3.4
|
||||
- **Title**: Add request ID middleware helper (Gin middleware)
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add request ID middleware helper (Gin middleware)
|
||||
|
||||
## Requirements
|
||||
- Add request ID middleware helper (Gin middleware)
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.3.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase0/0.4.1-create-githubworkflowsciyml.md
Normal file
40
docs/stories/phase0/0.4.1-create-githubworkflowsciyml.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 0.4.1: Create `.github/workflows/ci.yml`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.4.1
|
||||
- **Title**: Create `.github/workflows/ci.yml`:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.4
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `.github/workflows/ci.yml`:
|
||||
|
||||
## Requirements
|
||||
- Create `.github/workflows/ci.yml`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.4.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 0.4.2: Add `Makefile` with common commands:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.4.2
|
||||
- **Title**: Add `Makefile` with common commands:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.4
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add `Makefile` with common commands:
|
||||
|
||||
## Requirements
|
||||
- Add `Makefile` with common commands:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.4.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase0/0.5.1-install-gouberorgfx.md
Normal file
40
docs/stories/phase0/0.5.1-install-gouberorgfx.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 0.5.1: Install `go.uber.org/fx`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.5.1
|
||||
- **Title**: Install `go.uber.org/fx`
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install `go.uber.org/fx`
|
||||
|
||||
## Requirements
|
||||
- Install `go.uber.org/fx`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.5.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase0/0.5.2-create-internaldicontainergo.md
Normal file
40
docs/stories/phase0/0.5.2-create-internaldicontainergo.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 0.5.2: Create `internal/di/container.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.5.2
|
||||
- **Title**: Create `internal/di/container.go`:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/di/container.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/di/container.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.5.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 0.5.3: Create `cmd/platform/main.go` skeleton:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 0.5.3
|
||||
- **Title**: Create `cmd/platform/main.go` skeleton:
|
||||
- **Phase**: 0 - Project Setup & Foundation
|
||||
- **Section**: 0.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `cmd/platform/main.go` skeleton:
|
||||
|
||||
## Requirements
|
||||
- Create `cmd/platform/main.go` skeleton:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 0.5.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
47
docs/stories/phase0/README.md
Normal file
47
docs/stories/phase0/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Phase 0: Project Setup & Foundation
|
||||
|
||||
## Overview
|
||||
Initialize repository structure, set up Go modules and basic tooling, create configuration management foundation, and establish CI/CD skeleton.
|
||||
|
||||
## Tasks
|
||||
|
||||
### 0.1 Repository Bootstrap
|
||||
- [0.1.1 - Initialize Go Module](./0.1.1-initialize-go-module.md)
|
||||
- [0.1.2 - Create Directory Structure](./0.1.2-create-directory-structure.md)
|
||||
- [0.1.3 - Add Gitignore](./0.1.3-add-gitignore.md)
|
||||
- [0.1.4 - Create Initial README](./0.1.4-create-initial-readme.md)
|
||||
|
||||
### 0.2 Configuration System
|
||||
- [0.2.1 - Install Configuration Dependencies](./0.2.1-install-config-dependencies.md)
|
||||
- [0.2.2 - Create Config Interface](./0.2.2-create-config-interface.md)
|
||||
- [0.2.3 - Implement Config Loader](./0.2.3-implement-config-loader.md)
|
||||
- [0.2.4 - Create Configuration Files](./0.2.4-create-configuration-files.md)
|
||||
|
||||
### 0.3 Logging Foundation
|
||||
- [0.3.1 - Install Logging Dependencies](./0.3.1-install-logging-dependencies.md)
|
||||
- [0.3.2 - Create Logger Interface](./0.3.2-create-logger-interface.md) - Create `pkg/logger/logger.go` interface
|
||||
- [0.3.3 - Implement Zap Logger](./0.3.3-implement-zap-logger.md) - Implement `internal/logger/zap_logger.go`
|
||||
- [0.3.4 - Add Request ID Middleware](./0.3.4-add-request-id-middleware.md) - Create Gin middleware for request IDs
|
||||
|
||||
### 0.4 Basic CI/CD Pipeline
|
||||
- [0.4.1 - Create GitHub Actions Workflow](./0.4.1-create-github-actions-workflow.md)
|
||||
- [0.4.2 - Create Makefile](./0.4.2-create-makefile.md)
|
||||
|
||||
### 0.5 Dependency Injection Setup
|
||||
- [0.5.1 - Install FX Dependency](./0.5.1-install-fx-dependency.md)
|
||||
- [0.5.2 - Create DI Container](./0.5.2-create-di-container.md)
|
||||
- [0.5.3 - Create Main Entry Point](./0.5.3-create-main-entry-point.md)
|
||||
|
||||
## Deliverables Checklist
|
||||
- [ ] Repository structure in place
|
||||
- [ ] Configuration system loads YAML files and env vars
|
||||
- [ ] Structured logging works
|
||||
- [ ] CI pipeline runs linting and builds binary
|
||||
- [ ] Basic DI container initialized
|
||||
|
||||
## Acceptance Criteria
|
||||
- `go build ./cmd/platform` succeeds
|
||||
- `go test ./...` runs (even if tests are empty)
|
||||
- CI pipeline passes on empty commit
|
||||
- Config loads from `config/default.yaml`
|
||||
|
||||
40
docs/stories/phase1/1.1.1-extend-internaldicontainergo.md
Normal file
40
docs/stories/phase1/1.1.1-extend-internaldicontainergo.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.1.1: Extend `internal/di/container.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.1.1
|
||||
- **Title**: Extend `internal/di/container.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Extend `internal/di/container.go`:
|
||||
|
||||
## Requirements
|
||||
- Extend `internal/di/container.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.1.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.1.2-create-internaldiprovidersgo.md
Normal file
40
docs/stories/phase1/1.1.2-create-internaldiprovidersgo.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.1.2: Create `internal/di/providers.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.1.2
|
||||
- **Title**: Create `internal/di/providers.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/di/providers.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/di/providers.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.1.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.1.3-add-internaldicore_modulego.md
Normal file
40
docs/stories/phase1/1.1.3-add-internaldicore_modulego.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.1.3: Add `internal/di/core_module.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.1.3
|
||||
- **Title**: Add `internal/di/core_module.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add `internal/di/core_module.go`:
|
||||
|
||||
## Requirements
|
||||
- Add `internal/di/core_module.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.1.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.2.1-install-entgoioentcmdent.md
Normal file
40
docs/stories/phase1/1.2.1-install-entgoioentcmdent.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.2.1: Install `entgo.io/ent/cmd/ent`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.2.1
|
||||
- **Title**: Install `entgo.io/ent/cmd/ent`
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install `entgo.io/ent/cmd/ent`
|
||||
|
||||
## Requirements
|
||||
- Install `entgo.io/ent/cmd/ent`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.2.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
46
docs/stories/phase1/1.2.2-initialize-ent-schema.md
Normal file
46
docs/stories/phase1/1.2.2-initialize-ent-schema.md
Normal file
@@ -0,0 +1,46 @@
|
||||
# Task 1.2.2: Initialize Ent schema:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.2.2
|
||||
- **Title**: Initialize Ent schema:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Initialize Ent schema:
|
||||
|
||||
## Requirements
|
||||
- Initialize Ent schema:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.2.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
go run entgo.io/ent/cmd/ent init User Role Permission AuditLog
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.2.3: Define core entities in `internal/ent/schema/`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.2.3
|
||||
- **Title**: Define core entities in `internal/ent/schema/`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Define core entities in `internal/ent/schema/`:
|
||||
|
||||
## Requirements
|
||||
- Define core entities in `internal/ent/schema/`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.2.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.2.4: Generate Ent code: `go generate ./internal/ent`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.2.4
|
||||
- **Title**: Generate Ent code: `go generate ./internal/ent`
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Generate Ent code: `go generate ./internal/ent`
|
||||
|
||||
## Requirements
|
||||
- Generate Ent code: `go generate ./internal/ent`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.2.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.2.5: Create `internal/infra/database/client.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.2.5
|
||||
- **Title**: Create `internal/infra/database/client.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/infra/database/client.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/infra/database/client.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.2.5 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.2.6: Add database config to `config/default.yaml`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.2.6
|
||||
- **Title**: Add database config to `config/default.yaml`
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add database config to `config/default.yaml`
|
||||
|
||||
## Requirements
|
||||
- Add database config to `config/default.yaml`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.2.6 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.3.1: Install `github.com/prometheus/client_golang/prometheus`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.1
|
||||
- **Title**: Install `github.com/prometheus/client_golang/prometheus`
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install `github.com/prometheus/client_golang/prometheus`
|
||||
|
||||
## Requirements
|
||||
- Install `github.com/prometheus/client_golang/prometheus`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.3.2: Install `github.com/heptiolabs/healthcheck` (optional, or custom)
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.2
|
||||
- **Title**: Install `github.com/heptiolabs/healthcheck` (optional, or custom)
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install `github.com/heptiolabs/healthcheck` (optional, or custom)
|
||||
|
||||
## Requirements
|
||||
- Install `github.com/heptiolabs/healthcheck` (optional, or custom)
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Task 1.3.3: Create `pkg/health/health.go` interface:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.3
|
||||
- **Title**: Create `pkg/health/health.go` interface:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `pkg/health/health.go` interface:
|
||||
|
||||
## Requirements
|
||||
- Create `pkg/health/health.go` interface:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
type HealthChecker interface {
|
||||
Check(ctx context.Context) error
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.3.4: Implement `internal/health/registry.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.4
|
||||
- **Title**: Implement `internal/health/registry.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Implement `internal/health/registry.go`:
|
||||
|
||||
## Requirements
|
||||
- Implement `internal/health/registry.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.3.5-create-internalmetricsmetricsgo.md
Normal file
40
docs/stories/phase1/1.3.5-create-internalmetricsmetricsgo.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.3.5: Create `internal/metrics/metrics.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.5
|
||||
- **Title**: Create `internal/metrics/metrics.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/metrics/metrics.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/metrics/metrics.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.5 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.3.6: Add `/metrics` endpoint (Prometheus format)
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.6
|
||||
- **Title**: Add `/metrics` endpoint (Prometheus format)
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add `/metrics` endpoint (Prometheus format)
|
||||
|
||||
## Requirements
|
||||
- Add `/metrics` endpoint (Prometheus format)
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.6 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.3.7: Register endpoints in main HTTP router
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.3.7
|
||||
- **Title**: Register endpoints in main HTTP router
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.3
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Register endpoints in main HTTP router
|
||||
|
||||
## Requirements
|
||||
- Register endpoints in main HTTP router
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.3.7 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Task 1.4.1: Create `pkg/errorbus/errorbus.go` interface:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.4.1
|
||||
- **Title**: Create `pkg/errorbus/errorbus.go` interface:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.4
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `pkg/errorbus/errorbus.go` interface:
|
||||
|
||||
## Requirements
|
||||
- Create `pkg/errorbus/errorbus.go` interface:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.4.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
type ErrorPublisher interface {
|
||||
Publish(err error)
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.4.2: Implement `internal/errorbus/channel_bus.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.4.2
|
||||
- **Title**: Implement `internal/errorbus/channel_bus.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.4
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Implement `internal/errorbus/channel_bus.go`:
|
||||
|
||||
## Requirements
|
||||
- Implement `internal/errorbus/channel_bus.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.4.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.4.3: Add panic recovery middleware that publishes to error bus
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.4.3
|
||||
- **Title**: Add panic recovery middleware that publishes to error bus
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.4
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add panic recovery middleware that publishes to error bus
|
||||
|
||||
## Requirements
|
||||
- Add panic recovery middleware that publishes to error bus
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.4.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.4.4: Register error bus in DI container
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.4.4
|
||||
- **Title**: Register error bus in DI container
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.4
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Register error bus in DI container
|
||||
|
||||
## Requirements
|
||||
- Register error bus in DI container
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.4.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.5.1-install-githubcomgin-gonicgin.md
Normal file
40
docs/stories/phase1/1.5.1-install-githubcomgin-gonicgin.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.5.1: Install `github.com/gin-gonic/gin`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.5.1
|
||||
- **Title**: Install `github.com/gin-gonic/gin`
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install `github.com/gin-gonic/gin`
|
||||
|
||||
## Requirements
|
||||
- Install `github.com/gin-gonic/gin`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.5.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.5.2-create-internalserverservergo.md
Normal file
40
docs/stories/phase1/1.5.2-create-internalserverservergo.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.5.2: Create `internal/server/server.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.5.2
|
||||
- **Title**: Create `internal/server/server.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/server/server.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/server/server.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.5.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.5.3: Wire HTTP server into fx lifecycle:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.5.3
|
||||
- **Title**: Wire HTTP server into fx lifecycle:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Wire HTTP server into fx lifecycle:
|
||||
|
||||
## Requirements
|
||||
- Wire HTTP server into fx lifecycle:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.5.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.5.4: Update `cmd/platform/main.go` to use fx lifecycle
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.5.4
|
||||
- **Title**: Update `cmd/platform/main.go` to use fx lifecycle
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.5
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Update `cmd/platform/main.go` to use fx lifecycle
|
||||
|
||||
## Requirements
|
||||
- Update `cmd/platform/main.go` to use fx lifecycle
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.5.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase1/1.6.1-install-opentelemetry-packages.md
Normal file
40
docs/stories/phase1/1.6.1-install-opentelemetry-packages.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 1.6.1: Install OpenTelemetry packages:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.6.1
|
||||
- **Title**: Install OpenTelemetry packages:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.6
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install OpenTelemetry packages:
|
||||
|
||||
## Requirements
|
||||
- Install OpenTelemetry packages:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.6.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.6.2: Create `internal/observability/tracer.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.6.2
|
||||
- **Title**: Create `internal/observability/tracer.go`:
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.6
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/observability/tracer.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/observability/tracer.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.6.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.6.3: Add HTTP instrumentation middleware
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.6.3
|
||||
- **Title**: Add HTTP instrumentation middleware
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.6
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add HTTP instrumentation middleware
|
||||
|
||||
## Requirements
|
||||
- Add HTTP instrumentation middleware
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.6.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 1.6.4: Add trace context propagation to requests
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 1.6.4
|
||||
- **Title**: Add trace context propagation to requests
|
||||
- **Phase**: 1 - Core Kernel & Infrastructure
|
||||
- **Section**: 1.6
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add trace context propagation to requests
|
||||
|
||||
## Requirements
|
||||
- Add trace context propagation to requests
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 1.6.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 2.1.1: Install `github.com/golang-jwt/jwt/v5`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.1.1
|
||||
- **Title**: Install `github.com/golang-jwt/jwt/v5`
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Install `github.com/golang-jwt/jwt/v5`
|
||||
|
||||
## Requirements
|
||||
- Install `github.com/golang-jwt/jwt/v5`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.1.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
56
docs/stories/phase2/2.1.2-create-pkgauthauthgo-interfaces.md
Normal file
56
docs/stories/phase2/2.1.2-create-pkgauthauthgo-interfaces.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Task 2.1.2: Create `pkg/auth/auth.go` interfaces:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.1.2
|
||||
- **Title**: Create `pkg/auth/auth.go` interfaces:
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `pkg/auth/auth.go` interfaces:
|
||||
|
||||
## Requirements
|
||||
- Create `pkg/auth/auth.go` interfaces:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.1.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
type Authenticator interface {
|
||||
GenerateToken(userID string, roles []string, tenantID string) (string, error)
|
||||
VerifyToken(token string) (*TokenClaims, error)
|
||||
}
|
||||
|
||||
type TokenClaims struct {
|
||||
UserID string
|
||||
Roles []string
|
||||
TenantID string
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 2.1.3: Implement `internal/auth/jwt_auth.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.1.3
|
||||
- **Title**: Implement `internal/auth/jwt_auth.go`:
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Implement `internal/auth/jwt_auth.go`:
|
||||
|
||||
## Requirements
|
||||
- Implement `internal/auth/jwt_auth.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.1.3 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
40
docs/stories/phase2/2.1.4-create-internalauthmiddlewarego.md
Normal file
40
docs/stories/phase2/2.1.4-create-internalauthmiddlewarego.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Task 2.1.4: Create `internal/auth/middleware.go`:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.1.4
|
||||
- **Title**: Create `internal/auth/middleware.go`:
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `internal/auth/middleware.go`:
|
||||
|
||||
## Requirements
|
||||
- Create `internal/auth/middleware.go`:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.1.4 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 2.1.5: Add login endpoint: `POST /api/v1/auth/login`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.1.5
|
||||
- **Title**: Add login endpoint: `POST /api/v1/auth/login`
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add login endpoint: `POST /api/v1/auth/login`
|
||||
|
||||
## Requirements
|
||||
- Add login endpoint: `POST /api/v1/auth/login`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.1.5 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 2.1.6: Add refresh endpoint: `POST /api/v1/auth/refresh`
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.1.6
|
||||
- **Title**: Add refresh endpoint: `POST /api/v1/auth/refresh`
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.1
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Add refresh endpoint: `POST /api/v1/auth/refresh`
|
||||
|
||||
## Requirements
|
||||
- Add refresh endpoint: `POST /api/v1/auth/refresh`
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.1.6 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# Task 2.2.1: Create `pkg/identity/identity.go` interfaces:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.2.1
|
||||
- **Title**: Create `pkg/identity/identity.go` interfaces:
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Create `pkg/identity/identity.go` interfaces:
|
||||
|
||||
## Requirements
|
||||
- Create `pkg/identity/identity.go` interfaces:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.2.1 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
|
||||
## Code Reference
|
||||
|
||||
```go
|
||||
type UserRepository interface {
|
||||
FindByID(ctx context.Context, id string) (*User, error)
|
||||
FindByEmail(ctx context.Context, email string) (*User, error)
|
||||
Create(ctx context.Context, u *User) error
|
||||
Update(ctx context.Context, u *User) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
type UserService interface {
|
||||
Register(ctx context.Context, email, password string) (*User, error)
|
||||
VerifyEmail(ctx context.Context, token string) error
|
||||
ResetPassword(ctx context.Context, email string) error
|
||||
ChangePassword(ctx context.Context, userID, oldPassword, newPassword string) error
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,40 @@
|
||||
# Task 2.2.2: Implement `internal/identity/user_repo.go` using Ent:
|
||||
|
||||
## Metadata
|
||||
- **Task ID**: 2.2.2
|
||||
- **Title**: Implement `internal/identity/user_repo.go` using Ent:
|
||||
- **Phase**: 2 - Authentication & Authorization
|
||||
- **Section**: 2.2
|
||||
- **Status**: Pending
|
||||
- **Priority**: High
|
||||
- **Estimated Time**: TBD
|
||||
- **Dependencies**: TBD
|
||||
|
||||
## Description
|
||||
Implement `internal/identity/user_repo.go` using Ent:
|
||||
|
||||
## Requirements
|
||||
- Implement `internal/identity/user_repo.go` using Ent:
|
||||
|
||||
## Implementation Steps
|
||||
1. TODO: Add implementation steps
|
||||
2. TODO: Add implementation steps
|
||||
3. TODO: Add implementation steps
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] Task 2.2.2 is completed
|
||||
- [ ] All requirements are met
|
||||
- [ ] Code compiles and tests pass
|
||||
|
||||
## Related ADRs
|
||||
- See relevant ADRs in `docs/adr/`
|
||||
|
||||
## Implementation Notes
|
||||
- TODO: Add implementation notes
|
||||
|
||||
## Testing
|
||||
```bash
|
||||
# TODO: Add test commands
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user