Verifier Dim B (homogeneity + code↔docs confrontation) flagged 5 ADRs stuck at "Partially Implemented" while the corresponding code is live. Audit + status update: - ADR-0009 (Hybrid testing) → Implemented; SDK gen explicitly out of scope - ADR-0013 (OpenAPI toolchain) → Implemented; SDK gen explicitly out of scope, cross-refs ADR-0009 - ADR-0018 (User auth) → Implemented; user model, JWT auth, password reset, admin endpoints, greet personalization, BDD coverage all live (verified in pkg/user/, pkg/auth/, features/auth/) - ADR-0019 (Postgres) → Implemented (core); per-item next-steps audit: CI integration ✅, performance tuning + monitoring tracked separately - ADR-0024 (BDD test org) → Implemented Phase 1+2+3; PR #35 closed Phase 3 parallel testing with 2.85x speedup, strategy in ADR-0025 No code changes — pure status reconciliation. The Status field is now the single source of truth for what's done vs deferred, removing the "forever Partial" doc drift the verifier flagged.
996 lines
32 KiB
Markdown
996 lines
32 KiB
Markdown
# 13. OpenAPI/Swagger Toolchain Selection
|
|
|
|
**Date:** 2026-04-05
|
|
**Status:** Implemented (OpenAPI documentation operational; SDK generation explicitly out of scope, see ADR-0009)
|
|
**Authors:** Arcodange Team
|
|
**Implementation Date:** 2026-04-05
|
|
**Last Updated:** 2026-05-05
|
|
|
|
## Context
|
|
|
|
The dance-lessons-coach project requires comprehensive API documentation and testing capabilities. As the API evolves with v1 and v2 endpoints, we need a robust OpenAPI/Swagger toolchain to:
|
|
|
|
1. **Document APIs**: Generate interactive API documentation
|
|
2. **Test APIs**: Enable automated API testing
|
|
3. **Validate APIs**: Ensure API contracts are met
|
|
4. **Generate Clients**: Potentially generate API clients
|
|
5. **Version APIs**: Support multiple API versions
|
|
|
|
## Decision Drivers
|
|
|
|
* **Go Integration**: Must work well with Go/Chi router
|
|
* **Ease of Use**: Simple to implement and maintain
|
|
* **Comprehensive**: Support for all API endpoints and versions
|
|
* **Testing**: Enable both manual and automated testing
|
|
* **Standards Compliance**: Follow OpenAPI standards
|
|
* **Documentation Quality**: Generate professional, interactive docs
|
|
* **CI/CD Friendly**: Work well in automated pipelines
|
|
|
|
## Expected Outcomes (Critical Addition)
|
|
|
|
### What We Actually Need from OpenAPI Integration
|
|
|
|
#### 1. Documentation ✅ (PRIMARY REQUIREMENT)
|
|
- **Interactive API Documentation**: Swagger UI for exploring endpoints
|
|
- **Human-Readable Spec**: Clear documentation for developers
|
|
- **Endpoint Discovery**: Easy to find and understand all API methods
|
|
- **Request/Response Examples**: Sample payloads and responses
|
|
- **Version Documentation**: Clear v1 vs v2 documentation
|
|
|
|
#### 2. Tool Integration ✅ (SECONDARY REQUIREMENT)
|
|
- **Web Client Testing**: Postman/Insomnia import capability
|
|
- **API Exploration**: Interactive testing via Swagger UI
|
|
- **curl Examples**: Generated curl commands for endpoints
|
|
- **Browser Testing**: Direct API testing from documentation
|
|
- **Debugging**: Better visibility into API behavior
|
|
|
|
#### 3. SDK Generation ❌ (NICE-TO-HAVE, NOT CRITICAL)
|
|
- **TypeScript Client**: For potential web frontend
|
|
- **Go Client**: For internal service communication
|
|
- **Python Client**: For data science/ML integration
|
|
- **Mobile Clients**: Future iOS/Android SDKs
|
|
- **Consistency**: Generated clients match API exactly
|
|
|
|
### Priority Matrix
|
|
|
|
| Requirement | Priority | Current Solution | Alternative Solution |
|
|
|------------|----------|------------------|---------------------|
|
|
| Interactive Docs | 🔴 Critical | swaggo Swagger UI | oapi-codegen Swagger UI |
|
|
| API Exploration | 🟡 Important | swaggo + Postman | oapi-codegen + tools |
|
|
| Request Examples | 🟡 Important | swaggo annotations | OpenAPI spec examples |
|
|
| Web Testing | 🟢 Nice-to-have | swaggo try-it-out | oapi-codegen try-it-out |
|
|
| SDK Generation | 🔵 Future | Manual clients | oapi-codegen clients |
|
|
| Type Safety | 🔵 Future | Manual types | Generated types |
|
|
| Validation | 🔵 Future | Manual validation | Auto validation |
|
|
|
|
### Minimum Viable Integration
|
|
|
|
**What we can achieve with swaggo:**
|
|
1. ✅ Interactive Swagger UI at `/docs`
|
|
2. ✅ Complete API documentation
|
|
3. ✅ Try-it-out functionality
|
|
4. ✅ Postman/Insomnia integration
|
|
5. ✅ curl command generation
|
|
6. ✅ Multi-version support
|
|
7. ✅ Annotation-based simplicity
|
|
|
|
**What we defer to future:**
|
|
1. ❌ Automatic SDK generation
|
|
2. ❌ OpenAPI 3.0 advanced features
|
|
3. ❌ Automatic request validation
|
|
4. ❌ Type-safe client generation
|
|
5. ❌ Webhook/callback support
|
|
|
|
### Tool Selection Based on Requirements
|
|
|
|
**swaggo/swag meets 100% of current critical needs:**
|
|
- ✅ Documentation: Excellent Swagger UI
|
|
- ✅ Tool Integration: Postman/Insomnia/curl support
|
|
- ✅ Ease of Use: Simple annotations
|
|
- ✅ Chi Integration: Native support
|
|
- ✅ Implementation Speed: Can deploy in days
|
|
|
|
**oapi-codegen would provide additional nice-to-haves:**
|
|
- ❌ SDK Generation: Not currently needed
|
|
- ❌ Type Safety: Manual types sufficient at current scale
|
|
- ❌ OpenAPI 3.0: 2.0 sufficient for documentation
|
|
- ❌ Validation: Manual validation working well
|
|
|
|
### Decision Validation
|
|
|
|
**Does swaggo meet our actual requirements?**
|
|
- ✅ Documentation: Yes, excellent Swagger UI
|
|
- ✅ Tool Integration: Yes, Postman/Insomnia/curl
|
|
- ✅ SDK Generation: Not critical currently
|
|
- ✅ Implementation: Simple and fast
|
|
- ✅ Maintenance: Low overhead
|
|
|
|
**Would oapi-codegen provide significant value?**
|
|
- ❌ No immediate business need for SDK generation
|
|
- ❌ No requirement for OpenAPI 3.0 features
|
|
- ❌ Validation already implemented
|
|
- ❌ Type safety not critical at current scale
|
|
|
|
**Conclusion**: swaggo provides everything we actually need today.
|
|
|
|
## Considered Options
|
|
|
|
### Option 1: swaggo/swag + swaggo/gin-swagger
|
|
|
|
**Overview**: Popular Go OpenAPI/Swagger solution with Chi router support
|
|
|
|
**Pros:**
|
|
- ✅ Excellent Go integration
|
|
- ✅ Chi router support via `swaggo/files` and `swaggo/gin-swagger` (adaptable)
|
|
- ✅ Simple annotation-based approach
|
|
- ✅ Generates interactive Swagger UI
|
|
- ✅ OpenAPI 2.0 and 3.0 support
|
|
- ✅ Widely used in Go community
|
|
- ✅ Good documentation
|
|
- ✅ **Chi Framework Native**: Designed to work with Go HTTP frameworks
|
|
|
|
**Cons:**
|
|
- ❌ Primarily designed for Gin (requires adaptation for Chi)
|
|
- ❌ Annotation parsing can be fragile
|
|
- ❌ Limited advanced features
|
|
- ❌ OpenAPI 2.0 primarily (3.0 support limited)
|
|
|
|
### Option 1.5: Framework Compatibility Analysis (MISSING FROM ORIGINAL ADR)
|
|
|
|
**Critical Oversight**: The original ADR failed to properly evaluate framework compatibility, specifically:
|
|
|
|
1. **Echo Framework Dependency**: oapi-codegen's middleware is designed for Echo framework
|
|
2. **Chi Integration**: No native Chi support in oapi-codegen v1
|
|
3. **Adapter Complexity**: Significant development effort needed to adapt Echo middleware to Chi
|
|
4. **Maintenance Burden**: Custom adapters require ongoing maintenance
|
|
|
|
**Framework Compatibility Matrix:**
|
|
|
|
| Tool | Echo | Gin | Chi | Standard Library |
|
|
|------|------|-----|-----|------------------|
|
|
| swaggo/swag | ✅ | ✅ | ✅ | ✅ |
|
|
| go-swagger | ✅ | ✅ | ✅ | ✅ |
|
|
| oapi-codegen v1 | ✅ | ❌ | ❌ | ❌ |
|
|
| oapi-codegen v2 | ✅ | ✅ | ? | ✅ |
|
|
|
|
**Lesson Learned**: Framework compatibility must be a primary evaluation criterion for middleware tools.
|
|
|
|
**Implementation:**
|
|
```go
|
|
import (
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/swaggo/swag"
|
|
"github.com/swaggo/files"
|
|
"github.com/swaggo/gin-swagger"
|
|
// Chi adapter would be needed
|
|
)
|
|
|
|
// @title dance-lessons-coach API
|
|
// @version 1.0
|
|
// @description API for dance-lessons-coach service
|
|
// @host localhost:8080
|
|
// @BasePath /api
|
|
func main() {
|
|
r := chi.NewRouter()
|
|
// Chi adaptation of swagger routes
|
|
r.Mount("/swagger", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
ginSwagger.WrapHandler(swaggerFiles.Handler)(w, r)
|
|
}))
|
|
}
|
|
```
|
|
|
|
### Option 2: go-swagger/go-swagger
|
|
|
|
**Overview**: Comprehensive OpenAPI 2.0 toolkit for Go
|
|
|
|
**Pros:**
|
|
- ✅ Full OpenAPI 2.0 support
|
|
- ✅ Code generation (server + client)
|
|
- ✅ Validation capabilities
|
|
- ✅ Swagger UI integration
|
|
- ✅ Mature and stable
|
|
- ✅ Good for API-first design
|
|
|
|
**Cons:**
|
|
- ❌ OpenAPI 2.0 only (not 3.x)
|
|
- ❌ Steeper learning curve
|
|
- ❌ More complex setup
|
|
- ❌ Less Chi-specific integration
|
|
- ❌ Slower development cycle
|
|
|
|
**Implementation:**
|
|
```bash
|
|
# Generate server stubs
|
|
swagger generate server -f swagger.yml
|
|
|
|
# Generate client
|
|
swagger generate client -f swagger.yml
|
|
```
|
|
|
|
### Option 3: oapi-codegen + Chi Middleware
|
|
|
|
**Overview**: Modern OpenAPI 3.0 toolchain with Chi integration
|
|
|
|
**Pros:**
|
|
- ✅ OpenAPI 3.0+ support
|
|
- ✅ Excellent Chi router integration
|
|
- ✅ Type-safe request/response handling
|
|
- ✅ Validation middleware
|
|
- ✅ Client generation
|
|
- ✅ Active development
|
|
- ✅ Good performance
|
|
- ✅ Strong typing
|
|
|
|
**Cons:**
|
|
- ❌ Newer project (less battle-tested)
|
|
- ❌ Requires separate spec file management
|
|
- ❌ More boilerplate for simple cases
|
|
|
|
**Implementation:**
|
|
```go
|
|
import (
|
|
"github.com/deepmap/oapi-codegen/pkg/middleware"
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
func main() {
|
|
r := chi.NewRouter()
|
|
|
|
// Load OpenAPI spec
|
|
swagger, err := api.GetSwagger()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Add validation middleware
|
|
r.Use(middleware.OapiRequestValidator(swagger))
|
|
|
|
// Add Swagger UI
|
|
r.Mount("/docs", middleware.SwaggerUI(middleware.SwaggerUIOpts{
|
|
Spec: swagger,
|
|
Path: "/docs/openapi.json",
|
|
}))
|
|
}
|
|
```
|
|
|
|
### Option 4: bufbuild/connect + bufbuild/connect-go
|
|
|
|
**Overview**: Modern gRPC+JSON transcoding with OpenAPI support
|
|
|
|
**Pros:**
|
|
- ✅ gRPC + REST unified approach
|
|
- ✅ Protocol Buffers based
|
|
- ✅ OpenAPI generation
|
|
- ✅ Excellent performance
|
|
- ✅ Type safety
|
|
- ✅ Future-proof
|
|
|
|
**Cons:**
|
|
- ❌ Significant architectural change
|
|
- ❌ Steep learning curve
|
|
- ❌ Overkill for simple REST APIs
|
|
- ❌ Requires Protobuf expertise
|
|
- ❌ Less Swagger UI focus
|
|
|
|
**Implementation:**
|
|
```go
|
|
// Would require complete API redesign to gRPC
|
|
```
|
|
|
|
## Decision Outcome (Final Implementation)
|
|
|
|
**Chosen option:** **swaggo/swag with embedded documentation**
|
|
|
|
### Rationale
|
|
|
|
After thorough evaluation and implementation, we've successfully integrated swaggo/swag with the following key advantages:
|
|
|
|
**Key Reasons for Choosing swaggo/swag:**
|
|
|
|
1. **Native Chi Integration**: Works seamlessly with Chi router without adapters
|
|
2. **Annotation-Based**: Simple, intuitive annotation syntax directly in handler code
|
|
3. **Mature Ecosystem**: Widely adopted in Go community with excellent documentation
|
|
4. **OpenAPI 2.0 Support**: Sufficient for current API documentation needs
|
|
5. **Embedded Documentation**: Perfect for single-binary deployment using Go's `//go:embed`
|
|
6. **Interactive UI**: Built-in Swagger UI for API exploration and testing
|
|
7. **Code Generation**: Easy regeneration with `go generate` workflow
|
|
|
|
### Implementation Reality vs Original Plan
|
|
|
|
**Original Decision**: oapi-codegen + Chi Middleware
|
|
**Actual Implementation**: swaggo/swag with embedded documentation
|
|
|
|
#### Why We Changed
|
|
|
|
1. **Framework Compatibility**: swaggo works natively with Chi
|
|
2. **Implementation Speed**: Days vs weeks of development
|
|
3. **Lower Risk**: Proven, battle-tested solution
|
|
4. **Current Needs**: Documentation without SDK generation
|
|
5. **Team Capacity**: Limited resources for complex integration
|
|
|
|
#### What We Actually Need
|
|
|
|
✅ **Documentation**: Interactive Swagger UI for API exploration
|
|
✅ **Tool Integration**: Postman/Insomnia/curl support
|
|
✅ **API Exploration**: Try-it-out functionality
|
|
✅ **Multi-Version Support**: Clear v1 vs v2 documentation
|
|
|
|
❌ **SDK Generation**: Not currently needed
|
|
❌ **Type Safety**: Manual types sufficient at current scale
|
|
❌ **OpenAPI 3.0**: 2.0 sufficient for documentation
|
|
❌ **Auto Validation**: Manual validation working well
|
|
|
|
### Final Implementation
|
|
|
|
```bash
|
|
# 1. Install swaggo
|
|
go install github.com/swaggo/swag/cmd/swag@latest
|
|
|
|
# 2. Add swagger metadata to main.go
|
|
// @title dance-lessons-coach API
|
|
// @version 1.0
|
|
// @description API for dance-lessons-coach service
|
|
// @host localhost:8080
|
|
// @BasePath /api
|
|
package main
|
|
```
|
|
|
|
### Swag Formatting Integration
|
|
|
|
To ensure consistent swagger comment formatting, we've integrated `swag fmt` into our workflow:
|
|
|
|
#### Git Hooks
|
|
Added to `.git/hooks/pre-commit`:
|
|
```bash
|
|
# Run swag fmt to format swagger comments
|
|
echo "Running swag fmt..."
|
|
if command -v swag >/dev/null 2>&1; then
|
|
swag fmt
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: swag fmt failed"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "swag not installed, skipping swag fmt"
|
|
fi
|
|
```
|
|
|
|
#### CI/CD Integration
|
|
Added to `.gitea/workflows/go-ci-cd.yaml` lint-format job:
|
|
```yaml
|
|
- name: Install swag
|
|
run: go install github.com/swaggo/swag/cmd/swag@latest
|
|
|
|
- name: Run swag fmt
|
|
run: swag fmt
|
|
```
|
|
|
|
#### Benefits
|
|
- **Consistent Formatting**: Automatic formatting of swagger comments
|
|
- **Pre-Commit Validation**: Catches issues before commit
|
|
- **CI/CD Enforcement**: Ensures formatting in all pull requests
|
|
- **Team Consistency**: Everyone follows the same rules
|
|
- **Automatic Fixes**: Issues are fixed automatically
|
|
|
|
#### Usage
|
|
```bash
|
|
# Format swagger comments manually
|
|
swag fmt
|
|
|
|
# Format is automatically run in:
|
|
# - pre-commit hook
|
|
# - CI/CD lint-format job
|
|
```
|
|
=======
|
|
### Final Implementation
|
|
|
|
```bash
|
|
# 1. Install swaggo
|
|
go install github.com/swaggo/swag/cmd/swag@latest
|
|
|
|
# 2. Add swagger metadata to main.go
|
|
// @title dance-lessons-coach API
|
|
// @version 1.0
|
|
// @description API for dance-lessons-coach service
|
|
// @host localhost:8080
|
|
// @BasePath /api
|
|
package main
|
|
```
|
|
|
|
### Swag Formatting Integration
|
|
|
|
To ensure consistent swagger comment formatting, we've integrated `swag fmt` into our workflow:
|
|
|
|
#### Git Hooks
|
|
Added to `.git/hooks/pre-commit`:
|
|
```bash
|
|
# Run swag fmt to format swagger comments
|
|
echo "Running swag fmt..."
|
|
if command -v swag >/dev/null 2>&1; then
|
|
swag fmt
|
|
if [ $? -ne 0 ]; then
|
|
echo "ERROR: swag fmt failed"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "swag not installed, skipping swag fmt"
|
|
fi
|
|
```
|
|
|
|
#### CI/CD Integration
|
|
Added to `.gitea/workflows/go-ci-cd.yaml` lint-format job:
|
|
```yaml
|
|
- name: Install swag
|
|
run: go install github.com/swaggo/swag/cmd/swag@latest
|
|
|
|
- name: Run swag fmt
|
|
run: swag fmt
|
|
```
|
|
|
|
#### Benefits
|
|
- **Consistent Formatting**: Automatic formatting of swagger comments
|
|
- **Pre-Commit Validation**: Catches issues before commit
|
|
- **CI/CD Enforcement**: Ensures formatting in all pull requests
|
|
- **Team Consistency**: Everyone follows the same rules
|
|
- **Automatic Fixes**: Issues are fixed automatically
|
|
|
|
#### Usage
|
|
```bash
|
|
# Format swagger comments manually
|
|
swag fmt
|
|
|
|
# Format is automatically run in:
|
|
# - pre-commit hook
|
|
# - CI/CD lint-format job
|
|
```
|
|
|
|
### Annotation Placement Considerations
|
|
|
|
**Current Approach**: Annotations in `cmd/server/main.go`
|
|
|
|
**Pros**:
|
|
- Follows Go community conventions
|
|
- Works seamlessly with swaggo
|
|
- Clear entry point for API documentation
|
|
|
|
**Cons**:
|
|
- Mixes API metadata with main package
|
|
- Less separation of concerns
|
|
|
|
**Alternative**: Annotations in `pkg/server/server.go`
|
|
|
|
**Pros**:
|
|
- Better organization (all server code together)
|
|
- More logical separation
|
|
- Easier maintenance
|
|
|
|
**Cons**:
|
|
- May require swag configuration changes
|
|
- Less conventional
|
|
- Potential tooling issues
|
|
|
|
**Decision**: Keep annotations in `cmd/server/main.go` for now
|
|
|
|
**Rationale**:
|
|
1. Follows established community patterns
|
|
2. Works reliably with current toolchain
|
|
3. Minimizes risk of breaking changes
|
|
4. Can revisit if maintenance becomes difficult
|
|
|
|
**Future Consideration**: If the project grows significantly, we may revisit this decision and move annotations to the server package for better organization.
|
|
|
|
### What We Actually Implemented
|
|
|
|
```
|
|
# 3. Annotate handlers and models with hierarchical tags
|
|
// @Summary Get personalized greeting
|
|
// @Description Returns a greeting with the specified name
|
|
// @Tags API/v1/Greeting # Hierarchical tag: Domain/Version/Function
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param name path string true "Name to greet"
|
|
// @Success 200 {object} GreetResponse
|
|
// @Failure 400 {object} ErrorResponse
|
|
// @Router /v1/greet/{name} [get]
|
|
|
|
# 4. Generate documentation
|
|
go generate ./pkg/server/
|
|
|
|
# 5. Embed in server and add routes
|
|
//go:embed docs/swagger.json
|
|
var swaggerJSON embed.FS
|
|
|
|
// In server setup:
|
|
s.router.Handle("/swagger/doc.json", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
data, err := swaggerJSON.ReadFile("docs/swagger.json")
|
|
if err != nil {
|
|
http.Error(w, "Failed to read swagger.json", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(data)
|
|
}))
|
|
|
|
s.router.Get("/swagger/*", httpSwagger.WrapHandler)
|
|
```
|
|
|
|
### What We Did NOT Implement (From Original Plan)
|
|
|
|
```bash
|
|
# NOT IMPLEMENTED: oapi-codegen approach
|
|
# 1. Install oapi-codegen
|
|
# go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
|
|
|
|
# 2. Create OpenAPI spec (openapi.yaml)
|
|
# openapi: 3.0.3
|
|
# info:
|
|
# title: dance-lessons-coach API
|
|
# version: 1.0.0
|
|
|
|
# 3. Generate server types
|
|
# oapi-codegen -generate types,server,spec openapi.yaml > pkg/api/gen_api.go
|
|
|
|
# 4. Add Chi middleware
|
|
# r.Use(middleware.OapiRequestValidator(swagger))
|
|
```
|
|
```
|
|
|
|
### Implementation
|
|
|
|
# 3. Annotate handlers and models with hierarchical tags
|
|
// @Summary Get personalized greeting
|
|
// @Description Returns a greeting with the specified name
|
|
// @Tags API/v1/Greeting # Hierarchical tag: Domain/Version/Function
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param name path string true "Name to greet"
|
|
// @Success 200 {object} GreetResponse
|
|
// @Failure 400 {object} ErrorResponse
|
|
// @Router /v1/greet/{name} [get]
|
|
|
|
# Example v2 endpoint with hierarchical tag
|
|
// @Summary Get greeting (v2)
|
|
// @Description Returns a greeting message with validation (v2)
|
|
// @Tags API/v2/Greeting # Hierarchical tag: Domain/Version/Function
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param request body GreetRequest true "Greeting request"
|
|
// @Success 200 {object} GreetResponseV2
|
|
// @Failure 400 {object} ValidationError
|
|
// @Router /v2/greet [post]
|
|
|
|
# System endpoints use different domain
|
|
// @Summary Health check
|
|
// @Description Check if the service is healthy
|
|
// @Tags System/Health # Hierarchical tag: Domain/Function
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Success 200 {object} map[string]string "Service is healthy"
|
|
// @Router /health [get]
|
|
func (h *apiV1GreetHandler) handleGreetPath(w http.ResponseWriter, r *http.Request) {
|
|
// handler implementation
|
|
}
|
|
|
|
## Tagging Strategy Evolution
|
|
|
|
### Phase 1: Simple Tags (Initial Approach)
|
|
```go
|
|
// @Tags greet
|
|
// @Tags health
|
|
```
|
|
**Issue**: No version separation, all endpoints mixed together
|
|
|
|
### Phase 2: Version-Based Tags (Improved)
|
|
```go
|
|
// @Tags v1-greet
|
|
// @Tags v2-greet
|
|
// @Tags health
|
|
```
|
|
**Issue**: Still flat structure, no domain separation
|
|
|
|
### Phase 3: Hierarchical Tags (Current - Recommended)
|
|
```go
|
|
// @Tags API/v1/Greeting
|
|
// @Tags API/v2/Greeting
|
|
// @Tags System/Health
|
|
```
|
|
**Benefits**:
|
|
- Clear domain separation (API vs System)
|
|
- Version organization within domains
|
|
- Natural hierarchy in Swagger UI
|
|
- Scalable for future growth
|
|
|
|
## Hierarchical Tagging Best Practices
|
|
|
|
### 1. Domain-First Organization
|
|
- `API/` for business endpoints
|
|
- `System/` for infrastructure endpoints
|
|
- `Admin/` for administrative endpoints
|
|
- `Internal/` for internal-only endpoints
|
|
|
|
### 2. Consistent Structure
|
|
- API Domain: `API/{version}/{function}`
|
|
- System Domain: `System/{function}`
|
|
- Admin Domain: `Admin/{function}`
|
|
|
|
### 3. Versioning Strategy
|
|
- Use semantic versions: `v1`, `v2`, `v3`
|
|
- Keep versions consistent across domains
|
|
- Document breaking changes clearly
|
|
|
|
### 4. Function Naming
|
|
- Use singular nouns: `Greeting`, `User`, `Order`
|
|
- Be specific: `PaymentProcessing` vs `Payment`
|
|
- Avoid acronyms unless widely known
|
|
|
|
# 4. Generate documentation
|
|
go generate ./pkg/server/
|
|
|
|
# 5. Embed in server and add routes
|
|
//go:embed docs/swagger.json
|
|
var swaggerJSON embed.FS
|
|
|
|
// In server setup:
|
|
s.router.Handle("/swagger/doc.json", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
data, err := swaggerJSON.ReadFile("docs/swagger.json")
|
|
if err != nil {
|
|
http.Error(w, "Failed to read swagger.json", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(data)
|
|
}))
|
|
|
|
s.router.Get("/swagger/*", httpSwagger.WrapHandler)
|
|
```
|
|
|
|
### Implementation Plan
|
|
|
|
```bash
|
|
# 1. Install oapi-codegen
|
|
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest
|
|
|
|
# 2. Create OpenAPI spec (openapi.yaml)
|
|
openapi: 3.0.3
|
|
info:
|
|
title: dance-lessons-coach API
|
|
version: 1.0.0
|
|
description: API for dance-lessons-coach service
|
|
servers:
|
|
- url: http://localhost:8080/api
|
|
description: Development server
|
|
|
|
# 3. Generate server types
|
|
oapi-codegen -generate types,server,spec openapi.yaml > pkg/api/gen_api.go
|
|
|
|
# 4. Add Chi middleware
|
|
r.Use(middleware.OapiRequestValidator(swagger))
|
|
```
|
|
|
|
## Pros and Cons of the Options
|
|
|
|
### Option 1: swaggo/swag (NOW CHOSEN)
|
|
- **Good**: Simple, popular, good Go integration, mature, easy to use, works well with Chi
|
|
- **Bad**: OpenAPI 2.0 primarily, annotation-based can be fragile, less expressive
|
|
- **Decision**: Best balance of simplicity and functionality for current needs
|
|
|
|
### Option 2: go-swagger
|
|
- **Good**: Mature, full-featured, code generation, OpenAPI 2.0
|
|
- **Bad**: Complex setup, slower development, less Chi-specific integration
|
|
- **Decision**: Overkill for current simple API needs
|
|
|
|
### Option 3: oapi-codegen (PREVIOUSLY CHOSEN)
|
|
- **Good**: OpenAPI 3.0+, type-safe, active development
|
|
- **Bad**: Echo framework dependency, poor Chi integration, complex workarounds needed
|
|
- **Decision**: Too complex for current needs, better suited for larger projects
|
|
|
|
### Option 4: bufbuild/connect
|
|
- **Good**: Modern, gRPC+REST, performance, future-proof
|
|
- **Bad**: Architectural change, steep learning curve, overkill for simple REST API
|
|
- **Decision**: Not appropriate for current REST-focused architecture
|
|
|
|
## Trade-offs Analysis (Explicit)
|
|
|
|
### What We Gain (✅ Positive Trade-offs)
|
|
|
|
1. **Framework Compatibility**: Native Chi router support
|
|
2. **Implementation Speed**: Days vs weeks of development
|
|
3. **Lower Risk**: Proven, battle-tested solution
|
|
4. **Simpler Maintenance**: No custom adapters to maintain
|
|
5. **Team Familiarity**: Easier learning curve
|
|
6. **Immediate Deployment**: Solves documentation needs now
|
|
7. **Proven Ecosystem**: Widely used in production
|
|
|
|
### What We Give Up (❌ Negative Trade-offs)
|
|
|
|
1. **OpenAPI 3.0 Features**:
|
|
- Webhooks and callbacks
|
|
- Links between operations
|
|
- More expressive schemas
|
|
- Better reuse capabilities
|
|
|
|
2. **Automatic Type Generation**:
|
|
- No generated Go types from spec
|
|
- Manual type definitions required
|
|
- Potential for type mismatches
|
|
|
|
3. **Built-in Validation**:
|
|
- No automatic request validation
|
|
- Manual validation implementation
|
|
- More boilerplate code
|
|
|
|
4. **SDK Generation**:
|
|
- No automatic client generation
|
|
- Manual client development
|
|
- Potential inconsistency between clients and API
|
|
|
|
5. **Future-Proofing**:
|
|
- OpenAPI 2.0 is deprecated
|
|
- May need migration later
|
|
- Industry moving to 3.0+
|
|
|
|
### Trade-off Evaluation
|
|
|
|
**Critical Needs (Must Have):**
|
|
- ✅ Interactive Documentation: swaggo provides this
|
|
- ✅ API Exploration: swaggo provides this
|
|
- ✅ Tool Integration: swaggo provides this
|
|
- ✅ Multi-Version Support: swaggo provides this
|
|
|
|
**Nice-to-Haves (Can Defer):**
|
|
- ❌ SDK Generation: Not needed currently
|
|
- ❌ Type Safety: Manual types sufficient
|
|
- ❌ OpenAPI 3.0: 2.0 sufficient for docs
|
|
- ❌ Auto Validation: Manual validation working
|
|
|
|
### Cost-Benefit Analysis
|
|
|
|
**Cost of swaggo Approach:**
|
|
- 1-2 days implementation
|
|
- OpenAPI 2.0 limitation
|
|
- Manual type definitions
|
|
- Future migration possibility
|
|
|
|
**Benefit of swaggo Approach:**
|
|
- Solves immediate documentation needs
|
|
- Zero breaking changes
|
|
- Low maintenance overhead
|
|
- Team can focus on features
|
|
- Proven reliability
|
|
|
|
**Cost of oapi-codegen Approach:**
|
|
- 3-5 weeks implementation (with Echo migration)
|
|
- OR 2-3 weeks custom adapter development
|
|
- High risk of bugs
|
|
- Team learning curve
|
|
- Potential service disruption
|
|
|
|
**Benefit of oapi-codegen Approach:**
|
|
- OpenAPI 3.0 compliance
|
|
- Automatic type generation
|
|
- Built-in validation
|
|
- Future SDK generation
|
|
- Industry standard compliance
|
|
|
|
### Decision Justification
|
|
|
|
**The trade-offs favor swaggo because:**
|
|
|
|
1. **80/20 Rule**: Get 80% of value with 20% of effort
|
|
2. **Current Scale**: Small API doesn't need advanced features
|
|
3. **Team Capacity**: Limited resources better spent on features
|
|
4. **Risk Profile**: Cannot justify high-risk migration
|
|
5. **Business Needs**: Documentation solves immediate problems
|
|
6. **Future Flexibility**: Can migrate later if needs change
|
|
|
|
**When to reconsider oapi-codegen:**
|
|
- API grows to 50+ endpoints
|
|
- Need automatic SDK generation
|
|
- Adding microservices architecture
|
|
- Team has capacity for migration
|
|
- OpenAPI 2.0 becomes limiting
|
|
|
|
### Migration Path Forward
|
|
|
|
**Current Phase (0-6 months):**
|
|
- Implement swaggo for documentation
|
|
- Monitor API growth and complexity
|
|
- Document OpenAPI 3.0 requirements
|
|
|
|
**Future Phase (6-12 months):**
|
|
- Re-evaluate if API complexity increases
|
|
- Consider oapi-codegen if SDK generation needed
|
|
- Evaluate migration cost vs benefit
|
|
- Plan migration as part of larger updates
|
|
|
|
**Long-Term (12+ months):**
|
|
- Full OpenAPI 3.0 migration if justified
|
|
- Consider framework changes if needed
|
|
- Align with other architectural changes
|
|
- Budget time and resources appropriately
|
|
|
|
### Final Trade-off Summary
|
|
|
|
| Aspect | swaggo | oapi-codegen | Decision |
|
|
|--------|--------|--------------|----------|
|
|
| **Documentation** | ✅ Excellent | ✅ Excellent | ✅ Both good |
|
|
| **Tool Integration** | ✅ Good | ✅ Excellent | ✅ swaggo sufficient |
|
|
| **Implementation Time** | 1-2 days | 2-5 weeks | ✅ swaggo wins |
|
|
| **Risk** | Low | High | ✅ swaggo wins |
|
|
| **Maintenance** | Simple | Moderate | ✅ swaggo wins |
|
|
| **Type Safety** | ❌ Manual | ✅ Auto | ❌ Not critical |
|
|
| **SDK Generation** | ❌ Manual | ✅ Auto | ❌ Not needed |
|
|
| **OpenAPI Version** | 2.0 | 3.0+ | ❌ 2.0 sufficient |
|
|
| **Validation** | ❌ Manual | ✅ Auto | ❌ Existing works |
|
|
| **Team Learning** | Minimal | Significant | ✅ swaggo wins |
|
|
|
|
**Result**: swaggo wins 7-2 on critical factors
|
|
|
|
### Comparison with Original Choice
|
|
|
|
**What we gain by switching to swaggo:**
|
|
- ✅ **Actually works with Chi router**: Native compatibility vs complex adapters
|
|
- ✅ **Simpler to implement and maintain**: No framework adaptation needed
|
|
- ✅ **Faster to deploy**: Days vs weeks of development time
|
|
- ✅ **Better community support for Chi**: Proven Chi integration patterns
|
|
- ✅ **Reduced risk**: Mature, battle-tested solution
|
|
|
|
**What we lose:**
|
|
- ❌ OpenAPI 3.0 features: But 2.0 is sufficient for current needs
|
|
- ❌ Automatic type generation: Manual types are manageable at current scale
|
|
- ❌ Built-in validation: Can add custom validation later if needed
|
|
- ❌ Future-proof standard: Practical solution for current requirements
|
|
|
|
**Root Cause Analysis:**
|
|
The original decision failed to properly evaluate:
|
|
1. **Framework Compatibility**: oapi-codegen's Echo dependency was underestimated
|
|
2. **Integration Complexity**: Adapter development effort was not considered
|
|
3. **Team Bandwidth**: Maintenance burden of custom adapters
|
|
4. **Project Scale**: Over-engineering for current simple API needs
|
|
|
|
**Verdict**: The trade-offs are worth it for our current needs and team size. The framework compatibility issue alone makes swaggo the pragmatic choice.
|
|
|
|
### Framework Selection Lessons
|
|
|
|
**For Future ADRs:**
|
|
1. **Framework First**: Evaluate framework compatibility before features
|
|
2. **Pragmatic Choices**: Consider team size and maintenance capacity
|
|
3. **Implementation Testing**: Prove concepts before finalizing decisions
|
|
4. **Risk Assessment**: Evaluate integration complexity, not just features
|
|
5. **Scale Appropriateness**: Match tool complexity to project scale
|
|
|
|
**Decision Quality Checklist:**
|
|
- [x] Features and capabilities
|
|
- [ ] Framework compatibility ✓ (Added in revision)
|
|
- [x] Community support
|
|
- [ ] Implementation complexity ✓ (Added in revision)
|
|
- [x] Long-term maintenance
|
|
- [ ] Team expertise match ✓ (Added in revision)
|
|
|
|
### Mitigations
|
|
|
|
1. **Gradual Adoption**: Start with v2 API, migrate v1 later
|
|
2. **Documentation**: Comprehensive team training
|
|
3. **Automation**: Integrate into build scripts
|
|
4. **Templates**: Create OpenAPI spec templates
|
|
5. **CI/CD**: Add OpenAPI validation to pipeline
|
|
|
|
## Verification
|
|
|
|
### Acceptance Criteria
|
|
|
|
1. ✅ Generate OpenAPI spec for existing APIs
|
|
2. ✅ Integrate Swagger UI at `/api/docs`
|
|
3. ✅ Add request validation middleware
|
|
4. ✅ Generate TypeScript client from spec
|
|
5. ✅ Pass OpenAPI linting in CI/CD
|
|
6. ✅ Maintain backward compatibility
|
|
|
|
### Test Plan
|
|
|
|
```bash
|
|
# 1. Generate spec
|
|
oapi-codegen openapi.yaml
|
|
|
|
# 2. Start server with Swagger UI
|
|
./scripts/start-server.sh start
|
|
|
|
# 3. Access Swagger UI
|
|
open http://localhost:8080/api/docs
|
|
|
|
# 4. Test validation
|
|
curl -X POST http://localhost:8080/api/v2/greet \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"invalid_field": "test"}' # Should return 400
|
|
|
|
# 5. Generate client
|
|
oapi-codegen -generate typescript-client openapi.yaml > client.ts
|
|
```
|
|
|
|
## Related Decisions
|
|
|
|
- [ADR-0002: Chi Router](adr/0002-chi-router.md) - Routing framework
|
|
- [ADR-0010: API v2 Feature Flag](adr/0010-api-v2-feature-flag.md) - API versioning
|
|
- [ADR-0011: Validation Library](adr/0011-validation-library-selection.md) - Input validation
|
|
- [ADR-0009: Hybrid Testing](adr/0009-hybrid-testing-approach.md) - Testing strategy
|
|
|
|
## Future Considerations
|
|
|
|
1. **Migration Path**: Gradually migrate v1 API to OpenAPI
|
|
2. **Spec Management**: Establish OpenAPI spec governance
|
|
3. **Client SDKs**: Generate and publish official SDKs
|
|
4. **API Gateway**: Consider integration with API gateways
|
|
5. **Performance**: Monitor validation middleware overhead
|
|
6. **Tooling**: Explore additional oapi-codegen features
|
|
|
|
## Revision History
|
|
|
|
- **1.0 (2026-04-05)**: Initial proposal (oapi-codegen)
|
|
- **1.1 (2026-04-05)**: Added implementation details and verification plan
|
|
- **2.0 (2026-04-05)**: MAJOR REVISION - Switched to swaggo/swag due to integration challenges
|
|
- Changed from oapi-codegen to swaggo
|
|
- Updated implementation plan
|
|
- Revised pros/cons analysis
|
|
- Added migration considerations
|
|
- **2.1 (2026-04-05)**: CRITICAL ADDITION - Defined expected outcomes and requirements analysis
|
|
- Added "Expected Outcomes" section
|
|
- Defined priority matrix for requirements
|
|
- Clarified what we actually need vs nice-to-haves
|
|
- Validated decision against actual requirements
|
|
- Added framework compatibility analysis
|
|
|
|
## References
|
|
|
|
- [swaggo/swag GitHub](https://github.com/swaggo/swag)
|
|
- [OpenAPI 2.0 Specification](https://swagger.io/specification/v2/)
|
|
- [Chi Router Documentation](https://go-chi.io/#/)
|
|
- [Swagger UI](https://swagger.io/tools/swagger-ui/)
|
|
- [Go Embed Directive](https://pkg.go.dev/embed)
|
|
|
|
## Conclusion
|
|
|
|
### What We Actually Implemented
|
|
|
|
✅ **OpenAPI Documentation**: Comprehensive API documentation with swaggo/swag
|
|
✅ **Interactive Swagger UI**: Available at `/swagger/` for API exploration
|
|
✅ **Embedded Specification**: Single-binary deployment with embedded OpenAPI spec
|
|
✅ **Hierarchical Tagging**: Clear organization with Domain/Version/Function tags
|
|
✅ **Production Ready**: Fully tested and operational
|
|
|
|
### What We Did NOT Implement (From Original Plan)
|
|
|
|
❌ **oapi-codegen**: Using swaggo instead due to Chi compatibility
|
|
❌ **SDK Generation**: No generated Go/TypeScript/Python clients
|
|
❌ **OpenAPI 3.0**: Using OpenAPI 2.0 (sufficient for current needs)
|
|
❌ **Auto Validation**: Manual validation working well
|
|
❌ **Type Safety**: Manual types sufficient at current scale
|
|
|
|
### Why This is the Right Approach
|
|
|
|
1. **Framework Compatibility**: swaggo works natively with Chi router
|
|
2. **Implementation Speed**: Days vs weeks of development
|
|
3. **Lower Risk**: Proven, battle-tested solution
|
|
4. **Current Needs**: Documentation without SDK generation
|
|
5. **Team Capacity**: Limited resources for complex integration
|
|
|
|
### Future Migration Path
|
|
|
|
If we need SDK generation in the future:
|
|
1. Add oapi-codegen alongside swaggo (not instead of)
|
|
2. Generate SDKs from OpenAPI spec
|
|
3. Add SDK-based testing
|
|
4. Implement request validation middleware
|
|
5. Migrate to OpenAPI 3.0 if needed
|
|
|
|
**Current Status:** ✅ Implemented (OpenAPI documentation; SDK generation out of scope)
|
|
**Implementation:** swaggo/swag with embedded documentation
|
|
**Documentation:** http://localhost:8080/swagger/
|
|
**OpenAPI Spec:** http://localhost:8080/swagger/doc.json
|
|
**Swagger UI:** http://localhost:8080/swagger/index.html
|
|
|
|
**Proposed by:** Arcodange Team
|
|
**Implemented by:** 2026-04-05
|
|
**Last Updated:** 2026-04-05
|
|
**Status:** Production Ready for Current Documentation Needs
|
|
|
|
**Note:** This ADR has been updated to reflect the actual implementation (swaggo/swag) rather than the originally proposed approach (oapi-codegen). The change was made due to framework compatibility issues and pragmatic considerations for the project's current scale and needs. |