* 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>
startStack, restartStack, stopStack, and downStack each ran a separate
getStackSource query just to determine isGitStack for useOverrideFile,
even though requireComposeFile -> getStackComposeFile already looks up
the same stack_sources record.
Return sourceType from getStackComposeFile (GetComposeFileResult) and
requireComposeFile (RequireComposeResult), and have all four callers
read result.sourceType instead of querying the database again. No
behavior change: useOverrideFile is still set to true exactly when the
stack's source type is 'git'.
startStack and restartStack compute isGitStack and pass useOverrideFile
accordingly, so executeLocalCompose writes .env.dockhand with the DB
non-secret overrides before invoking docker compose. stopStack and
downStack never set this option, so whenever a .env file exists in the
stack's working directory (e.g. committed alongside compose.yaml in a
git stack), the legacy shell-env fallback in executeLocalCompose is
suppressed and .env.dockhand is never written or attached via
--env-file. Any required variable that only exists as a Dockhand panel
override then fails interpolation on stop/down, even though the same
stack deploys and starts successfully.
Mirror startStack/restartStack: compute isGitStack from the stack
source and pass useOverrideFile through in both operations.