Skip to content

resolveAccessIndex

resolveAccessIndex<TSubjects>(props): QueryIndex | undefined

Defined in: packages/core/src/access/resolveAccessRule.ts:249

Resolves the index an access rule contributes to a query, if any.

Called once per query, before the Convex query is built. Answers a query-scoped question (“which index narrows this query?”) rather than the document-scoped one hasPermission answers (“may they read this row?”).

Never authorizes. The per-document hasPermission pass still runs, so a missing or broader-than-necessary index can only cost reads — it can never admit a row a role does not permit. Failing to find an index is always safe; wrongly applying one is not, which is why every ambiguous case resolves to undefined (scan) rather than to a guess.

Returns undefined when the single contributing rule used the FLAT algebra rather than calling q.withIndex(…): there is a describable constraint, but no index to push it into. resolveAccessConstraint is the export that can still use it.

TSubjects extends Record<string, SubjectEntry> = Record<string, SubjectEntry>

Resolved SubjectMap, inferred from access. Generic for the same reason HasPermissionProps is: a concrete SubjectMap<…> instantiation is not assignable to the erased VexAccessConfig<Record<string, SubjectEntry>> default, because callback contravariance makes instantiations mutually unassignable (P-002). Pinning the default would reject every real defineAccess() result.

Input props.

VexAccessConfig<TSubjects, readonly AccessResource[], string, string | undefined, Partial<Record<string, CustomActionsInput>>>

Resolved access config; absent or enabled: false ⇒ no index.

string

Query-shaped action ("read" | "readDrafts").

Record<string, unknown>

Active organization, forwarded to the rule’s callback.

string

Subject slug (a collection or global slug).

Record<string, unknown> | null

Caller, or null for anonymous (resolves through access.anonRole).

QueryIndex | undefined

The index to apply, or undefined to scan unnarrowed.

const index = resolveAccessIndex({
access, user, resource: "pages", action: CRUD_ACTIONS.read,
});
// → { name: "by_author", range: (q) => q.eq("authorId", "u1") }