kailash 0.3.1__py3-none-any.whl → 0.4.0__py3-none-any.whl

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 (146) hide show
  1. kailash/__init__.py +33 -1
  2. kailash/access_control/__init__.py +129 -0
  3. kailash/access_control/managers.py +461 -0
  4. kailash/access_control/rule_evaluators.py +467 -0
  5. kailash/access_control_abac.py +825 -0
  6. kailash/config/__init__.py +27 -0
  7. kailash/config/database_config.py +359 -0
  8. kailash/database/__init__.py +28 -0
  9. kailash/database/execution_pipeline.py +499 -0
  10. kailash/middleware/__init__.py +306 -0
  11. kailash/middleware/auth/__init__.py +33 -0
  12. kailash/middleware/auth/access_control.py +436 -0
  13. kailash/middleware/auth/auth_manager.py +422 -0
  14. kailash/middleware/auth/jwt_auth.py +477 -0
  15. kailash/middleware/auth/kailash_jwt_auth.py +616 -0
  16. kailash/middleware/communication/__init__.py +37 -0
  17. kailash/middleware/communication/ai_chat.py +989 -0
  18. kailash/middleware/communication/api_gateway.py +802 -0
  19. kailash/middleware/communication/events.py +470 -0
  20. kailash/middleware/communication/realtime.py +710 -0
  21. kailash/middleware/core/__init__.py +21 -0
  22. kailash/middleware/core/agent_ui.py +890 -0
  23. kailash/middleware/core/schema.py +643 -0
  24. kailash/middleware/core/workflows.py +396 -0
  25. kailash/middleware/database/__init__.py +63 -0
  26. kailash/middleware/database/base.py +113 -0
  27. kailash/middleware/database/base_models.py +525 -0
  28. kailash/middleware/database/enums.py +106 -0
  29. kailash/middleware/database/migrations.py +12 -0
  30. kailash/{api/database.py → middleware/database/models.py} +183 -291
  31. kailash/middleware/database/repositories.py +685 -0
  32. kailash/middleware/database/session_manager.py +19 -0
  33. kailash/middleware/mcp/__init__.py +38 -0
  34. kailash/middleware/mcp/client_integration.py +585 -0
  35. kailash/middleware/mcp/enhanced_server.py +576 -0
  36. kailash/nodes/__init__.py +25 -3
  37. kailash/nodes/admin/__init__.py +35 -0
  38. kailash/nodes/admin/audit_log.py +794 -0
  39. kailash/nodes/admin/permission_check.py +864 -0
  40. kailash/nodes/admin/role_management.py +823 -0
  41. kailash/nodes/admin/security_event.py +1519 -0
  42. kailash/nodes/admin/user_management.py +944 -0
  43. kailash/nodes/ai/a2a.py +24 -7
  44. kailash/nodes/ai/ai_providers.py +1 -0
  45. kailash/nodes/ai/embedding_generator.py +11 -11
  46. kailash/nodes/ai/intelligent_agent_orchestrator.py +99 -11
  47. kailash/nodes/ai/llm_agent.py +407 -2
  48. kailash/nodes/ai/self_organizing.py +85 -10
  49. kailash/nodes/api/auth.py +287 -6
  50. kailash/nodes/api/rest.py +151 -0
  51. kailash/nodes/auth/__init__.py +17 -0
  52. kailash/nodes/auth/directory_integration.py +1228 -0
  53. kailash/nodes/auth/enterprise_auth_provider.py +1328 -0
  54. kailash/nodes/auth/mfa.py +2338 -0
  55. kailash/nodes/auth/risk_assessment.py +872 -0
  56. kailash/nodes/auth/session_management.py +1093 -0
  57. kailash/nodes/auth/sso.py +1040 -0
  58. kailash/nodes/base.py +344 -13
  59. kailash/nodes/base_cycle_aware.py +4 -2
  60. kailash/nodes/base_with_acl.py +1 -1
  61. kailash/nodes/code/python.py +293 -12
  62. kailash/nodes/compliance/__init__.py +9 -0
  63. kailash/nodes/compliance/data_retention.py +1888 -0
  64. kailash/nodes/compliance/gdpr.py +2004 -0
  65. kailash/nodes/data/__init__.py +22 -2
  66. kailash/nodes/data/async_connection.py +469 -0
  67. kailash/nodes/data/async_sql.py +757 -0
  68. kailash/nodes/data/async_vector.py +598 -0
  69. kailash/nodes/data/readers.py +767 -0
  70. kailash/nodes/data/retrieval.py +360 -1
  71. kailash/nodes/data/sharepoint_graph.py +397 -21
  72. kailash/nodes/data/sql.py +94 -5
  73. kailash/nodes/data/streaming.py +68 -8
  74. kailash/nodes/data/vector_db.py +54 -4
  75. kailash/nodes/enterprise/__init__.py +13 -0
  76. kailash/nodes/enterprise/batch_processor.py +741 -0
  77. kailash/nodes/enterprise/data_lineage.py +497 -0
  78. kailash/nodes/logic/convergence.py +31 -9
  79. kailash/nodes/logic/operations.py +14 -3
  80. kailash/nodes/mixins/__init__.py +8 -0
  81. kailash/nodes/mixins/event_emitter.py +201 -0
  82. kailash/nodes/mixins/mcp.py +9 -4
  83. kailash/nodes/mixins/security.py +165 -0
  84. kailash/nodes/monitoring/__init__.py +7 -0
  85. kailash/nodes/monitoring/performance_benchmark.py +2497 -0
  86. kailash/nodes/rag/__init__.py +284 -0
  87. kailash/nodes/rag/advanced.py +1615 -0
  88. kailash/nodes/rag/agentic.py +773 -0
  89. kailash/nodes/rag/conversational.py +999 -0
  90. kailash/nodes/rag/evaluation.py +875 -0
  91. kailash/nodes/rag/federated.py +1188 -0
  92. kailash/nodes/rag/graph.py +721 -0
  93. kailash/nodes/rag/multimodal.py +671 -0
  94. kailash/nodes/rag/optimized.py +933 -0
  95. kailash/nodes/rag/privacy.py +1059 -0
  96. kailash/nodes/rag/query_processing.py +1335 -0
  97. kailash/nodes/rag/realtime.py +764 -0
  98. kailash/nodes/rag/registry.py +547 -0
  99. kailash/nodes/rag/router.py +837 -0
  100. kailash/nodes/rag/similarity.py +1854 -0
  101. kailash/nodes/rag/strategies.py +566 -0
  102. kailash/nodes/rag/workflows.py +575 -0
  103. kailash/nodes/security/__init__.py +19 -0
  104. kailash/nodes/security/abac_evaluator.py +1411 -0
  105. kailash/nodes/security/audit_log.py +91 -0
  106. kailash/nodes/security/behavior_analysis.py +1893 -0
  107. kailash/nodes/security/credential_manager.py +401 -0
  108. kailash/nodes/security/rotating_credentials.py +760 -0
  109. kailash/nodes/security/security_event.py +132 -0
  110. kailash/nodes/security/threat_detection.py +1103 -0
  111. kailash/nodes/testing/__init__.py +9 -0
  112. kailash/nodes/testing/credential_testing.py +499 -0
  113. kailash/nodes/transform/__init__.py +10 -2
  114. kailash/nodes/transform/chunkers.py +592 -1
  115. kailash/nodes/transform/processors.py +484 -14
  116. kailash/nodes/validation.py +321 -0
  117. kailash/runtime/access_controlled.py +1 -1
  118. kailash/runtime/async_local.py +41 -7
  119. kailash/runtime/docker.py +1 -1
  120. kailash/runtime/local.py +474 -55
  121. kailash/runtime/parallel.py +1 -1
  122. kailash/runtime/parallel_cyclic.py +1 -1
  123. kailash/runtime/testing.py +210 -2
  124. kailash/utils/migrations/__init__.py +25 -0
  125. kailash/utils/migrations/generator.py +433 -0
  126. kailash/utils/migrations/models.py +231 -0
  127. kailash/utils/migrations/runner.py +489 -0
  128. kailash/utils/secure_logging.py +342 -0
  129. kailash/workflow/__init__.py +16 -0
  130. kailash/workflow/cyclic_runner.py +3 -4
  131. kailash/workflow/graph.py +70 -2
  132. kailash/workflow/resilience.py +249 -0
  133. kailash/workflow/templates.py +726 -0
  134. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/METADATA +253 -20
  135. kailash-0.4.0.dist-info/RECORD +223 -0
  136. kailash/api/__init__.py +0 -17
  137. kailash/api/__main__.py +0 -6
  138. kailash/api/studio_secure.py +0 -893
  139. kailash/mcp/__main__.py +0 -13
  140. kailash/mcp/server_new.py +0 -336
  141. kailash/mcp/servers/__init__.py +0 -12
  142. kailash-0.3.1.dist-info/RECORD +0 -136
  143. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/WHEEL +0 -0
  144. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/entry_points.txt +0 -0
  145. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/licenses/LICENSE +0 -0
  146. {kailash-0.3.1.dist-info → kailash-0.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,616 @@
1
+ """
2
+ Kailash SDK-based JWT Authentication Manager
3
+
4
+ Built entirely with Kailash SDK components - uses nodes and workflows
5
+ for all authentication operations. This demonstrates enterprise-grade
6
+ authentication using only Kailash patterns.
7
+ """
8
+
9
+ import json
10
+ import logging
11
+ import uuid
12
+ from datetime import datetime, timedelta, timezone
13
+ from typing import Any, Dict, List, Optional
14
+
15
+ # Import Kailash SDK components only
16
+ from kailash.nodes.base import Node, NodeParameter, register_node
17
+ from kailash.nodes.code import PythonCodeNode
18
+ from kailash.nodes.data import JSONReaderNode
19
+ from kailash.nodes.logic import MergeNode, SwitchNode
20
+ from kailash.nodes.security import CredentialManagerNode
21
+ from kailash.runtime.local import LocalRuntime
22
+ from kailash.workflow.builder import WorkflowBuilder
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ @register_node()
28
+ class JWTConfigNode(Node):
29
+ """Kailash node for JWT configuration management."""
30
+
31
+ def __init__(self, name: str = "jwt_config"):
32
+ super().__init__(name=name)
33
+ self.algorithm = "HS256" # Use symmetric for simplicity with Kailash
34
+ self.access_token_expire_minutes = 15
35
+ self.refresh_token_expire_days = 7
36
+ self.issuer = "kailash-middleware"
37
+ self.audience = "kailash-api"
38
+
39
+ def get_parameters(self) -> Dict[str, NodeParameter]:
40
+ return {
41
+ "algorithm": NodeParameter(
42
+ name="algorithm",
43
+ type=str,
44
+ required=False,
45
+ default="HS256",
46
+ description="JWT signing algorithm",
47
+ ),
48
+ "access_expire_minutes": NodeParameter(
49
+ name="access_expire_minutes",
50
+ type=int,
51
+ required=False,
52
+ default=15,
53
+ description="Access token expiration in minutes",
54
+ ),
55
+ "refresh_expire_days": NodeParameter(
56
+ name="refresh_expire_days",
57
+ type=int,
58
+ required=False,
59
+ default=7,
60
+ description="Refresh token expiration in days",
61
+ ),
62
+ }
63
+
64
+ def run(self, **kwargs) -> Dict[str, Any]:
65
+ """Return JWT configuration."""
66
+ return {
67
+ "config": {
68
+ "algorithm": getattr(self, "algorithm", "HS256"),
69
+ "access_token_expire_minutes": getattr(
70
+ self, "access_token_expire_minutes", 15
71
+ ),
72
+ "refresh_token_expire_days": getattr(
73
+ self, "refresh_token_expire_days", 7
74
+ ),
75
+ "issuer": getattr(self, "issuer", "kailash-middleware"),
76
+ "audience": getattr(self, "audience", "kailash-api"),
77
+ }
78
+ }
79
+
80
+ async def process(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
81
+ """Async wrapper for middleware compatibility."""
82
+ return self.run(**inputs)
83
+
84
+
85
+ class TokenGeneratorNode(PythonCodeNode):
86
+ """Kailash node for generating JWT tokens."""
87
+
88
+ def __init__(self, name: str = "token_generator"):
89
+ super().__init__(
90
+ name=name,
91
+ code="""
92
+ import jwt
93
+ import uuid
94
+ from datetime import datetime, timedelta, timezone
95
+
96
+ def generate_token(user_id, token_type='access', config=None, **claims):
97
+ '''Generate JWT token using Kailash patterns'''
98
+ config = config or {}
99
+
100
+ now = datetime.now(timezone.utc)
101
+
102
+ # Set expiration based on token type
103
+ if token_type == 'access':
104
+ expire_minutes = config.get('access_token_expire_minutes', 15)
105
+ exp = now + timedelta(minutes=expire_minutes)
106
+ else: # refresh
107
+ expire_days = config.get('refresh_token_expire_days', 7)
108
+ exp = now + timedelta(days=expire_days)
109
+
110
+ # Create payload with Kailash conventions
111
+ payload = {
112
+ 'sub': user_id,
113
+ 'iss': config.get('issuer', 'kailash-middleware'),
114
+ 'aud': config.get('audience', 'kailash-api'),
115
+ 'exp': int(exp.timestamp()),
116
+ 'iat': int(now.timestamp()),
117
+ 'jti': str(uuid.uuid4()),
118
+ 'token_type': token_type,
119
+ **claims
120
+ }
121
+
122
+ # Use simple secret for Kailash demo (in production, use proper key management)
123
+ secret = config.get('secret', 'kailash-jwt-secret-key')
124
+ algorithm = config.get('algorithm', 'HS256')
125
+
126
+ token = jwt.encode(payload, secret, algorithm=algorithm)
127
+
128
+ return {
129
+ 'token': token,
130
+ 'payload': payload,
131
+ 'expires_at': exp.isoformat(),
132
+ 'token_type': token_type
133
+ }
134
+
135
+ # Main execution
136
+ user_id = input_data.get('user_id')
137
+ token_type = input_data.get('token_type', 'access')
138
+ config = input_data.get('config', {})
139
+ claims = input_data.get('claims', {})
140
+
141
+ if not user_id:
142
+ result = {'error': 'user_id is required'}
143
+ else:
144
+ result = generate_token(user_id, token_type, config, **claims)
145
+ """,
146
+ )
147
+
148
+
149
+ class TokenVerifierNode(PythonCodeNode):
150
+ """Kailash node for verifying JWT tokens."""
151
+
152
+ def __init__(self, name: str = "token_verifier"):
153
+ super().__init__(
154
+ name=name,
155
+ code="""
156
+ import jwt
157
+ from datetime import datetime, timezone
158
+
159
+ def verify_token(token, config=None, blacklisted_tokens=None):
160
+ '''Verify JWT token using Kailash patterns'''
161
+ config = config or {}
162
+ blacklisted_tokens = blacklisted_tokens or set()
163
+
164
+ try:
165
+ # Check if token is blacklisted
166
+ if token in blacklisted_tokens:
167
+ return {
168
+ 'valid': False,
169
+ 'error': 'Token has been revoked',
170
+ 'error_type': 'revoked'
171
+ }
172
+
173
+ # Verify token
174
+ secret = config.get('secret', 'kailash-jwt-secret-key')
175
+ algorithm = config.get('algorithm', 'HS256')
176
+
177
+ payload = jwt.decode(
178
+ token,
179
+ secret,
180
+ algorithms=[algorithm],
181
+ issuer=config.get('issuer'),
182
+ audience=config.get('audience')
183
+ )
184
+
185
+ return {
186
+ 'valid': True,
187
+ 'payload': payload,
188
+ 'user_id': payload.get('sub'),
189
+ 'token_type': payload.get('token_type', 'access'),
190
+ 'expires_at': payload.get('exp'),
191
+ 'permissions': payload.get('permissions', []),
192
+ 'roles': payload.get('roles', []),
193
+ 'tenant_id': payload.get('tenant_id'),
194
+ 'session_id': payload.get('session_id')
195
+ }
196
+
197
+ except jwt.ExpiredSignatureError:
198
+ return {
199
+ 'valid': False,
200
+ 'error': 'Token has expired',
201
+ 'error_type': 'expired'
202
+ }
203
+ except jwt.InvalidTokenError as e:
204
+ return {
205
+ 'valid': False,
206
+ 'error': str(e),
207
+ 'error_type': 'invalid'
208
+ }
209
+ except Exception as e:
210
+ return {
211
+ 'valid': False,
212
+ 'error': f'Token verification failed: {str(e)}',
213
+ 'error_type': 'error'
214
+ }
215
+
216
+ # Main execution
217
+ token = input_data.get('token')
218
+ config = input_data.get('config', {})
219
+ blacklisted_tokens = input_data.get('blacklisted_tokens', set())
220
+
221
+ if not token:
222
+ result = {'valid': False, 'error': 'Token is required', 'error_type': 'missing'}
223
+ else:
224
+ result = verify_token(token, config, blacklisted_tokens)
225
+ """,
226
+ )
227
+
228
+
229
+ class RefreshTokenNode(PythonCodeNode):
230
+ """Kailash node for handling token refresh."""
231
+
232
+ def __init__(self, name: str = "refresh_token"):
233
+ super().__init__(
234
+ name=name,
235
+ code="""
236
+ def refresh_access_token(refresh_token_data, config, refresh_tracking):
237
+ '''Refresh access token using Kailash patterns'''
238
+
239
+ if not refresh_token_data.get('valid'):
240
+ return {
241
+ 'success': False,
242
+ 'error': 'Invalid refresh token',
243
+ 'error_type': 'invalid_refresh'
244
+ }
245
+
246
+ payload = refresh_token_data.get('payload', {})
247
+
248
+ # Check token type
249
+ if payload.get('token_type') != 'refresh':
250
+ return {
251
+ 'success': False,
252
+ 'error': 'Token is not a refresh token',
253
+ 'error_type': 'wrong_type'
254
+ }
255
+
256
+ jti = payload.get('jti')
257
+ user_id = payload.get('sub')
258
+
259
+ # Check refresh count (Kailash pattern for security)
260
+ refresh_info = refresh_tracking.get(jti, {})
261
+ max_refresh_count = config.get('max_refresh_count', 10)
262
+
263
+ if refresh_info.get('refresh_count', 0) >= max_refresh_count:
264
+ return {
265
+ 'success': False,
266
+ 'error': 'Refresh token has exceeded usage limit',
267
+ 'error_type': 'limit_exceeded'
268
+ }
269
+
270
+ # Update refresh tracking
271
+ refresh_info['refresh_count'] = refresh_info.get('refresh_count', 0) + 1
272
+ refresh_info['last_used'] = datetime.now().isoformat()
273
+ refresh_tracking[jti] = refresh_info
274
+
275
+ # Prepare new token creation data
276
+ return {
277
+ 'success': True,
278
+ 'user_id': user_id,
279
+ 'tenant_id': payload.get('tenant_id'),
280
+ 'session_id': payload.get('session_id'),
281
+ 'permissions': payload.get('permissions', []),
282
+ 'roles': payload.get('roles', []),
283
+ 'refresh_tracking': refresh_tracking
284
+ }
285
+
286
+ # Main execution
287
+ refresh_token_data = input_data.get('refresh_token_data', {})
288
+ config = input_data.get('config', {})
289
+ refresh_tracking = input_data.get('refresh_tracking', {})
290
+
291
+ result = refresh_access_token(refresh_token_data, config, refresh_tracking)
292
+ """,
293
+ )
294
+
295
+
296
+ class KailashJWTAuthManager:
297
+ """
298
+ JWT Authentication Manager built entirely with Kailash SDK components.
299
+
300
+ This demonstrates enterprise-grade authentication using only Kailash
301
+ nodes and workflows - no external dependencies beyond JWT library.
302
+ """
303
+
304
+ def __init__(self, secret_key: str = "kailash-jwt-secret-key"):
305
+ self.secret_key = secret_key
306
+ self.runtime = LocalRuntime()
307
+
308
+ # State management using Kailash patterns
309
+ self.blacklisted_tokens = set()
310
+ self.refresh_tracking = {}
311
+
312
+ # Create authentication workflows
313
+ self._create_workflows()
314
+
315
+ def _get_token_generator_code(self):
316
+ """Get token generator code for PythonCodeNode."""
317
+ return """
318
+ import jwt
319
+ import uuid
320
+ from datetime import datetime, timedelta, timezone
321
+
322
+ def generate_token(user_id, token_type='access', config=None, **claims):
323
+ '''Generate JWT token using Kailash patterns'''
324
+ config = config or {}
325
+
326
+ now = datetime.now(timezone.utc)
327
+
328
+ # Set expiration based on token type
329
+ if token_type == 'access':
330
+ expire_minutes = config.get('access_token_expire_minutes', 15)
331
+ exp = now + timedelta(minutes=expire_minutes)
332
+ else: # refresh
333
+ expire_days = config.get('refresh_token_expire_days', 7)
334
+ exp = now + timedelta(days=expire_days)
335
+
336
+ # Create payload with Kailash conventions
337
+ payload = {
338
+ 'sub': user_id,
339
+ 'iss': config.get('issuer', 'kailash-middleware'),
340
+ 'aud': config.get('audience', 'kailash-api'),
341
+ 'exp': int(exp.timestamp()),
342
+ 'iat': int(now.timestamp()),
343
+ 'jti': str(uuid.uuid4()),
344
+ 'token_type': token_type,
345
+ **claims
346
+ }
347
+
348
+ # Use simple secret for Kailash demo (in production, use proper key management)
349
+ secret = config.get('secret', 'kailash-jwt-secret-key')
350
+ algorithm = config.get('algorithm', 'HS256')
351
+
352
+ token = jwt.encode(payload, secret, algorithm=algorithm)
353
+
354
+ return {
355
+ 'token': token,
356
+ 'payload': payload,
357
+ 'expires_at': exp.isoformat(),
358
+ 'token_type': token_type
359
+ }
360
+
361
+ # Main execution
362
+ user_id = input_data.get('user_id')
363
+ token_type = input_data.get('token_type', 'access')
364
+ config = input_data.get('config', {})
365
+ claims = input_data.get('claims', {})
366
+
367
+ if not user_id:
368
+ result = {'error': 'user_id is required'}
369
+ else:
370
+ result = generate_token(user_id, token_type, config, **claims)
371
+ """
372
+
373
+ def _get_token_verifier_code(self):
374
+ """Get token verifier code for PythonCodeNode."""
375
+ return """
376
+ import jwt
377
+ from datetime import datetime, timezone
378
+
379
+ def verify_token(token, config=None, blacklisted_tokens=None):
380
+ config = config or {}
381
+ blacklisted_tokens = blacklisted_tokens or set()
382
+
383
+ try:
384
+ if token in blacklisted_tokens:
385
+ return {'valid': False, 'error': 'Token has been revoked', 'error_type': 'revoked'}
386
+
387
+ secret = config.get('secret', 'kailash-jwt-secret-key')
388
+ algorithm = config.get('algorithm', 'HS256')
389
+
390
+ payload = jwt.decode(token, secret, algorithms=[algorithm])
391
+
392
+ return {
393
+ 'valid': True,
394
+ 'payload': payload,
395
+ 'user_id': payload.get('sub'),
396
+ 'token_type': payload.get('token_type', 'access')
397
+ }
398
+
399
+ except jwt.ExpiredSignatureError:
400
+ return {'valid': False, 'error': 'Token has expired', 'error_type': 'expired'}
401
+ except jwt.InvalidTokenError as e:
402
+ return {'valid': False, 'error': str(e), 'error_type': 'invalid'}
403
+ except Exception as e:
404
+ return {'valid': False, 'error': f'Token verification failed: {str(e)}', 'error_type': 'error'}
405
+
406
+ token = input_data.get('token')
407
+ config = input_data.get('config', {})
408
+ blacklisted_tokens = input_data.get('blacklisted_tokens', set())
409
+
410
+ if not token:
411
+ result = {'valid': False, 'error': 'Token is required', 'error_type': 'missing'}
412
+ else:
413
+ result = verify_token(token, config, blacklisted_tokens)
414
+ """
415
+
416
+ def _create_workflows(self):
417
+ """Create Kailash workflows for authentication operations."""
418
+
419
+ # Token Creation Workflow
420
+ self.token_workflow = WorkflowBuilder()
421
+
422
+ config_id = self.token_workflow.add_node(
423
+ "JWTConfigNode", "jwt_config", {"name": "jwt_config"}
424
+ )
425
+ token_id = self.token_workflow.add_node(
426
+ "PythonCodeNode",
427
+ "generate_token",
428
+ {"name": "generate_token", "code": self._get_token_generator_code()},
429
+ )
430
+
431
+ self.token_workflow.add_connection(config_id, "config", token_id, "config")
432
+
433
+ # Token Verification Workflow
434
+ self.verify_workflow = WorkflowBuilder()
435
+
436
+ config_verify_id = self.verify_workflow.add_node(
437
+ "JWTConfigNode", "jwt_config_verify", {"name": "jwt_config_verify"}
438
+ )
439
+ verify_id = self.verify_workflow.add_node(
440
+ "PythonCodeNode",
441
+ "verify_token",
442
+ {"name": "verify_token", "code": self._get_token_verifier_code()},
443
+ )
444
+
445
+ self.verify_workflow.add_connection(
446
+ config_verify_id, "config", verify_id, "config"
447
+ )
448
+
449
+ # For simplicity, we'll use direct verification in methods instead of complex workflows
450
+
451
+ def create_access_token(
452
+ self,
453
+ user_id: str,
454
+ tenant_id: str = None,
455
+ session_id: str = None,
456
+ permissions: List[str] = None,
457
+ roles: List[str] = None,
458
+ ) -> str:
459
+ """Create access token using Kailash workflow."""
460
+
461
+ claims = {}
462
+ if tenant_id:
463
+ claims["tenant_id"] = tenant_id
464
+ if session_id:
465
+ claims["session_id"] = session_id
466
+ if permissions:
467
+ claims["permissions"] = permissions
468
+ if roles:
469
+ claims["roles"] = roles
470
+
471
+ inputs = {
472
+ "user_id": user_id,
473
+ "token_type": "access",
474
+ "claims": claims,
475
+ "config": {"secret": self.secret_key},
476
+ }
477
+
478
+ # Execute Kailash workflow
479
+ workflow = self.token_workflow.build()
480
+ results, _ = self.runtime.execute(workflow, parameters=inputs)
481
+
482
+ return results.get("generate_token", {}).get("token")
483
+
484
+ def create_refresh_token(
485
+ self, user_id: str, tenant_id: str = None, session_id: str = None
486
+ ) -> str:
487
+ """Create refresh token using Kailash workflow."""
488
+
489
+ claims = {}
490
+ if tenant_id:
491
+ claims["tenant_id"] = tenant_id
492
+ if session_id:
493
+ claims["session_id"] = session_id
494
+
495
+ inputs = {
496
+ "user_id": user_id,
497
+ "token_type": "refresh",
498
+ "claims": claims,
499
+ "config": {"secret": self.secret_key},
500
+ }
501
+
502
+ # Execute Kailash workflow
503
+ workflow = self.token_workflow.build()
504
+ results, _ = self.runtime.execute(workflow, parameters=inputs)
505
+
506
+ token_result = results.get("generate_token", {})
507
+ token = token_result.get("token")
508
+
509
+ # Track refresh token in Kailash pattern
510
+ if token:
511
+ payload = token_result.get("payload", {})
512
+ jti = payload.get("jti")
513
+ if jti:
514
+ self.refresh_tracking[jti] = {
515
+ "user_id": user_id,
516
+ "tenant_id": tenant_id,
517
+ "session_id": session_id,
518
+ "created_at": datetime.now(timezone.utc).isoformat(),
519
+ "refresh_count": 0,
520
+ }
521
+
522
+ return token
523
+
524
+ def create_token_pair(
525
+ self,
526
+ user_id: str,
527
+ tenant_id: str = None,
528
+ session_id: str = None,
529
+ permissions: List[str] = None,
530
+ roles: List[str] = None,
531
+ ) -> Dict[str, Any]:
532
+ """Create access and refresh token pair using Kailash workflows."""
533
+
534
+ access_token = self.create_access_token(
535
+ user_id, tenant_id, session_id, permissions, roles
536
+ )
537
+ refresh_token = self.create_refresh_token(user_id, tenant_id, session_id)
538
+
539
+ return {
540
+ "access_token": access_token,
541
+ "refresh_token": refresh_token,
542
+ "token_type": "Bearer",
543
+ "expires_in": 15 * 60, # 15 minutes in seconds
544
+ "scope": "kailash-api",
545
+ }
546
+
547
+ def verify_token(self, token: str) -> Dict[str, Any]:
548
+ """Verify token using Kailash workflow."""
549
+
550
+ inputs = {
551
+ "token": token,
552
+ "config": {"secret": self.secret_key},
553
+ "blacklisted_tokens": self.blacklisted_tokens,
554
+ }
555
+
556
+ # Execute Kailash verification workflow
557
+ workflow = self.verify_workflow.build()
558
+ results, _ = self.runtime.execute(workflow, parameters=inputs)
559
+
560
+ return results.get("verify_token", {})
561
+
562
+ def refresh_access_token(self, refresh_token: str) -> Dict[str, Any]:
563
+ """Refresh access token using simplified Kailash pattern."""
564
+
565
+ # Verify the refresh token
566
+ verify_result = self.verify_token(refresh_token)
567
+
568
+ if not verify_result.get("valid"):
569
+ return {"success": False, "error": "Invalid refresh token"}
570
+
571
+ payload = verify_result.get("payload", {})
572
+
573
+ if payload.get("token_type") != "refresh":
574
+ return {"success": False, "error": "Token is not a refresh token"}
575
+
576
+ # Create new token pair
577
+ return self.create_token_pair(
578
+ user_id=payload.get("sub"),
579
+ tenant_id=payload.get("tenant_id"),
580
+ session_id=payload.get("session_id"),
581
+ permissions=payload.get("permissions", []),
582
+ roles=payload.get("roles", []),
583
+ )
584
+
585
+ def revoke_token(self, token: str):
586
+ """Revoke token by adding to blacklist (Kailash pattern)."""
587
+ self.blacklisted_tokens.add(token)
588
+ logger.info(f"Revoked token (length: {len(token)})")
589
+
590
+ def revoke_all_user_tokens(self, user_id: str):
591
+ """Revoke all tokens for a user (Kailash pattern)."""
592
+ # Remove all refresh tokens for user
593
+ to_remove = []
594
+ for jti, data in self.refresh_tracking.items():
595
+ if data.get("user_id") == user_id:
596
+ to_remove.append(jti)
597
+
598
+ for jti in to_remove:
599
+ del self.refresh_tracking[jti]
600
+
601
+ logger.info(f"Revoked all tokens for user {user_id}")
602
+
603
+ def get_stats(self) -> Dict[str, Any]:
604
+ """Get authentication statistics (Kailash pattern)."""
605
+ return {
606
+ "active_refresh_tokens": len(self.refresh_tracking),
607
+ "blacklisted_tokens": len(self.blacklisted_tokens),
608
+ "auth_manager": "KailashJWTAuthManager",
609
+ "workflow_runtime": "LocalRuntime",
610
+ "nodes_used": [
611
+ "JWTConfigNode",
612
+ "TokenGeneratorNode",
613
+ "TokenVerifierNode",
614
+ "RefreshTokenNode",
615
+ ],
616
+ }
@@ -0,0 +1,37 @@
1
+ """
2
+ Communication Layer for Kailash Middleware
3
+
4
+ Handles all external communication including REST APIs, WebSockets,
5
+ events, and AI chat interfaces.
6
+ """
7
+
8
+ from .ai_chat import AIChatMiddleware, ChatMessage, WorkflowGenerator
9
+ from .api_gateway import APIGateway, create_gateway
10
+ from .events import (
11
+ EventPriority,
12
+ EventStream,
13
+ EventType,
14
+ NodeEvent,
15
+ UIEvent,
16
+ WorkflowEvent,
17
+ )
18
+ from .realtime import RealtimeMiddleware
19
+
20
+ __all__ = [
21
+ # Event system
22
+ "EventStream",
23
+ "EventType",
24
+ "EventPriority",
25
+ "WorkflowEvent",
26
+ "NodeEvent",
27
+ "UIEvent",
28
+ # Real-time communication
29
+ "RealtimeMiddleware",
30
+ # API Gateway
31
+ "APIGateway",
32
+ "create_gateway",
33
+ # AI Chat
34
+ "AIChatMiddleware",
35
+ "ChatMessage",
36
+ "WorkflowGenerator",
37
+ ]