Skip to content

Expose sharing rules through the metadata API - #25447

Draft
martmull wants to merge 1 commit into
claude/adversarial-agents-impl-vq7601-pr12from
claude/adversarial-agents-impl-vq7601-pr12b
Draft

Expose sharing rules through the metadata API#25447
martmull wants to merge 1 commit into
claude/adversarial-agents-impl-vq7601-pr12from
claude/adversarial-agents-impl-vq7601-pr12b

Conversation

@martmull

@martmull martmull commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Stacked on #25444 (sharingRule entity). Second half of PR 12 of the record sharing build plan (core-team-issues #2822): the metadata GraphQL surface for sharing rules.

What

  • sharingRules(objectMetadataId) query and createSharingRule, updateSharingRule, deleteSharingRule mutations under WorkspaceAuthGuard and SettingsPermissionGuard(DATA_MODEL), running through validateBuildAndRunWorkspaceMigration like the other metadata entities. Rules are created with a fresh universal identifier in the workspace custom application; objectMetadataId and applicationId are not editable.
  • SharingRuleDTO resolves its rowLevelPermissionPredicates and rowLevelPermissionPredicateGroups, filtered by sharingRuleId.
  • upsertRowLevelPermissionPredicates accepts either roleId or sharingRuleId (exactly one). The parent is resolved once, the rule must belong to the same object as the predicates, the ownership and enterprise checks are the ones the role path already runs, and predicates of other parents are never touched. Predicate DTOs carry a nullable roleId and a sharingRuleId.
  • RecordShareAccessLevel and RecordSharePrincipalType enums are reused from the record share DTOs.
  • Generated twenty-front metadata types and twenty-client-sdk metadata schema regenerated.

Tests

  • sharing-rule-crud.integration-spec.ts: create, list and update; criteria attached to a rule through upsertRowLevelPermissionPredicates with roleId: null; both parents refused; ROLE grantee without a role refused; a member without the data model permission refused; delete cascades the predicates and a later upsert against the deleted rule returns SHARING_RULE_NOT_FOUND.
  • Existing predicate, role and manifest sync suites unchanged.

Stack

  1. Record sharing 1/14: add the readability level on object metadata #25421 readability level
  2. Record sharing 2/14: add the recordShare hidden standard object and its service #25425 recordShare object and service
  3. Record sharing 3/14: gate reads and writes on private objects with record share rows #25426 read and write gate
  4. Record sharing 4/14: let a create state who may read the record with shareWith #25428 shareWith on create
  5. Record sharing 5/14: evaluate record shares in memory for events #25429 in-memory twin for events
  6. Record sharing 6/14: call recordings go private #25438 call recordings PRIVATE
  7. Record sharing 8/14: inherited objects follow their parent #25439 INHERITED objects
  8. Record sharing 9/14: sync writes mailbox and calendar share rows #25441 mailbox and calendar share rows
  9. Record sharing 10/14: email and calendar go private #25445 messages and calendar events PRIVATE
  10. Record sharing 11/14 (server): manual sharing and ownership #25443 manual sharing and ownership (server)
  11. Record sharing 11/14 (front): the Share action and dialog #25446 Share action and dialog (front)
  12. Record sharing 12/14 (storage): the sharingRule entity #25444 sharingRule entity
  13. this PR: sharing rule metadata API
  14. rule recalculation job (next)
  15. timeline guard for private linked records (next)
  16. Settings Sharing tab and level changes (next)

Generated by Claude Code

Review in cubic

Add the sharingRule GraphQL surface: sharingRules(objectMetadataId), createSharingRule, updateSharingRule and deleteSharingRule, guarded by the data model settings permission and run through the workspace migration runner. Row-level permission predicates now accept either a roleId or a sharingRuleId as parent, and a rule's predicates resolve from the rule. Generated front and client SDK metadata types are regenerated.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant