fix(openapi): recognize bare object type + document existing field on validate (#1532)

* fix(openapi): recognize bare `object` type in annotation parser

The @openapi annotation parser's parseMiniSchema() only recognized the
bare words integer/number/boolean/string as scalar types. Any other
bare word - including `object`, used in 16 route annotations across
the codebase (e.g. severity:object, envVars:object on
POST /api/stacks/{name}/validate) - silently fell through to the
generic string fallback, so these fields were documented in
static/openapi.json as {"type": "string"} instead of
{"type": "object"}.

Add a dedicated branch for bare `object`, producing an opaque object
schema (no declared properties, since the bare word carries no shape
information of its own - a documented shape should use the existing
{...} form).

Verified no other bare non-standard word is used in any body:/resp-*:
annotation line across the 257 route files, so this closes the gap
completely for the current codebase.

Fixes #1531

* docs(openapi): document the existing field on POST /api/stacks/{name}/validate

The handler reads body.existing (an optional boolean, undocumented)
to control self-exclusion of the stack's own running containers/ports
from the cross-stack collision checks - the exact case the endpoint's
own summary advertises as handled. Without it, a client built strictly
from the OpenAPI document has no way to learn the field exists, and
will validate an existing stack the same way as a new one, silently
reintroducing false-positive collision findings against the stack's
own containers.

Add existing:boolean to the body: annotation, plus a one-line
description explaining the true/omitted semantics.

Fixes #1530

---------

Co-authored-by: Jarek Krochmalski <jotka@users.noreply.github.com>
This commit is contained in:
Björn StrausmannandJarek Krochmalski authored and GitHub committed 2026-09-06 15:51:12 +05:30
1 parent 360c458144
commit 33c0c47855
3 files changed
+32 -2

No files matched your search

@@ -35,9 +35,10 @@ async function resolveDockerHostForConfig(envIdNum: number | undefined): Promise
*
* @openapi
* summary: Run the Compose Validate preflight linter on a compose file and return findings with severities and line numbers (requires the 'view' permission)
* description: Set existing:true when validating an already-deployed stack, so the stack's own running containers/ports are excluded from the cross-stack collision checks; omit it (or false) for a brand-new stack, where a name/port clash with a running stack of the same name must still be reported.
* path: name:string! Stack name (used to exclude the stack's own containers from cross-stack collision checks)
* query: env:integer Environment ID for the context-aware checks (from GET /api/environments)
* body: {compose:string!, config:{disabled:[string], severity:object}, envVars:object}
* body: {compose:string!, existing:boolean, config:{disabled:[string], severity:object}, envVars:object}
* body-example: {"compose":"services:\n web:\n image: nginx:latest\n ports: [\"8080:80\"]\n"}
* resp-200: {findings:[{ruleId:string!, severity:string!, message:string!, hint:string, service:string, line:integer, fix:object, fixDescription:string}]!, counts:{error:integer!, warn:integer!, info:integer!}!}
* resp-200-example: {"findings":[{"ruleId":"LATEST_TAG","severity":"warn","message":"\"web\" uses `:latest` (nginx:latest)","hint":"Pin a version tag for reproducible deploys and to enable newer-version detection.","service":"web","line":3}],"counts":{"error":0,"warn":1,"info":0}}