@stacksjs/auth 0.70.88 → 0.70.91

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.
Files changed (47) hide show
  1. package/dist/authentication.d.ts +43 -0
  2. package/dist/authentication.js +413 -0
  3. package/dist/authenticator.d.ts +17 -0
  4. package/dist/authenticator.js +14 -0
  5. package/dist/authorizable.d.ts +77 -0
  6. package/dist/authorizable.js +28 -0
  7. package/dist/client.d.ts +22 -0
  8. package/dist/client.js +26 -0
  9. package/dist/email-verification.d.ts +29 -0
  10. package/dist/email-verification.js +111 -0
  11. package/dist/gate.d.ts +180 -0
  12. package/dist/gate.js +203 -0
  13. package/dist/index.d.ts +36 -0
  14. package/dist/index.js +26 -0
  15. package/dist/internal-constants.d.ts +19 -0
  16. package/dist/internal-constants.js +1 -0
  17. package/dist/middleware.d.ts +14 -0
  18. package/dist/middleware.js +28 -0
  19. package/dist/passkey.d.ts +97 -0
  20. package/dist/passkey.js +76 -0
  21. package/dist/password/reset.d.ts +10 -0
  22. package/dist/password/reset.js +156 -0
  23. package/dist/policy.d.ts +33 -0
  24. package/dist/policy.js +91 -0
  25. package/dist/rate-limiter.d.ts +44 -0
  26. package/dist/rate-limiter.js +91 -0
  27. package/dist/rbac-seed.d.ts +24 -0
  28. package/dist/rbac-seed.js +30 -0
  29. package/dist/rbac-store-bqb.d.ts +18 -0
  30. package/dist/rbac-store-bqb.js +180 -0
  31. package/dist/rbac.d.ts +265 -0
  32. package/dist/rbac.js +324 -0
  33. package/dist/register.d.ts +3 -0
  34. package/dist/register.js +43 -0
  35. package/dist/session-auth.d.ts +67 -0
  36. package/dist/session-auth.js +151 -0
  37. package/dist/team.d.ts +121 -0
  38. package/dist/team.js +88 -0
  39. package/dist/token.d.ts +16 -0
  40. package/dist/token.js +21 -0
  41. package/dist/tokens.d.ts +284 -0
  42. package/dist/tokens.js +489 -0
  43. package/dist/two-factor.d.ts +67 -0
  44. package/dist/two-factor.js +113 -0
  45. package/dist/user.d.ts +34 -0
  46. package/dist/user.js +41 -0
  47. package/package.json +3 -3
