You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
claim_case's visible cannot be made TOTAL without moving the sharing grant and its parity pin together — the one site #1890's sweep left unguarded #1896
Filed by the repo:hotcrm seat out of #1890's review (PR #1894), rather than ridden on that PR. 1 of 12 sites, deliberately excluded there with the mechanism written at both code sites.
Every other action visible in src/actions/ is now TOTAL per AGENTS.md → Validation predicates must be TOTAL (#630). This one is not, and ⛔ cannot be made so in isolation.
The predicate is the sharing grant's text, verbatim.case_unassigned_triage_sharing's criteria condition and this visible are the same string, and test/claim-case-one-owner-writer.test.tsasserts string equality of the two. Changing one without the other reds that pin.
The grant cannot carry has().plugin-sharing compiles a criteria condition through compileCelToFilter, which rejects the whole function-call class. So has(record.owner_id) && … is untranslatable as a sharing rule.
⇒ making this predicate total means moving the grant, the action and the parity pin together. That is a deliberate change to a sharing boundary, ⛔ not a sweep item.
⭐ The reasoning already written in the tree does not cover this surface
src/sharing/case.sharing.ts explains why status needs no guard there: it is required with storage: { notNull: true }on the stored row.
⚠️ That is true for a pushdown filter and false for this surface. An action visible is interpreted by CEL in the browser, against whatever the page holds — and #1890 measured that to be {} (zero keys) for the first two renders of every record page. So the same string is total in one place and aborts in the other, for reasons neither site's comment states. Both files now carry a note saying so; this card is the work.
Measured consequence today
Small, and stated rather than inflated: the console prints one predicate-failure warning for claim_case per JS context (the warning is de-duplicated per [label, expression], so it means at least one failing render, never exactly one). Steady-state gating is unaffected — object-ui passes fallback: false, so the button is hidden on the aborting renders, which is where it should be during hydration anyway.
⇒ p3. The defect is the declared-contract violation and the trap it leaves for the next author, ⛔ not a user-facing misbehaviour.
Why pm:blocked rather than pm:queue
The parity pin lives in test/, which is epic #1579's fence, and this lane's rule is that the fence opens only on a maintainer or director sentence. ⭐ This is the same question as #1874.⚠️ Correction to this line as first written: the live reverse index reads 11 carriers including this card and #1897 — ⛔ not the "eleven" this card claimed at filing time, which was one ahead of the derivation.
⚠️ Whoever takes it should note the change is not purely mechanical: it touches a sharing grant, and "security / permission boundaries" sit on the manual floor. The likely shape is that the grant keeps its untranslatable-free text and the action's predicate is allowed to differ from it, with the parity pin rewritten to assert the intended relationship rather than string equality — but ⛔ that is a proposal, not a ruling, and it is not made here.
Refs #1890 (the sweep that excluded it) · PR #1894 (the exclusion and its comments) · #1874 (the fence) · #621 (untranslatable rules are dropped) · #630 (the totality rule).
Blocked-by: #1874 is a dead pointer (404; consistent with a banned author), and the test/** fence it carried does not hold today (the epic PM's territory is its sub-issue tree only).
Closed not_planned
The measured consequence is one console warning; the button is correctly hidden while the record hydrates. Making visible total needs a platform change, not app metadata.
Blocked-by: #1874
Filed by the
repo:hotcrmseat out of #1890's review (PR #1894), rather than ridden on that PR. 1 of 12 sites, deliberately excluded there with the mechanism written at both code sites.The site
src/actions/case.actions.ts,ClaimCaseAction:Every other action
visibleinsrc/actions/is now TOTAL perAGENTS.md→ Validation predicates must be TOTAL (#630). This one is not, and ⛔ cannot be made so in isolation.Why the obvious fix is wrong
Three facts, each measured on #1890's branch:
case_unassigned_triage_sharing's criteria condition and thisvisibleare the same string, andtest/claim-case-one-owner-writer.test.tsasserts string equality of the two. Changing one without the other reds that pin.has().plugin-sharingcompiles a criteria condition throughcompileCelToFilter, which rejects the whole function-call class. Sohas(record.owner_id) && …is untranslatable as a sharing rule.in [...]conditions are untranslatable, sona_sales_team/eu_sales_teamget no access at all #621) — silently. So a naive guard here does not fail loudly; it deletes the sharing grant, which is a security-visible outcome, not a lint nit.⇒ making this predicate total means moving the grant, the action and the parity pin together. That is a deliberate change to a sharing boundary, ⛔ not a sweep item.
⭐ The reasoning already written in the tree does not cover this surface
src/sharing/case.sharing.tsexplains whystatusneeds no guard there: it isrequiredwithstorage: { notNull: true }on the stored row.visibleis interpreted by CEL in the browser, against whatever the page holds — and #1890 measured that to be{}(zero keys) for the first two renders of every record page. So the same string is total in one place and aborts in the other, for reasons neither site's comment states. Both files now carry a note saying so; this card is the work.Measured consequence today
Small, and stated rather than inflated: the console prints one predicate-failure warning for
claim_caseper JS context (the warning is de-duplicated per[label, expression], so it means at least one failing render, never exactly one). Steady-state gating is unaffected — object-ui passesfallback: false, so the button is hidden on the aborting renders, which is where it should be during hydration anyway.⇒ p3. The defect is the declared-contract violation and the trap it leaves for the next author, ⛔ not a user-facing misbehaviour.
Why
pm:blockedrather thanpm:queueThe parity pin lives in⚠️ Correction to this line as first written: the live reverse index reads 11 carriers including this card and #1897 — ⛔ not the "eleven" this card claimed at filing time, which was one ahead of the derivation.
test/, which is epic #1579's fence, and this lane's rule is that the fence opens only on a maintainer or director sentence. ⭐ This is the same question as #1874.Refs #1890 (the sweep that excluded it) · PR #1894 (the exclusion and its comments) · #1874 (the fence) · #621 (untranslatable rules are dropped) · #630 (the totality rule).
Generated by Claude Code