Commit 91a947b
fix(stacks): mark promote approval executed AFTER preflight, not before (#11)
The Promote handler called MarkPromoteApprovalExecuted inside
consumeApprovedPromote BEFORE the promote preflight (source-services fetch,
image_ref check, target create/update, vault copy, env load) ran. Any
preflight failure (412 missing_image_ref / no_services, 503 lookup/create/
env_load, 400 vault, 402 cap) therefore burned the single-use approval to
'executed' while the promote never launched — stranding the operator with a
consumed, non-retryable approval and forcing a fresh email round-trip.
Split consumeApprovedPromote into:
- validateApprovedPromote — read-only checks (uuid, lookup, ownership,
status, from/to/kind match, expiry), runs at the original position so an
invalid approval still 4xxs early. Returns the row, no mutation.
- markApprovedPromoteExecuted — the 'executed' CAS flip + audit, called
ONLY after preflight fully succeeds, immediately before the runStackDeploy
launch.
A preflight failure now leaves the approval 'approved' and retryable. The
single-use guarantee is preserved: MarkPromoteApprovalExecuted's CAS still
returns 0 rows (409 approval_already_executed) on a concurrent double-consume.
Twin promote (consumeApprovedTwin in twin.go) has its own consume path and is
out of scope for this fix.
Coverage:
Symptom: preflight 412/503 strands a consumed (status='executed') approval
Enumeration: rg MarkPromoteApprovalExecuted + consumeApprovedPromote call sites in stack.go
Sites found: 1 (stack.go Promote; twin.go has a separate consumeApprovedTwin)
Sites touched: 1
Coverage test: TestStackPromote_ApprovalID_PreflightFails_StaysApproved (missing_image_ref),
TestStackPromote_ApprovalID_NoServices_StaysApproved,
TestStackPromote_ApprovalID_HappyPath_ExecutesOnce (executed once + single-use),
TestMarkApprovedPromoteExecuted_AlreadyExecuted_409 (CAS-miss arm),
TestStackFinal_ConsumeApproved_ExecuteError_503 (updated for new call order)
Live verified: awaiting post-merge auto-deploy (rule 14 build-SHA gate in CI)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>1 parent 498f5cf commit 91a947b
4 files changed
Lines changed: 314 additions & 21 deletions
File tree
- internal/handlers
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
46 | 55 | | |
47 | 56 | | |
48 | 57 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2010 | 2010 | | |
2011 | 2011 | | |
2012 | 2012 | | |
| 2013 | + | |
| 2014 | + | |
| 2015 | + | |
| 2016 | + | |
| 2017 | + | |
| 2018 | + | |
| 2019 | + | |
2013 | 2020 | | |
2014 | | - | |
2015 | | - | |
| 2021 | + | |
| 2022 | + | |
| 2023 | + | |
2016 | 2024 | | |
| 2025 | + | |
2017 | 2026 | | |
2018 | 2027 | | |
2019 | 2028 | | |
| |||
2307 | 2316 | | |
2308 | 2317 | | |
2309 | 2318 | | |
| 2319 | + | |
| 2320 | + | |
| 2321 | + | |
| 2322 | + | |
| 2323 | + | |
| 2324 | + | |
| 2325 | + | |
| 2326 | + | |
| 2327 | + | |
| 2328 | + | |
| 2329 | + | |
| 2330 | + | |
| 2331 | + | |
| 2332 | + | |
2310 | 2333 | | |
2311 | 2334 | | |
2312 | 2335 | | |
| |||
2408 | 2431 | | |
2409 | 2432 | | |
2410 | 2433 | | |
2411 | | - | |
2412 | | - | |
2413 | | - | |
2414 | | - | |
2415 | | - | |
| 2434 | + | |
| 2435 | + | |
| 2436 | + | |
| 2437 | + | |
| 2438 | + | |
| 2439 | + | |
| 2440 | + | |
| 2441 | + | |
| 2442 | + | |
| 2443 | + | |
| 2444 | + | |
| 2445 | + | |
| 2446 | + | |
| 2447 | + | |
2416 | 2448 | | |
2417 | 2449 | | |
2418 | 2450 | | |
2419 | 2451 | | |
2420 | 2452 | | |
2421 | 2453 | | |
2422 | | - | |
| 2454 | + | |
2423 | 2455 | | |
2424 | 2456 | | |
2425 | 2457 | | |
2426 | 2458 | | |
2427 | | - | |
| 2459 | + | |
2428 | 2460 | | |
2429 | 2461 | | |
2430 | | - | |
| 2462 | + | |
2431 | 2463 | | |
2432 | 2464 | | |
2433 | 2465 | | |
2434 | 2466 | | |
2435 | | - | |
| 2467 | + | |
2436 | 2468 | | |
2437 | 2469 | | |
2438 | 2470 | | |
2439 | 2471 | | |
2440 | 2472 | | |
2441 | 2473 | | |
2442 | | - | |
| 2474 | + | |
2443 | 2475 | | |
2444 | 2476 | | |
2445 | 2477 | | |
2446 | 2478 | | |
2447 | | - | |
| 2479 | + | |
2448 | 2480 | | |
2449 | 2481 | | |
2450 | 2482 | | |
2451 | | - | |
| 2483 | + | |
2452 | 2484 | | |
2453 | 2485 | | |
2454 | 2486 | | |
2455 | | - | |
| 2487 | + | |
2456 | 2488 | | |
2457 | 2489 | | |
2458 | 2490 | | |
2459 | 2491 | | |
2460 | 2492 | | |
2461 | 2493 | | |
2462 | 2494 | | |
2463 | | - | |
| 2495 | + | |
2464 | 2496 | | |
2465 | 2497 | | |
2466 | | - | |
| 2498 | + | |
| 2499 | + | |
| 2500 | + | |
| 2501 | + | |
| 2502 | + | |
| 2503 | + | |
| 2504 | + | |
| 2505 | + | |
| 2506 | + | |
| 2507 | + | |
| 2508 | + | |
| 2509 | + | |
| 2510 | + | |
| 2511 | + | |
| 2512 | + | |
| 2513 | + | |
| 2514 | + | |
| 2515 | + | |
2467 | 2516 | | |
2468 | 2517 | | |
2469 | | - | |
| 2518 | + | |
2470 | 2519 | | |
2471 | 2520 | | |
2472 | 2521 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
139 | | - | |
140 | | - | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
141 | 150 | | |
142 | 151 | | |
143 | 152 | | |
| |||
148 | 157 | | |
149 | 158 | | |
150 | 159 | | |
151 | | - | |
| 160 | + | |
152 | 161 | | |
153 | 162 | | |
154 | 163 | | |
| |||
0 commit comments