Repository navigation
fix(config): match legacy EC2 tenancy and AZ shapes in purchase suppressions - #1424
Conversation
…essions Part of #1232. Two legacy AWS EC2 shapes produced suppression variants that never matched the current rec, so a retried purchase could double-buy. Details tenancy "shared" (pre-2026-05-20) is now canonicalised to "default" in SuppressionVariant (write side and rec side) and in AppliesTo (so already stored "shared" rows match). A rec whose AZ field is empty but whose Details carry an AZ now uses the Details AZ; the field still wins when both are set. Non-EC2 services are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 4 billable files and costs up to $1.00.
Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing. Or wait 9 minutes for your next included review. View limit details
Comment |
|
Independent review 1 (cold, fresh context): VERDICT: APPROVE f66947f Findings (no blockers):
Attacked:
Plan: nit 1 (scope the AppliesTo tenancy canon to AWS EC2 via the row's Provider/Service) and the TrimSpace nit go into a follow-up commit on this branch after the second review, so both reviews see one more head. |
|
Independent review 2 (claude-fleet, cold): APPROVE at f66947f Blocking findings: none.
Reviewed by an independent agent with no author context (second reviewer). Review only: nothing was pushed, and the GitHub review state is unchanged. |
|
Both reviews approve f66947f, so this merges at that SHA. The shared review points go into a follow-up PR: scope the |
|
Local verification at
|
…pressions Since this branch was cut, main canonicalises the suppression service slug (CanonicalSuppressionService, used by suppressions_build.go after #1411/#1419/#1424/#1426), so an AWS ec2 recommendation is now stored as service "compute". The whole-row expectation in TestB3C1CompletionNotification still pinned "ec2". Update that one field to the exact current value; all other fields, the whole-struct comparison and the historical timestamp assertions are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: characterize completion notification clocks * test: preserve raw history timestamps in clock characterization * test(purchase): re-baseline the clock characterization on current suppressions Since this branch was cut, main canonicalises the suppression service slug (CanonicalSuppressionService, used by suppressions_build.go after #1411/#1419/#1424/#1426), so an AWS ec2 recommendation is now stored as service "compute". The whole-row expectation in TestB3C1CompletionNotification still pinned "ec2". Update that one field to the exact current value; all other fields, the whole-struct comparison and the historical timestamp assertions are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Part of #1232. This is a follow-up to #1411; the two shapes come from its independent review. Item 1 of #1232 is handled separately, so this PR does not close the issue.
Problem: a retried legacy EC2 execution can write a purchase suppression whose variant doesn't match the variant that was actually bought, so a later recommendation for that variant can be bought again. Two legacy row shapes cause this:
shared, and current recs carrydefault. The two never compared equal.details.availability_zone. The variant read only theAvailabilityZonefield, so it got AZ""and missed the zonal rec.Change:
RecommendationRecord.SuppressionVariant()builds the variant for both the suppression builder and the scheduler's matcher. For AWS EC2 only (ec2orcompute), it now maps tenancysharedtodefault, and it falls back to the Details AZ when the field is empty. When both are set, the field wins.PurchaseSuppression.AppliesToalso normalises tenancy on both sides of the comparison, so suppression rows already stored withsharedstill match.Tests:
TestBuildSuppressions_LegacyShapesCanonicalisedhas 6 cases: shared tenancy, the compute slug, a Details-only AZ, the field winning over Details, a modern rec unchanged, and a non-EC2 rec untouched.TestPurchaseSuppression_AppliesTo_LegacySharedTenancy.TestApplySuppressions_LegacyEC2Shapeshas 4 scheduler cases.AppliesTonormalisation fails both as well.SuppressionVariantfails the config test.Local:
go build ./...passes, andgo test -racepasses on config, scheduler, purchase and api.go test -tags integrationpasses on config and scheduler (testcontainers Postgres).🤖 Generated with Claude Code