@@ -0,0 +1,18 @@
1
+ import { isUniqueViolation } from '@stacksjs/orm';
2
+ import type { PermissionRecord, RbacStore, RoleRecord } from './rbac';
3
+ /**
4
+ * Swallow unique-constraint violations. Anything else is re-thrown so a
5
+ * "connection lost" mid-INSERT doesn't get silently treated as
6
+ * "already assigned".
7
+ *
8
+ * Exported for direct unit testing — the live pivot helpers below also use it.
9
+ */
10
+ export declare function swallowDuplicate(err: unknown): void;
11
+ /**
12
+ * Map a raw DB row to a typed record. Both `roles` and `permissions` share
13
+ * the same shape, so one mapper covers both — the call site provides the
14
+ * generic. Exported for unit testing.
15
+ */
16
+ export declare function toRecord<T extends RoleRecord | PermissionRecord>(row: Record<string, unknown> | undefined): T | null;
17
+ export declare function createBqbRbacStore(): RbacStore;
18
+ export { isUniqueViolation };
@@ -0,0 +1,180 @@
1
+ import { db } from "@stacksjs/database";
2
+ import { isUniqueViolation } from "@stacksjs/orm";
3
+
4
+ export { isUniqueViolation };
5
+ export function swallowDuplicate(err) {
6
+ if (!isUniqueViolation(err))
7
+ throw err;
8
+ }
9
+ export function toRecord(row) {
10
+ if (!row)
11
+ return null;
12
+ return {
13
+ id: Number(row.id),
14
+ name: String(row.name),
15
+ guard_name: String(row.guard_name),
16
+ description: row.description == null ? void 0 : String(row.description),
17
+ created_at: row.created_at == null ? void 0 : String(row.created_at),
18
+ updated_at: row.updated_at == null ? void 0 : String(row.updated_at)
19
+ };
20
+ }
21
+ async function insertAndFetch(table, name, guardName, description) {
22
+ await db.insertInto(table).values({ name, guard_name: guardName, description: description ?? null }).execute();
23
+ const row = await db.selectFrom(table).selectAll().where("name", "=", name).where("guard_name", "=", guardName).orderBy("id", "desc").limit(1).executeTakeFirst(), rec = toRecord(row);
24
+ if (!rec)
25
+ throw Error(`[rbac] insertAndFetch(${table}, ${name}, ${guardName}) succeeded but follow-up SELECT returned nothing`);
26
+ return rec;
27
+ }
28
+ async function pivotAttach(table, cols) {
29
+ let q = db.selectFrom(table).select("user_id" in cols ? "user_id" : "role_id");
30
+ for (const [k, v] of Object.entries(cols))
31
+ q = q.where(k, "=", v);
32
+ if (await q.limit(1).executeTakeFirst())
33
+ return;
34
+ try {
35
+ await db.insertInto(table).values(cols).execute();
36
+ } catch (err) {
37
+ swallowDuplicate(err);
38
+ }
39
+ }
40
+ async function pivotDetach(table, cols) {
41
+ let q = db.deleteFrom(table);
42
+ for (const [k, v] of Object.entries(cols))
43
+ q = q.where(k, "=", v);
44
+ await q.execute();
45
+ }
46
+ async function pivotDetachAll(table, column, value) {
47
+ await db.deleteFrom(table).where(column, "=", value).execute();
48
+ }
49
+ async function pivotSync(table, ownerColumn, ownerId, targetColumn, targetIds) {
50
+ const unique = Array.from(new Set(targetIds));
51
+ await db.transaction(async (rawTrx) => {
52
+ const trx = rawTrx;
53
+ await trx.deleteFrom(table).where(ownerColumn, "=", ownerId).execute();
54
+ if (unique.length === 0)
55
+ return;
56
+ const rows = unique.map((id) => ({ [ownerColumn]: ownerId, [targetColumn]: id }));
57
+ try {
58
+ await trx.insertInto(table).values(rows).execute();
59
+ } catch (err) {
60
+ swallowDuplicate(err);
61
+ for (const id of unique)
62
+ try {
63
+ await trx.insertInto(table).values({ [ownerColumn]: ownerId, [targetColumn]: id }).execute();
64
+ } catch (innerErr) {
65
+ swallowDuplicate(innerErr);
66
+ }
67
+ }
68
+ });
69
+ }
70
+ export function createBqbRbacStore() {
71
+ return {
72
+ async findRoleByName(name, guardName = "web") {
73
+ const row = await db.selectFrom("roles").selectAll().where("name", "=", name).where("guard_name", "=", guardName).limit(1).executeTakeFirst();
74
+ return toRecord(row);
75
+ },
76
+ async findRoleById(id) {
77
+ const row = await db.selectFrom("roles").selectAll().where("id", "=", id).limit(1).executeTakeFirst();
78
+ return toRecord(row);
79
+ },
80
+ async createRole(name, guardName = "web", description) {
81
+ return await insertAndFetch("roles", name, guardName, description);
82
+ },
83
+ async deleteRole(id) {
84
+ await db.deleteFrom("user_roles").where("role_id", "=", id).execute();
85
+ await db.deleteFrom("role_permissions").where("role_id", "=", id).execute();
86
+ await db.deleteFrom("roles").where("id", "=", id).execute();
87
+ },
88
+ async getAllRoles(guardName) {
89
+ let q = db.selectFrom("roles").selectAll();
90
+ if (guardName)
91
+ q = q.where("guard_name", "=", guardName);
92
+ return (await q.orderBy("id", "asc").execute()).map((r) => toRecord(r)).filter(Boolean);
93
+ },
94
+ async findPermissionByName(name, guardName = "web") {
95
+ const row = await db.selectFrom("permissions").selectAll().where("name", "=", name).where("guard_name", "=", guardName).limit(1).executeTakeFirst();
96
+ return toRecord(row);
97
+ },
98
+ async findPermissionById(id) {
99
+ const row = await db.selectFrom("permissions").selectAll().where("id", "=", id).limit(1).executeTakeFirst();
100
+ return toRecord(row);
101
+ },
102
+ async createPermission(name, guardName = "web", description) {
103
+ return await insertAndFetch("permissions", name, guardName, description);
104
+ },
105
+ async deletePermission(id) {
106
+ await db.deleteFrom("user_permissions").where("permission_id", "=", id).execute();
107
+ await db.deleteFrom("role_permissions").where("permission_id", "=", id).execute();
108
+ await db.deleteFrom("permissions").where("id", "=", id).execute();
109
+ },
110
+ async getAllPermissions(guardName) {
111
+ let q = db.selectFrom("permissions").selectAll();
112
+ if (guardName)
113
+ q = q.where("guard_name", "=", guardName);
114
+ return (await q.orderBy("id", "asc").execute()).map((r) => toRecord(r)).filter(Boolean);
115
+ },
116
+ async getUserRoles(userId) {
117
+ return (await db.selectFrom("roles").innerJoin("user_roles", "user_roles.role_id", "=", "roles.id").select([
118
+ "roles.id as id",
119
+ "roles.name as name",
120
+ "roles.guard_name as guard_name",
121
+ "roles.description as description",
122
+ "roles.created_at as created_at",
123
+ "roles.updated_at as updated_at"
124
+ ]).where("user_roles.user_id", "=", userId).orderBy("roles.id", "asc").execute()).map((r) => toRecord(r)).filter(Boolean);
125
+ },
126
+ assignRoleToUser(userId, roleId) {
127
+ return pivotAttach("user_roles", { user_id: userId, role_id: roleId });
128
+ },
129
+ removeRoleFromUser(userId, roleId) {
130
+ return pivotDetach("user_roles", { user_id: userId, role_id: roleId });
131
+ },
132
+ removeAllRolesFromUser(userId) {
133
+ return pivotDetachAll("user_roles", "user_id", userId);
134
+ },
135
+ syncUserRoles(userId, roleIds) {
136
+ return pivotSync("user_roles", "user_id", userId, "role_id", roleIds);
137
+ },
138
+ async getUserDirectPermissions(userId) {
139
+ return (await db.selectFrom("permissions").innerJoin("user_permissions", "user_permissions.permission_id", "=", "permissions.id").select([
140
+ "permissions.id as id",
141
+ "permissions.name as name",
142
+ "permissions.guard_name as guard_name",
143
+ "permissions.description as description",
144
+ "permissions.created_at as created_at",
145
+ "permissions.updated_at as updated_at"
146
+ ]).where("user_permissions.user_id", "=", userId).orderBy("permissions.id", "asc").execute()).map((r) => toRecord(r)).filter(Boolean);
147
+ },
148
+ assignPermissionToUser(userId, permissionId) {
149
+ return pivotAttach("user_permissions", { user_id: userId, permission_id: permissionId });
150
+ },
151
+ removePermissionFromUser(userId, permissionId) {
152
+ return pivotDetach("user_permissions", { user_id: userId, permission_id: permissionId });
153
+ },
154
+ removeAllPermissionsFromUser(userId) {
155
+ return pivotDetachAll("user_permissions", "user_id", userId);
156
+ },
157
+ syncUserPermissions(userId, permissionIds) {
158
+ return pivotSync("user_permissions", "user_id", userId, "permission_id", permissionIds);
159
+ },
160
+ async getRolePermissions(roleId) {
161
+ return (await db.selectFrom("permissions").innerJoin("role_permissions", "role_permissions.permission_id", "=", "permissions.id").select([
162
+ "permissions.id as id",
163
+ "permissions.name as name",
164
+ "permissions.guard_name as guard_name",
165
+ "permissions.description as description",
166
+ "permissions.created_at as created_at",
167
+ "permissions.updated_at as updated_at"
168
+ ]).where("role_permissions.role_id", "=", roleId).orderBy("permissions.id", "asc").execute()).map((r) => toRecord(r)).filter(Boolean);
169
+ },
170
+ assignPermissionToRole(roleId, permissionId) {
171
+ return pivotAttach("role_permissions", { role_id: roleId, permission_id: permissionId });
172
+ },
173
+ removePermissionFromRole(roleId, permissionId) {
174
+ return pivotDetach("role_permissions", { role_id: roleId, permission_id: permissionId });
175
+ },
176
+ syncRolePermissions(roleId, permissionIds) {
177
+ return pivotSync("role_permissions", "role_id", roleId, "permission_id", permissionIds);
178
+ }
179
+ };
180
+ }
package/dist/rbac.d.ts ADDED
@@ -0,0 +1,265 @@
1
+ import type { UserModel as OrmUserModel } from '@stacksjs/orm';
2
+ /**
3
+ * Set the RBAC store implementation
4
+ */
5
+ export declare function setRbacStore(rbacStore: RbacStore): void;
6
+ /**
7
+ * Flush the RBAC cache
8
+ */
9
+ export declare function flushRbacCache(): void;
10
+ /**
11
+ * Create a new role
12
+ */
13
+ export declare function createRole(name: string, guardName?: string, description?: string): Promise<RoleRecord>;
14
+ /**
15
+ * Find a role by name
16
+ */
17
+ export declare function findRole(name: string, guardName?: string): Promise<RoleRecord | null>;
18
+ /**
19
+ * Delete a role
20
+ */
21
+ export declare function deleteRole(name: string, guardName?: string): Promise<void>;
22
+ /**
23
+ * Get all roles
24
+ */
25
+ export declare function getAllRoles(guardName?: string): Promise<RoleRecord[]>;
26
+ /**
27
+ * Create a new permission
28
+ */
29
+ export declare function createPermission(name: string, guardName?: string, description?: string): Promise<PermissionRecord>;
30
+ /**
31
+ * Find a permission by name
32
+ */
33
+ export declare function findPermission(name: string, guardName?: string): Promise<PermissionRecord | null>;
34
+ /**
35
+ * Delete a permission
36
+ */
37
+ export declare function deletePermission(name: string, guardName?: string): Promise<void>;
38
+ /**
39
+ * Get all permissions
40
+ */
41
+ export declare function getAllPermissions(guardName?: string): Promise<PermissionRecord[]>;
42
+ /**
43
+ * Get all roles for a user
44
+ */
45
+ export declare function getUserRoles(user: UserModel | { id: number } | number): Promise<RoleRecord[]>;
46
+ /**
47
+ * Assign a role to a user
48
+ */
49
+ export declare function assignRole(user: UserModel | { id: number } | number, roleName: string, guardName?: string): Promise<void>;
50
+ /**
51
+ * Remove a role from a user
52
+ */
53
+ export declare function removeRole(user: UserModel | { id: number } | number, roleName: string, guardName?: string): Promise<void>;
54
+ /**
55
+ * Remove all roles from a user
56
+ */
57
+ export declare function removeAllRoles(user: UserModel | { id: number } | number): Promise<void>;
58
+ /**
59
+ * Sync roles for a user (replaces all current roles)
60
+ */
61
+ export declare function syncRoles(user: UserModel | { id: number } | number, roleNames: string[], guardName?: string): Promise<void>;
62
+ /**
63
+ * Check if a user has a specific role
64
+ */
65
+ export declare function hasRole(user: UserModel | { id: number } | number, roleName: string, guardName?: string): Promise<boolean>;
66
+ /**
67
+ * Check if a user has any of the given roles
68
+ */
69
+ export declare function hasAnyRole(user: UserModel | { id: number } | number, roleNames: string[], guardName?: string): Promise<boolean>;
70
+ /**
71
+ * Check if a user has all of the given roles
72
+ */
73
+ export declare function hasAllRoles(user: UserModel | { id: number } | number, roleNames: string[], guardName?: string): Promise<boolean>;
74
+ /**
75
+ * Get all permissions for a user (direct + via roles)
76
+ */
77
+ export declare function getUserPermissions(user: UserModel | { id: number } | number): Promise<PermissionRecord[]>;
78
+ /**
79
+ * Give a direct permission to a user
80
+ */
81
+ export declare function givePermission(user: UserModel | { id: number } | number, permissionName: string, guardName?: string): Promise<void>;
82
+ /**
83
+ * Revoke a direct permission from a user
84
+ */
85
+ export declare function revokePermission(user: UserModel | { id: number } | number, permissionName: string, guardName?: string): Promise<void>;
86
+ /**
87
+ * Revoke all direct permissions from a user
88
+ */
89
+ export declare function revokeAllPermissions(user: UserModel | { id: number } | number): Promise<void>;
90
+ /**
91
+ * Sync direct permissions for a user
92
+ */
93
+ export declare function syncPermissions(user: UserModel | { id: number } | number, permissionNames: string[], guardName?: string): Promise<void>;
94
+ /**
95
+ * Check if a user has a specific permission (direct or via role)
96
+ */
97
+ export declare function hasPermission(user: UserModel | { id: number } | number, permissionName: string, guardName?: string): Promise<boolean>;
98
+ /**
99
+ * Check if a user has any of the given permissions
100
+ */
101
+ export declare function hasAnyPermission(user: UserModel | { id: number } | number, permissionNames: string[], guardName?: string): Promise<boolean>;
102
+ /**
103
+ * Check if a user has all of the given permissions
104
+ */
105
+ export declare function hasAllPermissions(user: UserModel | { id: number } | number, permissionNames: string[], guardName?: string): Promise<boolean>;
106
+ /**
107
+ * Get all permissions for a role
108
+ */
109
+ export declare function getRolePermissions(roleId: number): Promise<PermissionRecord[]>;
110
+ /**
111
+ * Assign a permission to a role
112
+ */
113
+ export declare function givePermissionToRole(roleName: string, permissionName: string, guardName?: string): Promise<void>;
114
+ /**
115
+ * Remove a permission from a role
116
+ */
117
+ export declare function revokePermissionFromRole(roleName: string, permissionName: string, guardName?: string): Promise<void>;
118
+ /**
119
+ * Sync permissions for a role
120
+ */
121
+ export declare function syncRolePermissions(roleName: string, permissionNames: string[], guardName?: string): Promise<void>;
122
+ /**
123
+ * Add RBAC methods to a user object
124
+ *
125
+ * @example
126
+ * const user = withRbac(authenticatedUser)
127
+ * if (await user.hasRole('admin')) { ... }
128
+ * await user.assignRole('editor')
129
+ */
130
+ export declare function withRbac<T extends UserModel | { id: number }>(user: T): T & RbacMethods;
131
+ /**
132
+ * RBAC facade for convenient access
133
+ */
134
+ export declare const Rbac: {
135
+ setStore: unknown;
136
+ flushCache: unknown;
137
+ createRole: typeof createRole;
138
+ findRole: typeof findRole;
139
+ deleteRole: typeof deleteRole;
140
+ getAllRoles: typeof getAllRoles;
141
+ createPermission: typeof createPermission;
142
+ findPermission: typeof findPermission;
143
+ deletePermission: typeof deletePermission;
144
+ getAllPermissions: typeof getAllPermissions;
145
+ getUserRoles: typeof getUserRoles;
146
+ assignRole: typeof assignRole;
147
+ removeRole: typeof removeRole;
148
+ removeAllRoles: typeof removeAllRoles;
149
+ syncRoles: typeof syncRoles;
150
+ hasRole: typeof hasRole;
151
+ hasAnyRole: typeof hasAnyRole;
152
+ hasAllRoles: typeof hasAllRoles;
153
+ getUserPermissions: typeof getUserPermissions;
154
+ givePermission: typeof givePermission;
155
+ revokePermission: typeof revokePermission;
156
+ revokeAllPermissions: typeof revokeAllPermissions;
157
+ syncPermissions: typeof syncPermissions;
158
+ hasPermission: typeof hasPermission;
159
+ hasAnyPermission: typeof hasAnyPermission;
160
+ hasAllPermissions: typeof hasAllPermissions;
161
+ getRolePermissions: typeof getRolePermissions;
162
+ givePermissionToRole: typeof givePermissionToRole;
163
+ revokePermissionFromRole: typeof revokePermissionFromRole;
164
+ syncRolePermissions: typeof syncRolePermissions;
165
+ withRbac: typeof withRbac
166
+ };
167
+ export declare interface RoleRecord {
168
+ id: number
169
+ name: string
170
+ guard_name: string
171
+ description?: string
172
+ created_at?: string
173
+ updated_at?: string
174
+ }
175
+ export declare interface PermissionRecord {
176
+ id: number
177
+ name: string
178
+ guard_name: string
179
+ description?: string
180
+ created_at?: string
181
+ updated_at?: string
182
+ }
183
+ export declare interface RolePermissionPivot {
184
+ role_id: number
185
+ permission_id: number
186
+ created_at?: string
187
+ }
188
+ export declare interface UserRolePivot {
189
+ user_id: number
190
+ role_id: number
191
+ created_at?: string
192
+ }
193
+ export declare interface UserPermissionPivot {
194
+ user_id: number
195
+ permission_id: number
196
+ created_at?: string
197
+ }
198
+ /**
199
+ * RBAC database adapter interface.
200
+ * Implement this to connect RBAC to your database layer.
201
+ */
202
+ export declare interface RbacStore {
203
+ findRoleByName(name: string, guardName?: string): Promise<RoleRecord | null>
204
+ findRoleById(id: number): Promise<RoleRecord | null>
205
+ createRole(name: string, guardName?: string, description?: string): Promise<RoleRecord>
206
+ deleteRole(id: number): Promise<void>
207
+ getAllRoles(guardName?: string): Promise<RoleRecord[]>
208
+ findPermissionByName(name: string, guardName?: string): Promise<PermissionRecord | null>
209
+ findPermissionById(id: number): Promise<PermissionRecord | null>
210
+ createPermission(name: string, guardName?: string, description?: string): Promise<PermissionRecord>
211
+ deletePermission(id: number): Promise<void>
212
+ getAllPermissions(guardName?: string): Promise<PermissionRecord[]>
213
+ getUserRoles(userId: number): Promise<RoleRecord[]>
214
+ assignRoleToUser(userId: number, roleId: number): Promise<void>
215
+ removeRoleFromUser(userId: number, roleId: number): Promise<void>
216
+ removeAllRolesFromUser(userId: number): Promise<void>
217
+ syncUserRoles(userId: number, roleIds: number[]): Promise<void>
218
+ getUserDirectPermissions(userId: number): Promise<PermissionRecord[]>
219
+ assignPermissionToUser(userId: number, permissionId: number): Promise<void>
220
+ removePermissionFromUser(userId: number, permissionId: number): Promise<void>
221
+ removeAllPermissionsFromUser(userId: number): Promise<void>
222
+ syncUserPermissions(userId: number, permissionIds: number[]): Promise<void>
223
+ getRolePermissions(roleId: number): Promise<PermissionRecord[]>
224
+ assignPermissionToRole(roleId: number, permissionId: number): Promise<void>
225
+ removePermissionFromRole(roleId: number, permissionId: number): Promise<void>
226
+ syncRolePermissions(roleId: number, permissionIds: number[]): Promise<void>
227
+ }
228
+ // ─── Authorizable Mixin (add to user objects) ───────────────────
229
+ export declare interface RbacMethods {
230
+ hasRole(roleName: string, guardName?: string): Promise<boolean>
231
+ hasAnyRole(roleNames: string[], guardName?: string): Promise<boolean>
232
+ hasAllRoles(roleNames: string[], guardName?: string): Promise<boolean>
233
+ hasPermission(permissionName: string, guardName?: string): Promise<boolean>
234
+ hasAnyPermission(permissionNames: string[], guardName?: string): Promise<boolean>
235
+ hasAllPermissions(permissionNames: string[], guardName?: string): Promise<boolean>
236
+ getRoles(): Promise<RoleRecord[]>
237
+ getPermissions(): Promise<PermissionRecord[]>
238
+ assignRole(roleName: string, guardName?: string): Promise<void>
239
+ removeRole(roleName: string, guardName?: string): Promise<void>
240
+ syncRoles(roleNames: string[], guardName?: string): Promise<void>
241
+ givePermission(permissionName: string, guardName?: string): Promise<void>
242
+ revokePermission(permissionName: string, guardName?: string): Promise<void>
243
+ syncPermissions(permissionNames: string[], guardName?: string): Promise<void>
244
+ }
245
+ // Use the row/instance shape from orm so role helpers operate on the
246
+ // authenticated user object, not the User class constructor.
247
+ declare type UserModel = OrmUserModel;
248
+ /**
249
+ * FIFO-bounded Map. Wraps Map with a hard size cap; on overflow, the
250
+ * oldest entry (Map insertion order) is evicted. Used for the RBAC
251
+ * per-user caches because the previous unbounded `Map<number, ...>`
252
+ * grew without limit across the process lifetime — a long-running
253
+ * server serving many distinct users would OOM eventually
254
+ * (stacksjs/stacks#1860 M-5). Same shape as `BoundedMap` in
255
+ * `@stacksjs/router/stacks-router.ts`.
256
+ */
257
+ declare class BoundedMap<K, V> {
258
+ constructor(max: number);
259
+ get(key: K): V | undefined;
260
+ has(key: K): boolean;
261
+ set(key: K, value: V): this;
262
+ delete(key: K): boolean;
263
+ clear(): void;
264
+ }
265
+ export default Rbac;