Skip to content

fix: preserve independent rule changes during queued saves - #26

Merged
xiaYuTian11 merged 2 commits into
xiaYuTian11:masterfrom
Shy7777:fix/atomic-rule-updates
Sep 11, 2026
Merged

xiaYuTian11 merged 2 commits into
xiaYuTian11:masterfrom
Shy7777:fix/atomic-rule-updates

Conversation

@Shy7777

@Shy7777 Shy7777 commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

改动说明 / What does this PR do?

连续修改不同规则时,保存队列虽然会依次发送请求,但请求里的整张规则表已经在入队前生成。如果两个操作使用同一旧快照,后一次成功保存会覆盖前一次修改;例如依次关闭 EMAIL 和 PHONE,最终 EMAIL 又恢复开启。

这次新增受现有控制面校验保护的 /api/config/builtin_rules 接口,只在配置锁内合并明确修改的规则。单项开关和全部开启/关闭都沿用原来的保存队列、结果反馈及缓存刷新,避免携带无关规则的旧值。配置尚未加载或没有可用规则时,全部开启/关闭按钮会禁用,避免发送空请求。原有整体配置接口保持兼容。

影响范围 / Scope

  • 控制面 / API
  • 前端规则设置与保存队列

验证 / Validation

新增 4 项回归检查,覆盖独立修改、并发保存、批量及重复修改、非法更新的原子拒绝,以及 Host / Origin / token 校验。

本地 macOS / Python 3.13:539 项单元测试通过;Python 编译检查、流式和出口代理冒烟、前端构建、Lint、中英文字典对齐及版本一致性检查均通过。

自检 / Checklist

  • 未提交真实密钥、内网地址或个人数据
  • 未新增对外网络请求
  • 提交信息符合 Conventional Commits
  • 遵循项目 AGPL-3.0 开源许可

Copilot AI lite review requested due to automatic review settings September 11, 2026 10:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Bulk rule actions can submit an empty payload before the initial configuration fetch completes, causing the request to be rejected.

Pull request overview

This PR prevents queued built-in rule saves from overwriting independent changes by applying atomic partial updates.

Changes:

  • Added a guarded /api/config/builtin_rules endpoint.
  • Updated frontend rule saves to submit deltas.
  • Added concurrency, validation, bulk-update, and security regression tests.
File summaries
File Description
tests/test_atomic_rule_updates.py Tests atomic updates and validation.
frontend/src/pages/Settings.tsx Routes rule changes through queued saves.
frontend/src/api/settings.ts Adds the partial rule-save API client.
engine/panel.py Implements atomic built-in rule updates.
Review details

Suppressed comments (1)

frontend/src/pages/Settings.tsx:1385

  • Because cfg is undefined during the initial config fetch, builtinRules is {} and either button builds an empty payload. The new endpoint explicitly rejects empty objects (panel.py:3617-3619), so clicking All On/All Off before the fetch completes now returns 400 instead of applying the requested bulk action. Build the payload from the complete BUILTIN_RULE_GROUPS list (or disable the buttons until cfg is loaded) so the request is always non-empty and includes every rule.
                  save(() => saveBuiltinRules(next), t('settings.toast.allOn'))
                }}>{t('settings.words.allOn')}</Button>
                <Button size="sm" variant="outline" className="h-6 text-[11px]" onClick={() => {
                  const next = Object.fromEntries(Object.keys(builtinRules).map((r) => [r, false]))
                  save(() => saveBuiltinRules(next), t('settings.toast.allOff'))
  • Files reviewed: 4/4 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@xiaYuTian11
xiaYuTian11 merged commit 427e3cd into xiaYuTian11:master Sep 11, 2026
1 check passed
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.

3 participants