From adfae5adee9c59d9c9ee1052a6b61c83383c38f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sat, 3 Oct 2026 14:59:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E4=BC=9A=E5=91=98=E8=AE=A1=E4=BB=B7):=20?= =?UTF-8?q?=E9=9B=B6=E6=97=B6=E9=95=BF=E8=B4=A6=E6=9C=9F=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=8C=89=E9=9D=9E=E6=B3=95=E5=85=A5=E5=8F=82=E6=8B=92=E7=BB=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - module-runtime/membership/upgrade.rs:账期窗口校验由 < 改为 <=,cycle_resets_at 等于 cycle_started_at 时不再退化成「剩余比例为 0」 Co-authored-by: Junie --- server-rs/crates/module-runtime/src/membership/upgrade.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server-rs/crates/module-runtime/src/membership/upgrade.rs b/server-rs/crates/module-runtime/src/membership/upgrade.rs index 29e9f18b8..df71b8e1c 100644 --- a/server-rs/crates/module-runtime/src/membership/upgrade.rs +++ b/server-rs/crates/module-runtime/src/membership/upgrade.rs @@ -127,12 +127,15 @@ pub fn check_runtime_profile_membership_upgrade_allowed( /// 总期数不在入参里,而是由目标周期类型推导(`cycle_kind.cycle_count()`),所以「期号越界」 /// 相对该推导值判断,`cycle_count` 与周期类型天然对齐。`now` 只校验下界——已过期报价按 /// 「剩余比例为 0」返回,属既有契约。 +/// +/// 账期窗口要求严格递增(`cycle_started_at < cycle_resets_at`):零时长窗口没有有效分母, +/// 按非法入参拒绝,而不是让它退化成「剩余比例为 0」。 fn validate_runtime_profile_membership_upgrade_quote_input( input: &RuntimeProfileMembershipUpgradeQuoteInput, ) -> Result<(), RuntimeProfileMembershipUpgradeRejection> { let cycle_count = input.target.cycle_kind.cycle_count(); let cycle_index_out_of_range = input.cycle_index == 0 || input.cycle_index > cycle_count; - let window_out_of_order = input.cycle_resets_at_micros < input.cycle_started_at_micros; + let window_out_of_order = input.cycle_resets_at_micros <= input.cycle_started_at_micros; let now_before_window = input.now_micros < input.cycle_started_at_micros; if cycle_index_out_of_range || window_out_of_order || now_before_window { return Err(RuntimeProfileMembershipUpgradeRejection::InvalidQuoteInput);