SPEC-0007: OpenAPI 3.0 Documentation and Swagger UI
Overview
This specification defines the OpenAPI 3.0 documentation system for the joe-links REST API. It covers the annotation approach (swaggo/swag), the Swagger UI serving endpoint, the spec generation workflow, and the required documentation completeness standards.
See 📝 ADR-0010 (OpenAPI & Swagger UI), 📝 ADR-0008 (REST API Layer), 📝 ADR-0009 (API Token Auth).
Requirements
Requirement: OpenAPI Spec Generation
The application MUST use swaggo/swag to generate an OpenAPI 3.0 JSON spec from Go handler annotations. The generated files (swagger.json, swagger.yaml, docs.go) MUST be committed to docs/swagger/ so the binary can be built without swag installed. A make swagger target MUST exist that runs swag init to regenerate the spec.
Scenario: Build Without swag Installed
- WHEN
go build ./...is run on a machine withoutswaginPATH - THEN the build MUST succeed using the committed
docs/swagger/docs.go
Scenario: Regeneration
- WHEN
make swaggeris run - THEN
docs/swagger/swagger.json,docs/swagger/swagger.yaml, anddocs/swagger/docs.goMUST be regenerated without error
Requirement: Swagger UI Endpoint
The application MUST serve Swagger UI at GET /api/docs/ using github.com/swaggo/http-swagger. The raw OpenAPI JSON spec MUST be accessible at GET /api/docs/swagger.json. Both endpoints MUST be accessible without authentication.
Scenario: Swagger UI Accessible Without Auth
- WHEN an unauthenticated client sends
GET /api/docs/ - THEN the server MUST return
200 OKwith HTML containing the Swagger UI
Scenario: Spec JSON Accessible
- WHEN a client sends
GET /api/docs/swagger.json - THEN the server MUST return
200 OKwith a valid OpenAPI 3.0 JSON document
Scenario: Spec Route Registration
- WHEN the router is initialized
- THEN
GET /api/docs/*MUST be registered before the slug catch-all resolver
Requirement: Main Swagger Annotation Block
The application entry point (or a dedicated docs.go file in cmd/joe-links/) MUST include a swaggo main annotation block declaring:
@title:joe-links API@version:1.0@description: A brief description of the joe-links service@host: omitted (determined at runtime) or set viaswag init --host@BasePath:/api/v1@securityDefinitions.apikey BearerToken@in header@name Authorization
Scenario: BasePath in Spec
- WHEN the spec is parsed
- THEN the
basePathorserversentry MUST indicate/api/v1
Scenario: Security Scheme Declared
- WHEN the spec is parsed
- THEN a
BearerTokenAPI key security scheme MUST be present, sourced from theAuthorizationheader
Requirement: Handler Annotation Completeness
Every handler function registered on the /api/v1 router MUST have a complete swaggo annotation block including:
@Summary— one-line description@Tags— resource group (e.g.,links,tags,users,admin,tokens)@Accept jsonand@Produce json@Paramfor every path, query, and body parameter@Successfor every 2xx response code with the response type@Failurefor every expected 4xx/5xx code with the error type@Security BearerToken(on all endpoints requiring authentication)@Routerwith the path and HTTP method
Scenario: All Endpoints Documented
- WHEN
make swaggerruns and the spec is generated - THEN every route registered under
/api/v1MUST appear in the spec'spathsobject
Scenario: Unauthenticated Endpoints
- WHEN an endpoint does not require authentication (e.g., none in the current API)
- THEN the
@Securityannotation MUST be omitted from that endpoint's annotation block
Requirement: Request/Response Type Declarations
All request body and response types used in @Param body and @Success/@Failure annotations MUST be declared as Go structs in the internal/api/ package. These structs serve as the authoritative schema for both Go type-checking and OpenAPI generation.
Required struct declarations:
CreateLinkRequest,UpdateLinkRequest,LinkResponse,LinkListResponseCreateTokenRequest,TokenResponse,TokenListResponseUpdateRoleRequest,UserResponse,UserListResponseTagResponse,TagListResponseErrorResponseAddOwnerRequest,OwnerResponse
Scenario: Type Appears in Spec
- WHEN
LinkResponseis used in a@Success 200 {object} api.LinkResponseannotation - THEN the generated spec MUST include a
LinkResponseschema definition with all exported fields
Requirement: Swagger UI Authorization
The Swagger UI MUST include the BearerToken security scheme in its "Authorize" dialog, allowing developers to enter their PAT and test protected endpoints directly from the browser.
Scenario: Authorize Dialog Present
- WHEN a user opens
/api/docs/in a browser - THEN an "Authorize" button MUST be visible that opens a dialog to enter a Bearer token
Scenario: Authenticated Request via Swagger UI
- WHEN a user enters a valid PAT in the Swagger UI Authorize dialog and executes
GET /api/v1/links - THEN the request MUST include
Authorization: Bearer <token>and return a200 OKresponse
Requirement: Spec Freshness in CI
The project's CI MUST include a step that runs make swagger and verifies the generated files match the committed files. If they differ, the CI check MUST fail with a message indicating the spec needs to be regenerated.
Scenario: CI Fails on Stale Spec
- WHEN a handler annotation is changed but
make swaggeris not run before committing - THEN the CI diff check MUST detect the mismatch and fail the build
Requirement: swag Makefile Target
The Makefile MUST include a swagger target that invokes:
swag init -g cmd/joe-links/main.go \
-o docs/swagger \
--outputTypes json,yaml,go \
--parseDependency \
--parseInternal
The --parseDependency and --parseInternal flags MUST be set so swag resolves type definitions from internal/api/ packages.
Scenario: Make Swagger Target Exists
- WHEN
make swaggeris run in the project root - THEN the command MUST execute
swag initwith the flags above