Updated existing Architecture Decision Records: - Added user authentication references to ADR-0008 (BDD Testing) - Updated ADR-0016 (CI/CD Pipeline) with authentication workflow - Enhanced ADR-0017 (Trunk-based Development) with BDD integration - Added security considerations to multiple ADRs - Updated cross-references throughout documentation Removed deprecated files: - docker-compose.cicd-test.yml (replaced by docker-compose.yml) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
997 lines
32 KiB
Markdown
997 lines
32 KiB
Markdown
# 13. OpenAPI/Swagger Toolchain Selection
|
|
|
|
**Date:** 2026-04-05
|
|
**Status:** ✅ Partially Implemented (Documentation only)
|
|
**Authors:** Arcodange Team
|
|
**Implementation Date:** 2026-04-05
|
|
**Last Updated:** 2026-04-05
|
|
**Status:** OpenAPI documentation operational, SDK generation deferred
|
|
|
|
## 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:** ✅ Partially Implemented (Documentation only)
|
|
**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. |