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
sales-manager profile: crm_forecast declares allowDelete: false beside modifyAllRecords: true, which objectstack now refuses at build (objectstack#25707); choose Modify All with delete, or edit without delete #2277
Ruled: 6395693217 · letter B · 2026-10-25T09:00:06Z
Filing gate ③, a follow-up owed by a landed change: the HotCRM consequence of objectstack-ai/objectstack#25707 (merged f6ba1343ba, ruling A 6377890121 on objectstack-ai/objectstack#25575). Filed by the objectstack domain:spec seat 2 (objectstack seat post #18549) · sunhaolin · session session_01PC4NPXPgPmpDRG9DdDnyXT. The seat committed to this card in its ACCEPT (6390192995, item 8), and the contract review (6390432689) recorded it. ⛔ Not a claim. Grade and routing are HotCRM triage's.
What changed upstream
modifyAllRecords (Modify All Records) is the write bypass for edit, delete and transfer, as in Salesforce. The permission evaluator grants delete on that bit and never reads allowDelete. So an object-permission entry with allowDelete: false beside modifyAllRecords: true has always let its holder delete. The false was never enforced.
From the next @objectstack/spec release after 18.1.0, ObjectPermissionSchemarefuses that pair at build and publish: one issue at objects.<object>.allowDelete. The lint rule security-modify-all-delete-withheld reports it too. The runtime does not change.
The comment above it says the intent is org-wide read and write on a private object (#488). No other entry in src/** sets the pair.
What happens, and when
Deployed today: nothing changes. A built 17.1 artifact carrying this entry is rewritten at load to allowDelete: true by the ADR-0087 conversion permission-modify-all-allow-delete-false-to-true. That is exactly what the evaluator already did: a sales manager could always delete forecasts.
After HotCRM upgrades @objectstack/spec past 18.1.0:os build / os validate refuse this profile at objects.crm_forecast.allowDelete until the entry is changed.
The choice (HotCRM's, by what the sales manager should be able to do)
A. Keep Modify All, which includes delete: remove allowDelete: false (or write allowDelete: true). No behaviour changes; the declaration now says what was always enforced.
B. Edit every forecast, delete none (RULED, 6395693217): remove modifyAllRecords, keep allowEdit: true / allowDelete: false, and add a criteria sharing rule. This is the route ruling A names: { type: 'criteria', object: 'crm_forecast', condition: "record.id != ''", accessLevel: 'edit', sharedWith: { type: 'position', value: '<the sales manager position>' } }. An edit share opens update and never delete (ADR-0111 D3), and the object needs an owner-write default (private or public_read). Measured upstream on a booted stack: update 200, delete 403, create 403. A literal condition: 'true' is never served; use a field predicate every row satisfies.
The comment at :55–:56 ("org-wide read AND write") reads like B was the intent, but only HotCRM can say whether a sales manager deletes forecasts.
Dedupe
Semantic search in objectstack-ai/hotcrm, "crm_forecast sales manager modifyAllRecords allowDelete false permission refused": 3 hits, all closed. #705 (Modify All not opening row-level write on 17.0-rc) and #880 (contract write depth) are older platform questions, and #2044 is unrelated. None is this refusal. New.
Claim: PM loop round 5
Session: session_014xanhPEmGTMTfVH4UokwJT
Account: os-elon-musk
Branch: claude/issue-2277-forecast-edit-share
Worktree: /home/claude/hotcrm-2277
Domain: repo:hotcrm
Seat: repo:hotcrm#1
File surface: src/sales/profiles/sales-manager.profile.ts, src/sales/sharing/** (a new forecast criteria share and its registration), the tests that pin sales-manager forecast access, content/docs/** release-notes or permission pages that describe it, .changeset/ (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: default, effort: medium
Clause-②: no
Responsibility: HotCRM app | none | the users of this surface
Thread-read: 6395693217
Serial constraints cleared: ruling B recorded (6395693217); no other open PR touches sales-manager.profile.ts
Dispatched under the maintainer's ruling 「13458 A ; 2277 2038 同意」 (2026-10-25T09:00:06Z) and 「hotcrm允许派发 p3」.
PR #2282 merged through the merge queue at the ACCEPTed head 4de04c5. The seat's review of record is the ## 席位核对 comment on the PR. Fixes #2277 closed this card. In the same act, pm:dispatched is removed and the assignee cleared.
Ruling: batch #14 item 7 (optional, from PR #2282 finding 1) · letter A · maintainer 「同意」 2026-10-25T13:58:53Z
A = a Sales Manager keeps allowTransfer on crm_forecast. The transfer bit PR #2282 kept beside the edit share stands; the rostered deviation in test/ownership-model.test.ts (TRANSFER_WITHOUT_MODIFY_ALL = ['crm_forecast']) is the intended state. No follow-up PR.
Activity
os-elon-musk commentedon Oct 25, 2026
Ruling: batch #13 item 4 · letter B · maintainer 「13458 A ; 2277 2038 同意」 2026-10-25T09:00:06Z(「同意」= 简报推荐的 B)
B = 销售经理对
crm_forecast全员可改、无人可删。src/sales/profiles/sales-manager.profile.ts:57去掉modifyAllRecords: true,保留allowEdit: true/allowDelete: false(viewAllRecords: true照旧),并加一条 criteria 共享规则:accessLevel: 'edit',sharedWith为销售经理职位(sales_manager),condition用全行满足的字段谓词(不能写字面'true');对象 OWD 保持private。先例形状见src/sales/sharing/account.sharing.ts。上游实测:update 200、delete 403、create 403。这是行为变化(经理失去事实上的删除权),要进 6.0.0 发布说明;:55–:56 的注释改成与 B 一致。工作量 S,一个 PR。
维护者动作已完成:本卡入
pm:queue;裁不派,由 HotCRM 席位派发。批 #13 简报:https://claude.ai/artifact/PqFEhLdWm4A335J6n16JmPGenerated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
Claim: PM loop round 5
Session:
session_014xanhPEmGTMTfVH4UokwJTAccount:
os-elon-muskBranch:
claude/issue-2277-forecast-edit-shareWorktree: /home/claude/hotcrm-2277
Domain:
repo:hotcrmSeat:
repo:hotcrm#1File surface:
src/sales/profiles/sales-manager.profile.ts, src/sales/sharing/** (a new forecast criteria share and its registration), the tests that pin sales-manager forecast access, content/docs/** release-notes or permission pages that describe it, .changeset/(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: default,effort: mediumClause-②: no
Responsibility:
HotCRM app | none | the users of this surfaceThread-read: 6395693217
Serial constraints cleared: ruling B recorded (6395693217); no other open PR touches
sales-manager.profile.tsDispatched under the maintainer's ruling 「13458 A ; 2277 2038 同意」 (2026-10-25T09:00:06Z) and 「hotcrm允许派发 p3」.
Generated by Claude Code
objectstack-fleet commentedon Oct 25, 2026
Landed ·
repo:hotcrmseat 1 ·os-elon-musk· sessionsession_014xanhPEmGTMTfVH4UokwJT· 2026-10-25T09:49ZPR #2282 merged through the merge queue at the ACCEPTed head
4de04c5. The seat's review of record is the## 席位核对comment on the PR.Fixes #2277closed this card. In the same act,pm:dispatchedis removed and the assignee cleared.Generated by Claude Code
os-elon-musk commentedon Oct 25, 2026
Ruling: batch #14 item 7 (optional, from PR #2282 finding 1) · letter A · maintainer 「同意」 2026-10-25T13:58:53Z
A = a Sales Manager keeps
allowTransferoncrm_forecast. The transfer bit PR #2282 kept beside the edit share stands; the rostered deviation intest/ownership-model.test.ts(TRANSFER_WITHOUT_MODIFY_ALL = ['crm_forecast']) is the intended state. No follow-up PR.Generated by Claude Code