Skip to main content
Status:🚀 ACTIVE
Date:📅 unknown
Domain:📦 OpenAPI 3.0 Documentation and Swagger UI

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 without swag in PATH
  • THEN the build MUST succeed using the committed docs/swagger/docs.go

Scenario: Regeneration

  • WHEN make swagger is run
  • THEN docs/swagger/swagger.json, docs/swagger/swagger.yaml, and docs/swagger/docs.go MUST 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 OK with HTML containing the Swagger UI

Scenario: Spec JSON Accessible

  • WHEN a client sends GET /api/docs/swagger.json
  • THEN the server MUST return 200 OK with 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 via swag init --host
  • @BasePath: /api/v1
  • @securityDefinitions.apikey BearerToken
  • @in header
  • @name Authorization

Scenario: BasePath in Spec

  • WHEN the spec is parsed
  • THEN the basePath or servers entry MUST indicate /api/v1

Scenario: Security Scheme Declared

  • WHEN the spec is parsed
  • THEN a BearerToken API key security scheme MUST be present, sourced from the Authorization header

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 json and @Produce json
  • @Param for every path, query, and body parameter
  • @Success for every 2xx response code with the response type
  • @Failure for every expected 4xx/5xx code with the error type
  • @Security BearerToken (on all endpoints requiring authentication)
  • @Router with the path and HTTP method

Scenario: All Endpoints Documented

  • WHEN make swagger runs and the spec is generated
  • THEN every route registered under /api/v1 MUST appear in the spec's paths object

Scenario: Unauthenticated Endpoints

  • WHEN an endpoint does not require authentication (e.g., none in the current API)
  • THEN the @Security annotation 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, LinkListResponse
  • CreateTokenRequest, TokenResponse, TokenListResponse
  • UpdateRoleRequest, UserResponse, UserListResponse
  • TagResponse, TagListResponse
  • ErrorResponse
  • AddOwnerRequest, OwnerResponse

Scenario: Type Appears in Spec

  • WHEN LinkResponse is used in a @Success 200 {object} api.LinkResponse annotation
  • THEN the generated spec MUST include a LinkResponse schema 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 a 200 OK response

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 swagger is 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 swagger is run in the project root
  • THEN the command MUST execute swag init with the flags above