From afc6f3ee26fbab69a3b4d1f5c38ad9a5c5ba4fb2 Mon Sep 17 00:00:00 2001 From: Astrid Gealer Date: Fri, 16 Oct 2026 12:43:25 +0100 Subject: [PATCH 1/2] docs(ladder): document provider commitment precision at PurchaseLayer The AWS purchase boundary already floors Savings Plan commitments to five decimals and refuses amounts outside [0.001, 1000000] (#403). Record that contract on LadderCapability.PurchaseLayer, require future providers to floor (never round up) and refuse out-of-range amounts, and note that Azure and GCP have no ladder implementation yet. Refs #354 Co-Authored-By: Claude Opus 5.5 --- pkg/ladder/capability.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/ladder/capability.go b/pkg/ladder/capability.go index 769a5130..0fd1df3e 100644 --- a/pkg/ladder/capability.go +++ b/pkg/ladder/capability.go @@ -58,6 +58,16 @@ type LadderCapability interface { // the float64 cost fields of common.Recommendation. This is a documented // precision seam; exact-decimal plumbing through the purchase path is // addressed in a later PR. + // + // Provider commitment precision (go#354): implementations MUST floor the + // commitment to the provider's precision before submission, never round + // it up, and MUST refuse (not submit) an amount outside the provider's + // accepted range, including one that floors to zero. Callers converting + // a *big.Rat amount to float64 must not round it up either. + // - AWS Savings Plans: truncated to 5 decimal places; amounts outside + // [0.001, 1000000] USD/hr are refused before any API call. + // - Azure, GCP: no LadderCapability implementation yet; each must + // document and enforce its precision here when one is added. PurchaseLayer(ctx context.Context, layer LayerType, rec common.Recommendation, opts common.PurchaseOptions) (common.PurchaseResult, error) // ReshapeBuffer exchanges or modifies buffer-layer commitments to improve From 47d844023ec0c7fe1e2a5ef1802d2365eee7049b Mon Sep 17 00:00:00 2001 From: Astrid Gealer Date: Fri, 16 Oct 2026 12:50:25 +0100 Subject: [PATCH 2/2] docs(ladder): order the AWS range check before truncation; note convertible RIs Addresses review nits on #438. Co-Authored-By: Claude Opus 5.5 --- pkg/ladder/capability.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/ladder/capability.go b/pkg/ladder/capability.go index 0fd1df3e..01c0489a 100644 --- a/pkg/ladder/capability.go +++ b/pkg/ladder/capability.go @@ -64,8 +64,11 @@ type LadderCapability interface { // it up, and MUST refuse (not submit) an amount outside the provider's // accepted range, including one that floors to zero. Callers converting // a *big.Rat amount to float64 must not round it up either. - // - AWS Savings Plans: truncated to 5 decimal places; amounts outside - // [0.001, 1000000] USD/hr are refused before any API call. + // - AWS Savings Plans: the raw amount is range-checked first (outside + // [0.001, 1000000] USD/hr, NaN, Inf or <= 0 is refused before any + // API call), then truncated to 5 decimal places. + // - AWS convertible RIs: purchased as a whole instance count + // (rec.Count > 0), so there is no dollar amount to floor. // - Azure, GCP: no LadderCapability implementation yet; each must // document and enforce its precision here when one is added. PurchaseLayer(ctx context.Context, layer LayerType, rec common.Recommendation, opts common.PurchaseOptions) (common.PurchaseResult, error)