You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Establish the compile-time permission contract that the client and server authorization surfaces will share. This is the first delivery stage of #173 and intentionally changes no runtime authorization behavior.
Current DX
CanParams currently accepts open strings and an open parameter record:
That means a misspelling such as blog:drafts, an invalid combination such as blog:draft/delete, or an incorrect record parameter compiles. Consumers must discover built-in permission names from docs or package source, and third-party plugins have no common typed registration mechanism.
Proposed DX
Each plugin exports a server-safe permission catalog from a neutral subpath. BTST derives a correlated resource/action/params request union and makes the registered request available consistently to client and server APIs.
Permission types improve authoring, discovery, refactoring, and auditability. They are not runtime security enforcement; the authoritative server behavior is tracked separately by the next child issue.
Scope
Introduce a framework-neutral permission statement/registry contract.
Derive a correlated resource/action/params request type rather than independent resource and action unions.
Support actions with required, optional, and absent parameter objects.
Export the built-in permission catalog for every maintained plugin from a neutral /permissions subpath that imports neither client nor API runtime code.
Provide an application and third-party plugin extension mechanism that does not require repetitive generics at each hook/component call.
Apply the registered permission type to the public type surfaces used by client and server authorization without changing their runtime behavior.
Provide an explicit dynamic/unsafe request type for values originating outside the typed registry without weakening the default path.
Document structural adaptation to Better Auth access-control statements without coupling BTST core to Better Auth.
Acceptance criteria
The isomorphic permission entry imports no React runtime, framework runtime, database package, request API, environment secret, server-only, or client-only marker.
Built-in plugin catalogs use a documented namespaced resource convention and have no duplicate resource ownership.
CanParams or its replacement is derived as a correlated union of valid resource/action/params tuples.
useCan, <CanAccess>, route permission declarations, client/server provider callbacks, and future server helpers consume the same registered request type.
Application-local and third-party resources extend the registry without casts or repeated generics at each use site.
A misspelled blog:drafts resource fails a type test.
An undeclared blog:draft/delete pair fails a type test.
Missing, extra, and incorrectly typed record parameters fail representative type tests.
A representative third-party permission is accepted across client and server type surfaces.
Neutral permission exports are available in ESM/CJS declarations and do not pull /client or /api runtime modules into their graph.
Existing runtime tests remain unchanged and green, proving this issue introduces no authorization behavior change.
Package typecheck, declaration build, permission type tests, and docs build pass.
Non-goals
Invoking the server policy or changing endpoint authorization behavior.
Building a role, ACL, ABAC, or database policy engine.
Adding a fluent permission DSL or permission code generation.
Treating TypeScript validation as a security boundary.
Parent
Purpose
Establish the compile-time permission contract that the client and server authorization surfaces will share. This is the first delivery stage of #173 and intentionally changes no runtime authorization behavior.
Current DX
CanParamscurrently accepts open strings and an open parameter record:That means a misspelling such as
blog:drafts, an invalid combination such asblog:draft/delete, or an incorrect record parameter compiles. Consumers must discover built-in permission names from docs or package source, and third-party plugins have no common typed registration mechanism.Proposed DX
Each plugin exports a server-safe permission catalog from a neutral subpath. BTST derives a correlated resource/action/params request union and makes the registered request available consistently to client and server APIs.
Normal authoring retains the existing object syntax with autocomplete:
Permission types improve authoring, discovery, refactoring, and auditability. They are not runtime security enforcement; the authoritative server behavior is tracked separately by the next child issue.
Scope
/permissionssubpath that imports neither client nor API runtime code.Acceptance criteria
server-only, orclient-onlymarker.CanParamsor its replacement is derived as a correlated union of valid resource/action/params tuples.useCan,<CanAccess>, route permission declarations, client/server provider callbacks, and future server helpers consume the same registered request type.blog:draftsresource fails a type test.blog:draft/deletepair fails a type test./clientor/apiruntime modules into their graph.Non-goals
Blocked by
Blocks