Skip to content

fix(admin): reject negative cache_hit_input_per_m in the model validator - #190

Merged
argszero merged 1 commit into
mainfrom
fix/validate-cache-hit-price
Sep 13, 2026
Merged

argszero merged 1 commit into
mainfrom
fix/validate-cache-hit-price

Conversation

@argszero

Copy link
Copy Markdown
Owner

Summary

validate_common(src/routes/admin_models.rs)此前校验了模型 6 个价格字段中的 5 个(input_per_m / output_per_m / peak_input_per_m / peak_output_per_m / peak_cache_hit_input_per_m),独漏 cache_hit_input_per_m —— 恰是已校验的高峰变体 peak_cache_hit_input_per_m 的非高峰兄弟。因此 POST/PATCH /api/admin/models 可以存入负数的缓存命中价。

该值会一路无钳制地流入结算:billing::effective_prices → billing::raw_cost / calc_points → gateway.rs 的 pts → billing::settle。在 settle 中 UPDATE quotas SET balance = balance - pts:当 pts < 0 时这是加法(消费者被充值),而 earn = round5(pts * 0.9) 为负 ⇒ 分享者被倒扣。也就是说,一次管理员写入即可把「收费」翻转为对该模型所有消费者的充值。

本 PR 补上这条缺失的校验,使 6 个价格字段遵循同一规则(≥ 0)。

实测:calc_points(1M 未命中 @1.0, 1M 命中 @-9.0) = -8(同一调用在文档默认命中价 0 下为 +1)。

Related Issue

无关联 issue —— 该缺陷由本项目自查(运行期探针复现)发现,非社区 issue。

Changes

  • 功能/修复说明:validate_common 新增 cache_hit_input_per_m 参数并加入 >= 0 判据(复用既有文案「价格不能为负数」);create / patch 两个调用点各传入该值
  • 涉及配置/数据结构的改动已同步示例文件:不涉及(未改配置结构;config.example.toml 的该字段含义不变)

Tests

  • cargo test 全部通过(179 passed,基线 178 → 179)
  • cargo fmt --check 通过
  • cargo clippy -- -D warnings 通过
  • 新增/更新了单元测试:admin_models_rejects_negative_cache_hit_price
    • CREATE cache_hit_input_per_m: -3 → 400
    • PATCH 改为 -9 → 400,且断言库中原值未被写入
    • 边界阳性对照:cache_hit_input_per_m: 0 → 200(0 是文档默认「命中部分免费」,判据为 < 0.0,不得误拒)
    • 兄弟字段 peak_cache_hit_input_per_m: -3 仍 → 400(回归保护)

A/B 取证:仅回退 || cache_hit_input_per_m < 0.0 一行 ⇒ 恰好 1 红 / 178 绿(红者为「CREATE 负数应 400」断言,实际观测到 200),边界 0 对照与其余测试保持绿。文件已逐字节还原(md5 一致)。

Checklist

  • 分支命名符合约定(fix/)
  • Commit message 使用 Conventional Commits 格式
  • 单一职责,改动最小化(生产代码 +5 行,改动 1 个文件 + 1 个测试文件)

validate_common checked 5 of the model's 6 price fields for non-negativity
but skipped cache_hit_input_per_m (the non-peak sibling of the peak variant
it does check), so POST/PATCH /api/admin/models accepted a negative
cache-hit price. That value reaches billing::raw_cost unclamped, and
billing::settle does balance - pts, so a negative pts credits the consumer
and makes the sharing owner's earn negative. Add the missing check so all
six price fields follow one rule.
@argszero
argszero merged commit 5fcc68e into main Sep 13, 2026
1 check passed
@argszero
argszero deleted the fix/validate-cache-hit-price branch September 13, 2026 00:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant