@juspay/neurolink 9.31.1 → 9.32.0

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 (162) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/auth/AuthProviderFactory.d.ts +71 -0
  3. package/dist/auth/AuthProviderFactory.js +111 -0
  4. package/dist/auth/AuthProviderRegistry.d.ts +33 -0
  5. package/dist/auth/AuthProviderRegistry.js +190 -0
  6. package/dist/auth/RequestContext.d.ts +23 -0
  7. package/dist/auth/RequestContext.js +78 -0
  8. package/dist/auth/authContext.d.ts +198 -0
  9. package/dist/auth/authContext.js +314 -0
  10. package/dist/auth/errors.d.ts +63 -0
  11. package/dist/auth/errors.js +39 -0
  12. package/dist/auth/index.d.ts +20 -8
  13. package/dist/auth/index.js +35 -7
  14. package/dist/auth/middleware/AuthMiddleware.d.ts +181 -0
  15. package/dist/auth/middleware/AuthMiddleware.js +519 -0
  16. package/dist/auth/middleware/rateLimitByUser.d.ts +282 -0
  17. package/dist/auth/middleware/rateLimitByUser.js +554 -0
  18. package/dist/auth/providers/BaseAuthProvider.d.ts +259 -0
  19. package/dist/auth/providers/BaseAuthProvider.js +723 -0
  20. package/dist/auth/providers/CognitoProvider.d.ts +61 -0
  21. package/dist/auth/providers/CognitoProvider.js +304 -0
  22. package/dist/auth/providers/KeycloakProvider.d.ts +61 -0
  23. package/dist/auth/providers/KeycloakProvider.js +393 -0
  24. package/dist/auth/providers/auth0.d.ts +59 -0
  25. package/dist/auth/providers/auth0.js +274 -0
  26. package/dist/auth/providers/betterAuth.d.ts +51 -0
  27. package/dist/auth/providers/betterAuth.js +182 -0
  28. package/dist/auth/providers/clerk.d.ts +65 -0
  29. package/dist/auth/providers/clerk.js +317 -0
  30. package/dist/auth/providers/custom.d.ts +64 -0
  31. package/dist/auth/providers/custom.js +112 -0
  32. package/dist/auth/providers/firebase.d.ts +63 -0
  33. package/dist/auth/providers/firebase.js +226 -0
  34. package/dist/auth/providers/jwt.d.ts +68 -0
  35. package/dist/auth/providers/jwt.js +212 -0
  36. package/dist/auth/providers/oauth2.d.ts +73 -0
  37. package/dist/auth/providers/oauth2.js +303 -0
  38. package/dist/auth/providers/supabase.d.ts +63 -0
  39. package/dist/auth/providers/supabase.js +259 -0
  40. package/dist/auth/providers/workos.d.ts +61 -0
  41. package/dist/auth/providers/workos.js +284 -0
  42. package/dist/auth/serverBridge.d.ts +14 -0
  43. package/dist/auth/serverBridge.js +25 -0
  44. package/dist/auth/sessionManager.d.ts +142 -0
  45. package/dist/auth/sessionManager.js +437 -0
  46. package/dist/cli/commands/authProviders.d.ts +43 -0
  47. package/dist/cli/commands/authProviders.js +399 -0
  48. package/dist/cli/commands/proxy.js +4 -2
  49. package/dist/cli/factories/authCommandFactory.d.ts +23 -5
  50. package/dist/cli/factories/authCommandFactory.js +108 -5
  51. package/dist/cli/parser.js +1 -1
  52. package/dist/client/auth/AuthProviderFactory.js +111 -0
  53. package/dist/client/auth/AuthProviderRegistry.js +190 -0
  54. package/dist/client/auth/RequestContext.js +78 -0
  55. package/dist/client/auth/accountPool.js +178 -0
  56. package/dist/client/auth/authContext.js +314 -0
  57. package/dist/client/auth/errors.js +39 -0
  58. package/dist/client/auth/index.js +61 -0
  59. package/dist/client/auth/middleware/AuthMiddleware.js +519 -0
  60. package/dist/client/auth/middleware/rateLimitByUser.js +554 -0
  61. package/dist/client/auth/providers/BaseAuthProvider.js +723 -0
  62. package/dist/client/auth/providers/CognitoProvider.js +304 -0
  63. package/dist/client/auth/providers/KeycloakProvider.js +393 -0
  64. package/dist/client/auth/providers/auth0.js +274 -0
  65. package/dist/client/auth/providers/betterAuth.js +182 -0
  66. package/dist/client/auth/providers/clerk.js +317 -0
  67. package/dist/client/auth/providers/custom.js +112 -0
  68. package/dist/client/auth/providers/firebase.js +226 -0
  69. package/dist/client/auth/providers/jwt.js +212 -0
  70. package/dist/client/auth/providers/oauth2.js +303 -0
  71. package/dist/client/auth/providers/supabase.js +259 -0
  72. package/dist/client/auth/providers/workos.js +284 -0
  73. package/dist/client/auth/serverBridge.js +25 -0
  74. package/dist/client/auth/sessionManager.js +437 -0
  75. package/dist/client/core/infrastructure/baseRegistry.js +5 -1
  76. package/dist/client/index.js +25 -0
  77. package/dist/client/mcp/toolRegistry.js +11 -1
  78. package/dist/client/neurolink.js +218 -0
  79. package/dist/client/rag/ChunkerRegistry.js +2 -2
  80. package/dist/client/rag/metadata/MetadataExtractorRegistry.js +2 -2
  81. package/dist/client/rag/reranker/RerankerRegistry.js +2 -2
  82. package/dist/client/server/routes/agentRoutes.js +20 -2
  83. package/dist/client/types/authTypes.js +2 -1
  84. package/dist/core/infrastructure/baseRegistry.d.ts +3 -1
  85. package/dist/core/infrastructure/baseRegistry.js +5 -1
  86. package/dist/index.d.ts +1 -0
  87. package/dist/index.js +25 -0
  88. package/dist/lib/auth/AuthProviderFactory.d.ts +71 -0
  89. package/dist/lib/auth/AuthProviderFactory.js +112 -0
  90. package/dist/lib/auth/AuthProviderRegistry.d.ts +33 -0
  91. package/dist/lib/auth/AuthProviderRegistry.js +191 -0
  92. package/dist/lib/auth/RequestContext.d.ts +23 -0
  93. package/dist/lib/auth/RequestContext.js +79 -0
  94. package/dist/lib/auth/authContext.d.ts +198 -0
  95. package/dist/lib/auth/authContext.js +315 -0
  96. package/dist/lib/auth/errors.d.ts +63 -0
  97. package/dist/lib/auth/errors.js +40 -0
  98. package/dist/lib/auth/index.d.ts +20 -8
  99. package/dist/lib/auth/index.js +35 -7
  100. package/dist/lib/auth/middleware/AuthMiddleware.d.ts +181 -0
  101. package/dist/lib/auth/middleware/AuthMiddleware.js +520 -0
  102. package/dist/lib/auth/middleware/rateLimitByUser.d.ts +282 -0
  103. package/dist/lib/auth/middleware/rateLimitByUser.js +555 -0
  104. package/dist/lib/auth/providers/BaseAuthProvider.d.ts +259 -0
  105. package/dist/lib/auth/providers/BaseAuthProvider.js +724 -0
  106. package/dist/lib/auth/providers/CognitoProvider.d.ts +61 -0
  107. package/dist/lib/auth/providers/CognitoProvider.js +305 -0
  108. package/dist/lib/auth/providers/KeycloakProvider.d.ts +61 -0
  109. package/dist/lib/auth/providers/KeycloakProvider.js +394 -0
  110. package/dist/lib/auth/providers/auth0.d.ts +59 -0
  111. package/dist/lib/auth/providers/auth0.js +275 -0
  112. package/dist/lib/auth/providers/betterAuth.d.ts +51 -0
  113. package/dist/lib/auth/providers/betterAuth.js +183 -0
  114. package/dist/lib/auth/providers/clerk.d.ts +65 -0
  115. package/dist/lib/auth/providers/clerk.js +318 -0
  116. package/dist/lib/auth/providers/custom.d.ts +64 -0
  117. package/dist/lib/auth/providers/custom.js +113 -0
  118. package/dist/lib/auth/providers/firebase.d.ts +63 -0
  119. package/dist/lib/auth/providers/firebase.js +227 -0
  120. package/dist/lib/auth/providers/jwt.d.ts +68 -0
  121. package/dist/lib/auth/providers/jwt.js +213 -0
  122. package/dist/lib/auth/providers/oauth2.d.ts +73 -0
  123. package/dist/lib/auth/providers/oauth2.js +304 -0
  124. package/dist/lib/auth/providers/supabase.d.ts +63 -0
  125. package/dist/lib/auth/providers/supabase.js +260 -0
  126. package/dist/lib/auth/providers/workos.d.ts +61 -0
  127. package/dist/lib/auth/providers/workos.js +285 -0
  128. package/dist/lib/auth/serverBridge.d.ts +14 -0
  129. package/dist/lib/auth/serverBridge.js +26 -0
  130. package/dist/lib/auth/sessionManager.d.ts +142 -0
  131. package/dist/lib/auth/sessionManager.js +438 -0
  132. package/dist/lib/core/infrastructure/baseRegistry.d.ts +3 -1
  133. package/dist/lib/core/infrastructure/baseRegistry.js +5 -1
  134. package/dist/lib/index.d.ts +1 -0
  135. package/dist/lib/index.js +25 -0
  136. package/dist/lib/mcp/toolRegistry.js +11 -1
  137. package/dist/lib/neurolink.d.ts +42 -1
  138. package/dist/lib/neurolink.js +218 -0
  139. package/dist/lib/rag/ChunkerRegistry.js +2 -2
  140. package/dist/lib/rag/metadata/MetadataExtractorRegistry.js +2 -2
  141. package/dist/lib/rag/reranker/RerankerRegistry.js +2 -2
  142. package/dist/lib/server/routes/agentRoutes.js +20 -2
  143. package/dist/lib/types/authTypes.d.ts +937 -1
  144. package/dist/lib/types/authTypes.js +2 -1
  145. package/dist/lib/types/configTypes.d.ts +46 -0
  146. package/dist/lib/types/generateTypes.d.ts +6 -0
  147. package/dist/lib/types/index.d.ts +1 -0
  148. package/dist/lib/types/streamTypes.d.ts +6 -0
  149. package/dist/mcp/toolRegistry.js +11 -1
  150. package/dist/neurolink.d.ts +42 -1
  151. package/dist/neurolink.js +218 -0
  152. package/dist/rag/ChunkerRegistry.js +2 -2
  153. package/dist/rag/metadata/MetadataExtractorRegistry.js +2 -2
  154. package/dist/rag/reranker/RerankerRegistry.js +2 -2
  155. package/dist/server/routes/agentRoutes.js +20 -2
  156. package/dist/types/authTypes.d.ts +937 -1
  157. package/dist/types/authTypes.js +2 -1
  158. package/dist/types/configTypes.d.ts +46 -0
  159. package/dist/types/generateTypes.d.ts +6 -0
  160. package/dist/types/index.d.ts +1 -0
  161. package/dist/types/streamTypes.d.ts +6 -0
  162. package/package.json +2 -1
