Files
dance-lessons-coach/adr/0013-openapi-swagger-toolchain.md
2026-05-05 08:07:08 +02:00

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.