VexAccessConfigInput
Defined in: packages/core/src/access/types.ts:907
Input shape for the defineAccess builder.
Type Param
Section titled “Type Param”TUserCollection
{ slug } shape naming the user collection.
Type Param
Section titled “Type Param”TOrgCollection
{ slug } shape naming the org collection; undefined if absent.
VexAccessConfig for the resolved runtime shape.
Type Parameters
Section titled “Type Parameters”TRoles
Section titled “TRoles”TRoles extends readonly string[]
Tuple of role name literals.
TResources
Section titled “TResources”TResources extends readonly AccessResource[] = readonly AccessResource[]
Structural resource tuple ({ slug, versions? }).
TCustomResources
Section titled “TCustomResources”TCustomResources extends Record<string, CustomResourceInput> = { }
Custom resource declarations.
TUserSlug
Section titled “TUserSlug”TUserSlug extends CollectionSlug = CollectionSlug
TOrgSlug
Section titled “TOrgSlug”TOrgSlug extends CollectionSlug | undefined = undefined
TCustomActions
Section titled “TCustomActions”TCustomActions extends Partial<Record<TResources[number]["slug"] | TUserSlug | Extract<TOrgSlug, string>, CustomActionsInput>> = { }
TPermissions
Section titled “TPermissions”TPermissions = Record<TRoles[number], RolePermissions<SubjectMap<TResources, TCustomResources, TUserSlug, TOrgSlug, TCustomActions>, InferDocTypeFromSlug<TUserSlug>, TOrgSlug extends string ? InferDocTypeFromSlug<TOrgSlug> : never, TUserSlug, TOrgSlug>>
The inferred permissions literal, which is what
makes each callback’s return type inspectable by ValidateFieldMaps.
Properties
Section titled “Properties”anonRole?
Section titled “anonRole?”
optionalanonRole?:TRoles[number]
Defined in: packages/core/src/access/types.ts:936
OPTIONAL. Role applied when a caller’s roles resolve empty — no session,
or an anonymous user (e.g. Better Auth anonymous plugin) whose
userRolesField is unset. Explicit roles always win over this fallback.
Omitted → empty roles deny, exactly as before.
customActions?
Section titled “customActions?”
optionalcustomActions?:TCustomActions&Partial<Record<TUserSlug|TResources[number]["slug"] |Extract<TOrgSlug,string>,CustomActionsInput>> & { [K in string | number | symbol]: never }
Defined in: packages/core/src/access/types.ts:965
Extra actions per resource, beyond CRUD. Keys must be declared resource slugs (or the user/org collection slugs).
Three constituents, each load-bearing:
TCustomActions— the inference site; carries the caller’s literal declaration into the phantomSubjectMap.Partial<Record<slugs, …>>— the COMPLETION source. Key completions come from the property’s contextual type, and a bare unresolved type parameter offers nothing; this constituent names the slug union directly, which is resolvable in the first inference round (resourcesand the slugs are not context-sensitive). Redundant for checking — the bound already constrains values.- The exactness map — the TYPO guard. The
Partial<Record<…>>bound cannot reject a bad key on its own: an all-optional target is a “weak type”, so TypeScript errors only when the object shares ZERO keys with it — one valid entry beside a garbage key passes, because structural subtyping permits extra properties and per-key excess checking does not fire against a generic-constrained inference. Mapping every key NOT in the slug union tonevermakes the garbage entry’s value unassignable AT ITS OWN KEY, restoring both the error and its location.
customResources?
Section titled “customResources?”
optionalcustomResources?:TCustomResources
Defined in: packages/core/src/access/types.ts:981
Custom, non-resource subjects with arbitrary action unions and optional
typed data. Example: { apiKeys: { actions: ["create", "revoke"] } }.
enabled?
Section titled “enabled?”
optionalenabled?:boolean
Defined in: packages/core/src/access/types.ts:928
Default: true. Turn access control on or off.
organizations?
Section titled “organizations?”
optionalorganizations?:boolean
Defined in: packages/core/src/access/types.ts:1028
Default: false. Whether organizations are an ENFORCED tenancy
boundary in this project, not just available data — developer-approved,
binding (the pre-existing behavior keyed orgCollectionSlug alone into
view scoping, which silently broke a project that only declared
orgCollectionSlug for its own callbacks’ benefit, with no org data
ever seeded). Currently drives ONE thing: whether saved (vex_views)
shared views are scoped to the caller’s own organization at all
(listViews/loadSharedSavedListViewWheres/saveView/removeView, server, and
useCanAccessSharedSavedListViews, client — all resolve this through the SAME
shared predicate, isViewOrganizationScopingEnabled, so none of them
can disagree). Requires orgCollectionSlug to be set too — this
flag has no effect without it.
When false (the default): shared-view CRUD is exactly the
pre-organization-scoping behavior — any caller with the relevant
VIEW_ACTIONS permission can create, read, update, and delete ANY
shared view, including an org-less one, regardless of organization.
orgCollectionSlug?
Section titled “orgCollectionSlug?”
optionalorgCollectionSlug?:TOrgSlug
Defined in: packages/core/src/access/types.ts:1007
Slug of the organization collection. When present, organization is
available (typed via the registry) in every permission callback; when
omitted, callbacks have no organization key. Declaring this alone does
NOT scope saved views (or anything else) to the caller’s own
organization — it only says WHERE organization data lives, for a
project’s own permission callbacks to read. Set organizations
to actually enforce organization-scoped behavior.
permissions
Section titled “permissions”permissions:
TPermissions&ValidateFieldMaps<TPermissions,SubjectMap<TResources,TCustomResources,TUserSlug,TOrgSlug,TCustomActions>> & { [K in string | number | symbol]: never }
Defined in: packages/core/src/access/types.ts:1040
Permission matrix: role → subject → check. See RolePermissions for shapes and wildcard semantics.
Intersected with ValidateFieldMaps so a returned field map naming
an unknown field is a compile error at that entry. The bare TPermissions
member is what makes the literal inferrable; the constraint on
TPermissions (declared on defineAccess) is what keeps every callback’s
props contextually typed.
resources
Section titled “resources”resources:
TResources
Defined in: packages/core/src/access/types.ts:942
Collections/globals contributing subjects, keyed by slug.
roles:
TRoles
Defined in: packages/core/src/access/types.ts:939
Role identifiers; keys of the permissions matrix.
userCollectionSlug
Section titled “userCollectionSlug”userCollectionSlug:
TUserSlug
Defined in: packages/core/src/access/types.ts:989
Slug of the collection whose documents are user in callbacks. A plain
slug string — the full collection often does not exist at authoring time
(auth-adapter collections merge later, inside defineConfig); the
document type resolves from the generated registry by slug.
userRolesField
Section titled “userRolesField”userRolesField:
string
Defined in: packages/core/src/access/types.ts:996
REQUIRED. The field on the user document that holds the user’s role(s).
Value may be string or string[]; hasPermission normalizes both.
Callers never pass roles separately — they always ride the user document.