fix: finish Azure fixed claims after external resource cleanup - #2572
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: blocked before merge. Reviewed September 26, 2026, 10:12 AM ET / 14:12 UTC (Revision 4). ClawSweeper reviewWhat this changesThe PR lets Azure force-stop finish an existing fixed-lease claim after external cleanup by checking that the VM and named companion resources are absent, and adds documentation and regression coverage. Merge readiness⛔ Blocked before merge - 3 items remain Current main and v0.66.0 still refuse this recovery case, while this PR has distinct work supported by a live Azure run. The remaining blocker is an explicit owner decision on the documented point-in-time absence guarantee. Priority: P2 Review scores
Verification
How this fits togetherCrabbox's Go CLI resolves an exact local lease claim before its Azure client checks cloud resources. The fixed-lease engine retains the claim on a failed check or writes a terminal receipt after successful verification. flowchart LR
A[Force-stop request] --> B[Exact local claim]
B --> C[Azure resource reads]
C --> D{All resources absent?}
D -- Yes --> E[Terminal receipt]
D -- No --> F[Claim retained for retry]
Decision needed
Why: Separate Azure reads and the local receipt cannot be atomic; accepting the resulting resource-tracking limit is an operator-contract choice. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Ship the narrow read-only force-stop recovery with its existing claim format and operator guidance once the Azure fixed-lease owner accepts the point-in-time terminal contract. Do we have a high-confidence way to reproduce the issue? Yes, at source level: current main and v0.66.0 refuse a missing cleanup binding, and the PR reports that refusal in a released CLI run with a retained claim. This review did not run Azure. Is this the best way to solve the issue? Yes for the proposed recovery case: read-only checks avoid deleting a replacement resource, and the reported rollback checks support the existing claim format. The terminal guarantee still needs owner acceptance. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 4bd59bb96b6a. LabelsLabel changes: No label changes. Label justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (3 earlier review cycles)
|
Prepare #2572 for landing with explicit point-in-time absence semantics and a maintainer changelog entry. Co-authored-by: galiniliev <5711535+galiniliev@users.noreply.github.com>
What Problem This Solves
Fixes Azure fixed-lease stop getting stuck after external cleanup removes the VM and companions while the retained local claim has no original cleanup binding.
User Impact
stop --force --provider azure --id <canonical-cbx-id>can finish that existing claim after verifying that the VM, NIC, public IP, managed OS disk, and quarantine NSG are all absent. Any remaining resource, including an owned or untagged disk, blocks recovery and leaves the claim available for retry. Inspect and clean up remaining resources in Azure first. No configuration, secrets, or claim migration changes are required.Absence checks are point-in-time observations, not a lock on other Azure writers. Resources recreated after their checks may still exist when the local claim becomes terminal; terminal retries do not inspect Azure again. Inspect and clean up any recreated resources directly in Azure.
Why This Change Was Made
Recovery without a historical binding now performs only Azure GET requests and uses the existing fixed-claim lifecycle and terminal receipt. It verifies absence both during preparation and before local completion, rejects non-native or ambiguous not-found errors, and does not initiate from automatic cleanup.
This narrows the feature to absence-only claim recovery. The destructive orphan branch and
orphan-v1binding are removed. Azure's unconditional name-addressed companion DELETE cannot guard against a replacement after attestation; the new path therefore grants no Azure deletion authority. The existingv1cleanup path is unchanged. Remaining-resource errors give external-cleanup guidance. Landing preparation adds a maintainer changelog entry crediting @galiniliev and documents the point-in-time recovery limit; the Go implementation and test sources remain unchanged from the live-tested revision.Evidence
Validated revision
66d66b2f6ad68cc9755597dd135e179ae84ceab2on macOS arm64 with Go 1.26.5. The live-tested binary SHA256 is0a29dc51f8fba38177e7c5f50e24d6b4aafac0778e05612d778c24b5b325ba8d. Passed:Committed SDK-transport regressions cover all five resource kinds, owned/foreign/untagged remaining resources, replacement between preparation and completion, VM reappearance during verification, authorization and transport failures, ambiguous 404s, missing fixed identity, and automatic-cleanup exclusion. The transport fails on every non-GET request. The CLI lifecycle regression verifies interruption retains the existing claim without a new binding, a retry publishes the terminal receipt, and a terminal retry does not repeat provider work. Existing
v1interrupted-cleanup tests remain in place.Real Azure CLI proof, September 26, 2026 UTC: built this production CLI and ran the actual
stop --forcecommand with an isolated, seeded existing-format fixed claim against a disposable resource group. A real quarantine NSG had a foreign lease tag; the VM and other companion names were absent. No VM was provisioned, so this is live recovery proof from representative retained state, not a live VM-create/delete lifecycle smoke. The released v0.66.0 macOS arm64 binary was downloaded and verified against its published SHA256 checksum.Redacted command result:
Rollback before completion retains the old version's original recovery limitation; it does not strand a new persisted dialect. Neither the claim schema nor the old companion cleanup dialect changes. Azure reads do not create a global writer lock: resources created after an absence observation are never deleted by this recovery path. Simulated transport tests prove the no-mutation boundary; the live NSG readback proves rejection leaves the observed resource unchanged.
Landing preparation
Prepared at
49e8af640678c6032a3f70140f744218944cd17aon Linux amd64 with Go 1.26.5 and Node 24.21.0. This follow-up changes only the stop documentation and maintainer changelog; Go implementation and test sources are identical to the live-tested revision above. No additional live Azure run was performed. Passed:Validation used an isolated environment without inherited provider settings. Documentation checks covered all 62 commands and 253 Markdown files; all 20 generated-docs tests passed. The prepared head merges without conflicts with main at
4bd59bb9; branch history was not rewritten.Review and landing preparation session.