ReadonlyDescriptionHuman-readable description of what this provider covers.
ReadonlyDomainOpt-in marker read by ClassFactory (see ClassResolutionResult): this class CANNOT
function standalone — every member below is abstract, so a base instance is a method-less
stub. TypeScript's abstract is erased at runtime, so the factory cannot detect that on its
own; without this marker an unresolvable ProviderClassName would silently be handed back
as a live "provider" and blow up later at the first method call.
With the marker set, CreateInstance throws and TryCreateInstance returns
{Resolved: false, Instance: null} — both of which PermissionEngine handles by skipping
the domain.
ReadonlySupportedWhat actions this provider can evaluate.
ReadonlySupportedWhat grantee types this provider supports.
ReadonlySupportsWhether this provider supports explicit Deny records.
ReadonlySupportsProtectedboolsMap a { Read?: boolean, Update?: boolean, … } descriptor to a canonical
PermissionAction[]. Replaces the 9 hand-rolled copies that each walked
their row's CRUD-ish booleans and pushed action names.
Output order matches the canonical order declared in PermissionAction.
Entries that are null/undefined/false are skipped.
ProtectedbuildBuild a NormalizedPermission with DomainName and Effect
pre-filled from the provider. Centralizes the ~10-field literal that
used to be constructed in every GetUserResources / GetEffectivePermissions /
GetResourcePermissions implementation.
Effect defaults to 'Allow' since the vast majority of providers don't
support Deny. Providers that emit Deny records (EntityPermissionProvider)
pass { effect: 'Deny' } explicitly.
ProtectedbulkGiven a list of IDs, fetch {ID, <nameField>} from entityName and return
a Map<ID, name>. Used by providers whose domain views don't denormalize
a resource name onto the permission row (AI Agents, Artifacts, Collections).
Returns an empty Map when ids is empty or the RunView fails — callers should
treat a missing key as "name unknown."
OptionalnameField: stringCheck if a user has a specific permission on a specific resource.
The user whose permissions are being checked (roles come from user.UserRoles).
The resource type within this domain (e.g., entity name, resource type name).
The specific resource ID; null for domain-wide checks.
The action being requested.
Optionalprovider: IMetadataProviderProtectedfetchStandard RunView wrapper that logs failures with <ProviderClass>.<methodName>:
prefix and returns the row list (or [] on failure). Replaces the boilerplate
that each provider previously carried around its RunView calls.
Get all effective permissions a user has on a specific resource. Returns an empty array when the user has no access.
Optionalprovider: IMetadataProviderEvery ACR where this user is the grantor. Only unexpired rules are returned — an expired ACR can't be acted on, so surfacing it in "Shared by me" would be noise.
ACRs where this user is the User-type grantee AND someone else issued the grant. Excludes rules the user created for themselves. Role/Everyone/Public grants don't belong in the personal "Shared with me" view — they're always aggregated, and there's no single recipient they were shared with. Only unexpired rules are returned.
Get all permissions granted on a specific resource across every grantee. Powers the Sharing Center's "Resource Access Report" view.
Optionalprovider: IMetadataProviderDefault implementation returns [] — providers should override to advertise
their supported resource types (see IPermissionProvider.GetResourceTypes).
Optionalprovider: IMetadataProviderGet all resources within this domain that the user has access to. Powers the Sharing Center's "User Access Report" view.
OptionalresourceType: stringOptional filter to one resource type within the domain.
Optionalprovider: IMetadataProvider
Wraps
MJ: Access Control Rulesbehind the unified PermissionProviderBase contract.ACRs are record-scoped permissions on any entity, using a single polymorphic
(GranteeType, GranteeID)column pair. They support the broadest grantee set (User, Role, Everyone, Public), the full CRUD+Share action set, and optional time-bound expiration viaExpiresAt.resourceTypeis the entity name the ACR targets (e.g.,"Accounts"); the provider resolves it to the EntityID before querying.resourceIdis theRecordIDvalue (typically a UUID but stored as nvarchar(500) to accommodate composite keys).