Split out of #488. The object-grant half was fixed in #547; this is the remaining record-level coverage question, kept separate because it needs a business decision, not just metadata.
The gap
sales_rep holds readScope: 'own' on crm_quote, crm_task and crm_contract (all private OWD), and no sharing rule exists for any of these objects. Meanwhile accounts do have widening rules (north_america_territory, europe_territory, account_team_sharing).
So a rep who receives an account through a territory rule opens it and finds:
- the Contacts related list populated (contacts are
controlled_by_parent → follow the account),
- the Opportunities / Quotes / Contracts / Tasks related lists empty or partial — those objects stay own-only, and nothing derives or shares them alongside the account.
The page promises a 360° view of the shared account; record-level security delivers a keyhole. Same shape for service_agent: they read the account org-wide but see only their own cases/tasks on it.
Decision needed (per object)
Whose records should someone see on an account they can read but don't own?
| Object |
Option 1 — criteria sharing rule |
Option 2 — OWD change |
Option 3 — status quo |
crm_quote |
Share quotes whose account matches the territory rules (duplicates the territory criteria per child object; brittle) |
controlled_by_parent on the opportunity or account — pricing follows the deal |
Own-only is arguably correct for pricing |
crm_contract |
Share active contracts with the account's team |
controlled_by_parent (account) — a contract is account data |
Own-only hides renewals from the very team sharing the account |
crm_task |
Share open tasks by account territory |
Keep private — tasks are personal by design |
Probably fine as-is |
Notes:
test/authorization-coverage.test.ts (added in #547) will keep whatever is decided consistent — e.g. if quotes go controlled_by_parent, the inert-scope and parent-resolution checks apply automatically.
Split out of #488. The object-grant half was fixed in #547; this is the remaining record-level coverage question, kept separate because it needs a business decision, not just metadata.
The gap
sales_repholdsreadScope: 'own'oncrm_quote,crm_taskandcrm_contract(allprivateOWD), and no sharing rule exists for any of these objects. Meanwhile accounts do have widening rules (north_america_territory,europe_territory,account_team_sharing).So a rep who receives an account through a territory rule opens it and finds:
controlled_by_parent→ follow the account),The page promises a 360° view of the shared account; record-level security delivers a keyhole. Same shape for
service_agent: they read the account org-wide but see only their own cases/tasks on it.Decision needed (per object)
Whose records should someone see on an account they can read but don't own?
crm_quotecontrolled_by_parenton the opportunity or account — pricing follows the dealcrm_contractcontrolled_by_parent(account) — a contract is account datacrm_taskNotes:
privatebut every account-sharing rule then needs a mirrored rule per child object, and the criteria drift apart over time.crm_opportunityhas the same question one level up (own-only + a single ≥$100k director rule), and Ownership model mismatch: app-authoredownerlookups vs the platform'sowner_id— reassigning Owner in the UI does not move record access #548 (owner vsowner_id) affects how "own" is evaluated everywhere here.test/authorization-coverage.test.ts(added in #547) will keep whatever is decided consistent — e.g. if quotes gocontrolled_by_parent, the inert-scope and parent-resolution checks apply automatically.