@classytic/arc 2.6.2 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -1
- package/dist/{BaseController-AbbRx3e0.mjs → BaseController-CpMfCXdn.mjs} +214 -16
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-CTn28N4y.mjs → adapters-BxGgSHjj.mjs} +7 -13
- package/dist/applyPermissionResult-D6GPMsvh.mjs +37 -0
- package/dist/audit/index.d.mts +1 -1
- package/dist/audit/index.mjs +1 -1
- package/dist/audit/mongodb.d.mts +1 -1
- package/dist/audit/mongodb.mjs +1 -1
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +7 -6
- package/dist/auth/mongoose.d.mts +191 -0
- package/dist/auth/mongoose.mjs +73 -0
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-lz0IRbXJ.mjs → betterAuthOpenApi-CCw3YX0g.mjs} +1 -1
- package/dist/cache/index.d.mts +2 -2
- package/dist/cache/index.mjs +2 -2
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +7 -5
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-C1XCMtqM.mjs → core-BWekSEju.mjs} +41 -13
- package/dist/{createApp-D2w0LdYJ.mjs → createApp-B_nvKNAQ.mjs} +11 -11
- package/dist/{defineResource-Ckxg6HrZ.mjs → defineResource-DZzyl4a4.mjs} +73 -56
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/dynamic/index.d.mts +2 -2
- package/dist/dynamic/index.mjs +2 -2
- package/dist/{elevation-BEdACOLB.mjs → elevation-By_p2lnn.mjs} +1 -1
- package/dist/elevation-Dm-HTBCt.d.mts +23 -0
- package/dist/{errorHandler-Do4vVQ1f.d.mts → errorHandler-COa51ho_.d.mts} +1 -1
- package/dist/{errorHandler-r2595m8T.mjs → errorHandler-DXUttWEO.mjs} +1 -1
- package/dist/{eventPlugin-DW45v4V5.d.mts → eventPlugin-BgLxJkIB.d.mts} +1 -1
- package/dist/{eventPlugin-Ba00swHF.mjs → eventPlugin-DsaNNXzZ.mjs} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +1 -1
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/mongodb.d.mts +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/index-BYpRGXif.d.mts +640 -0
- package/dist/{index-B4uZm82R.d.mts → index-KXM8_JmQ.d.mts} +47 -4
- package/dist/{index-DrCqa3Jq.d.mts → index-StgFaQKD.d.mts} +3 -3
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +10 -9
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +2 -2
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/{interface-CrN45qz1.d.mts → interface-Dwzqt4mn.d.mts} +204 -18
- package/dist/{mongodb-pMvOlR5_.d.mts → mongodb-Bq90j-Uj.d.mts} +1 -1
- package/dist/{mongodb-kltrBPa1.d.mts → mongodb-DdyYlIXg.d.mts} +1 -1
- package/dist/{openapi-CBmZ6EQN.mjs → openapi-C5UhIeWu.mjs} +1 -1
- package/dist/org/index.d.mts +2 -2
- package/dist/org/index.mjs +1 -1
- package/dist/permissions/index.d.mts +4 -4
- package/dist/permissions/index.mjs +3 -2
- package/dist/{permissions-C8ImI8gC.mjs → permissions-CH4cNwJi.mjs} +358 -64
- package/dist/plugins/index.d.mts +4 -4
- package/dist/plugins/index.mjs +10 -10
- package/dist/plugins/response-cache.mjs +1 -1
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/policies/index.d.mts +1 -1
- package/dist/presets/index.d.mts +3 -3
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +53 -3
- package/dist/presets/multiTenant.mjs +89 -47
- package/dist/{presets-BMfdy34e.mjs → presets-BFrGvvjL.mjs} +2 -2
- package/dist/{queryCachePlugin-DcmETvcB.d.mts → queryCachePlugin-Bw8XyJpX.d.mts} +1 -1
- package/dist/{queryCachePlugin-XtFplYO9.mjs → queryCachePlugin-CwTpR04-.mjs} +2 -2
- package/dist/{redis-D0Qc-9EW.d.mts → redis-CyCntzTO.d.mts} +1 -1
- package/dist/{redis-stream-BW9UKLZM.d.mts → redis-stream-We_Ucl9-.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-DH3c3e-T.mjs → resourceToTools-CkVSSzKg.mjs} +313 -33
- package/dist/rpc/index.d.mts +1 -1
- package/dist/rpc/index.mjs +1 -1
- package/dist/scope/index.d.mts +3 -2
- package/dist/scope/index.mjs +4 -3
- package/dist/{sse-BF7GR7IB.mjs → sse-Bp3dabF1.mjs} +2 -2
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +4 -3
- package/dist/types/index.mjs +1 -1
- package/dist/types-AOD8fxIw.mjs +229 -0
- package/dist/types-CNEbix8T.d.mts +286 -0
- package/dist/{types-DurlBP2N.d.mts → types-ClmkMDK1.d.mts} +1 -1
- package/dist/{types-C1Z28coa.d.mts → types-D0qf0Mf4.d.mts} +9 -9
- package/dist/types-DPsC0taJ.d.mts +178 -0
- package/dist/utils/index.d.mts +3 -3
- package/dist/utils/index.mjs +5 -5
- package/package.json +34 -22
- package/skills/arc/SKILL.md +278 -6
- package/skills/arc/references/multi-tenancy.md +208 -0
- package/dist/elevation-C_taLQrM.d.mts +0 -147
- package/dist/index-NGZksqM5.d.mts +0 -398
- package/dist/types-BNUccdcf.d.mts +0 -101
- package/dist/types-BhtYdxZU.mjs +0 -91
- /package/dist/{EventTransport-wc5hSLik.d.mts → EventTransport-CUpRK_Lg.d.mts} +0 -0
- /package/dist/{HookSystem-COkyWztM.mjs → HookSystem-D7lfx--K.mjs} +0 -0
- /package/dist/{ResourceRegistry-C6ngvOnn.mjs → ResourceRegistry-DsHiG9cL.mjs} +0 -0
- /package/dist/{caching-BSXB-Xr7.mjs → caching-5DtLwIqb.mjs} +0 -0
- /package/dist/{circuitBreaker-JP2GdJ4b.d.mts → circuitBreaker-DwxrljLB.d.mts} +0 -0
- /package/dist/{circuitBreaker-BOBOpN2w.mjs → circuitBreaker-l18oRgL5.mjs} +0 -0
- /package/dist/{errors-CcVbl1-T.d.mts → errors-CCSsMpXE.d.mts} +0 -0
- /package/dist/{errors-NoQKsbAT.mjs → errors-Cg58SLNi.mjs} +0 -0
- /package/dist/{externalPaths-DpO-s7r8.d.mts → externalPaths-Dg7OLsKo.d.mts} +0 -0
- /package/dist/{fields-DFwdaWCq.d.mts → fields-CYuLMJPD.d.mts} +0 -0
- /package/dist/{interface-gr-7qo9j.d.mts → interface-B9rHWPxD.d.mts} +0 -0
- /package/dist/{interface-D_BWALyZ.d.mts → interface-CnluRL4_.d.mts} +0 -0
- /package/dist/{logger-Dz3j1ItV.mjs → logger-DLg8-Ueg.mjs} +0 -0
- /package/dist/{memory-BFAYkf8H.mjs → memory-Cp7_cAko.mjs} +0 -0
- /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
- /package/dist/{mongodb-BuQ7fNTg.mjs → mongodb-mlgxkYI3.mjs} +0 -0
- /package/dist/{pluralize-CcT6qF0a.mjs → pluralize-COpOVar8.mjs} +0 -0
- /package/dist/{registry-I-ogLgL9.mjs → registry-B3lRFBWo.mjs} +0 -0
- /package/dist/{requestContext-DYtmNpm5.mjs → requestContext-xHIKedG6.mjs} +0 -0
- /package/dist/{schemaConverter-DjzHpFam.mjs → schemaConverter-0TyONAwM.mjs} +0 -0
- /package/dist/{sessionManager-wbkYj2HL.d.mts → sessionManager-IW4sbIea.d.mts} +0 -0
- /package/dist/{tracing-bz_U4EM1.d.mts → tracing-65B51Dw3.d.mts} +0 -0
- /package/dist/{typeGuards-Cj5Rgvlg.mjs → typeGuards-CcFZXgU7.mjs} +0 -0
- /package/dist/{utils-Dc0WhlIl.mjs → utils-B-l6410F.mjs} +0 -0
- /package/dist/{versioning-BzfeHmhj.mjs → versioning-aUUVziBY.mjs} +0 -0
|
@@ -0,0 +1,640 @@
|
|
|
1
|
+
import { r as RequestScope } from "./types-CNEbix8T.mjs";
|
|
2
|
+
import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-DPsC0taJ.mjs";
|
|
3
|
+
import { i as CacheStore, t as CacheLogger } from "./interface-CnluRL4_.mjs";
|
|
4
|
+
import { FastifyRequest } from "fastify";
|
|
5
|
+
|
|
6
|
+
//#region src/permissions/applyPermissionResult.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Normalize a permission check return value (`boolean | PermissionResult`)
|
|
9
|
+
* into a concrete `PermissionResult`. This is the only place in Arc that
|
|
10
|
+
* promotes booleans to results — keeps the type narrowing honest everywhere.
|
|
11
|
+
*/
|
|
12
|
+
declare function normalizePermissionResult(result: boolean | PermissionResult): PermissionResult;
|
|
13
|
+
/**
|
|
14
|
+
* Minimal shape of a Fastify request that can receive permission side-effects.
|
|
15
|
+
* We avoid depending on the full augmented `FastifyRequest` type here because
|
|
16
|
+
* `_policyFilters` / `scope` are declared via ambient module augmentation in
|
|
17
|
+
* multiple places and the unaugmented interface is what the core routers see.
|
|
18
|
+
*/
|
|
19
|
+
type RequestSink = FastifyRequest & {
|
|
20
|
+
_policyFilters?: Record<string, unknown>;
|
|
21
|
+
scope?: RequestScope;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Apply a granted `PermissionResult` to a Fastify request — merges row-level
|
|
25
|
+
* filters into `_policyFilters` and conditionally installs the scope.
|
|
26
|
+
*
|
|
27
|
+
* **Scope install rule:** only writes `scope` when the current request scope
|
|
28
|
+
* is absent or `public`. This prevents downgrading an already-authenticated
|
|
29
|
+
* request (e.g. Better Auth set `member`, then a permission check returns a
|
|
30
|
+
* narrower `service` scope — the original `member` wins because it came from
|
|
31
|
+
* a more authoritative source).
|
|
32
|
+
*
|
|
33
|
+
* Safe to call with a non-granted result — it simply no-ops. Callers should
|
|
34
|
+
* still check `result.granted` and send an error response before reaching here,
|
|
35
|
+
* but this function tolerates the misuse defensively.
|
|
36
|
+
*/
|
|
37
|
+
declare function applyPermissionResult(result: PermissionResult, request: RequestSink): void;
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/permissions/roleHierarchy.d.ts
|
|
40
|
+
/**
|
|
41
|
+
* Role Hierarchy — Composable RBAC Inheritance
|
|
42
|
+
*
|
|
43
|
+
* Expands roles based on an inheritance map. Apply at scope-building time
|
|
44
|
+
* so that requireRoles() works with the already-expanded list.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { createRoleHierarchy } from '@classytic/arc/permissions';
|
|
49
|
+
*
|
|
50
|
+
* const hierarchy = createRoleHierarchy({
|
|
51
|
+
* superadmin: ['admin'],
|
|
52
|
+
* admin: ['branch_manager'],
|
|
53
|
+
* branch_manager: ['member'],
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* // When building scope:
|
|
57
|
+
* const expandedRoles = hierarchy.expand(user.roles);
|
|
58
|
+
* // ['superadmin'] → ['superadmin', 'admin', 'branch_manager', 'member']
|
|
59
|
+
*
|
|
60
|
+
* // Check inclusion:
|
|
61
|
+
* hierarchy.includes(['admin'], 'branch_manager'); // true (admin inherits branch_manager)
|
|
62
|
+
* hierarchy.includes(['member'], 'admin'); // false (child doesn't inherit parent)
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
interface RoleHierarchy {
|
|
66
|
+
/** Expand roles to include all inherited (child) roles. Deduplicated. */
|
|
67
|
+
expand(roles: readonly string[]): string[];
|
|
68
|
+
/** Check if any of the user's roles (expanded) include the required role. */
|
|
69
|
+
includes(userRoles: readonly string[], requiredRole: string): boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a role hierarchy from a parent → children map.
|
|
73
|
+
*
|
|
74
|
+
* Each key is a parent role, each value is the array of roles it inherits.
|
|
75
|
+
* Inheritance is transitive: if A → B and B → C, then A expands to [A, B, C].
|
|
76
|
+
* Circular references are handled safely (visited set).
|
|
77
|
+
*/
|
|
78
|
+
declare function createRoleHierarchy(map: Record<string, readonly string[]>): RoleHierarchy;
|
|
79
|
+
declare namespace presets_d_exports {
|
|
80
|
+
export { adminOnly, authenticated, fullPublic, ownerWithAdminBypass, publicRead, publicReadAdminWrite, readOnly };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* ResourcePermissions shape — matches the type in types/index.ts
|
|
84
|
+
*/
|
|
85
|
+
interface ResourcePermissions<TDoc = any> {
|
|
86
|
+
list?: PermissionCheck<TDoc>;
|
|
87
|
+
get?: PermissionCheck<TDoc>;
|
|
88
|
+
create?: PermissionCheck<TDoc>;
|
|
89
|
+
update?: PermissionCheck<TDoc>;
|
|
90
|
+
delete?: PermissionCheck<TDoc>;
|
|
91
|
+
}
|
|
92
|
+
type PermissionOverrides<TDoc = any> = Partial<ResourcePermissions<TDoc>>;
|
|
93
|
+
/**
|
|
94
|
+
* Public read, authenticated write.
|
|
95
|
+
* list + get = allowPublic(), create + update + delete = requireAuth()
|
|
96
|
+
*/
|
|
97
|
+
declare function publicRead<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
98
|
+
/**
|
|
99
|
+
* Public read, admin write.
|
|
100
|
+
* list + get = allowPublic(), create + update + delete = requireRoles(['admin'])
|
|
101
|
+
*/
|
|
102
|
+
declare function publicReadAdminWrite<TDoc = any>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
103
|
+
/**
|
|
104
|
+
* All operations require authentication.
|
|
105
|
+
*/
|
|
106
|
+
declare function authenticated<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
107
|
+
/**
|
|
108
|
+
* All operations require specific roles.
|
|
109
|
+
* @param roles - Required roles (user needs at least one). Default: ['admin']
|
|
110
|
+
*/
|
|
111
|
+
declare function adminOnly<TDoc = any>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
112
|
+
/**
|
|
113
|
+
* Owner-scoped with admin bypass.
|
|
114
|
+
* list = auth (scoped to owner), get = auth, create = auth,
|
|
115
|
+
* update + delete = ownership check with admin bypass.
|
|
116
|
+
*
|
|
117
|
+
* @param ownerField - Field containing owner ID (default: 'userId')
|
|
118
|
+
* @param bypassRoles - Roles that bypass ownership check (default: ['admin'])
|
|
119
|
+
*/
|
|
120
|
+
declare function ownerWithAdminBypass<TDoc = any>(ownerField?: Extract<keyof TDoc, string> | string, bypassRoles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
121
|
+
/**
|
|
122
|
+
* Full public access — no auth required for any operation.
|
|
123
|
+
* Use sparingly (dev/testing, truly public APIs).
|
|
124
|
+
*/
|
|
125
|
+
declare function fullPublic<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
126
|
+
/**
|
|
127
|
+
* Read-only: list + get authenticated, write operations denied.
|
|
128
|
+
* Useful for computed/derived resources.
|
|
129
|
+
*/
|
|
130
|
+
declare function readOnly<TDoc = any>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
131
|
+
//#endregion
|
|
132
|
+
//#region src/permissions/index.d.ts
|
|
133
|
+
interface DynamicPermissionMatrixConfig {
|
|
134
|
+
/**
|
|
135
|
+
* Resolve role → resource → actions map dynamically (DB/API/config service).
|
|
136
|
+
* Called at permission-check time (or cache miss if cache enabled).
|
|
137
|
+
*/
|
|
138
|
+
resolveRolePermissions: (ctx: PermissionContext) => Record<string, Record<string, readonly string[]>> | Promise<Record<string, Record<string, readonly string[]>>>;
|
|
139
|
+
/**
|
|
140
|
+
* Optional cache store adapter.
|
|
141
|
+
* Use MemoryCacheStore for single-instance apps or RedisCacheStore for distributed setups.
|
|
142
|
+
*/
|
|
143
|
+
cacheStore?: CacheStore<Record<string, Record<string, readonly string[]>>>;
|
|
144
|
+
/** Optional logger for cache/runtime failures (default: console) */
|
|
145
|
+
logger?: CacheLogger;
|
|
146
|
+
/**
|
|
147
|
+
* Legacy convenience in-memory cache config.
|
|
148
|
+
* If `cacheStore` is not provided and ttlMs > 0, Arc creates an internal MemoryCacheStore.
|
|
149
|
+
*/
|
|
150
|
+
cache?: {
|
|
151
|
+
/** Cache TTL in milliseconds */ttlMs: number; /** Optional custom cache key builder */
|
|
152
|
+
key?: (ctx: PermissionContext) => string | null | undefined; /** Hard entry cap for internal memory store (default: 1000) */
|
|
153
|
+
maxEntries?: number;
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** Minimal publish/subscribe interface for cross-node cache invalidation. */
|
|
157
|
+
interface PermissionEventBus {
|
|
158
|
+
publish: <T>(type: string, payload: T) => Promise<void>;
|
|
159
|
+
subscribe: (pattern: string, handler: (event: {
|
|
160
|
+
payload: unknown;
|
|
161
|
+
}) => void | Promise<void>) => Promise<(() => void) | undefined>;
|
|
162
|
+
}
|
|
163
|
+
interface ConnectEventsOptions {
|
|
164
|
+
/** Called on remote invalidation for app-specific cleanup (e.g., resolver cache) */
|
|
165
|
+
onRemoteInvalidation?: (orgId: string) => void | Promise<void>;
|
|
166
|
+
/** Custom event type (default: 'arc.permissions.invalidated') */
|
|
167
|
+
eventType?: string;
|
|
168
|
+
}
|
|
169
|
+
interface DynamicPermissionMatrix {
|
|
170
|
+
can: (permissions: Record<string, readonly string[]>) => PermissionCheck;
|
|
171
|
+
canAction: (resource: string, action: string) => PermissionCheck;
|
|
172
|
+
requireRole: (...roles: string[]) => PermissionCheck;
|
|
173
|
+
requireMembership: () => PermissionCheck;
|
|
174
|
+
requireTeamMembership: () => PermissionCheck;
|
|
175
|
+
/** Invalidate cached permissions for a specific organization */
|
|
176
|
+
invalidateByOrg: (orgId: string) => Promise<void>;
|
|
177
|
+
clearCache: () => Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* Connect to an event system for cross-node cache invalidation.
|
|
180
|
+
*
|
|
181
|
+
* Late-binding: call after the event plugin is registered (e.g., in onReady hook).
|
|
182
|
+
* Once connected, `invalidateByOrg()` auto-publishes an event, and incoming
|
|
183
|
+
* events from other nodes trigger local cache invalidation.
|
|
184
|
+
* Echo is suppressed via per-process nodeId matching.
|
|
185
|
+
*/
|
|
186
|
+
connectEvents(events: PermissionEventBus, options?: ConnectEventsOptions): Promise<void>;
|
|
187
|
+
/** Disconnect from the event system. Safe to call even if never connected. */
|
|
188
|
+
disconnectEvents(): Promise<void>;
|
|
189
|
+
/** Whether events are currently connected. */
|
|
190
|
+
readonly eventsConnected: boolean;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Allow public access (no authentication required)
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```typescript
|
|
197
|
+
* permissions: {
|
|
198
|
+
* list: allowPublic(),
|
|
199
|
+
* get: allowPublic(),
|
|
200
|
+
* }
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
declare function allowPublic(): PermissionCheck;
|
|
204
|
+
/**
|
|
205
|
+
* Require authentication (any authenticated user)
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```typescript
|
|
209
|
+
* permissions: {
|
|
210
|
+
* create: requireAuth(),
|
|
211
|
+
* update: requireAuth(),
|
|
212
|
+
* }
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
declare function requireAuth(): PermissionCheck;
|
|
216
|
+
/**
|
|
217
|
+
* Require specific roles
|
|
218
|
+
*
|
|
219
|
+
* @param roles - Required roles (user needs at least one)
|
|
220
|
+
* @param options - Optional bypass roles
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* permissions: {
|
|
225
|
+
* create: requireRoles(['admin', 'editor']),
|
|
226
|
+
* delete: requireRoles(['admin']),
|
|
227
|
+
* }
|
|
228
|
+
*
|
|
229
|
+
* // With bypass roles
|
|
230
|
+
* permissions: {
|
|
231
|
+
* update: requireRoles(['owner'], { bypassRoles: ['admin', 'superadmin'] }),
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
/**
|
|
236
|
+
* Require one of the specified roles. Checks BOTH platform roles
|
|
237
|
+
* (`user.role`) AND organization roles (`scope.orgRoles`) by default —
|
|
238
|
+
* passing in either layer grants access. Elevated scope always passes.
|
|
239
|
+
*
|
|
240
|
+
* Accepts EITHER variadic strings OR a single readonly array — both forms
|
|
241
|
+
* produce identical behavior. Use whichever reads better at the call site.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* requireRoles('admin') // single role, variadic
|
|
246
|
+
* requireRoles('admin', 'editor') // multiple roles, variadic
|
|
247
|
+
* requireRoles(['admin', 'editor']) // array form
|
|
248
|
+
* requireRoles(['admin'], { bypassRoles: ['superadmin'] }) // with options
|
|
249
|
+
* requireRoles(['admin'], { includeOrgRoles: false }) // platform-only
|
|
250
|
+
* ```
|
|
251
|
+
*
|
|
252
|
+
* **2.7.1 BREAKING CHANGE:** `includeOrgRoles` now defaults to `true`. The
|
|
253
|
+
* old default (`false`, platform-only) was a footgun for the common case of
|
|
254
|
+
* Better Auth's organization plugin where roles like 'admin' are assigned at
|
|
255
|
+
* the org level. To restore the old behavior explicitly, pass
|
|
256
|
+
* `{ includeOrgRoles: false }`.
|
|
257
|
+
*
|
|
258
|
+
* For org-only role checks, prefer `requireOrgRole('admin')`.
|
|
259
|
+
*/
|
|
260
|
+
declare function requireRoles(role: string, ...rest: string[]): PermissionCheck;
|
|
261
|
+
declare function requireRoles(roles: readonly string[], options?: {
|
|
262
|
+
bypassRoles?: readonly string[];
|
|
263
|
+
/**
|
|
264
|
+
* Also check org membership roles (`scope.orgRoles`) when in org context.
|
|
265
|
+
* Default: `true` (changed in 2.7.1).
|
|
266
|
+
*
|
|
267
|
+
* Set to `false` to restore the pre-2.7.1 behavior of checking only
|
|
268
|
+
* platform roles (`user.role`). For org-only role checks, prefer
|
|
269
|
+
* `requireOrgRole('admin')` instead.
|
|
270
|
+
*/
|
|
271
|
+
includeOrgRoles?: boolean;
|
|
272
|
+
}): PermissionCheck;
|
|
273
|
+
/**
|
|
274
|
+
* **Alias of `requireRoles()`** — checks both platform roles AND org roles.
|
|
275
|
+
*
|
|
276
|
+
* Since 2.7.1, `requireRoles()` defaults to `includeOrgRoles: true`, which
|
|
277
|
+
* means `roles('admin')` and `requireRoles('admin')` are now functionally
|
|
278
|
+
* identical. This helper is preserved for backwards compatibility and for
|
|
279
|
+
* call sites that prefer the shorter `roles()` name.
|
|
280
|
+
*
|
|
281
|
+
* **For new code, prefer `requireRoles()`** — it's the canonical name and
|
|
282
|
+
* matches the rest of the `requireXxx()` family (`requireAuth`, `requireOwnership`,
|
|
283
|
+
* `requireOrgRole`, etc.).
|
|
284
|
+
*
|
|
285
|
+
* For platform-only checks: `requireRoles(['admin'], { includeOrgRoles: false })`
|
|
286
|
+
* For org-only checks: `requireOrgRole('admin')`
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* // These are identical:
|
|
291
|
+
* roles('admin', 'editor')
|
|
292
|
+
* requireRoles('admin', 'editor')
|
|
293
|
+
* requireRoles(['admin', 'editor'])
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
declare function roles(...args: string[] | [readonly string[]]): PermissionCheck;
|
|
297
|
+
/**
|
|
298
|
+
* Require resource ownership
|
|
299
|
+
*
|
|
300
|
+
* Returns filters to scope queries to user's owned resources.
|
|
301
|
+
*
|
|
302
|
+
* @param ownerField - Field containing owner ID (default: 'userId')
|
|
303
|
+
* @param options - Optional bypass roles
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* permissions: {
|
|
308
|
+
* update: requireOwnership('userId'),
|
|
309
|
+
* delete: requireOwnership('createdBy', { bypassRoles: ['admin'] }),
|
|
310
|
+
* }
|
|
311
|
+
* ```
|
|
312
|
+
*/
|
|
313
|
+
declare function requireOwnership<TDoc = Record<string, unknown>>(ownerField?: Extract<keyof TDoc, string> | string, options?: {
|
|
314
|
+
bypassRoles?: readonly string[];
|
|
315
|
+
}): PermissionCheck<TDoc>;
|
|
316
|
+
/**
|
|
317
|
+
* Combine multiple checks - ALL must pass (AND logic).
|
|
318
|
+
*
|
|
319
|
+
* Each child runs against the **accumulated** state of previous children:
|
|
320
|
+
* - `filters` from earlier children are merged into the next child's
|
|
321
|
+
* `_policyFilters` (so e.g. `requireOwnership` sees row-level scoping)
|
|
322
|
+
* - `scope` from earlier children is installed on the request before the
|
|
323
|
+
* next child runs (so e.g. `requireOrgMembership` after `requireApiKey`
|
|
324
|
+
* sees the service scope from the API key check)
|
|
325
|
+
*
|
|
326
|
+
* The final returned `PermissionResult` carries both the merged `filters` AND
|
|
327
|
+
* the merged `scope`, so the outer middleware's `applyPermissionResult` call
|
|
328
|
+
* sees the same end-state.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```typescript
|
|
332
|
+
* // CRUD permissions composed across roles + ownership
|
|
333
|
+
* permissions: {
|
|
334
|
+
* update: allOf(
|
|
335
|
+
* requireAuth(),
|
|
336
|
+
* requireRoles(['editor']),
|
|
337
|
+
* requireOwnership('createdBy')
|
|
338
|
+
* ),
|
|
339
|
+
* }
|
|
340
|
+
*
|
|
341
|
+
* // Custom auth + org membership — first check installs the scope,
|
|
342
|
+
* // second check reads it.
|
|
343
|
+
* permissions: {
|
|
344
|
+
* list: allOf(requireApiKey(), requireOrgMembership()),
|
|
345
|
+
* }
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
declare function allOf(...checks: PermissionCheck[]): PermissionCheck;
|
|
349
|
+
/**
|
|
350
|
+
* Combine multiple checks - ANY must pass (OR logic)
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```typescript
|
|
354
|
+
* permissions: {
|
|
355
|
+
* update: anyOf(
|
|
356
|
+
* requireRoles(['admin']),
|
|
357
|
+
* requireOwnership('createdBy')
|
|
358
|
+
* ),
|
|
359
|
+
* }
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
declare function anyOf(...checks: PermissionCheck[]): PermissionCheck;
|
|
363
|
+
/**
|
|
364
|
+
* Deny all access
|
|
365
|
+
*
|
|
366
|
+
* @example
|
|
367
|
+
* ```typescript
|
|
368
|
+
* permissions: {
|
|
369
|
+
* delete: denyAll('Deletion not allowed'),
|
|
370
|
+
* }
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
declare function denyAll(reason?: string): PermissionCheck;
|
|
374
|
+
/**
|
|
375
|
+
* Dynamic permission based on context
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* permissions: {
|
|
380
|
+
* update: when((ctx) => ctx.data?.status === 'draft'),
|
|
381
|
+
* }
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
declare function when<TDoc = Record<string, unknown>>(condition: (ctx: PermissionContext<TDoc>) => boolean | Promise<boolean>): PermissionCheck<TDoc>;
|
|
385
|
+
/**
|
|
386
|
+
* Require an org-bound caller. Grants access for any scope kind that
|
|
387
|
+
* carries org context: `member` (human user with org membership), `service`
|
|
388
|
+
* (API key bound to an org), or `elevated` (platform admin). Denies for
|
|
389
|
+
* `public` and `authenticated` scopes (no org context).
|
|
390
|
+
*
|
|
391
|
+
* This is the canonical "is the caller acting inside an org" check, and the
|
|
392
|
+
* usual partner for `multiTenantPreset` — if a route is multi-tenant
|
|
393
|
+
* filtered, you almost always want this gate too.
|
|
394
|
+
*
|
|
395
|
+
* Reads `request.scope` set by auth adapters or by upstream permission
|
|
396
|
+
* checks via `PermissionResult.scope` (e.g. a custom `requireApiKey()`).
|
|
397
|
+
*
|
|
398
|
+
* @example
|
|
399
|
+
* ```typescript
|
|
400
|
+
* permissions: {
|
|
401
|
+
* list: requireOrgMembership(),
|
|
402
|
+
* get: requireOrgMembership(),
|
|
403
|
+
*
|
|
404
|
+
* // Composed with an OAuth-style scope check for API-key callers
|
|
405
|
+
* create: allOf(requireOrgMembership(), requireServiceScope('jobs:write')),
|
|
406
|
+
* }
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
declare function requireOrgMembership<TDoc = Record<string, unknown>>(): PermissionCheck<TDoc>;
|
|
410
|
+
/**
|
|
411
|
+
* Require specific org-level roles.
|
|
412
|
+
* Reads `request.scope.orgRoles` (set by auth adapters).
|
|
413
|
+
* Elevated scope always passes (platform admin bypass).
|
|
414
|
+
*
|
|
415
|
+
* **Service scopes (API keys) always fail this check** — services don't
|
|
416
|
+
* carry user-style org roles, only OAuth-style `scopes` strings. For routes
|
|
417
|
+
* that should accept BOTH human admins AND API keys, compose explicitly:
|
|
418
|
+
*
|
|
419
|
+
* ```typescript
|
|
420
|
+
* permissions: {
|
|
421
|
+
* create: anyOf(
|
|
422
|
+
* requireOrgRole('admin'), // human path
|
|
423
|
+
* requireServiceScope('jobs:write'), // machine path
|
|
424
|
+
* ),
|
|
425
|
+
* }
|
|
426
|
+
* ```
|
|
427
|
+
*
|
|
428
|
+
* This separation is intentional — implicit "API key bypasses role checks"
|
|
429
|
+
* is the kind of footgun that ships data breaches. Services must opt into
|
|
430
|
+
* specific scopes the same way OAuth clients do.
|
|
431
|
+
*
|
|
432
|
+
* @param roles - Required org roles (user needs at least one)
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* ```typescript
|
|
436
|
+
* permissions: {
|
|
437
|
+
* create: requireOrgRole('admin', 'owner'),
|
|
438
|
+
* delete: requireOrgRole('owner'),
|
|
439
|
+
* }
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
442
|
+
declare function requireOrgRole<TDoc = Record<string, unknown>>(...args: string[] | [readonly string[]]): PermissionCheck<TDoc>;
|
|
443
|
+
/**
|
|
444
|
+
* Require specific OAuth-style scope strings on a service (API key) identity.
|
|
445
|
+
*
|
|
446
|
+
* Reads `request.scope.scopes` — only populated when the scope kind is
|
|
447
|
+
* `service`. Mirrors how OAuth 2.0 / Better Auth's apiKey plugin / API
|
|
448
|
+
* gateways express machine permissions: a comma- or array-encoded list of
|
|
449
|
+
* scope strings like `'jobs:read'`, `'jobs:write'`, `'memories:*'`.
|
|
450
|
+
*
|
|
451
|
+
* **Pass behavior:**
|
|
452
|
+
* - `service` scope where `scopes` contains ANY of the required strings → grant
|
|
453
|
+
* - `elevated` scope (platform admin) → grant
|
|
454
|
+
* - Anything else → deny with a clear reason
|
|
455
|
+
*
|
|
456
|
+
* Notably this does **not** grant for `member` scopes — humans go through
|
|
457
|
+
* `requireOrgRole`. For routes that should accept both, compose with `anyOf`:
|
|
458
|
+
*
|
|
459
|
+
* ```typescript
|
|
460
|
+
* permissions: {
|
|
461
|
+
* create: anyOf(
|
|
462
|
+
* requireOrgRole('admin'),
|
|
463
|
+
* requireServiceScope('jobs:write'),
|
|
464
|
+
* ),
|
|
465
|
+
* }
|
|
466
|
+
* ```
|
|
467
|
+
*
|
|
468
|
+
* @param scopes - Required scope strings (caller needs at least one)
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* ```typescript
|
|
472
|
+
* // Variadic
|
|
473
|
+
* requireServiceScope('jobs:write')
|
|
474
|
+
* requireServiceScope('jobs:read', 'jobs:write')
|
|
475
|
+
*
|
|
476
|
+
* // Array
|
|
477
|
+
* requireServiceScope(['jobs:read', 'jobs:write'])
|
|
478
|
+
*
|
|
479
|
+
* // Composed with org membership for org-scoped API keys
|
|
480
|
+
* permissions: {
|
|
481
|
+
* list: allOf(requireOrgMembership(), requireServiceScope('jobs:read')),
|
|
482
|
+
* create: allOf(requireOrgMembership(), requireServiceScope('jobs:write')),
|
|
483
|
+
* }
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
declare function requireServiceScope<TDoc = Record<string, unknown>>(...args: string[] | [readonly string[]]): PermissionCheck<TDoc>;
|
|
487
|
+
/**
|
|
488
|
+
* Require app-defined scope context dimensions (branch, project, department,
|
|
489
|
+
* region, workspace, etc.) on the current request.
|
|
490
|
+
*
|
|
491
|
+
* Reads `request.scope.context` (a `Readonly<Record<string, string>>` slot
|
|
492
|
+
* available on `member`, `service`, and `elevated` scope kinds). Arc takes
|
|
493
|
+
* no position on what dimensions you use — you set them, you check them.
|
|
494
|
+
*
|
|
495
|
+
* **Three call shapes:**
|
|
496
|
+
*
|
|
497
|
+
* ```typescript
|
|
498
|
+
* // 1. Presence check — key must exist on scope.context
|
|
499
|
+
* requireScopeContext('branchId')
|
|
500
|
+
*
|
|
501
|
+
* // 2. Value match — key must equal a specific string
|
|
502
|
+
* requireScopeContext('branchId', 'eng-paris')
|
|
503
|
+
*
|
|
504
|
+
* // 3. Multi-key (object form, AND semantics) — every key must match
|
|
505
|
+
* requireScopeContext({ branchId: 'eng-paris', projectId: 'p-123' })
|
|
506
|
+
* requireScopeContext({ region: 'eu', branchId: undefined }) // 'undefined' = presence-only for that key
|
|
507
|
+
* ```
|
|
508
|
+
*
|
|
509
|
+
* **Pass behavior:**
|
|
510
|
+
* - All required keys present (and matching values when specified) → grant
|
|
511
|
+
* - `elevated` scope (platform admin) → grant unconditionally (cross-context bypass)
|
|
512
|
+
* - Any required key missing or mismatched → deny with a clear reason
|
|
513
|
+
* - Scope kind without context support (`public`, `authenticated`) → deny
|
|
514
|
+
*
|
|
515
|
+
* Pairs with `multiTenantPreset({ tenantFields: [...] })` for row-level
|
|
516
|
+
* filtering on the same dimensions.
|
|
517
|
+
*
|
|
518
|
+
* @example
|
|
519
|
+
* ```typescript
|
|
520
|
+
* permissions: {
|
|
521
|
+
* // Branch-scoped CRUD — caller must have branchId in their scope context
|
|
522
|
+
* list: allOf(requireOrgMembership(), requireScopeContext('branchId')),
|
|
523
|
+
*
|
|
524
|
+
* // Project admin — caller must have BOTH project context AND admin role
|
|
525
|
+
* delete: allOf(requireOrgRole('admin'), requireScopeContext('projectId')),
|
|
526
|
+
*
|
|
527
|
+
* // Region-locked endpoint
|
|
528
|
+
* euOnly: requireScopeContext('region', 'eu'),
|
|
529
|
+
* }
|
|
530
|
+
* ```
|
|
531
|
+
*/
|
|
532
|
+
declare function requireScopeContext<TDoc = Record<string, unknown>>(keyOrMap: string | Record<string, string | undefined>, value?: string): PermissionCheck<TDoc>;
|
|
533
|
+
/**
|
|
534
|
+
* Require that the caller's scope grants access to a target organization
|
|
535
|
+
* — either the current org or one of its ancestors (`scope.ancestorOrgIds`).
|
|
536
|
+
*
|
|
537
|
+
* Designed for parent-child organization hierarchies (holding company →
|
|
538
|
+
* subsidiary → branch, MSP → managed tenants, white-label parent → child
|
|
539
|
+
* accounts) where some routes need to accept "this org OR any org I have
|
|
540
|
+
* access to via the chain". Arc takes no position on the source of the
|
|
541
|
+
* chain — your auth function loads `ancestorOrgIds` from your own data
|
|
542
|
+
* model. There's no automatic inheritance: every route opts in explicitly.
|
|
543
|
+
*
|
|
544
|
+
* **Two call shapes:**
|
|
545
|
+
*
|
|
546
|
+
* ```typescript
|
|
547
|
+
* // Static target — rare, used when one route only ever acts on one org
|
|
548
|
+
* requireOrgInScope('acme-holding')
|
|
549
|
+
*
|
|
550
|
+
* // Dynamic target — extracted from request params/body/headers per call
|
|
551
|
+
* requireOrgInScope((ctx) => ctx.request.params.orgId)
|
|
552
|
+
* requireOrgInScope((ctx) => ctx.request.body?.organizationId)
|
|
553
|
+
* ```
|
|
554
|
+
*
|
|
555
|
+
* **Pass behavior:**
|
|
556
|
+
* - Target equals `scope.organizationId` → grant
|
|
557
|
+
* - Target appears in `scope.ancestorOrgIds` → grant
|
|
558
|
+
* - `elevated` scope → grant unconditionally (cross-org admin bypass)
|
|
559
|
+
* - Target is undefined (extractor returned nothing) → deny with reason
|
|
560
|
+
* - Anything else → deny with target name in reason
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* ```typescript
|
|
564
|
+
* // /orgs/:orgId/jobs — caller can act on any org in their hierarchy chain
|
|
565
|
+
* permissions: {
|
|
566
|
+
* list: requireOrgInScope((ctx) => ctx.request.params.orgId),
|
|
567
|
+
* create: allOf(
|
|
568
|
+
* requireOrgInScope((ctx) => ctx.request.body?.organizationId),
|
|
569
|
+
* requireOrgRole('admin'),
|
|
570
|
+
* ),
|
|
571
|
+
* }
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
574
|
+
declare function requireOrgInScope<TDoc = Record<string, unknown>>(target: string | ((ctx: PermissionContext<TDoc>) => string | undefined)): PermissionCheck<TDoc>;
|
|
575
|
+
/**
|
|
576
|
+
* Create a scoped permission system for resource-action patterns.
|
|
577
|
+
* Maps org roles to fine-grained permissions without external API calls.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```typescript
|
|
581
|
+
* const perms = createOrgPermissions({
|
|
582
|
+
* statements: {
|
|
583
|
+
* product: ['create', 'update', 'delete'],
|
|
584
|
+
* order: ['create', 'approve'],
|
|
585
|
+
* },
|
|
586
|
+
* roles: {
|
|
587
|
+
* owner: { product: ['create', 'update', 'delete'], order: ['create', 'approve'] },
|
|
588
|
+
* admin: { product: ['create', 'update'], order: ['create'] },
|
|
589
|
+
* member: { product: [], order: [] },
|
|
590
|
+
* },
|
|
591
|
+
* });
|
|
592
|
+
*
|
|
593
|
+
* defineResource({
|
|
594
|
+
* permissions: {
|
|
595
|
+
* create: perms.can({ product: ['create'] }),
|
|
596
|
+
* delete: perms.can({ product: ['delete'] }),
|
|
597
|
+
* }
|
|
598
|
+
* });
|
|
599
|
+
* ```
|
|
600
|
+
*/
|
|
601
|
+
declare function createOrgPermissions(config: {
|
|
602
|
+
statements: Record<string, readonly string[]>;
|
|
603
|
+
roles: Record<string, Record<string, readonly string[]>>;
|
|
604
|
+
}): {
|
|
605
|
+
can: (permissions: Record<string, string[]>) => PermissionCheck;
|
|
606
|
+
requireRole: (...roles: string[]) => PermissionCheck;
|
|
607
|
+
requireMembership: () => PermissionCheck;
|
|
608
|
+
requireTeamMembership: () => PermissionCheck;
|
|
609
|
+
};
|
|
610
|
+
/**
|
|
611
|
+
* Create a dynamic role-based permission matrix.
|
|
612
|
+
*
|
|
613
|
+
* Use this when role/action mappings are managed outside code
|
|
614
|
+
* (e.g., admin UI matrix, DB-stored ACLs, remote policy service).
|
|
615
|
+
*
|
|
616
|
+
* Supports:
|
|
617
|
+
* - org role union (any assigned org role can grant)
|
|
618
|
+
* - global bypass roles
|
|
619
|
+
* - wildcard resource/action (`*`)
|
|
620
|
+
* - optional in-memory cache
|
|
621
|
+
*/
|
|
622
|
+
declare function createDynamicPermissionMatrix(config: DynamicPermissionMatrixConfig): DynamicPermissionMatrix;
|
|
623
|
+
/**
|
|
624
|
+
* Require membership in the active team.
|
|
625
|
+
* User must be authenticated, a member of the active org, AND have an active team.
|
|
626
|
+
*
|
|
627
|
+
* Better Auth teams are flat member groups (no team-level roles).
|
|
628
|
+
* Reads `request.scope.teamId` set by the Better Auth adapter.
|
|
629
|
+
*
|
|
630
|
+
* @example
|
|
631
|
+
* ```typescript
|
|
632
|
+
* permissions: {
|
|
633
|
+
* list: requireTeamMembership(),
|
|
634
|
+
* create: requireTeamMembership(),
|
|
635
|
+
* }
|
|
636
|
+
* ```
|
|
637
|
+
*/
|
|
638
|
+
declare function requireTeamMembership<TDoc = Record<string, unknown>>(): PermissionCheck<TDoc>;
|
|
639
|
+
//#endregion
|
|
640
|
+
export { RoleHierarchy as A, authenticated as C, publicRead as D, presets_d_exports as E, applyPermissionResult as M, normalizePermissionResult as N, publicReadAdminWrite as O, adminOnly as S, ownerWithAdminBypass as T, requireScopeContext as _, allOf as a, roles as b, createDynamicPermissionMatrix as c, requireAuth as d, requireOrgInScope as f, requireRoles as g, requireOwnership as h, PermissionEventBus as i, createRoleHierarchy as j, readOnly as k, createOrgPermissions as l, requireOrgRole as m, DynamicPermissionMatrix as n, allowPublic as o, requireOrgMembership as p, DynamicPermissionMatrixConfig as r, anyOf as s, ConnectEventsOptions as t, denyAll as u, requireServiceScope as v, fullPublic as w, when as x, requireTeamMembership as y };
|