Symptom
On a git stack, update_stack_env with isSecret:false variables returns success (env.nonSecretsWritten: N) but the variables:
- never appear in
get_stack_env,
- leave
validate_stack_env reporting them as missing / valid: false,
- never show in the Dockhand UI's stack env editor,
- and are not used by deploys.
Secrets (isSecret:true) work fine. Variables entered through the Dockhand UI dialog on the same git stack are immediately visible to get_stack_env, validate_stack_env, and deploys.
Reproduced live on Dockhand v1.0.43 (hawser-edge environment), mcp-dockhand ghcr.io/strausmann/mcp-dockhand:latest (pulled 2026-08-20, ≥ v1.10.0).
Reproduction
- Create a git stack with no env vars.
update_stack_env with {key: "FOO", value: "bar", isSecret: false} → success: true, env.nonSecretsWritten: 1.
get_stack_env → FOO absent. validate_stack_env → FOO not in defined. UI env pane → empty.
- Enter
FOO in the UI stack dialog instead → everything sees it.
Root cause (verified against both sources)
remove_stack_env_vars has the mirrored problem — it removes non-secrets from the file, so it cannot remove a git stack's DB-stored non-secrets.
Contributing cause: upstream OpenAPI is misleading
With FEAT_API_DOCS=true on Dockhand v1.0.43, PUT /api/stacks/{name}/env is documented as "Save a stack's secret env vars to the DB (secrets never hit disk)" and GET as "non-secrets from file" — the git-stack branch is not documented at all. The PUT body schema also declares variables: string[], while the handler requires [{key, value, isSecret}]. Since mcp-dockhand is built to follow this document, the wrong routing follows naturally. Probably worth an upstream Finsys/dockhand doc issue too.
Proposed fix
In update_stack_env (and remove_stack_env_vars): resolve the stack's sourceType first; when git, send non-secrets to PUT /api/stacks/{name}/env (the DB, together with secrets) instead of /env/raw; keep the current /env/raw routing for internal/adopted stacks. Update both tool descriptions to state the per-source-type routing.
Symptom
On a git stack,
update_stack_envwithisSecret:falsevariables returns success (env.nonSecretsWritten: N) but the variables:get_stack_env,validate_stack_envreporting them asmissing/valid: false,Secrets (
isSecret:true) work fine. Variables entered through the Dockhand UI dialog on the same git stack are immediately visible toget_stack_env,validate_stack_env, and deploys.Reproduced live on Dockhand v1.0.43 (hawser-edge environment), mcp-dockhand
ghcr.io/strausmann/mcp-dockhand:latest(pulled 2026-08-20, ≥ v1.10.0).Reproduction
update_stack_envwith{key: "FOO", value: "bar", isSecret: false}→success: true,env.nonSecretsWritten: 1.get_stack_env→FOOabsent.validate_stack_env→FOOnot indefined. UI env pane → empty.FOOin the UI stack dialog instead → everything sees it.Root cause (verified against both sources)
Since PR fix(tools): route isSecret:false vars to .env in update_stack_env (#109) #110 (the fix for update_stack_env with isSecret:false silently fails to persist non-secret vars #109, released v1.9.1),
update_stack_envroutes allisSecret:falsevariables toPUT /api/stacks/{name}/env/raw(the.envfile) — for every stack type.But Dockhand reads git-stack env from the database, not the file.
Finsys/dockhandsrc/routes/api/stacks/[name]/env/+server.ts(GET):Deploys and the UI use the same DB store for git stacks.
So the fix(tools): route isSecret:false vars to .env in update_stack_env (#109) #110 routing is correct for internal/adopted stacks (where update_stack_env with isSecret:false silently fails to persist non-secret vars #109's orphaned-DB-row bug lived) but inverts the bug for git stacks: the
.envfile is now the orphaned, invisible store.remove_stack_env_varshas the mirrored problem — it removes non-secrets from the file, so it cannot remove a git stack's DB-stored non-secrets.Contributing cause: upstream OpenAPI is misleading
With
FEAT_API_DOCS=trueon Dockhand v1.0.43,PUT /api/stacks/{name}/envis documented as "Save a stack's secret env vars to the DB (secrets never hit disk)" and GET as "non-secrets from file" — the git-stack branch is not documented at all. The PUT body schema also declaresvariables: string[], while the handler requires[{key, value, isSecret}]. Since mcp-dockhand is built to follow this document, the wrong routing follows naturally. Probably worth an upstream Finsys/dockhand doc issue too.Proposed fix
In
update_stack_env(andremove_stack_env_vars): resolve the stack'ssourceTypefirst; whengit, send non-secrets toPUT /api/stacks/{name}/env(the DB, together with secrets) instead of/env/raw; keep the current/env/rawrouting for internal/adopted stacks. Update both tool descriptions to state the per-source-type routing.