Repository navigation
fix(api): treat re-enabling a disabled entry on an armed plan as an escalation - #1875
Conversation
…scalation planArmEscalates compared providers and services, which ignore Enabled, so a PUT that turned a disabled entry back on skipped the execute:purchases arming grant and the armed plan started buying for it again. A disabled-to-enabled flip on an armed plan now needs the grant, like a new service does. The stored plan fixture now matches real data (entries created through the API are enabled). Closes #1777 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 36 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
CHANGES REQUESTED 4259c53 by claude-nibblets Cold review of #1875 (closes #1777, +53/-5, arming-grant path). The logic is right; one blocker, lint. Blocker: Lint Code is red at this head (run 42661468621; CI Success fails as a result), one issue: internal/api/auto_purchase_grant.go:85, gocritic rangeValCopy: What I checked (the fix itself is sound):
Everything else at this head passes (39 pass, 1 skipping); I will re-check once the lint issue is fixed. |
golangci-lint's gocritic rangeValCopy flagged the 312-byte ServiceConfig copy per iteration. Index the map instead. No behavior change. Refs #1777 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
APPROVE @ c07148d by claude-nibblets Delta 4259c53..c07148d is a 2-line change in CI at this head: Lint Code and Unit Tests pass; 38 pass, 1 pending, 1 skipping. |
|
Note from claude-nibblets at c07148d (my APPROVE above stands for the code): the required check |
|
Update from claude-nibblets at c07148d: the CI re-run I asked for has completed. CI Success, Lint Code, Unit Tests and Run pre-commit hooks pass (41 pass, 1 skipping) and mergeStateStatus is CLEAN, so the earlier red |
Closes #1777
What
On an armed plan (enabled, auto_purchase, with a cap), a
PUT /api/plans/{id}that turns a disabled services entry back on skipped theexecute:purchasesarming-grant check.planArmEscalatescompared providers and services, which ignoreEnabled, so a disabled-to-enabled flip was not an escalation and the plan started buying for that entry again with no grant.A disabled-to-enabled flip on an armed plan now counts as an escalation (
reEnablesEntry,internal/api/auto_purchase_grant.go), so it needs the grant like a new service does. An admin-key caller gets the gate's existing refusal. Entries that are new are already caught by the service-set check, so only an existing entry that flips is counted. Bound plans are covered byboundGroupsEscalatetoo; the clauses are OR'd.How it is proven
TestPlanArmEscalates_ReEnabledEntry(disabled to enabled, enabled stays, disabled stays, enabled to disabled) and two PUT-level cases (admin refused,execute:purchasesallowed).internal/apipackage passes on the rebased tree.TestUpdatePlanGated_RefusesReenablingStrippedEntry) now asserts the gate sees the write; its 409 assertions are unchanged because the binding refusal runs first. The shared stored-plan fixture now has an enabled entry, matching real data.boundGroupsEscalate): no findings; the reviewer confirmed the PUT merge keeps stored keys, so a re-keyed entry is not an escape.Notes
Safe default taken for the open decision in the issue: fail closed (re-enable needs the grant).
🤖 Generated with Claude Code