| name | swagger-annotations |
| description | Use when adding or modifying any HTTP handler in a GO project using GIN framework — every handler MUST carry swaggo annotations and a `make swagger` run must accompany the commit. Drift is enforced by `make swagger-check` in `make check`. |
Swagger Annotations (GlamGo-api)
When to use
Whenever you create, modify, or remove an HTTP handler in cmd/api, internal/<aggregate>/handler.go, or pkg/ginx/endpoint/<name>/handler.go. Drift between annotations and internal/swaggerdocs/ fails CI.
The five-line workflow
- Add or update the swag annotations above the handler
func.
- If the request type uses
Patch[T] (dual-decode), update the parallel *Doc mirror struct.
- Run
make swagger.
- Stage
internal/swaggerdocs/ along with your handler change.
- Commit;
make check will run make swagger-check and fail if anything was missed.
Annotation skeleton
Place annotations as the last comment block before func. Keep any existing WHY paragraph; separate the two with a blank comment line.
func (h *Handler) GetByID(c *gin.Context) { ... }
Tag taxonomy
Reuse existing tags before inventing new ones:
users — /api/v1/users/*
health — /health, /ready
- (future)
auth, providers, bookings, discovery
Errors
Always reference errorx.ErrorResponse (envelope: { "error": { "code", "message", "details" } }). Never reference errorx.AppError directly — that's the in-process value, not the wire shape.
Standard @Failure set per route:
400 — request validation, including unknown fields on PATCH (USER_INVALID_*, VALIDATION_UNKNOWN_FIELDS).
401 — missing or invalid Bearer token. Required on every @Security BearerAuth route.
403 — caller authenticated but not authorized for this resource (omit if no such case).
404 — resource not found. Omit if not applicable.
409 — conflict (duplicate email on register, version mismatch).
500 — generic server error. Always include.
Dual-decode (Patch[T]) endpoints
Patch[T] is an internal generic with a custom UnmarshalJSON. swag introspects struct fields, so it would render the meaningless internal shape (Set/Null/Value).
Convention: add a *Doc mirror struct with plain pointer types and annotate against the mirror.
Example: internal/user/patch.go defines PatchUserRequest; internal/user/patch_doc.go defines PatchUserRequestDoc with *string, *int, *AddressInput fields. Annotate as:
When you add a field to PatchUserRequest, mirror it into the *Doc struct in the same commit. make swagger-check indirectly catches drift: any PatchUserRequest change produces a different rendered spec; if the mirror lags, the diff is visibly missing the new field.
General info
The package-level doc comment of cmd/api/main.go carries @title, @version, @host, @BasePath, and @securityDefinitions.apikey BearerAuth. Edit there if API metadata changes (version bumps, base path moves).
Wiring (already done — reference only)
pkg/ginx/endpoint/swagger/handler.go — Register(*gin.Engine) mounts /swagger/*any. Wired in cmd/api/main.go before AuthMiddleware so the UI is public.
internal/swaggerdocs/ — generator output, committed.
Makefile — swagger, swagger-check, tools targets.
Checklist before pushing
See also
- ADR:
docs/decisions/2026-05-05-api-docs-swaggo.md
- Wire envelope:
pkg/ginx/middleware/error.go
- Dual-decode:
docs/decisions/2026-05-04-patch-dual-decode.md