@plyaz/auth 1.0.1 → 1.0.3

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 (46) hide show
  1. package/commits.txt +2 -5
  2. package/dist/index.cjs +389 -15649
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.mjs +96 -139
  5. package/dist/index.mjs.map +1 -1
  6. package/package.json +3 -2
  7. package/release_message.txt +25 -0
  8. package/src/adapters/clerk/clerk.adapter.ts +1 -1
  9. package/src/adapters/next-auth/next-auth.adapter.ts +2 -2
  10. package/src/client/hooks/index.ts +5 -0
  11. package/src/client/hooks/useAuth.ts +4 -125
  12. package/src/client/hooks/useConnectedAccounts.ts +1 -13
  13. package/src/client/hooks/usePermissions.ts +6 -10
  14. package/src/client/hooks/useRBAC.ts +2 -8
  15. package/src/client/hooks/useSession.ts +4 -7
  16. package/src/client/index.ts +3 -0
  17. package/src/client/providers/AuthProvider.tsx +4 -89
  18. package/src/client/store/auth.store.ts +5 -72
  19. package/src/client/utils/createAuthContextValues.ts +66 -0
  20. package/src/client/utils/handleAuthAction.ts +29 -0
  21. package/src/core/blacklist/token.blacklist.ts +1 -5
  22. package/src/db/repositories/connected-account.repository.ts +11 -11
  23. package/src/db/repositories/user.repository.ts +20 -18
  24. package/src/flows/sign-in.flow.ts +1 -38
  25. package/src/flows/sign-up.flow.ts +11 -56
  26. package/src/index.ts +1 -8
  27. package/src/libs/supabase.helper.ts +8 -7
  28. package/src/providers/base/auth-provider.interface.ts +2 -21
  29. package/src/rbac/dynamic-roles.ts +22 -68
  30. package/src/rbac/permission-checker.ts +3 -32
  31. package/src/rbac/role-hierarchy.ts +0 -30
  32. package/src/server/decorators/current-user.decorator.ts +3 -2
  33. package/src/server/middleware/session.middleware.ts +1 -14
  34. package/src/server/services/auth.service.ts +16 -16
  35. package/src/server/services/session.service.ts +3 -4
  36. package/src/server/services/token.service.ts +3 -3
  37. package/src/session/cookie-store.ts +18 -18
  38. package/src/session/enhanced-session-manager.ts +2 -49
  39. package/src/session/redis-store.ts +2 -50
  40. package/src/strategies/oauth.strategy.ts +1 -8
  41. package/src/tokens/refresh-token-manager.ts +1 -100
  42. package/src/tokens/token-validator.ts +2 -46
  43. package/src/common/errors/auth.errors.ts +0 -64
  44. package/src/common/errors/specific-auth-errors.ts +0 -197
  45. package/src/common/types/auth.types.ts +0 -650
  46. package/src/common/types/index.ts +0 -303
@@ -1,11 +1,11 @@
1
1
  import { createClient } from "@supabase/supabase-js";
2
+
2
3
  import type {
3
4
  ConnectedAccount,
4
5
  ConnectedAccountRepository as IConnectedAccountRepository,
5
6
  CreateConnectedAccountData,
6
7
  UpdateConnectedAccountData,
7
- } from "@/common/types/auth.types";
8
-
8
+ } from "@plyaz/types";
9
9
  /**
10
10
  * Repository for managing connected accounts (provider account linking)
11
11
  *
@@ -98,7 +98,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
98
98
  */
