kailash 0.4.0__py3-none-any.whl → 0.4.1__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.
@@ -1,12 +1,13 @@
1
1
  """
2
- SecurityEventNode - Security event monitoring and alerting
2
+ SecurityEventNode - Security event processing and monitoring
3
3
  """
4
4
 
5
+ import json
5
6
  import logging
6
7
  from dataclasses import dataclass
7
8
  from datetime import datetime, timezone
8
9
  from enum import Enum
9
- from typing import Any, Dict, Optional
10
+ from typing import Any, Dict, List, Optional
10
11
 
11
12
  from kailash.nodes.base import Node, NodeParameter, register_node
12
13
 
@@ -21,16 +22,14 @@ class SeverityLevel(str, Enum):
21
22
 
22
23
  @dataclass
23
24
  class SecurityEvent:
24
- """Represents a security event."""
25
-
26
25
  event_type: str
27
26
  severity: SeverityLevel
28
- timestamp: datetime
29
- source: str
30
- description: str
31
- details: Dict[str, Any]
27
+ message: str
32
28
  user_id: Optional[str] = None
33
- ip_address: Optional[str] = None
29
+ resource_id: Optional[str] = None
30
+ timestamp: Optional[str] = None
31
+ metadata: Optional[Dict[str, Any]] = None
32
+ source: Optional[str] = None
34
33
  session_id: Optional[str] = None
35
34
  correlation_id: Optional[str] = None
36
35
 
@@ -42,91 +41,93 @@ class SecurityEventNode(Node):
42
41
  def __init__(
43
42
  self,
44
43
  name: str,
45
- severity_threshold: str = "INFO",
46
- enable_alerting: bool = False,
44
+ alert_threshold: str = "HIGH",
45
+ enable_real_time: bool = True,
47
46
  **kwargs,
48
47
  ):
49
48
  super().__init__(name=name, **kwargs)
50
- self.severity_threshold = SeverityLevel(severity_threshold)
51
- self.enable_alerting = enable_alerting
49
+ self.alert_threshold = SeverityLevel(alert_threshold)
50
+ self.enable_real_time = enable_real_time
52
51
  self.logger = logging.getLogger(f"security.{name}")
53
52
 
54
53
  def get_parameters(self) -> Dict[str, NodeParameter]:
