Repository navigation
fix(azure/savingsplans)!: refuse a malformed idempotency token before the purchase PUT - #495
Conversation
|
@coderabbitai review |
|
Warning Review limit reached
This review includes 5 billable files and costs up to $1.25.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 47 minutes for your next included review. View limit details
Comment |
|
Independent review verdict: CLEAN at a8e2e1cReviewer: fresh Claude agent (Sonnet, high effort), not the author, cold brief, focused on the money path. The PR body was treated as a claim. Coordinator: claude-cc-reviewer. Blocking findings: none. Purchase path (
Empty token: Breaking change (
Pin and other purchase paths:
What was attacked and how (
Gate: p3, no closing issue. Merge once CI is green. |
Move providers/azure from pkg 4566498 to 7383c3a so the savingsplans purchase path can call common.OrderIDFromToken (#487). Notable pkg changes pulled in (all additive): - feat(common): OrderIDFromToken and ErrInvalidIdempotencyToken (#487) - feat(common): EC2 platform, tenancy and scope dimensions on Commitment - fix(recfilter): match EC2 commitments on those dimensions when deduplicating - feat(insurance): decode plan line-item identity and read complete pages - docs(ladder): document provider commitment precision at PurchaseLayer Refs #104 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the purchase PUT PurchaseCommitment silently turned a non-empty but malformed idempotency token into a timestamp alias name, so a re-drive would PUT a second alias and buy a second Savings Plan. Derive the alias name with common.OrderIDFromToken right after the currency is resolved, before the body and the alias client are built, and return the error without any PUT. An empty token still falls back to the timestamp name (CLI path). Remove the now caller-less common.ReservationOrderID and its test. BREAKING CHANGE: common.ReservationOrderID was removed in favor of common.OrderIDFromToken, which returns an error wrapping common.ErrInvalidIdempotencyToken for a malformed non-empty token. Refs #104 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e PurchaseCommitment doc Name OrderIDFromToken in the PurchaseCommitment doc and document the malformed-token error. Reword the comments to claim only what the test proves, and give the mock a poller so the fallback mutant fails on an assertion instead of a nil-pointer panic. Refs #104 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
a8e2e1c to
3ae04d7
Compare
Summary
Part 2 of 2 for #104 item A09-020 (part 1: #487, which added
common.OrderIDFromTokenandErrInvalidIdempotencyToken).Before this change, a non-empty idempotency token that could not be formatted as a GUID made the Azure Savings Plan purchase silently fall back to a fresh
cudly-<ns>alias, so a re-drive of that purchase was no longer idempotent and could buy a second plan.build(azure): bump theproviders/azurepkg pin4566498f2a08->7383c3a7db7e(the feat(common): add OrderIDFromToken, which fails loud on a malformed idempotency token #487 merge). Everything else the bump pulls in is additive (Commitment EC2 dimensions, recfilter EC2 dedupe, insurance line-item decode and paging, ladder docs); no azure changes were needed for it.fix(azure/savingsplans)!:PurchaseCommitmentderives the alias name withOrderIDFromTokenright after the commitment currency is resolved, before the purchase body and alias client are built, and returns a failed result wrappingErrInvalidIdempotencyToken(token masked) before any PUT.common.ReservationOrderIDand its test are deleted.test(azure/savingsplans): tighter test and corrected doc comment from review.BREAKING CHANGE:
common.ReservationOrderIDis removed; usecommon.OrderIDFromToken. No caller remains in this repo, and the CLI, MCP and platform pin older pkg versions and call neither symbol.Behavior: an empty token (the CLI path) still gets the timestamp fallback alias. Real producers (
DeriveIdempotencyToken, 64-char hex) are unaffected.Refs #104 (A06-006 refers to
internal/servercode that is not in this repo, so this PR does not close the issue). GCP's equivalent gap is #488.Tests
TestPurchaseCommitment_MalformedTokenFailsBeforePUT(abcand 32 non-hex chars):errors.Is(err, common.ErrInvalidIdempotencyToken), zeroBeginCreatecalls, raw token absent from the error;The existing deterministic-name and empty-token fallback tests pass.
Fail-before:
ReservationOrderIDno longer exists, so main's behavior was reproduced as a mutant (swallow the error and fall back to a fresh alias). It fails the test on the error assertion (client_test.go:395), not a panic.Verification
make build,make vet,(cd providers/azure && GOWORK=off go build ./... && GOWORK=off go test -race -short ./services/savingsplans/...),(cd pkg && GOWORK=off go test -race -short ./common/...), pinned golangci-lint v2.10.1 onpkgandproviders/azure(0 issues each),go mod tidy -diffclean, gofmt, and the commit/pre-push hooks pass. Unit-level evidence only.Local review: two adversarial passes by a non-author reviewer (the same one that reviewed the plan and #487). Pass 1: stale doc, an overclaiming ordering comment, and a mutant that failed by panic (fixed in the third commit); pass 2: nothing actionable. No textual overlap with #491 (it edits
client.goaround lines 141-200; this PR around 348-390).🤖 Generated with Claude Code