fix(stacks): harden stack management with security, validation, and logging (#520)

* fix(stacks): harden stack management with security fixes, validation alignment, and logging

Validate WebSocket stack names with isValidStackName() to close a
path-traversal gap on the /api/stacks/:stackName/logs WS endpoint.
Align POST /api/stacks to use the canonical validator (allows underscores).
Replace error: any catch blocks with error: unknown + type narrowing.
Add cache invalidation to PUT /api/stacks/:stackName/env.
Rename DELETE param from :name to :stackName for consistency.

Add standard [Stacks] lifecycle logs and diagnostic [Stacks:debug] logs
gated behind the Developer Mode toggle (with 5s TTL cache).
Extract shared isDebugEnabled() and getErrorMessage() utilities.

Frontend: roll back optimistic status on API failure, guard unsaved
changes when switching stacks, pre-check duplicate names in App Store.

* docs(settings): update Developer Mode description to mention debug diagnostics
This commit is contained in:
Anso
2026-04-12 05:43:15 -04:00
committed by GitHub
parent 3ad1ab5c84
commit 2465f7607e
11 changed files with 350 additions and 30 deletions
+13
View File
@@ -138,6 +138,19 @@ export function AppStoreView({ onDeploySuccess }: AppStoreViewProps) {
toast.error("Stack name is required");
return;
}
// Pre-check for duplicate stack name
try {
const checkRes = await apiFetch('/stacks');
if (checkRes.ok) {
const existingStacks: string[] = await checkRes.json();
if (existingStacks.includes(stackName.trim())) {
toast.error(`A stack named "${stackName.trim()}" already exists. Choose a different name.`);
return;
}
}
} catch { /* proceed to deploy; backend will catch duplicates */ }
setIsDeploying(true);
const modifiedTemplate = { ...selectedTemplate };