From d955f6164e45bc1004ed3a8d98e3bac2ce1b2cfc Mon Sep 17 00:00:00 2001 From: hanafish <1106510024@qq.com> Date: Tue, 28 Jul 2026 16:07:44 +0800 Subject: [PATCH] fix(orgs): reject URLs as organization names --- .cursor/rules/root-cause-first.mdc | 21 ++++++++++++++++ AGENTS.md | 18 ++++++++++++++ CLAUDE.md | 18 ++++++++++++++ .../src/projects/io/orgs.rs | 24 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 .cursor/rules/root-cause-first.mdc diff --git a/.cursor/rules/root-cause-first.mdc b/.cursor/rules/root-cause-first.mdc new file mode 100644 index 000000000..1599aeac1 --- /dev/null +++ b/.cursor/rules/root-cause-first.mdc @@ -0,0 +1,21 @@ +--- +description: Require source-level fixes for malformed or polluted domain data +alwaysApply: true +--- + +# Root-Cause-First Bug Fixing + +When malformed, stale, duplicated, or unexpected data appears in the UI: + +1. Do not start with a UI filter, hidden row, fallback label, or string-pattern special case. +2. Determine whether the value is persisted/remote domain data or only a presentation defect. +3. Inspect the authoritative source and trace all transformations and writers to the earliest boundary that created the invalid state. +4. Fix the invariant at that boundary: input parsing, API/RPC ingestion, persistence, sync reconciliation, or canonical state projection. +5. Add a regression test at the producing boundary. A render/selector test alone is insufficient. +6. Handle historical pollution separately: inventory dependencies, confirm destructive cleanup, clean narrowly, and read back the authoritative source. +7. UI filtering is allowed only for an explicit product requirement or as defense-in-depth after the source fix. Never use it as the sole fix for invalid upstream data. +8. Do not change adjacent valid behavior without an explicit request. + +Before declaring success, report: authoritative source, root cause, producing write path, source-level invariant, historical remediation, and verification evidence. + +Any UI predicate that hides malformed data must cite an explicit product requirement. If the value violates the domain model, reject the UI-only patch until the producing path is fixed and regression-tested. diff --git a/AGENTS.md b/AGENTS.md index 190507896..8dad4db31 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,6 +32,24 @@ If the skill block isn't already prefetched in your context, read its `SKILL.md` --- +## Root-Cause-First Bug Fixing + +When malformed, stale, duplicated, or unexpected data appears in the UI: + +1. **Do not start with a UI filter, hidden row, fallback label, or string-pattern special case.** First determine whether the value is real persisted/remote domain data or only a presentation defect. +2. Identify the authoritative source, inspect the actual stored payload, and trace every transformation and writer back to the earliest boundary that created the invalid state. +3. Fix the invariant at that authoritative boundary: user-input parsing, API/RPC ingestion, persistence write, sync reconciliation, or canonical state projection. +4. Add a regression test at the producing boundary proving the invalid state can no longer be created. A selector/render test alone is not sufficient. +5. Treat historical pollution separately: inventory dependent data, get confirmation before destructive cleanup, perform the narrowest cleanup, then read back the authoritative source. +6. UI filtering is allowed only when exclusion is an explicit product requirement or defense-in-depth **after** the source fix. It must never be the sole fix for invalid upstream data. +7. Do not change adjacent valid behavior unless the user explicitly requests it. + +Before declaring the issue fixed, report the authoritative source, root cause, producing write path, source-level invariant, historical remediation, and verification evidence. + +Review gate: any UI predicate introduced to hide malformed data must cite an explicit product requirement. If the value violates the domain model, reject the UI-only patch until the producing path is fixed and covered by a regression test. + +--- + ## Default Delivery Flow ### Touching `*.tsx` files (UI work) diff --git a/CLAUDE.md b/CLAUDE.md index ef244e480..d29e25df5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -32,6 +32,24 @@ If the skill block isn't already prefetched in your context, read its `SKILL.md` --- +## Root-Cause-First Bug Fixing + +When malformed, stale, duplicated, or unexpected data appears in the UI: + +1. **Do not start with a UI filter, hidden row, fallback label, or string-pattern special case.** First determine whether the value is real persisted/remote domain data or only a presentation defect. +2. Identify the authoritative source, inspect the actual stored payload, and trace every transformation and writer back to the earliest boundary that created the invalid state. +3. Fix the invariant at that authoritative boundary: user-input parsing, API/RPC ingestion, persistence write, sync reconciliation, or canonical state projection. +4. Add a regression test at the producing boundary proving the invalid state can no longer be created. A selector/render test alone is not sufficient. +5. Treat historical pollution separately: inventory dependent data, get confirmation before destructive cleanup, perform the narrowest cleanup, then read back the authoritative source. +6. UI filtering is allowed only when exclusion is an explicit product requirement or defense-in-depth **after** the source fix. It must never be the sole fix for invalid upstream data. +7. Do not change adjacent valid behavior unless the user explicitly requests it. + +Before declaring the issue fixed, report the authoritative source, root cause, producing write path, source-level invariant, historical remediation, and verification evidence. + +Review gate: any UI predicate introduced to hide malformed data must cite an explicit product requirement. If the value violates the domain model, reject the UI-only patch until the producing path is fixed and covered by a regression test. + +--- + ## Default Delivery Flow ### Touching `*.tsx` files (UI work) diff --git a/src-tauri/crates/project-management/src/projects/io/orgs.rs b/src-tauri/crates/project-management/src/projects/io/orgs.rs index 34c7fa051..c15d10062 100644 --- a/src-tauri/crates/project-management/src/projects/io/orgs.rs +++ b/src-tauri/crates/project-management/src/projects/io/orgs.rs @@ -54,6 +54,9 @@ pub fn create_project_org(request: &CreateProjectOrgRequest) -> Result