54
+ """Define parameters for security event processing."""
55
55
  return {
56
56
  "event_type": NodeParameter(
57
57
  name="event_type",
58
58
  type=str,
59
- required=True,
60
59
  description="Type of security event",
60
+ default="security_check",
61
61
  ),
62
62
  "severity": NodeParameter(
63
63
  name="severity",
64
64
  type=str,
65
- required=True,
66
65
  description="Event severity level",
66
+ default="INFO",
67
+ ),
68
+ "message": NodeParameter(
69
+ name="message",
70
+ type=str,
71
+ description="Security event message",
72
+ default="",
73
+ ),
74
+ "user_id": NodeParameter(
75
+ name="user_id",
76
+ type=str,
77
+ description="User ID associated with event",
78
+ default=None,
67
79
  ),
68
- "details": NodeParameter(
69
- name="details",
80
+ "metadata": NodeParameter(
81
+ name="metadata",
70
82
  type=dict,
71
- required=False,
72
- description="Security event details",
83
+ description="Additional event metadata",
84
+ default=None,
73
85
  ),
74
86
  }
75
87
 
76
- def process(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
77
- """Process security event."""
78
-
79
- event_type = inputs.get("event_type")
88
+ def execute(self, **inputs) -> Dict[str, Any]:
89
+ """Execute security event processing."""
90
+ event_type = inputs.get("event_type", "security_check")
80
91
  severity = SeverityLevel(inputs.get("severity", "INFO"))
81
- details = inputs.get("details", {})
82
-
83
- security_event = {
84
- "event_type": event_type,
85
- "severity": severity.value,
86
- "timestamp": datetime.now(timezone.utc).isoformat(),
87
- "details": details,
88
- }
89
-
90
- # Log security event
91
- self.logger.warning(f"SECURITY: {event_type} [{severity.value}] - {details}")
92
-
93
- # Trigger alerts if needed
94
- alert_triggered = False
95
- if self.enable_alerting and self._should_alert(severity):
96
- alert_triggered = self._trigger_alert(security_event)
92
+ message = inputs.get("message", "")
93
+ user_id = inputs.get("user_id")
94
+ metadata = inputs.get("metadata", {})
95
+
96
+ # Create security event
97
+ security_event = SecurityEvent(
98
+ event_type=event_type,
99
+ severity=severity,
100
+ message=message,
101
+ user_id=user_id,
102
+ metadata=metadata,
103
+ timestamp=datetime.now(timezone.utc).isoformat(),
104
+ )
105
+
106
+ # Log the event
107
+ log_message = f"[{severity.value}] {event_type}: {message}"
108
+ if user_id:
109
+ log_message += f" (User: {user_id})"
110
+
111
+ # Use appropriate log level based on severity
112
+ if severity in [SeverityLevel.CRITICAL, SeverityLevel.HIGH]:
113
+ self.logger.error(log_message)
114
+ elif severity == SeverityLevel.MEDIUM:
115
+ self.logger.warning(log_message)
116
+ else:
117
+ self.logger.info(log_message)
118
+
119
+ # Check for alerting
120
+ should_alert = severity.value >= self.alert_threshold.value
97
121
 
98
122
  return {
99
- "event_processed": True,
100
- "event": security_event,
101
- "alert_triggered": alert_triggered,
102
- }
103
-
104
- def _should_alert(self, severity: SeverityLevel) -> bool:
105
- """Determine if alert should be triggered."""
106
- severity_order = {
107
- SeverityLevel.INFO: 0,
108
- SeverityLevel.LOW: 1,
109
- SeverityLevel.MEDIUM: 2,
110
- SeverityLevel.HIGH: 3,
111
- SeverityLevel.CRITICAL: 4,
123
+ "security_event": {
124
+ "event_type": security_event.event_type,
125
+ "severity": security_event.severity.value,
126
+ "message": security_event.message,
127
+ "user_id": security_event.user_id,
128
+ "timestamp": security_event.timestamp,
129
+ "metadata": security_event.metadata,
130
+ },
131
+ "alert_triggered": should_alert,
132
+ "logged": True,
112
133
  }
113
-
114
- return severity_order[severity] >= severity_order[self.severity_threshold]
115
-
116
- def _trigger_alert(self, event: Dict[str, Any]) -> bool:
117
- """Trigger security alert (placeholder)."""
118
- # In production, this would integrate with alerting systems
119
- self.logger.critical(f"SECURITY ALERT: {event}")
120
- return True
121
-
122
- def run(self, **kwargs) -> Dict[str, Any]:
123
- """Alias for process method."""
124
- return self.process(kwargs)
125
-
126
- def execute(self, **kwargs) -> Dict[str, Any]:
127
- """Alias for process method."""
128
- return self.process(kwargs)
129
-
130
- async def async_run(self, **kwargs) -> Dict[str, Any]:
131
- """Async execution method for enterprise integration."""
132
- return self.run(**kwargs)
kailash/security.py CHANGED
@@ -667,7 +667,7 @@ def sanitize_input(
667
667
  try:
668
668
  import statsmodels.api as sm
669
669
 
670
- allowed_types.extend([sm.OLS, sm.GLM, sm.GLS, sm.WLS, sm.RegressionResults])
670
+ allowed_types.extend([sm.OLS, sm.GLM, sm.GLS, sm.WLS])
671
671
  except ImportError:
672
672
  pass
673
673
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kailash
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Python SDK for the Kailash container-node architecture
5
5
  Home-page: https://github.com/integrum/kailash-python-sdk
6
6
  Author: Integrum
@@ -116,6 +116,7 @@ Dynamic: requires-python
116
116
  - 📈 **High Performance**: Optimized execution engine supporting 100,000+ iteration workflows
117
117
  - 📁 **Complete Finance Workflow Library (v0.3.1)**: Production-ready financial workflows with AI analysis
118
118
  - 💼 **Enterprise Workflow Patterns**: Credit risk, portfolio optimization, trading signals, fraud detection
119
+ - 🔔 **Production Alert System**: Rich Discord alerts with rate limiting, retry logic, and rich embed support
119
120
  - 🏭 **Session 067 Enhancements**: Business workflow templates, data lineage tracking, automatic credential rotation
120
121
  - 🔄 **Zero-Downtime Operations**: Automatic credential rotation with enterprise notifications and audit trails
121
122
  - 🌉 **Enterprise Middleware (v0.4.0)**: Production-ready middleware architecture with real-time agent-frontend communication, dynamic workflows, and AI chat integration
@@ -174,6 +175,7 @@ pip install kailash[user-management]
174
175
  # Everything
175
176
  pip install kailash[all]
176
177
  ```
178
+ >>>>>>> origin/main
177
179
 
178
180
  ## 🎯 Who Is This For?
179
181
 
@@ -522,6 +524,7 @@ api.run()
522
524
  - **API**: RESTClientNode, GraphQLNode, AuthNode, HTTPRequestNode
523
525
  - **Logic**: SwitchNode, MergeNode, ConvergenceCheckerNode
524
526
  - **Code**: PythonCodeNode, WorkflowNode
527
+ - **Alerts**: DiscordAlertNode with rich embeds and rate limiting
525
528
  - **Security**: EnhancedAccessControlManager (ABAC with 16 operators)
526
529
 
527
530
  ### Runtimes
@@ -1,10 +1,10 @@
1
- kailash/__init__.py,sha256=vryDzVzXgXkzymSGHJmrlB0c6MNSmUhbWDPGmE4H3Ms,1797
1
+ kailash/__init__.py,sha256=FdEB2WokgGOcUMo19ACxoI2MowIWcSm3zeZvWt5nVAc,1792
2
2
  kailash/__main__.py,sha256=vr7TVE5o16V6LsTmRFKG6RDKUXHpIWYdZ6Dok2HkHnI,198
3
3
  kailash/access_control.py,sha256=2ctdRFeSeu-d7DU04Aovxh6Rt_4t3IyQfkKEjTeQiMM,25519
4
4
  kailash/access_control_abac.py,sha256=FPfa_8PuDP3AxTjdWfiH3ntwWO8NodA0py9W8SE5dno,30263
5
5
  kailash/manifest.py,sha256=qzOmeMGWz20Sp4IJitSH9gTVbGng7hlimc96VTW4KI8,24814
6
6
  kailash/sdk_exceptions.py,sha256=dueSUxUYqKXmHS5mwl6QtEzP6a0rMGXcBFGCh5sT0tg,10179
7
- kailash/security.py,sha256=2hHb3Ag-jZ7UCvjUiX0JK2fBRaIhNFYpI3fN_JPPOgA,26455
7
+ kailash/security.py,sha256=eTb5rq92vFz7xU1Ov5gM5izRIAi2JQO3Pmf0xe2U3ls,26433
8
8
  kailash/access_control/__init__.py,sha256=6ZKYHe8SqEdiog369KMmqXBPKM77eBuncwIRbBG8ij4,3958
9
9
  kailash/access_control/managers.py,sha256=Vg2inaZqR2GBXsySvPZcEqQtFHgF94z7A_wUHMtA3qA,14431
10
10
  kailash/access_control/rule_evaluators.py,sha256=niguhjThBjA0jIXvdKdGAXzdSM_bAd0ebphGgRrDFKU,15337
@@ -59,29 +59,33 @@ kailash/middleware/database/session_manager.py,sha256=Pzj7c2TZnM3GRty2igSaxmLOf0
59
59
  kailash/middleware/mcp/__init__.py,sha256=EdZB8zOMSBEEmudRzs8ksz9QZJYWQMEx7Tm1MOwIWnI,922
60
60
  kailash/middleware/mcp/client_integration.py,sha256=opzhB5TUts_ND8gARXh93nKCc1u4kwo6SqNMMWqMcSU,18258
61
61
  kailash/middleware/mcp/enhanced_server.py,sha256=I82oRfzADPBM0ExxFNhZ-tI2kJTVBF0Hjx4uHfWkA2o,18456
62
- kailash/nodes/__init__.py,sha256=aRN9tWHDAK0juyD1TXmlqVDA28pUwMC5pCx8RPBnBI4,910
62
+ kailash/nodes/__init__.py,sha256=E6CEp1ooq4GgFhKtwVAczOhPt5N3x-AVQ-R0n3_IFyA,936
63
63
  kailash/nodes/base.py,sha256=5selOpaQvLXoy4VaiTbMxB7NbUhQ4tXdUF31-nPSGnc,51291
64
64
  kailash/nodes/base_async.py,sha256=cjp0tedoxvwqr9fdC385vqInb3WTR0Wcx3ecLxhHiY0,6593
65
65
  kailash/nodes/base_cycle_aware.py,sha256=Xpze9xZzLepWeLpi9Y3tMn1dm2LVv-omr5TSQuGTtWo,13377
66
66
  kailash/nodes/base_with_acl.py,sha256=kY_OWfjHWy6uCw60zGgGybqk7dnNL6kST69cFbd9XqM,11844
67
67
  kailash/nodes/mixins.py,sha256=ncAdNQPe1sphLByeerP6G_s8mjFLt7dM4baiozzIBPA,12083
68
68
  kailash/nodes/validation.py,sha256=tuBZRZkDiEdvfeU7JaRB7v2-j1vxPYMJ1gVaJ-PKHRk,12117
69
- kailash/nodes/admin/__init__.py,sha256=DLX9fwHRwGdt5ShDwIWh75PTpSIUzLhb_oBRFBBAUlA,1239
70
- kailash/nodes/admin/audit_log.py,sha256=wv5E2xDPjC6DTgc1PVOt2YINV8JoHXc4Aj0Jpt0EGbY,28329
69
+ kailash/nodes/admin/__init__.py,sha256=C9_pK2w0rH6JEV_-roypeasAIyIhEFKKnH-npGBeew0,1508
70
+ kailash/nodes/admin/audit_log.py,sha256=IsG91W7QDllhVsXRMXAw9LmSpZAJKn-4hFUZDHs-xao,28339
71
71
  kailash/nodes/admin/permission_check.py,sha256=yA_vHWzMg3KH27oDnu1M6IWfxXWsRnH0m8x72YKkrFI,32484
72
72
  kailash/nodes/admin/role_management.py,sha256=2jDQak5jIblP5Dd7vSCKt7h-4vbi6AEhCynu3blQ3vw,30184
73
- kailash/nodes/admin/security_event.py,sha256=CzB6hF48Ip1CtJmZ_Y1GHwAbwo5wiI4PK-ILRb0jl98,56289
73
+ kailash/nodes/admin/security_event.py,sha256=We_nGn6_J004b7LQVd0nKU6LmhJ6vyrl5zySC3xVdfo,56336
74
74
  kailash/nodes/admin/user_management.py,sha256=Z31mDGC5J_73DtauH5fqGnv9MmEOPgxKOfIGGalR9GA,35305
75
75
  kailash/nodes/ai/__init__.py,sha256=rslxIS8jlovshiNgWqVzQjD_kfT_3h3Ct03sk-iRe6U,2202
76
76
  kailash/nodes/ai/a2a.py,sha256=QpTPl-Cm6mqzM0unLfqPrgEu964QP47g5p2T4clVPMs,70004
77
77
  kailash/nodes/ai/agents.py,sha256=CRA3cdapQjpuvOniXUh6ZVWAlRxUIepVw1BROW6QzdY,20373
78
- kailash/nodes/ai/ai_providers.py,sha256=-JJZNTk6NWnVzSMGJpc1vNN7m2zxqpJnmuszjtAFDE8,52975
78
+ kailash/nodes/ai/ai_providers.py,sha256=XK7AzC8uL8nIxukZs6bxX4g75vcxCbehefgvR4QJgXk,62824
79
79
  kailash/nodes/ai/embedding_generator.py,sha256=rsos3B6oWrgGTMIbwSWIBzGH9kq3SFVD_-bEDrujBRs,31860
80
80
  kailash/nodes/ai/intelligent_agent_orchestrator.py,sha256=xw44C-CkcNH3SVmEJ49o4oNV3o4ZqjLE9aLpggwoIXs,83021
81
81
  kailash/nodes/ai/iterative_llm_agent.py,sha256=pv54W_YDfDPDl6DJf0ul9_rs2mL2kE_C59sSAJ4CRn8,52884
82
- kailash/nodes/ai/llm_agent.py,sha256=gsT_QNyNdrhM6S87wPmOWBuNVJUrlDNsi2KP6Wfy_0c,76411
82
+ kailash/nodes/ai/llm_agent.py,sha256=Beb07UNzCvPjHLTgYG9HeGsmuAXGLPjcExY30DghBfA,77566
83
83
  kailash/nodes/ai/models.py,sha256=wsEeUTuegy87mnLtKgSTg7ggCXvC1n3MsL-iZ4qujHs,16393
84
84
  kailash/nodes/ai/self_organizing.py,sha256=M7yCLkN4I1JCNU7PWuwrqwQSlaG9MJVxYIR44TV52MM,62877
85
+ kailash/nodes/ai/vision_utils.py,sha256=OHD9cVH_mq0WpJyQkNTj_mpipIVWfSV_bF9eA6CdyeA,4166
86
+ kailash/nodes/alerts/__init__.py,sha256=CY3agJ7VQ4yU68BhxMCaj18EGEaDecYfLxceHHP4o9c,782
87
+ kailash/nodes/alerts/base.py,sha256=qFU3cBF7jJNjScA0BJv2mTYCUTNQjbr4wTDEEvIGvRE,7598
88
+ kailash/nodes/alerts/discord.py,sha256=IPVyhb0i0QcWXxdP3MyeGCDP30pdSu-bEV-ueh9fwN0,16980
85
89
  kailash/nodes/api/__init__.py,sha256=dzK6kiAdJcTQa7NSBkSmd5CCTSefBlMZMewGlTJSr0c,2334
86
90
  kailash/nodes/api/auth.py,sha256=mve8rdshFIfLpkJX6M9opgDDru1LjcTyf3KpuCs1wd0,30869
87
91
  kailash/nodes/api/graphql.py,sha256=6UBqWBbAysrerrx9lQMwwRM6mZT4-65ZINPhC_ObWmA,16975
@@ -114,7 +118,7 @@ kailash/nodes/data/retrieval.py,sha256=H8Qb2R64fQ_OeaQBh6jVn7-xLuygiF3fjzbh4ssNO
114
118
  kailash/nodes/data/sharepoint_graph.py,sha256=J1_KZQ5s8yXkjGY1PjsMY7T8viKARi3os5P8CXpmn2U,37160
115
119
  kailash/nodes/data/sources.py,sha256=tvgDDDerWELD6QkAm73ciKmNakD_SYMd50idlOjpbF0,3632
116
120
  kailash/nodes/data/sql.py,sha256=ByBr_IaJuHJahyrgrtixFcWTZjE9A1XkSMCHE1K_9mo,33933
117
- kailash/nodes/data/streaming.py,sha256=Ap1m-OvZq6IfI2tNZI4Pok3ooxor5mjbsqNZ4yaYEeE,37059
121
+ kailash/nodes/data/streaming.py,sha256=VE4e3CNuRAdjckV8UXFpkTj3mPLY2cicoZwnkq10ZnE,37163
118
122
  kailash/nodes/data/vector_db.py,sha256=pwCl-3tyk_Cv_VQ8GafgodJ1yM88W1BXCIcYC56XoqU,32056
119
123
  kailash/nodes/data/writers.py,sha256=-RPLetKhKAPXOU6YPwMkVRXF8by6ROhgICm3aUnGcFs,17537
120
124
  kailash/nodes/enterprise/__init__.py,sha256=1a6SsEnzozP4MSFDo-Yimzx-e65NwnmGeTDMammSrtk,407
@@ -151,11 +155,11 @@ kailash/nodes/rag/strategies.py,sha256=FqJKiVb1Mq4BfJNFwrugKg_ovf7ULbyuF_uTvs4VQ
151
155
  kailash/nodes/rag/workflows.py,sha256=PL9d3Lk15drwo2QVdNR9B61EpZ8Kc1crjnqFXc10O1I,20008
152
156
  kailash/nodes/security/__init__.py,sha256=oaoZdbKhjEZ8vtUHGRPZPDixInzFDmhUZg4ou_Lz6mI,611
153
157
  kailash/nodes/security/abac_evaluator.py,sha256=l2DT-akmJ_etM9ImmLydYNvd8TGDejTziFuoWCrqCDU,50289
154
- kailash/nodes/security/audit_log.py,sha256=o81LqlQglggmVWyC_dqqMH8X7thduFpJLSN5tGGyNcs,2817
158
+ kailash/nodes/security/audit_log.py,sha256=zjwLoWHJLhkJiD5rRmE8H2mSEE7-6EHh_FR0FT91uLU,3130
155
159
  kailash/nodes/security/behavior_analysis.py,sha256=-V6Vq1WwACxK6B607ykKOh9HZhCPbY4NPvaUHBkjqsQ,71543
156
160
  kailash/nodes/security/credential_manager.py,sha256=USFQvX-ZPB537IEtKfD7y6alcVpOAIpAr0bj9V68W_k,14964
157
161
  kailash/nodes/security/rotating_credentials.py,sha256=qP04ARlrQAqEljOCXAmn-bsQlLFgoWlqZWerRD-srjo,28884
158
- kailash/nodes/security/security_event.py,sha256=SNl1114GdCNwbvhTvAm20sv4X7BPx4alYEdRbKHf1_Q,3978
162
+ kailash/nodes/security/security_event.py,sha256=yVP8foaki-LDD16mlRapaPsbaWMwsum5J_V0n1bnqvw,4150
159
163
  kailash/nodes/security/threat_detection.py,sha256=F-8QXx3FOZi1-poZdfTHa_phY1ectl4jYkzjfl3ck8U,40065
160
164
  kailash/nodes/testing/__init__.py,sha256=TpaRD5YHwT6R3pI0r0WU99-Vgixj6gmCbZewnt8K8uI,274
161
165
  kailash/nodes/testing/credential_testing.py,sha256=FiiVyBqL-fdHw7t6g7_Wq3104siM83llOmi-UFykMEw,17919
@@ -215,9 +219,9 @@ kailash/workflow/state.py,sha256=UTZxs5-Ona6uvBhx1__i6-RX8gB4qazkBIWE7uyRmWQ,760
215
219
  kailash/workflow/templates.py,sha256=MTIMHGyQML6omLbqeKDbTVIVykfXG6pIFWTTsGBUHN0,48591
216
220
  kailash/workflow/validation.py,sha256=JIbIajWVIaWHSvWtgZ4WUVJaBaUOCz5B9cyTwM--dL4,33060
217
221
  kailash/workflow/visualization.py,sha256=ICMWCWqh5fOQ7eJygbvu2PMWHxe-H5_0epwdZuz8cMw,19737
218
- kailash-0.4.0.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
219
- kailash-0.4.0.dist-info/METADATA,sha256=2JfJnEKn9YDTMrvtsZPxHT4lLvxcDx7cqH1D4TTcNls,24595
220
- kailash-0.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
221
- kailash-0.4.0.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
222
- kailash-0.4.0.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
223
- kailash-0.4.0.dist-info/RECORD,,
222
+ kailash-0.4.1.dist-info/licenses/LICENSE,sha256=Axe6g7bTrJkToK9h9j2SpRUKKNaDZDCo2lQ2zPxCE6s,1065
223
+ kailash-0.4.1.dist-info/METADATA,sha256=KN5COKUq4zgWFi10SlSZFDln22hgMj9qb7TyZAJTLq8,24793
224
+ kailash-0.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
225
+ kailash-0.4.1.dist-info/entry_points.txt,sha256=M_q3b8PG5W4XbhSgESzIJjh3_4OBKtZFYFsOdkr2vO4,45
226
+ kailash-0.4.1.dist-info/top_level.txt,sha256=z7GzH2mxl66498pVf5HKwo5wwfPtt9Aq95uZUpH6JV0,8
227
+ kailash-0.4.1.dist-info/RECORD,,