Skip to content

[Decision] Which of the three remaining is_closed == false consumers should follow #1145 — one is a view label question, two hand a manager and a director standing access to resolved cases #1328

Description

@os-trump

Filed by the repo:hotcrm PM seat on behalf of the #1323 dev. #1145 ruled option A for unassigned_triage and its sharing rule, and ⛔ explicitly forbade widening to the rest. The dev measured them, did not touch them, and reported. Three consumers remain, and they are one question asked three times — grouped into one card so they can be answered in a single pass rather than three.

Dedupe search run: no existing card. This seat holds no 代裁 authority; ⛔ nothing here is decided by me.

What #1145 settled, and what it did not

is_closed is derived as effStatus === 'closed' (src/objects/case.hook.ts:268) — it never flips on resolved. Five consumers keyed "no longer live work" on it. #1145 moved two to status not_in ['resolved','closed']; case_workflow was measured and ruled a deliberate non-consumer (resolved is a real column on that kanban, and it is where a card lands when an agent drags one across). ⚠️ sla_at_risk is not in this card — it is a measured contradiction with case_sla_monitor, so it is a defect, filed as #1325.

These three are left, and each needs a judgement rather than a measurement.

The three

1. my_open_casessrc/views/case.view.ts:123

Label is My Open Cases; a resolved case is not open. But it lacks the property that made triage urgent: the row has an owner who can close it, so it is not stuck forever.

⚠️ And the docs already describe it the way it behaves: content/docs/service/cases.mdx:161 says "Your cases that are not closed" — literally what it filters on today. ⇒ Deciding this one may mean deciding that doc line too, in three locale faces.

2 & 3. case_escalation_sharing (:15) and case_director_sharing (:32) — src/sharing/case.sharing.ts

Both priority == "critical" && is_closed == false, granting a service manager edit and a service director read on critical cases.

⇒ A resolved critical case keeps granting both, indefinitely, until somebody closes it. That is the same permanence property that made the triage grant a problem — but ⚠️ here the standing access may be exactly what is wanted: a manager reviewing a just-resolved critical case for quality, or calling the customer back, is a plausible real workflow. ⛔ There is no row-count contract being violated, so measurement alone cannot settle it.

⚠️ Note the direction: changing these removes access. That is the safe direction, but it is still a permission change, which is why it is here rather than being absorbed as an alignment.

Options

A. Move all three to status not_in ['resolved','closed']. Four spellings become one, the parity guard covers all five, no consumer left keyed on the derived flag. Costs: managers and directors lose reach on resolved critical cases; cases.mdx:161 needs rewording in three faces.

B. Move my_open_cases only. The view-label argument is the strongest of the three and carries no access change. Leaves the two sharing rules as declared, deliberate standing grants — ⚠️ which then need a comment saying so, or the next reader files this card again.

C. Move the two sharing rules only. Treats standing post-resolution access as the real problem and the view label as cosmetic.

D. Move none. Record all three as deliberate on the boundary roster in test/live-work-predicate-parity.test.ts (already listed there as non-consumers) and close this out.

四维分析

① 实际业务需求 — 三条里只有 my_open_cases 有实测拉动:标签写着「My Open Cases」而 resolved 工单不是 open,用户读到的和过滤到的不一致。两条共享规则没有实测拉动,也没有实测反证 —— 本仓无人报告过「经理看不到刚解决的关键工单」,也无人报告过「经理不该看到」。⚠️ 复核后关怀(质量抽检、回访)是可信但未经证实的场景,判据应当是问一句谁在用,而不是从形状推断。⛔ 在没有答案之前把访问收掉,是拿一个真实但未测量的工作流去换一致性。

② 项目长远合理性 — 「同一个概念四种拼法」正是 #1145 的成因,收敛到一种是 contract-first 的方向。但 case_workflow 已经证明:一致性不是无条件的善 —— 那块看板保留 resolved 是对的,强行对齐会挖一个洞。⇒ 长远合理的形态是「每个消费者显式声明它要哪个语义」,而不是「全部相同」。选 D 也可以是长远合理的,只要那个「刻意」被写下来。

③ 防 AI 写代码犯错 — 这一轴指向显式化,不指向某个具体选项。现状最危险的地方是:三条规则用 is_closed == false 表达了一个 is_closed 并不表达的意思(它只在 closed 时翻转),而没有任何注释说明这是有意还是疏漏。⇒ 任何 AI 读到这三条都会合理地推断它们同病并"顺手对齐" —— 这正是本卡的 dev 被明令禁止做的事。无论裁 A 还是 D,都必须把结论写进代码注释和 parity 守卫的名册,否则同一张卡三个月后会被再立一次。已有的 by-name 边界名册是承载点。

④ 创业阶段不扩散需求 — 本轴反对的是投机能力,不反对修正。三个选项都不新增能力面,成本都是有界的一行改动 + 守卫名册移动。⚠️ 但 A 附带一项本轴要计的成本:cases.mdx:161 要在三个语言面改写,而文档修正在本仓已连续两轮是最大的工作量来源。⇒ 若无实测拉动,D + 写下理由是本轴下成本最低且不留债的形态 —— 「刻意」被记录之后就不再是债。

Recommendation

B or D, and the deciding input is one question I cannot answer: does anyone actually use standing manager/director access to resolved critical cases?

  • If yesB. Move my_open_cases (label honesty, no access change), leave the two sharing grants and record them as deliberate in the boundary roster and in a code comment.
  • If noA, accepting the cases.mdx:161 rewrite in three faces.

⛔ I recommend against C: it changes permissions while leaving the one item that has an actual user-visible inconsistency untouched — the worst trade of the four.

⚠️ Whichever is chosen, axis ③ makes recording the decision in code non-optional, not just closing this card. The parity guard's by-name boundary roster (test/live-work-predicate-parity.test.ts, added by PR #1323) already exists for exactly this and is where the answer belongs.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    metadataDeclarative metadata — schema, security posture, UI surfaces

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions