R-569: stack-lifecycle handlers pick their status by error KIND, not English words

stop/start/restart/update, remove and delete matched "protected", "not found", "not deployed",
"still running", "not orphaned" in err.Error(). New sentinels in internal/stacks
(stack_errors.go) carried by the producers in manager.go/delete.go via util.KindErrorf (message
bytes unchanged); api.stackOpStatusFor maps them. Tests: reworded-message table per family,
wiring check over all three handlers, producers keep kind + words.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 21:36:54 +02:00
parent 9271f33359
commit d15ad105be
7 changed files with 203 additions and 47 deletions
@@ -0,0 +1,21 @@
package stacks
import "errors"
// R-569 — the stack-lifecycle refusals carry a KIND, so the API's stop/start/restart/update, remove
// and delete handlers pick their status code with errors.Is instead of matching "protected",
// "not found", "not deployed", "still running" or "not orphaned" in the error text. The messages are
// unchanged byte for byte (util.KindErrorf); a reworded message no longer moves a status code.
// Pinned by TestR569_StackOpStatus_SurvivesRewording (internal/api).
var (
// ErrStackNotFound — no stack by that name (API: 404).
ErrStackNotFound = errors.New("stack not found")
// ErrProtectedStack — an infrastructure stack the household may not stop/remove/delete (API: 403).
ErrProtectedStack = errors.New("stack is protected")
// ErrNotDeployed — remove asked of a stack with nothing deployed (API: 409).
ErrNotDeployed = errors.New("stack is not deployed")
// ErrStillRunning — remove/delete asked of a running stack (API: 409).
ErrStillRunning = errors.New("stack is still running")
// ErrNotOrphaned — delete asked of a stack that is not orphaned (API: 409).
ErrNotOrphaned = errors.New("stack is not orphaned")
)