99
99
  async findByProvider(
100
100
  provider: string,
101
- providerAccountId: string,
101
+ providerAccountId: string
102
102
  ): Promise<ConnectedAccount | null> {
103
103
  const { data, error } = await this.supabase
104
104
  .from("connected_accounts")
@@ -116,7 +116,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
116
116
  */
117
117
  async findByProviderAndId(
118
118
  provider: string,
119
- providerAccountId: string,
119
+ providerAccountId: string
120
120
  ): Promise<ConnectedAccount | null> {
121
121
  return this.findByProvider(provider, providerAccountId);
122
122
  }
@@ -127,7 +127,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
127
127
  async updateTokens(
128
128
  accountId: string,
129
129
  accessToken: string,
130
- refreshToken?: string,
130
+ refreshToken?: string
131
131
  ): Promise<void> {
132
132
  const updateData = {
133
133
  access_token_encrypted: accessToken,
@@ -158,7 +158,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
158
158
  */
159
159
  async update(
160
160
  id: string,
161
- data: UpdateConnectedAccountData,
161
+ data: UpdateConnectedAccountData
162
162
  ): Promise<ConnectedAccount> {
163
163
  const updateData = this.buildUpdateData(data);
164
164
 
@@ -244,7 +244,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
244
244
  async linkAccount(
245
245
  userId: string,
246
246
  provider: string,
247
- providerData: ConnectedAccount,
247
+ providerData: ConnectedAccount
248
248
  ): Promise<ConnectedAccount> {
249
249
  const accountData = {
250
250
  user_id: userId,
@@ -316,7 +316,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
316
316
  private emitAccountLinkedEvent(
317
317
  userId: string,
318
318
  provider: string,
319
- accountId: string,
319
+ accountId: string
320
320
  ): void {
321
321
  // Mock event emission - in real implementation would use event system
322
322
  globalThis.console.log("Event: auth.account.linked", {
@@ -337,7 +337,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
337
337
  private emitAccountUnlinkedEvent(
338
338
  userId: string,
339
339
  provider: string,
340
- accountId: string,
340
+ accountId: string
341
341
  ): void {
342
342
  // Mock event emission - in real implementation would use event system
343
343
  globalThis.console.log("Event: auth.account.unlinked", {
@@ -353,7 +353,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
353
353
  * @private
354
354
  */
355
355
  private transformToDbFormat(
356
- data: CreateConnectedAccountData,
356
+ data: CreateConnectedAccountData
357
357
  ): Record<
358
358
  string,
359
359
  string | undefined | Record<string, unknown> | Date | boolean
@@ -388,7 +388,7 @@ export class ConnectedAccountRepository implements IConnectedAccountRepository {
388
388
  * @private
389
389
  */
390
390
  private buildUpdateData(
391
- data: UpdateConnectedAccountData,
391
+ data: UpdateConnectedAccountData
392
392
  ): Record<string, string> {
393
393
  const result: Record<string, string> = {
394
394
  updated_at: new Date().toString(),
@@ -1,11 +1,13 @@
1
1
  import { createClient } from "@supabase/supabase-js";
2
+
2
3
  import type {
3
- User,
4
+ AUTHPROVIDER,
5
+ AuthUser,
4
6
  UserRepository as IUserRepository,
5
7
  CreateUserData,
6
8
  UpdateUserData,
7
- } from "@/common/types/auth.types";
8
- import type { AUTHPROVIDER, AuthUser } from "@plyaz/types";
9
+ UserInfo,
10
+ } from "@plyaz/types";
9
11
  /**
10
12
  * Repository for managing user accounts
11
13
  *
@@ -35,7 +37,7 @@ export class UserRepository implements IUserRepository {
35
37
  constructor(
36
38
  supabaseUrl: string,
37
39
  supabaseKey: string,
38
- private schema: "public" | "backoffice" = "public",
40
+ private schema: "public" | "backoffice" = "public"
39
41
  ) {
40
42
  this.supabase = createClient(supabaseUrl, supabaseKey);
41
43
  }
@@ -45,7 +47,7 @@ export class UserRepository implements IUserRepository {
45
47
  * @param id - User UUID
46
48
  * @returns Promise resolving to User or null if not found
47
49
  */
48
- async findById(id: string): Promise<User | null> {
50
+ async findById(id: string): Promise<UserInfo | null> {
49
51
  const { data, error } = await this.supabase
50
52
  .from("users")
51
53
  .select("*")
@@ -60,7 +62,7 @@ export class UserRepository implements IUserRepository {
60
62
  * @param email - User email address
61
63
  * @returns Promise resolving to User or null if not found
62
64
  */
63
- async findByEmail(email: string): Promise<User | null> {
65
+ async findByEmail(email: string): Promise<UserInfo | null> {
64
66
  const { data, error } = await this.supabase
65
67
  .from("users")
66
68
  .select("*")
@@ -79,8 +81,8 @@ export class UserRepository implements IUserRepository {
79
81
  */
80
82
  async findByProviderAccount(
81
83
  provider: string,
82
- providerAccountId: string,
83
- ): Promise<User | null> {
84
+ providerAccountId: string
85
+ ): Promise<UserInfo | null> {
84
86
  const { data: accountData, error: accountError } = await this.supabase
85
87
  .from("connected_accounts")
86
88
  .select("user_id")
@@ -97,7 +99,7 @@ export class UserRepository implements IUserRepository {
97
99
  * @returns Promise resolving to created User
98
100
  * @throws Error if creation fails
99
101
  */
100
- async create(data: CreateUserData): Promise<User> {
102
+ async create(data: CreateUserData): Promise<UserInfo> {
101
103
  const insertData = this.transformToDbFormat(data);
102
104
  const { data: userData, error } = await this.supabase
103
105
  .from("users")
@@ -117,7 +119,7 @@ export class UserRepository implements IUserRepository {
117
119
  * @returns Promise resolving to updated User
118
120
  * @throws Error if update fails
119
121
  */
120
- async update(id: string, data: UpdateUserData): Promise<User> {
122
+ async update(id: string, data: UpdateUserData): Promise<UserInfo> {
121
123
  const updateData = this.buildUpdateData(data);
122
124
  const { data: userData, error } = await this.supabase
123
125
  .from("users")
@@ -145,8 +147,8 @@ export class UserRepository implements IUserRepository {
145
147
  */
146
148
  async findByCredentials(
147
149
  email: string,
148
- passwordHash: string,
149
- ): Promise<User | null> {
150
+ passwordHash: string
151
+ ): Promise<UserInfo | null> {
150
152
  const { data, error } = await this.supabase
151
153
  .from("users")
152
154
  .select("*")
@@ -162,7 +164,7 @@ export class UserRepository implements IUserRepository {
162
164
  async assignRole(
163
165
  userId: string,
164
166
  role: string,
165
- assignedBy?: string,
167
+ assignedBy?: string
166
168
  ): Promise<void> {
167
169
  const { error } = await this.supabase.from("user_roles").insert({
168
170
  user_id: userId,
@@ -219,7 +221,7 @@ export class UserRepository implements IUserRepository {
219
221
  * @param clerkId - Clerk user identifier
220
222
  * @returns User or null if not found
221
223
  */
222
- async findByClerkId(clerkId: string): Promise<User | null> {
224
+ async findByClerkId(clerkId: string): Promise<UserInfo | null> {
223
225
  const { data, error } = await this.supabase
224
226
  .from("users")
225
227
  .select("*")
@@ -234,7 +236,7 @@ export class UserRepository implements IUserRepository {
234
236
  * @param address - Wallet address
235
237
  * @returns User or null if not found
236
238
  */
237
- async findByWalletAddress(address: string): Promise<User | null> {
239
+ async findByWalletAddress(address: string): Promise<UserInfo | null> {
238
240
  const { data: accountData, error: accountError } = await this.supabase
239
241
  .from("connected_accounts")
240
242
  .select("user_id")
@@ -252,7 +254,7 @@ export class UserRepository implements IUserRepository {
252
254
  * @param status - Onboarding status ('completed' | 'pending' | 'skipped')
253
255
  * @returns Updated user
254
256
  */
255
- async updateOnboardingStatus(userId: string, status: string): Promise<User> {
257
+ async updateOnboardingStatus(userId: string, status: string): Promise<UserInfo> {
256
258
  const updateData: Partial<AuthUser> = {
257
259
  updatedAt: new Date(),
258
260
  };
@@ -274,7 +276,7 @@ export class UserRepository implements IUserRepository {
274
276
  * @private
275
277
  */
276
278
  private transformToDbFormat(
277
- data: CreateUserData,
279
+ data: CreateUserData
278
280
  ): Record<string, string | AUTHPROVIDER | undefined> {
279
281
  return {
280
282
  email: data.email,
@@ -313,7 +315,7 @@ export class UserRepository implements IUserRepository {
313
315
  * Map database row to User interface
314
316
  * @private
315
317
  */
316
- private mapToUser(data: User): User {
318
+ private mapToUser(data: UserInfo): UserInfo {
317
319
  return {
318
320
  id: data.id,
319
321
  email: data.email,
@@ -4,46 +4,9 @@
4
4
  */
5
5
 
6
6
  import { NUMERIX } from "@plyaz/config";
7
- import type { AuthTokens, AuthUser } from "@plyaz/types";
7
+ import type { JWTManagerSignin, PasswordServiceSignin, SessionManagerSignin, SignInCredentials, SignInResult, UserRepositorySignin } from "@plyaz/types";
8
8
 
9
- export interface SignInCredentials {
10
- email: string;
11
- password: string;
12
- rememberMe?: boolean;
13
- }
14
-
15
- export interface SignInResult {
16
- user: AuthUser;
17
- tokens: AuthTokens;
18
- requiresMFA?: boolean;
19
- mfaToken?: string;
20
- }
21
-
22
- /** User repository type based on usage */
23
- export interface UserRepositorySignin {
24
- findByEmail(email: string): Promise<AuthUser | null>;
25
- findById(userId: string): Promise<AuthUser | null>;
26
- }
27
9
 
28
- /** JWT manager type based on usage */
29
- export interface JWTManagerSignin {
30
- generateTokens(userId: string): Promise<AuthTokens>;
31
- verifyToken(token: string): Promise<{ userId: string }>;
32
- }
33
-
34
- /** Session manager type based on usage */
35
- export interface SessionManagerSignin {
36
- createSession(session: {
37
- userId: string;
38
- expiresAt: Date;
39
- metadata?: Record<string, true>;
40
- }): Promise<void>;
41
- }
42
-
43
- /** Password service type based on usage */
44
- export interface PasswordServiceSignin {
45
- verify(password: string, passwordHash: string | undefined): Promise<boolean>;
46
- }
47
10
 
48
11
  export class SignInFlow {
49
12
  constructor(
@@ -3,67 +3,22 @@
3
3
  * @module @plyaz/auth/flows/sign-up
4
4
  */
5
5
 
6
- import type { AuthTokens, AuthUser } from "@plyaz/types";
7
-
8
- export interface SignUpData {
9
- email: string;
10
- password: string;
11
- firstName?: string;
12
- lastName?: string;
13
- metadata?: Record<string, string>;
14
- }
15
-
16
- export interface SignUpResult {
17
- user: AuthUser;
18
- tokens: AuthTokens;
19
- requiresVerification?: boolean;
20
- }
21
-
22
- /** User repository type based on usage */
23
- export interface UserRepositorySignUp {
24
- findByEmail(email: string): Promise<AuthUser | null>;
25
- create(data: {
26
- email: string;
27
- passwordHash: string;
28
- firstName?: string;
29
- lastName?: string;
30
- metadata?: Record<string, string>;
31
- emailVerified: boolean;
32
- }): Promise<AuthUser>;
33
- findById(userId: string): Promise<AuthUser>;
34
- updateEmailVerification(
35
- userId: string,
36
- verified: boolean,
37
- ): Promise<AuthUser | null>;
38
- }
39
-
40
- /** JWT manager type based on usage */
41
- export interface JWTManagerSignUp {
42
- generateTokens(userId: string): Promise<AuthTokens>;
43
- generateVerificationToken(userId: string): Promise<string>;
44
- verifyToken(token: string): Promise<{ userId: string }>;
45
- }
46
-
47
- /** Password service type based on usage */
48
- export interface PasswordServiceSignUp {
49
- hash(password: string): Promise<string>;
50
- }
51
-
52
- /** Email service type based on usage */
53
- export interface EmailService {
54
- sendVerificationEmail(args: {
55
- to: string;
56
- token: string;
57
- userId: string;
58
- }): Promise<void>;
59
- }
6
+ import type {
7
+ AuthUser,
8
+ EmailService,
9
+ JWTManagerSignUp,
10
+ PasswordServiceSignUp,
11
+ SignUpData,
12
+ SignUpResult,
13
+ UserRepositorySignUp,
14
+ } from "@plyaz/types";
60
15
 
61
16
  export class SignUpFlow {
62
17
  constructor(
63
18
  private userRepository: UserRepositorySignUp,
64
19
  private jwtManager: JWTManagerSignUp,
65
20
  private passwordService: PasswordServiceSignUp,
66
- private emailService: EmailService,
21
+ private emailService: EmailService
67
22
  ) {}
68
23
 
69
24
  async execute(data: SignUpData): Promise<SignUpResult> {
@@ -120,7 +75,7 @@ export class SignUpFlow {
120
75
  const payload = await this.jwtManager.verifyToken(token);
121
76
  const user = await this.userRepository.updateEmailVerification(
122
77
  payload.userId,
123
- true,
78
+ true
124
79
  );
125
80
 
126
81
  if (!user) {
package/src/index.ts CHANGED
@@ -43,11 +43,4 @@ export {
43
43
  export * from "./server/middleware";
44
44
 
45
45
  // Frontend (React)
46
- export { AuthProvider } from "./client/providers/AuthProvider";
47
- export { useAuth } from "./client/hooks/useAuth";
48
- export { useSession } from "./client/hooks/useSession";
49
- export { useRBAC } from "./client/hooks/useRBAC";
50
- export { useConnectedAccounts } from "./client/hooks/useConnectedAccounts";
51
- export { usePermissions } from "./client/hooks/usePermissions";
52
- export { useAuthStore } from "./client/store/auth.store";
53
- export { ProtectedRoute } from "./client/components/ProtectedRoute";
46
+ export * from "./client"
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ AuthDeviceInfo,
2
3
  AUTHPROVIDER,
3
4
  AuthUser,
4
5
  ConnectedAccount,
@@ -10,12 +11,12 @@ import { randomBytes } from "crypto";
10
11
  import { supabase } from "./supabaseClient";
11
12
  import { NUMERIX } from "@plyaz/config";
12
13
 
13
- export interface DeviceInfo {
14
- ip: string;
15
- browser: string;
16
- os: string;
17
- userAgent: string;
18
- }
14
+ // export interface DeviceInfo {
15
+ // ip: string;
16
+ // browser: string;
17
+ // os: string;
18
+ // userAgent: string;
19
+ // }
19
20
 
20
21
  /**
21
22
  * Create a new user
@@ -86,7 +87,7 @@ export async function updateLastLogin(userId: string): Promise<void> {
86
87
  */
87
88
  export async function createUserSession(
88
89
  userId: string,
89
- deviceInfo: DeviceInfo,
90
+ deviceInfo: AuthDeviceInfo,
90
91
  ): Promise<Session & { accessToken: string }> {
91
92
  const thirtyTwo = 32;
92
93
  const accessToken = randomBytes(thirtyTwo).toString("hex");
@@ -3,29 +3,10 @@
3
3
  * @module @plyaz/auth/providers/base/auth-provider
4
4
  */
5
5
 
6
- import type { AuthTokens, AuthUser } from "@plyaz/types";
6
+ import type { AuthenticationProvider, AuthProviderConfig, AuthTokens, AuthUser } from "@plyaz/types";
7
7
 
8
- export interface AuthProviderConfig {
9
- clientId: string;
10
- clientSecret: string;
11
- redirectUri: string;
12
- scopes?: string[];
13
- }
14
-
15
- export interface AuthProvider {
16
- readonly name: string;
17
- readonly type: "oauth" | "traditional" | "web3";
18
-
19
- initialize(config: AuthProviderConfig): Promise<void>;
20
- authenticate(credentials: {
21
- code: string;
22
- }): Promise<{ user: AuthUser; tokens: AuthTokens }>;
23
- refreshToken(refreshToken: string): Promise<AuthTokens>;
24
- revokeToken(token: string): Promise<void>;
25
- getUserProfile(accessToken: string): Promise<AuthUser>;
26
- }
27
8
 
28
- export abstract class BaseAuthProvider implements AuthProvider {
9
+ export abstract class BaseAuthProvider implements AuthenticationProvider {
29
10
  abstract readonly name: string;
30
11
  abstract readonly type: "oauth" | "traditional" | "web3";
31
12
 
@@ -24,58 +24,12 @@
24
24
  */
25
25
 
26
26
  import { NUMERIX } from "@plyaz/config";
27
- import { AUTH_EVENTS } from "@plyaz/types";
28
-
29
- /**
30
- * Dynamic role assignment
31
- */
32
- export interface DynamicRoleAssignment {
33
- /** Assignment ID */
34
- id: string;
35
- /** User ID */
36
- userId: string;
37
- /** Role ID or name */
38
- roleId: string;
39
- /** Assignment conditions */
40
- conditions?: Record<string, string>;
41
- /** Assignment expiration */
42
- expiresAt?: Date;
43
- /** Assignment reason */
44
- reason?: string;
45
- /** Assigned by user ID */
46
- assignedBy?: string;
47
- /** Assignment metadata */
48
- metadata?: Record<string, string>;
49
- /** Created at */
50
- createdAt: Date;
51
- /** Is active */
52
- isActive: boolean;
53
- }
54
-
55
- /**
56
- * Role condition evaluator function
57
- */
58
- export type RoleConditionEvaluator = (
59
- userId: string,
60
- conditions: Record<string, string>,
61
- context?: Record<string, string>,
62
- ) => Promise<boolean>;
63
-
64
- /**
65
- * Dynamic roles configuration
66
- */
67
- export interface DynamicRolesConfig {
68
- /** Enable role expiration */
69
- enableExpiration: boolean;
70
- /** Default role TTL in seconds */
71
- defaultTTL: number;
72
- /** Enable condition evaluation */
73
- enableConditions: boolean;
74
- /** Maximum assignments per user */
75
- maxAssignmentsPerUser: number;
76
- /** Enable audit logging */
77
- enableAuditLog: boolean;
78
- }
27
+ import {
28
+ AUTH_EVENTS,
29
+ type DynamicRolesConfig,
30
+ type DynamicRoleAssignment,
31
+ type RoleConditionEvaluator,
32
+ } from "@plyaz/types";
79
33
 
80
34
  /**
81
35
  * Dynamic roles manager implementation
@@ -124,7 +78,7 @@ export class DynamicRoles {
124
78
  conditions?: Record<string, string>,
125
79
  expiresAt?: Date,
126
80
  assignedBy?: string,
127
- reason?: string,
81
+ reason?: string
128
82
  ): Promise<string> {
129
83
  // Check assignment limits
130
84
  await this.enforceAssignmentLimits(userId);
@@ -183,7 +137,7 @@ export class DynamicRoles {
183
137
  conditions?: Record<string, string>,
184
138
  duration: number = this.config.defaultTTL,
185
139
  assignedBy?: string,
186
- reason?: string,
140
+ reason?: string
187
141
  ): Promise<string> {
188
142
  const expiresAt = new Date(Date.now() + duration * NUMERIX.THOUSAND);
189
143
 
@@ -193,7 +147,7 @@ export class DynamicRoles {
193
147
  conditions,
194
148
  expiresAt,
195
149
  assignedBy,
196
- reason ?? "Temporary assignment",
150
+ reason ?? "Temporary assignment"
197
151
  );
198
152
  }
199
153
 
@@ -206,7 +160,7 @@ export class DynamicRoles {
206
160
  async revokeAssignment(
207
161
  assignmentId: string,
208
162
  revokedBy?: string,
209
- reason?: string,
163
+ reason?: string
210
164
  ): Promise<void> {
211
165
  const assignment = this.assignments.get(assignmentId);
212
166
 
@@ -244,7 +198,7 @@ export class DynamicRoles {
244
198
  async revokeAllUserAssignments(
245
199
  userId: string,
246
200
  revokedBy?: string,
247
- reason?: string,
201
+ reason?: string
248
202
  ): Promise<void> {
249
203
  const userAssignmentSet = this.userAssignments.get(userId);
250
204
 
@@ -267,7 +221,7 @@ export class DynamicRoles {
267
221
  */
268
222
  async getUserRoles(
269
223
  userId: string,
270
- context?: Record<string, string>,
224
+ context?: Record<string, string>
271
225
  ): Promise<string[]> {
272
226
  const userAssignmentSet = this.userAssignments.get(userId);
273
227
 
@@ -296,7 +250,7 @@ export class DynamicRoles {
296
250
  const conditionsMet = await this.evaluateConditions(
297
251
  userId,
298
252
  assignment.conditions,
299
- context,
253
+ context
300
254
  );
301
255
 
302
256
  if (!conditionsMet) {
@@ -320,7 +274,7 @@ export class DynamicRoles {
320
274
  async hasRole(
321
275
  userId: string,
322
276
  roleId: string,
323
- context?: Record<string, string>,
277
+ context?: Record<string, string>
324
278
  ): Promise<boolean> {
325
279
  const userRoles = await this.getUserRoles(userId, context);
326
280
  return userRoles.includes(roleId);
@@ -343,7 +297,7 @@ export class DynamicRoles {
343
297
  */
344
298
  getUserAssignments(
345
299
  userId: string,
346
- includeInactive = false,
300
+ includeInactive = false
347
301
  ): DynamicRoleAssignment[] {
348
302
  const userAssignmentSet = this.userAssignments.get(userId);
349
303
 
@@ -371,7 +325,7 @@ export class DynamicRoles {
371
325
  */
372
326
  registerConditionEvaluator(
373
327
  conditionType: string,
374
- evaluator: RoleConditionEvaluator,
328
+ evaluator: RoleConditionEvaluator
375
329
  ): void {
376
330
  this.conditionEvaluators.set(conditionType, evaluator);
377
331
  }
@@ -383,7 +337,7 @@ export class DynamicRoles {
383
337
  */
384
338
  async extendAssignment(
385
339
  assignmentId: string,
386
- newExpiresAt: Date,
340
+ newExpiresAt: Date
387
341
  ): Promise<void> {
388
342
  const assignment = this.assignments.get(assignmentId);
389
343
 
@@ -482,7 +436,7 @@ export class DynamicRoles {
482
436
  private async evaluateConditions(
483
437
  userId: string,
484
438
  conditions: Record<string, string>,
485
- context?: Record<string, string>,
439
+ context?: Record<string, string>
486
440
  ): Promise<boolean> {
487
441
  for (const [conditionType, conditionValue] of Object.entries(conditions)) {
488
442
  const evaluator = this.conditionEvaluators.get(conditionType);
@@ -491,7 +445,7 @@ export class DynamicRoles {
491
445
  const result = await evaluator(
492
446
  userId,
493
447
  { [conditionType]: conditionValue },
494
- context,
448
+ context
495
449
  );
496
450
  if (!result) {
497
451
  return false;
@@ -517,7 +471,7 @@ export class DynamicRoles {
517
471
 
518
472
  if (userAssignments.length >= this.config.maxAssignmentsPerUser) {
519
473
  throw new Error(
520
- `Maximum assignments per user exceeded: ${this.config.maxAssignmentsPerUser}`,
474
+ `Maximum assignments per user exceeded: ${this.config.maxAssignmentsPerUser}`
521
475
  );
522
476
  }
523
477
  }
@@ -541,7 +495,7 @@ export class DynamicRoles {
541
495
  async () => {
542
496
  await this.cleanupExpiredAssignments();
543
497
  },
544
- NUMERIX.FIVE * NUMERIX.SIXTY * NUMERIX.THOUSAND,
498
+ NUMERIX.FIVE * NUMERIX.SIXTY * NUMERIX.THOUSAND
545
499
  );
546
500
  }
547
501
 
@@ -571,7 +525,7 @@ export class DynamicRoles {
571
525
  private emitRoleRevokedEvent(
572
526
  assignment: DynamicRoleAssignment,
573
527
  revokedBy?: string,
574
- reason?: string,
528
+ reason?: string
575
529
  ): void {
576
530
  // Mock event emission - in real implementation would use event system
577
531
  globalThis.console.log(`Event: ${AUTH_EVENTS.ROLE_REVOKED}`, {