@@ -0,0 +1,438 @@
1
+ // src/lib/auth/sessionManager.ts
2
+ import { logger } from "../utils/logger.js";
3
+ /** Mask an identifier for safe logging: show first 4 chars + "***" */
4
+ function maskId(id) {
5
+ if (id.length <= 4) {
6
+ return "***";
7
+ }
8
+ return `${id.slice(0, 4)}***`;
9
+ }
10
+ /**
11
+ * In-memory session storage
12
+ *
13
+ * Simple session storage using Map. Suitable for single-instance deployments
14
+ * or development. Sessions are lost on restart.
15
+ */
16
+ export class MemorySessionStorage {
17
+ sessions = new Map();
18
+ userSessions = new Map();
19
+ async get(sessionId) {
20
+ const session = this.sessions.get(sessionId);
21
+ if (!session) {
22
+ return null;
23
+ }
24
+ // Check expiration
25
+ if (session.expiresAt && new Date() > session.expiresAt) {
26
+ await this.delete(sessionId);
27
+ return null;
28
+ }
29
+ return session;
30
+ }
31
+ async set(session) {
32
+ this.sessions.set(session.id, session);
33
+ // Track user's sessions
34
+ if (!this.userSessions.has(session.user.id)) {
35
+ this.userSessions.set(session.user.id, new Set());
36
+ }
37
+ this.userSessions.get(session.user.id).add(session.id);
38
+ }
39
+ async delete(sessionId) {
40
+ const session = this.sessions.get(sessionId);
41
+ if (session) {
42
+ const userSessionSet = this.userSessions.get(session.user.id);
43
+ if (userSessionSet) {
44
+ userSessionSet.delete(sessionId);
45
+ if (userSessionSet.size === 0) {
46
+ this.userSessions.delete(session.user.id);
47
+ }
48
+ }
49
+ this.sessions.delete(sessionId);
50
+ }
51
+ }
52
+ async getUserSessions(userId) {
53
+ const sessionIds = this.userSessions.get(userId);
54
+ if (!sessionIds) {
55
+ return [];
56
+ }
57
+ const sessions = [];
58
+ for (const sessionId of sessionIds) {
59
+ const session = await this.get(sessionId);
60
+ if (session) {
61
+ sessions.push(session);
62
+ }
63
+ }
64
+ return sessions;
65
+ }
66
+ async deleteUserSessions(userId) {
67
+ const sessionIds = this.userSessions.get(userId);
68
+ if (sessionIds) {
69
+ for (const sessionId of sessionIds) {
70
+ this.sessions.delete(sessionId);
71
+ }
72
+ this.userSessions.delete(userId);
73
+ }
74
+ }
75
+ async clear() {
76
+ this.sessions.clear();
77
+ this.userSessions.clear();
78
+ }
79
+ async isHealthy() {
80
+ return true;
81
+ }
82
+ }
83
+ /**
84
+ * Redis session storage
85
+ *
86
+ * Distributed session storage using Redis. Suitable for multi-instance
87
+ * deployments. Requires ioredis or similar Redis client.
88
+ *
89
+ * Note: Redis client must be provided or configured via environment.
90
+ */
91
+ export class RedisSessionStorage {
92
+ prefix;
93
+ ttl;
94
+ redisUrl;
95
+ client = null;
96
+ initPromise = null;
97
+ constructor(config) {
98
+ this.redisUrl = config.url;
99
+ this.prefix = config.prefix || "neurolink:sessions:";
100
+ this.ttl = config.ttl || 3600;
101
+ }
102
+ async getClient() {
103
+ if (this.client) {
104
+ return this.client;
105
+ }
106
+ if (!this.initPromise) {
107
+ this.initPromise = this.createClient();
108
+ }
109
+ return this.initPromise;
110
+ }
111
+ async createClient() {
112
+ try {
113
+ // Use variable indirection to prevent TypeScript from resolving the module at compile time
114
+ const moduleName = "ioredis";
115
+ const ioredis = await import(/* @vite-ignore */ moduleName);
116
+ const Redis = ioredis.default || ioredis.Redis;
117
+ this.client = new Redis(this.redisUrl);
118
+ return this.client;
119
+ }
120
+ catch {
121
+ this.initPromise = null;
122
+ logger.error('Redis client (ioredis) not available. Install ioredis package and ensure Redis is reachable when using storage: "redis".');
123
+ throw new Error("Redis client not available");
124
+ }
125
+ }
126
+ sessionKey(sessionId) {
127
+ return `${this.prefix}${sessionId}`;
128
+ }
129
+ userSessionsKey(userId) {
130
+ return `${this.prefix}user:${userId}`;
131
+ }
132
+ async get(sessionId) {
133
+ try {
134
+ const client = await this.getClient();
135
+ const data = await client.get(this.sessionKey(sessionId));
136
+ if (!data) {
137
+ return null;
138
+ }
139
+ const session = JSON.parse(data);
140
+ // Parse dates
141
+ session.createdAt = new Date(session.createdAt);
142
+ if (session.expiresAt !== null && session.expiresAt !== undefined) {
143
+ session.expiresAt = new Date(session.expiresAt);
144
+ }
145
+ // Check expiration
146
+ if (new Date() > session.expiresAt) {
147
+ await this.delete(sessionId);
148
+ return null;
149
+ }
150
+ return session;
151
+ }
152
+ catch (error) {
153
+ logger.error("Redis session get error:", error);
154
+ return null;
155
+ }
156
+ }
157
+ async set(session) {
158
+ try {
159
+ const client = await this.getClient();
160
+ // Calculate TTL from session expiration
161
+ const ttlSeconds = session.expiresAt
162
+ ? Math.max(1, Math.floor((session.expiresAt.getTime() - Date.now()) / 1000))
163
+ : this.ttl;
164
+ // Store session
165
+ await client.setex(this.sessionKey(session.id), ttlSeconds, JSON.stringify(session));
166
+ // Track user's sessions
167
+ await client.sadd(this.userSessionsKey(session.user.id), session.id);
168
+ await client.expire(this.userSessionsKey(session.user.id), this.ttl);
169
+ }
170
+ catch (error) {
171
+ logger.error("Redis session set error:", error);
172
+ throw error;
173
+ }
174
+ }
175
+ async delete(sessionId) {
176
+ try {
177
+ const client = await this.getClient();
178
+ // Read the raw session data directly instead of calling this.get(),
179
+ // which checks expiration and calls this.delete() — causing infinite
180
+ // recursion for expired sessions.
181
+ const data = await client.get(this.sessionKey(sessionId));
182
+ if (data) {
183
+ try {
184
+ const session = JSON.parse(data);
185
+ await client.srem(this.userSessionsKey(session.user.id), sessionId);
186
+ }
187
+ catch {
188
+ // If parsing fails, we still delete the key below
189
+ logger.warn(`Failed to parse session data for cleanup: ${maskId(sessionId)}`);
190
+ }
191
+ }
192
+ await client.del(this.sessionKey(sessionId));
193
+ }
194
+ catch (error) {
195
+ logger.error("Redis session delete error:", error);
196
+ }
197
+ }
198
+ async getUserSessions(userId) {
199
+ try {
200
+ const client = await this.getClient();
201
+ const sessionIds = await client.smembers(this.userSessionsKey(userId));
202
+ const sessions = [];
203
+ for (const sessionId of sessionIds) {
204
+ const session = await this.get(sessionId);
205
+ if (session) {
206
+ sessions.push(session);
207
+ }
208
+ }
209
+ return sessions;
210
+ }
211
+ catch (error) {
212
+ logger.error("Redis getUserSessions error:", error);
213
+ return [];
214
+ }
215
+ }
216
+ async deleteUserSessions(userId) {
217
+ try {
218
+ const client = await this.getClient();
219
+ const sessionIds = await client.smembers(this.userSessionsKey(userId));
220
+ for (const sessionId of sessionIds) {
221
+ await client.del(this.sessionKey(sessionId));
222
+ }
223
+ await client.del(this.userSessionsKey(userId));
224
+ }
225
+ catch (error) {
226
+ logger.error("Redis deleteUserSessions error:", error);
227
+ }
228
+ }
229
+ async clear() {
230
+ try {
231
+ const client = await this.getClient();
232
+ // Use SCAN instead of KEYS to avoid blocking Redis in production
233
+ let cursor = "0";
234
+ do {
235
+ const [nextCursor, keys] = await client.scan(cursor, "MATCH", `${this.prefix}*`, "COUNT", "100");
236
+ cursor = nextCursor;
237
+ if (keys.length > 0) {
238
+ await client.del(...keys);
239
+ }
240
+ } while (cursor !== "0");
241
+ }
242
+ catch (error) {
243
+ logger.error("Redis clear error:", error);
244
+ }
245
+ }
246
+ async isHealthy() {
247
+ try {
248
+ const client = await this.getClient();
249
+ const pong = await client.ping();
250
+ return pong === "PONG";
251
+ }
252
+ catch {
253
+ return false;
254
+ }
255
+ }
256
+ async disconnect() {
257
+ if (this.client) {
258
+ await this.client.quit();
259
+ this.client = null;
260
+ this.initPromise = null;
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * Session Manager
266
+ *
267
+ * High-level session management that handles session lifecycle,
268
+ * automatic refresh, and storage abstraction.
269
+ */
270
+ export class SessionManager {
271
+ storage;
272
+ config;
273
+ constructor(config = {}) {
274
+ this.config = {
275
+ ...config,
276
+ duration: config.duration || 3600,
277
+ autoRefresh: config.autoRefresh ?? true,
278
+ refreshThreshold: config.refreshThreshold || 300,
279
+ storage: config.storage || "memory",
280
+ };
281
+ // Initialize storage based on config
282
+ this.storage = this.createStorage();
283
+ }
284
+ createStorage() {
285
+ switch (this.config.storage) {
286
+ case "redis":
287
+ if (!this.config.redis?.url) {
288
+ logger.warn("Redis URL not provided, falling back to memory storage");
289
+ return new MemorySessionStorage();
290
+ }
291
+ return new RedisSessionStorage({
292
+ url: this.config.redis.url,
293
+ prefix: this.config.redis.prefix,
294
+ ttl: this.config.redis.ttl || this.config.duration,
295
+ });
296
+ case "memory":
297
+ default:
298
+ return new MemorySessionStorage();
299
+ }
300
+ }
301
+ /**
302
+ * Create a new session
303
+ */
304
+ async createSession(user, metadata) {
305
+ const sessionId = crypto.randomUUID();
306
+ const now = new Date();
307
+ const duration = this.config.duration || 3600;
308
+ const session = {
309
+ id: sessionId,
310
+ user,
311
+ createdAt: now,
312
+ expiresAt: new Date(now.getTime() + duration * 1000),
313
+ isValid: true,
314
+ ipAddress: metadata?.ipAddress,
315
+ userAgent: metadata?.userAgent,
316
+ deviceId: metadata?.deviceId,
317
+ };
318
+ await this.storage.set(session);
319
+ logger.debug(`Session created: ${maskId(sessionId)} for user: ${maskId(user.id)}`);
320
+ return session;
321
+ }
322
+ /**
323
+ * Get a session by ID
324
+ *
325
+ * Optionally auto-refreshes if close to expiration.
326
+ */
327
+ async getSession(sessionId, autoRefresh = this.config.autoRefresh) {
328
+ const session = await this.storage.get(sessionId);
329
+ if (!session) {
330
+ return null;
331
+ }
332
+ // Auto-refresh if close to expiration
333
+ if (autoRefresh && this.shouldRefresh(session)) {
334
+ return this.refreshSession(sessionId);
335
+ }
336
+ return session;
337
+ }
338
+ /**
339
+ * Check if session should be refreshed
340
+ */
341
+ shouldRefresh(session) {
342
+ if (!session.expiresAt) {
343
+ return false;
344
+ }
345
+ const threshold = this.config.refreshThreshold || 300;
346
+ const timeUntilExpiry = (session.expiresAt.getTime() - Date.now()) / 1000;
347
+ return timeUntilExpiry < threshold;
348
+ }
349
+ /**
350
+ * Refresh a session
351
+ */
352
+ async refreshSession(sessionId) {
353
+ const session = await this.storage.get(sessionId);
354
+ if (!session) {
355
+ return null;
356
+ }
357
+ const duration = this.config.duration || 3600;
358
+ session.expiresAt = new Date(Date.now() + duration * 1000);
359
+ await this.storage.set(session);
360
+ logger.debug(`Session refreshed: ${maskId(sessionId)}`);
361
+ return session;
362
+ }
363
+ /**
364
+ * Destroy a session
365
+ */
366
+ async destroySession(sessionId) {
367
+ await this.storage.delete(sessionId);
368
+ logger.debug(`Session destroyed: ${maskId(sessionId)}`);
369
+ }
370
+ /**
371
+ * Get all sessions for a user
372
+ */
373
+ async getUserSessions(userId) {
374
+ return this.storage.getUserSessions(userId);
375
+ }
376
+ /**
377
+ * Destroy all sessions for a user (global logout)
378
+ */
379
+ async destroyAllUserSessions(userId) {
380
+ await this.storage.deleteUserSessions(userId);
381
+ logger.debug(`All sessions destroyed for user: ${maskId(userId)}`);
382
+ }
383
+ /**
384
+ * Validate a session is still active
385
+ */
386
+ async validateSession(sessionId) {
387
+ const session = await this.storage.get(sessionId);
388
+ return session !== null && session.isValid;
389
+ }
390
+ /**
391
+ * Update session metadata
392
+ */
393
+ async updateSessionMetadata(sessionId, metadata) {
394
+ const session = await this.storage.get(sessionId);
395
+ if (!session) {
396
+ return null;
397
+ }
398
+ session.metadata = {
399
+ ...session.metadata,
400
+ ...metadata,
401
+ };
402
+ await this.storage.set(session);
403
+ return session;
404
+ }
405
+ /**
406
+ * Health check
407
+ */
408
+ async isHealthy() {
409
+ return this.storage.isHealthy();
410
+ }
411
+ /**
412
+ * Clear all sessions (for testing/cleanup)
413
+ */
414
+ async clear() {
415
+ await this.storage.clear();
416
+ }
417
+ }
418
+ /**
419
+ * Create session storage based on configuration
420
+ */
421
+ export function createSessionStorage(config) {
422
+ switch (config.storage) {
423
+ case "redis":
424
+ if (!config.redis?.url) {
425
+ logger.warn("Redis URL not provided, falling back to memory storage");
426
+ return new MemorySessionStorage();
427
+ }
428
+ return new RedisSessionStorage({
429
+ url: config.redis.url,
430
+ prefix: config.redis.prefix,
431
+ ttl: config.redis.ttl || config.duration,
432
+ });
433
+ case "memory":
434
+ default:
435
+ return new MemorySessionStorage();
436
+ }
437
+ }
438
+ //# sourceMappingURL=sessionManager.js.map
@@ -10,7 +10,9 @@ export declare abstract class BaseRegistry<TItem, TMetadata = unknown> {
10
10
  protected initPromise: Promise<void> | null;
11
11
  protected abstract registerAll(): Promise<void>;
12
12
  ensureInitialized(): Promise<void>;
13
- register(id: string, factory: () => Promise<TItem>, metadata: TMetadata): void;
13
+ register(id: string, factory: () => Promise<TItem>, aliases?: string[], options?: {
14
+ metadata: TMetadata;
15
+ }): void;
14
16
  get(id: string): Promise<TItem | undefined>;
15
17
  has(id: string): boolean;
16
18
  list(): Array<{
@@ -14,8 +14,12 @@ export class BaseRegistry {
14
14
  await this.initPromise;
15
15
  this.initialized = true;
16
16
  }
17
- register(id, factory, metadata) {
17
+ register(id, factory, aliases = [], options) {
18
+ const metadata = options?.metadata ?? {};
18
19
  this.items.set(id, { factory, metadata });
20
+ for (const alias of aliases) {
21
+ this.items.set(alias.toLowerCase(), { factory, metadata });
22
+ }
19
23
  logger.debug(`Registered ${id} in registry`);
20
24
  }
21
25
  async get(id) {
@@ -374,3 +374,4 @@ export { RAGASEvaluator } from "./evaluation/ragasEvaluator.js";
374
374
  export { RetryManager } from "./evaluation/retryManager.js";
375
375
  export { mapToEvaluationData } from "./evaluation/scoring.js";
376
376
  export type { EnhancedConversationTurn, EnhancedEvaluationContext, EvaluationConfig, EvaluationResult, GetPromptFunction, QualityErrorDetails, QueryIntentAnalysis, } from "./types/evaluationTypes.js";
377
+ export { AuthProviderFactory, createAuthProvider, AuthProviderRegistry, AuthError as AuthErrorFactory, AuthErrorCodes, BaseAuthProvider, InMemorySessionStorage, AuthProviderError, createAuthMiddleware as createAuthProviderMiddleware, createRBACMiddleware, createProtectedMiddleware, createExpressAuthMiddleware, createRequestContext, extractToken, AuthMiddlewareError, AuthMiddlewareErrorCodes, type MiddlewareHandler as AuthMiddlewareHandler, type MiddlewareResult, type NextFunction, type ExpressMiddleware, UserRateLimiter, MemoryRateLimitStorage, RedisRateLimitStorage, createRateLimitByUserMiddleware, createAuthenticatedRateLimitMiddleware, createRateLimitStorage, type RateLimitConfig as AuthRateLimitConfig, type RateLimitResult, type RateLimitMiddlewareResult, type RateLimitStorage, SessionManager, MemorySessionStorage, RedisSessionStorage, createSessionStorage, type SessionStorageInterface, AuthContextHolder, globalAuthContext, getAuthContext, getCurrentUser, getCurrentSession, isAuthenticated, hasRole, hasAnyRole, hasPermission, hasAllPermissions, requireAuth, requireRole, requirePermission, requireUser, runWithAuthContext, createAuthenticatedContext, RequestContext, NEUROLINK_RESOURCE_ID_KEY, NEUROLINK_THREAD_ID_KEY, createAuthValidatorFromProvider, } from "./auth/index.js";
package/dist/lib/index.js CHANGED
@@ -509,4 +509,29 @@ export { PromptBuilder } from "./evaluation/prompts.js";
509
509
  export { RAGASEvaluator } from "./evaluation/ragasEvaluator.js";
510
510
  export { RetryManager } from "./evaluation/retryManager.js";
511
511
  export { mapToEvaluationData } from "./evaluation/scoring.js";
512
+ // ============================================================================
513
+ // AUTHENTICATION PROVIDERS - Multi-provider Auth Integration
514
+ // ============================================================================
515
+ // Single-sourced from ./auth/index.js. Only aliases that differ from the
516
+ // canonical export name are listed explicitly; everything else is re-exported
517
+ // as-is.
518
+ export {
519
+ // Factory & Registry
520
+ AuthProviderFactory, createAuthProvider, AuthProviderRegistry,
521
+ // Unified error factory
522
+ AuthError as AuthErrorFactory, AuthErrorCodes,
523
+ // Base Provider
524
+ BaseAuthProvider, InMemorySessionStorage, AuthProviderError,
525
+ // Auth Middleware (aliased to avoid conflict with server createAuthMiddleware)
526
+ createAuthMiddleware as createAuthProviderMiddleware, createRBACMiddleware, createProtectedMiddleware, createExpressAuthMiddleware, createRequestContext, extractToken, AuthMiddlewareError, AuthMiddlewareErrorCodes,
527
+ // Rate Limiting Middleware
528
+ UserRateLimiter, MemoryRateLimitStorage, RedisRateLimitStorage, createRateLimitByUserMiddleware, createAuthenticatedRateLimitMiddleware, createRateLimitStorage,
529
+ // Session Management
530
+ SessionManager, MemorySessionStorage, RedisSessionStorage, createSessionStorage,
531
+ // Auth Context
532
+ AuthContextHolder, globalAuthContext, getAuthContext, getCurrentUser, getCurrentSession, isAuthenticated, hasRole, hasAnyRole, hasPermission, hasAllPermissions, requireAuth, requireRole, requirePermission, requireUser, runWithAuthContext, createAuthenticatedContext,
533
+ // Request Context
534
+ RequestContext, NEUROLINK_RESOURCE_ID_KEY, NEUROLINK_THREAD_ID_KEY,
535
+ // Server Bridge
536
+ createAuthValidatorFromProvider, } from "./auth/index.js";
512
537
  //# sourceMappingURL=index.js.map
@@ -11,6 +11,7 @@ import { detectCategory, createMCPServerInfo } from "../utils/mcpDefaults.js";
11
11
  import { FlexibleToolValidator } from "./flexibleToolValidator.js";
12
12
  import { HITLUserRejectedError, HITLTimeoutError } from "../hitl/hitlErrors.js";
13
13
  import { withSpan, tracers, ATTR } from "../telemetry/index.js";
14
+ import { getAuthContext } from "../auth/authContext.js";
14
15
  export class MCPToolRegistry extends MCPRegistry {
15
16
  tools = new Map();
16
17
  toolImplementations = new Map(); // Store actual tool implementations
@@ -290,11 +291,20 @@ export class MCPToolRegistry extends MCPRegistry {
290
291
  : "mcp";
291
292
  span.setAttribute("tool.type", toolType);
292
293
  span.setAttribute(ATTR.MCP_SERVER_ID, serverId);
294
+ // Try to get auth context if available
295
+ let authUserId;
296
+ try {
297
+ const authCtx = getAuthContext();
298
+ authUserId = authCtx?.user?.id;
299
+ }
300
+ catch {
301
+ // Auth context not available — that's fine
302
+ }
293
303
  // Create execution context if not provided
294
304
  const execContext = {
295
305
  ...context,
296
306
  sessionId: context?.sessionId ?? randomUUID(),
297
- userId: context?.userId,
307
+ userId: context?.userId ?? authUserId,
298
308
  };
299
309
  // Get the tool implementation using the resolved toolId
300
310
  const toolImpl = this.toolImplementations.get(toolId);
@@ -14,7 +14,8 @@ import { MCPToolRegistry } from "./mcp/toolRegistry.js";
14
14
  import type { MetricsSummary, TraceView } from "./observability/metricsAggregator.js";
15
15
  import type { SpanData } from "./observability/types/spanTypes.js";
16
16
  import type { JsonObject, NeuroLinkEvents, TypedEventEmitter } from "./types/common.js";
17
- import type { MCPEnhancementsConfig, NeurolinkConstructorConfig } from "./types/configTypes.js";
17
+ import type { AuthenticatedContext, MastraAuthProvider } from "./types/authTypes.js";
18
+ import type { MCPEnhancementsConfig, NeuroLinkAuthConfig, NeurolinkConstructorConfig } from "./types/configTypes.js";
18
19
  import type { ChatMessage } from "./types/conversation.js";
19
20
  import type { ExternalMCPOperationResult, ExternalMCPServerInstance, ExternalMCPToolInfo } from "./types/externalMcp.js";
20
21
  import type { GenerateOptions, GenerateResult } from "./types/generateTypes.js";
@@ -64,6 +65,9 @@ export declare class NeuroLink {
64
65
  private conversationMemoryNeedsInit;
65
66
  private conversationMemoryConfig?;
66
67
  private enableOrchestration;
68
+ private authProvider?;
69
+ private pendingAuthConfig?;
70
+ private authInitPromise?;
67
71
  private hitlManager?;
68
72
  private _sessionCostUsd;
69
73
  private fileRegistry;
@@ -1664,6 +1668,43 @@ export declare class NeuroLink {
1664
1668
  * Check if a session needs compaction.
1665
1669
  */
1666
1670
  needsCompaction(sessionId: string, provider?: string, model?: string): boolean;
1671
+ /**
1672
+ * Set the authentication provider for the NeuroLink instance
1673
+ *
1674
+ * @param config - Auth provider or configuration to create one
1675
+ */
1676
+ setAuthProvider(config: NeuroLinkAuthConfig): Promise<void>;
1677
+ /**
1678
+ * Get the currently configured authentication provider
1679
+ */
1680
+ getAuthProvider(): MastraAuthProvider | undefined;
1681
+ /**
1682
+ * Lazily initialize the auth provider from pendingAuthConfig.
1683
+ * Called on first use (generate/stream with auth token) to avoid
1684
+ * async work in the synchronous constructor.
1685
+ */
1686
+ private ensureAuthProvider;
1687
+ /**
1688
+ * Set the current authentication context for request handling.
1689
+ *
1690
+ * Delegates to the global AuthContextHolder so that auth state is NOT
1691
+ * stored as an instance field (which would leak between concurrent requests
1692
+ * sharing the same NeuroLink singleton). Prefer `runWithAuthContext()` from
1693
+ * `authContext.ts` for proper request-scoped context via AsyncLocalStorage.
1694
+ *
1695
+ * @param context - The authenticated user context
1696
+ */
1697
+ setAuthContext(context: AuthenticatedContext): Promise<void>;
1698
+ /**
1699
+ * Get the current authentication context.
1700
+ *
1701
+ * Checks AsyncLocalStorage first, then falls back to the global holder.
1702
+ */
1703
+ getAuthContext(): Promise<AuthenticatedContext | undefined>;
1704
+ /**
1705
+ * Clear the current authentication context
1706
+ */
1707
+ clearAuthContext(): Promise<void>;
1667
1708
  /**
1668
1709
  * Get the external server manager instance
1669
1710
  * Used internally by server adapters for external MCP server management