From 9df4a292109104ef19fdc51fcb174170aee9116a Mon Sep 17 00:00:00 2001 From: mrhid6 Date: Thu, 13 Aug 2026 07:54:56 +0000 Subject: [PATCH] fix: Separate stacked securityDefinitions into distinct comment groups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit swag v2.0.0-rc5's parseSecAttributesV3 resolves a security scheme's map key via getSecurityDefinitionKey(lines), which scans from the start of whatever comment-line slice it was handed and returns the first @securitydefinitions match — ignoring the current parse position entirely. Three @securityDefinitions.apikey blocks stacked in one Go comment group (the three were separated only by bare '//' lines, which do not split an ast.CommentGroup) therefore all resolved to the first block's name (cookieAuth), with the last block's in/name/description winning: the generated document had exactly one securityScheme, keyed cookieAuth, body esoAuth. Separating the three blocks with real blank source lines splits them into three distinct ast.CommentGroups, so swag's file-level comment scan (which requires no other tokens between them, same rule Go uses for doc comments) hands each block its own line slice and each resolves its own key. Regenerated openapi.json now carries all three schemes with correct bodies, referenced with no dangling security requirements. --- server/cmd/main.go | 38 ++++++++++++++++----------- server/internal/api/docs/openapi.json | 11 ++++++++ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/server/cmd/main.go b/server/cmd/main.go index 8d5a573..6976b21 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -29,24 +29,32 @@ import ( "github.com/gin-gonic/gin" ) -// @title Vantage API -// @version 1.0 -// @description The Vantage control plane REST API. Authenticate with a browser session cookie, or with an API token created under Settings → API tokens. -// @BasePath /api -// +// @title Vantage API +// @version 1.0 +// @description The Vantage control plane REST API. Authenticate with a browser session cookie, or with an API token created under Settings → API tokens. +// @BasePath /api + +// Each @securityDefinitions.apikey block below is deliberately its own +// comment group, separated by a real blank line rather than a bare "//": Go's +// parser only splits ast.CommentGroups on an actual blank line, and +// swag v2.0.0-rc5's parseSecAttributesV3 resolves a scheme's map key by +// scanning from the start of whatever comment group it was handed — so three +// stacked blocks sharing one group all collapse onto the first block's name. +// Three groups means three independent scans, each finding its own name. + // @securityDefinitions.apikey cookieAuth -// @in cookie -// @name km_session -// +// @in cookie +// @name km_session + // @securityDefinitions.apikey bearerAuth -// @in header -// @name Authorization -// @description An API token, sent as "Bearer vt_…". Scoped and optionally expiring. -// +// @in header +// @name Authorization +// @description An API token, sent as "Bearer vt_…". Scoped and optionally expiring. + // @securityDefinitions.apikey esoAuth -// @in header -// @name Authorization -// @description The External Secrets read token, rotated under Settings. It reaches /api/secrets/{group}/values and nothing else. It is a different credential from an API token, and the two must never be substituted for one another. +// @in header +// @name Authorization +// @description The External Secrets read token, rotated under Settings. It reaches /api/secrets/{group}/values and nothing else. It is a different credential from an API token, and the two must never be substituted for one another. func main() { mongoURI := getEnv("MONGO_URI", "mongodb://localhost:27017") diff --git a/server/internal/api/docs/openapi.json b/server/internal/api/docs/openapi.json index 8de7249..94a528b 100644 --- a/server/internal/api/docs/openapi.json +++ b/server/internal/api/docs/openapi.json @@ -2002,7 +2002,18 @@ } }, "securitySchemes": { + "bearerAuth": { + "description": "An API token, sent as \"Bearer vt_…\". Scoped and optionally expiring.", + "in": "header", + "name": "Authorization", + "type": "apiKey" + }, "cookieAuth": { + "in": "cookie", + "name": "km_session", + "type": "apiKey" + }, + "esoAuth": { "description": "The External Secrets read token, rotated under Settings. It reaches /api/secrets/{group}/values and nothing else. It is a different credential from an API token, and the two must never be substituted for one another.", "in": "header", "name": "Authorization",