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);