| title |
services.sharing |
| description |
Record-level sharing and editability checks. |
- Stability:
stable
- Canonical source:
packages/spec/src/contracts/sharing-service.ts
services.sharing.buildReadFilter(object: string, context: SharingExecutionContext): Promise<unknown | null>
services.sharing.canEdit(object: string, recordId: string, context: SharingExecutionContext): Promise<boolean>
services.sharing.grant(input: GrantShareInput, context: SharingExecutionContext): Promise<RecordShare>
services.sharing.revoke(shareId: string, context: SharingExecutionContext): Promise<void>
services.sharing.listShares(object: string, recordId: string, context: SharingExecutionContext): Promise<RecordShare[]>
buildReadFilter: null means unrestricted read; otherwise returns an engine filter
canEdit: boolean decision
grant/listShares: normalized RecordShare rows
FORBIDDEN (403) — a write denied by the canEdit gate. Thrown by the sharing engine middleware; canEdit itself returns false rather than throwing.
VALIDATION_FAILED — grant/revoke called without a required field (object, recordId, recipientId, or shareId). revoke is otherwise a no-op when the share id is not found.
const allowed = await services.sharing.canEdit('contract', ctx.input.id, {
userId: ctx.session?.userId,
// The hook exposes the caller's org as `organizationId` (the `session.tenantId`
// alias was removed in v11, #3290); it feeds the sharing context's `tenantId`.
tenantId: ctx.session?.organizationId,
positions: ctx.session?.positions,
});
if (!allowed) throw new Error('PERMISSION_DENIED');