zexus 1.6.2
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.
- package/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# src/zexus/policy_engine.py
|
|
2
|
+
"""
|
|
3
|
+
Policy-as-Code Engine for Zexus PROTECT Feature
|
|
4
|
+
Implements declarative security policy injection with VERIFY and RESTRICT
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, List, Any, Callable, Optional
|
|
8
|
+
from .object import Object, Boolean as BooleanObj, String, Integer, NULL, EvaluationError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ===============================================
|
|
12
|
+
# POLICY RULE TYPES
|
|
13
|
+
# ===============================================
|
|
14
|
+
|
|
15
|
+
class PolicyRule:
|
|
16
|
+
"""Base class for policy rules"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, description: str = ""):
|
|
19
|
+
self.description = description
|
|
20
|
+
|
|
21
|
+
def evaluate(self, context: Dict[str, Any]) -> tuple[bool, str]:
|
|
22
|
+
"""
|
|
23
|
+
Evaluate the policy rule
|
|
24
|
+
Returns: (success: bool, message: str)
|
|
25
|
+
"""
|
|
26
|
+
raise NotImplementedError("Subclasses must implement evaluate()")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class VerifyRule(PolicyRule):
|
|
30
|
+
"""VERIFY rule - checks a boolean condition"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, condition_fn: Callable, description: str = "Verification check"):
|
|
33
|
+
super().__init__(description)
|
|
34
|
+
self.condition_fn = condition_fn
|
|
35
|
+
|
|
36
|
+
def evaluate(self, context: Dict[str, Any]) -> tuple[bool, str]:
|
|
37
|
+
try:
|
|
38
|
+
result = self.condition_fn(context)
|
|
39
|
+
success = result.value if isinstance(result, BooleanObj) else bool(result)
|
|
40
|
+
message = self.description if not success else ""
|
|
41
|
+
return success, message
|
|
42
|
+
except Exception as e:
|
|
43
|
+
return False, f"Verification failed: {str(e)}"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class RestrictRule(PolicyRule):
|
|
47
|
+
"""RESTRICT rule - applies constraints to data"""
|
|
48
|
+
|
|
49
|
+
def __init__(self, field_name: str, constraints: List[Callable], description: str = ""):
|
|
50
|
+
super().__init__(description)
|
|
51
|
+
self.field_name = field_name
|
|
52
|
+
self.constraints = constraints
|
|
53
|
+
|
|
54
|
+
def evaluate(self, context: Dict[str, Any]) -> tuple[bool, str]:
|
|
55
|
+
value = context.get(self.field_name)
|
|
56
|
+
|
|
57
|
+
if value is None:
|
|
58
|
+
return False, f"Field '{self.field_name}' not found in context"
|
|
59
|
+
|
|
60
|
+
for constraint in self.constraints:
|
|
61
|
+
try:
|
|
62
|
+
result = constraint(value, context)
|
|
63
|
+
passed = result.value if isinstance(result, BooleanObj) else bool(result)
|
|
64
|
+
if not passed:
|
|
65
|
+
return False, f"Constraint failed for '{self.field_name}'"
|
|
66
|
+
except Exception as e:
|
|
67
|
+
return False, f"Constraint evaluation error: {str(e)}"
|
|
68
|
+
|
|
69
|
+
return True, ""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# ===============================================
|
|
73
|
+
# PROTECTION POLICY
|
|
74
|
+
# ===============================================
|
|
75
|
+
|
|
76
|
+
class ProtectionPolicy:
|
|
77
|
+
"""Represents a complete protection policy for a target"""
|
|
78
|
+
|
|
79
|
+
def __init__(self, target_name: str, enforcement_level: str = "strict"):
|
|
80
|
+
self.target_name = target_name
|
|
81
|
+
self.enforcement_level = enforcement_level # "strict", "warn", "audit", "permissive"
|
|
82
|
+
self.rules: List[PolicyRule] = []
|
|
83
|
+
self.middleware_chain: List[Callable] = []
|
|
84
|
+
self.on_violation: Optional[Callable] = None
|
|
85
|
+
self.audit_log: List[Dict[str, Any]] = []
|
|
86
|
+
|
|
87
|
+
def add_rule(self, rule: PolicyRule):
|
|
88
|
+
"""Add a policy rule"""
|
|
89
|
+
self.rules.append(rule)
|
|
90
|
+
|
|
91
|
+
def add_middleware(self, middleware: Callable):
|
|
92
|
+
"""Add middleware to the protection chain"""
|
|
93
|
+
self.middleware_chain.append(middleware)
|
|
94
|
+
|
|
95
|
+
def set_violation_handler(self, handler: Callable):
|
|
96
|
+
"""Set handler for policy violations"""
|
|
97
|
+
self.on_violation = handler
|
|
98
|
+
|
|
99
|
+
def evaluate(self, context: Dict[str, Any]) -> tuple[bool, List[str]]:
|
|
100
|
+
"""
|
|
101
|
+
Evaluate all policy rules
|
|
102
|
+
Returns: (all_passed: bool, violation_messages: List[str])
|
|
103
|
+
"""
|
|
104
|
+
violations = []
|
|
105
|
+
|
|
106
|
+
for rule in self.rules:
|
|
107
|
+
passed, message = rule.evaluate(context)
|
|
108
|
+
|
|
109
|
+
if not passed:
|
|
110
|
+
violations.append(message)
|
|
111
|
+
|
|
112
|
+
# Log the violation
|
|
113
|
+
self._audit_violation(rule, message, context)
|
|
114
|
+
|
|
115
|
+
# Handle based on enforcement level
|
|
116
|
+
if self.enforcement_level == "strict":
|
|
117
|
+
# Strict mode: fail immediately
|
|
118
|
+
return False, violations
|
|
119
|
+
elif self.enforcement_level == "warn":
|
|
120
|
+
# Warn mode: continue but collect violations
|
|
121
|
+
print(f"⚠️ Policy Warning ({self.target_name}): {message}")
|
|
122
|
+
elif self.enforcement_level == "audit":
|
|
123
|
+
# Audit mode: log only, allow execution
|
|
124
|
+
pass
|
|
125
|
+
# permissive mode: do nothing
|
|
126
|
+
|
|
127
|
+
# All rules passed or enforcement allows it
|
|
128
|
+
all_passed = len(violations) == 0
|
|
129
|
+
return all_passed, violations
|
|
130
|
+
|
|
131
|
+
def execute_middleware(self, context: Dict[str, Any], original_fn: Callable):
|
|
132
|
+
"""Execute middleware chain"""
|
|
133
|
+
# Build middleware chain
|
|
134
|
+
def final_handler():
|
|
135
|
+
return original_fn(context)
|
|
136
|
+
|
|
137
|
+
# Wrap with each middleware (reverse order for proper nesting)
|
|
138
|
+
handler = final_handler
|
|
139
|
+
for middleware in reversed(self.middleware_chain):
|
|
140
|
+
current_handler = handler
|
|
141
|
+
handler = lambda ctx=context, mw=middleware, h=current_handler: mw(ctx, h)
|
|
142
|
+
|
|
143
|
+
# Execute the chain
|
|
144
|
+
return handler()
|
|
145
|
+
|
|
146
|
+
def _audit_violation(self, rule: PolicyRule, message: str, context: Dict[str, Any]):
|
|
147
|
+
"""Log a policy violation"""
|
|
148
|
+
import time
|
|
149
|
+
self.audit_log.append({
|
|
150
|
+
'timestamp': time.time(),
|
|
151
|
+
'target': self.target_name,
|
|
152
|
+
'rule': rule.description,
|
|
153
|
+
'message': message,
|
|
154
|
+
'context_keys': list(context.keys()),
|
|
155
|
+
'enforcement_level': self.enforcement_level
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
def get_audit_log(self) -> List[Dict[str, Any]]:
|
|
159
|
+
"""Get audit log"""
|
|
160
|
+
return self.audit_log
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# ===============================================
|
|
164
|
+
# POLICY REGISTRY
|
|
165
|
+
# ===============================================
|
|
166
|
+
|
|
167
|
+
class PolicyRegistry:
|
|
168
|
+
"""Global registry for protection policies"""
|
|
169
|
+
|
|
170
|
+
def __init__(self):
|
|
171
|
+
self.policies: Dict[str, ProtectionPolicy] = {}
|
|
172
|
+
self.protected_functions: Dict[str, Callable] = {}
|
|
173
|
+
|
|
174
|
+
def register_policy(self, target_name: str, policy: ProtectionPolicy):
|
|
175
|
+
"""Register a protection policy for a target"""
|
|
176
|
+
self.policies[target_name] = policy
|
|
177
|
+
|
|
178
|
+
def get_policy(self, target_name: str) -> Optional[ProtectionPolicy]:
|
|
179
|
+
"""Get policy for a target"""
|
|
180
|
+
return self.policies.get(target_name)
|
|
181
|
+
|
|
182
|
+
def protect_function(self, func_name: str, original_fn: Callable, policy: ProtectionPolicy):
|
|
183
|
+
"""Wrap a function with policy enforcement"""
|
|
184
|
+
self.protected_functions[func_name] = original_fn
|
|
185
|
+
self.register_policy(func_name, policy)
|
|
186
|
+
|
|
187
|
+
def execute_protected(self, func_name: str, context: Dict[str, Any]):
|
|
188
|
+
"""Execute a protected function with policy checks"""
|
|
189
|
+
policy = self.get_policy(func_name)
|
|
190
|
+
original_fn = self.protected_functions.get(func_name)
|
|
191
|
+
|
|
192
|
+
if not policy or not original_fn:
|
|
193
|
+
raise ValueError(f"Function '{func_name}' not registered for protection")
|
|
194
|
+
|
|
195
|
+
# Evaluate policy
|
|
196
|
+
passed, violations = policy.evaluate(context)
|
|
197
|
+
|
|
198
|
+
if not passed and policy.enforcement_level == "strict":
|
|
199
|
+
error_msg = "; ".join(violations)
|
|
200
|
+
if policy.on_violation:
|
|
201
|
+
return policy.on_violation(violations, context)
|
|
202
|
+
raise EvaluationError(f"Policy violation for {func_name}: {error_msg}")
|
|
203
|
+
|
|
204
|
+
# Execute middleware chain
|
|
205
|
+
return policy.execute_middleware(context, original_fn)
|
|
206
|
+
|
|
207
|
+
def list_protected_targets(self) -> List[str]:
|
|
208
|
+
"""List all protected targets"""
|
|
209
|
+
return list(self.policies.keys())
|
|
210
|
+
|
|
211
|
+
def get_audit_summary(self) -> Dict[str, Any]:
|
|
212
|
+
"""Get summary of all audit logs"""
|
|
213
|
+
total_violations = 0
|
|
214
|
+
by_target = {}
|
|
215
|
+
|
|
216
|
+
for target_name, policy in self.policies.items():
|
|
217
|
+
violations = policy.get_audit_log()
|
|
218
|
+
total_violations += len(violations)
|
|
219
|
+
by_target[target_name] = len(violations)
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
'total_violations': total_violations,
|
|
223
|
+
'by_target': by_target,
|
|
224
|
+
'protected_targets': len(self.policies)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# Global policy registry
|
|
229
|
+
_policy_registry = PolicyRegistry()
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def get_policy_registry() -> PolicyRegistry:
|
|
233
|
+
"""Get the global policy registry"""
|
|
234
|
+
return _policy_registry
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# ===============================================
|
|
238
|
+
# POLICY BUILDER (DSL Support)
|
|
239
|
+
# ===============================================
|
|
240
|
+
|
|
241
|
+
class PolicyBuilder:
|
|
242
|
+
"""Builder for creating policies from PROTECT blocks"""
|
|
243
|
+
|
|
244
|
+
def __init__(self, target_name: str):
|
|
245
|
+
self.policy = ProtectionPolicy(target_name)
|
|
246
|
+
|
|
247
|
+
def add_verify_condition(self, condition_fn: Callable, description: str = ""):
|
|
248
|
+
"""Add a VERIFY rule"""
|
|
249
|
+
rule = VerifyRule(condition_fn, description)
|
|
250
|
+
self.policy.add_rule(rule)
|
|
251
|
+
return self
|
|
252
|
+
|
|
253
|
+
def add_restrict_constraint(self, field_name: str, constraints: List[Callable], description: str = ""):
|
|
254
|
+
"""Add a RESTRICT rule"""
|
|
255
|
+
rule = RestrictRule(field_name, constraints, description)
|
|
256
|
+
self.policy.add_rule(rule)
|
|
257
|
+
return self
|
|
258
|
+
|
|
259
|
+
def set_enforcement(self, level: str):
|
|
260
|
+
"""Set enforcement level"""
|
|
261
|
+
self.policy.enforcement_level = level
|
|
262
|
+
return self
|
|
263
|
+
|
|
264
|
+
def with_middleware(self, middleware: Callable):
|
|
265
|
+
"""Add middleware"""
|
|
266
|
+
self.policy.add_middleware(middleware)
|
|
267
|
+
return self
|
|
268
|
+
|
|
269
|
+
def on_violation(self, handler: Callable):
|
|
270
|
+
"""Set violation handler"""
|
|
271
|
+
self.policy.set_violation_handler(handler)
|
|
272
|
+
return self
|
|
273
|
+
|
|
274
|
+
def build(self) -> ProtectionPolicy:
|
|
275
|
+
"""Build and return the policy"""
|
|
276
|
+
return self.policy
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# ===============================================
|
|
280
|
+
# BUILT-IN POLICY CONSTRAINTS
|
|
281
|
+
# ===============================================
|
|
282
|
+
|
|
283
|
+
def length_constraint(min_len: int = 0, max_len: int = float('inf')):
|
|
284
|
+
"""Create a length constraint for strings"""
|
|
285
|
+
def check(value: Object, context: Dict[str, Any]) -> BooleanObj:
|
|
286
|
+
if isinstance(value, String):
|
|
287
|
+
length = len(value.value)
|
|
288
|
+
return BooleanObj(min_len <= length <= max_len)
|
|
289
|
+
return BooleanObj(False)
|
|
290
|
+
return check
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def contains_constraint(substring: str):
|
|
294
|
+
"""Create a contains constraint for strings"""
|
|
295
|
+
def check(value: Object, context: Dict[str, Any]) -> BooleanObj:
|
|
296
|
+
if isinstance(value, String):
|
|
297
|
+
return BooleanObj(substring in value.value)
|
|
298
|
+
return BooleanObj(False)
|
|
299
|
+
return check
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def range_constraint(min_val: int = float('-inf'), max_val: int = float('inf')):
|
|
303
|
+
"""Create a range constraint for numbers"""
|
|
304
|
+
def check(value: Object, context: Dict[str, Any]) -> BooleanObj:
|
|
305
|
+
if isinstance(value, Integer):
|
|
306
|
+
return BooleanObj(min_val <= value.value <= max_val)
|
|
307
|
+
return BooleanObj(False)
|
|
308
|
+
return check
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def equality_constraint(expected_value: Any):
|
|
312
|
+
"""Create an equality constraint"""
|
|
313
|
+
def check(value: Object, context: Dict[str, Any]) -> BooleanObj:
|
|
314
|
+
if hasattr(value, 'value'):
|
|
315
|
+
return BooleanObj(value.value == expected_value)
|
|
316
|
+
return BooleanObj(value == expected_value)
|
|
317
|
+
return check
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def caller_constraint(allowed_callers: List[str]):
|
|
321
|
+
"""Create a constraint checking TX.caller"""
|
|
322
|
+
def check(value: Object, context: Dict[str, Any]) -> BooleanObj:
|
|
323
|
+
caller = context.get('TX', {}).get('caller', '')
|
|
324
|
+
if isinstance(caller, String):
|
|
325
|
+
caller = caller.value
|
|
326
|
+
return BooleanObj(caller in allowed_callers)
|
|
327
|
+
return check
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
# ===============================================
|
|
331
|
+
# UTILITY FUNCTIONS
|
|
332
|
+
# ===============================================
|
|
333
|
+
|
|
334
|
+
def create_policy(target_name: str) -> PolicyBuilder:
|
|
335
|
+
"""Create a new policy builder"""
|
|
336
|
+
return PolicyBuilder(target_name)
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def protect_target(target_name: str, policy: ProtectionPolicy, original_fn: Callable):
|
|
340
|
+
"""Register a target with protection policy"""
|
|
341
|
+
registry = get_policy_registry()
|
|
342
|
+
registry.protect_function(target_name, original_fn, policy)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def check_policy(target_name: str, context: Dict[str, Any]) -> tuple[bool, List[str]]:
|
|
346
|
+
"""Check if context passes policy for target"""
|
|
347
|
+
registry = get_policy_registry()
|
|
348
|
+
policy = registry.get_policy(target_name)
|
|
349
|
+
|
|
350
|
+
if not policy:
|
|
351
|
+
return True, [] # No policy means no restrictions
|
|
352
|
+
|
|
353
|
+
return policy.evaluate(context)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def execute_protected(target_name: str, context: Dict[str, Any]):
|
|
357
|
+
"""Execute a protected function"""
|
|
358
|
+
registry = get_policy_registry()
|
|
359
|
+
return registry.execute_protected(target_name, context)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def get_audit_summary() -> Dict[str, Any]:
|
|
363
|
+
"""Get audit summary for all policies"""
|
|
364
|
+
registry = get_policy_registry()
|
|
365
|
+
return registry.get_audit_summary()
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""Performance profiler for Zexus code."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
import tracemalloc
|
|
5
|
+
from typing import Dict, List, Any
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from collections import defaultdict
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class FunctionProfile:
|
|
12
|
+
"""Profile data for a function."""
|
|
13
|
+
name: str
|
|
14
|
+
calls: int = 0
|
|
15
|
+
total_time: float = 0.0
|
|
16
|
+
self_time: float = 0.0
|
|
17
|
+
memory_allocated: int = 0
|
|
18
|
+
memory_peak: int = 0
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class ProfileReport:
|
|
23
|
+
"""Complete profiling report."""
|
|
24
|
+
total_time: float
|
|
25
|
+
total_calls: int
|
|
26
|
+
memory_peak: int
|
|
27
|
+
functions: Dict[str, FunctionProfile] = field(default_factory=dict)
|
|
28
|
+
hotspots: List[FunctionProfile] = field(default_factory=list)
|
|
29
|
+
|
|
30
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
31
|
+
"""Convert report to dictionary."""
|
|
32
|
+
return {
|
|
33
|
+
'total_time': self.total_time,
|
|
34
|
+
'total_calls': self.total_calls,
|
|
35
|
+
'memory_peak': self.memory_peak,
|
|
36
|
+
'functions': {
|
|
37
|
+
name: {
|
|
38
|
+
'calls': prof.calls,
|
|
39
|
+
'total_time': prof.total_time,
|
|
40
|
+
'self_time': prof.self_time,
|
|
41
|
+
'memory_allocated': prof.memory_allocated,
|
|
42
|
+
'memory_peak': prof.memory_peak
|
|
43
|
+
}
|
|
44
|
+
for name, prof in self.functions.items()
|
|
45
|
+
},
|
|
46
|
+
'hotspots': [
|
|
47
|
+
{
|
|
48
|
+
'name': prof.name,
|
|
49
|
+
'calls': prof.calls,
|
|
50
|
+
'total_time': prof.total_time,
|
|
51
|
+
'self_time': prof.self_time
|
|
52
|
+
}
|
|
53
|
+
for prof in self.hotspots
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Profiler:
|
|
59
|
+
"""Performance profiler for Zexus code execution."""
|
|
60
|
+
|
|
61
|
+
def __init__(self):
|
|
62
|
+
self.enabled = False
|
|
63
|
+
self.start_time = 0.0
|
|
64
|
+
self.functions = {}
|
|
65
|
+
self.call_stack = []
|
|
66
|
+
self.memory_enabled = False
|
|
67
|
+
|
|
68
|
+
def start(self, enable_memory: bool = True):
|
|
69
|
+
"""Start profiling."""
|
|
70
|
+
self.enabled = True
|
|
71
|
+
self.memory_enabled = enable_memory
|
|
72
|
+
self.start_time = time.time()
|
|
73
|
+
self.functions = {}
|
|
74
|
+
self.call_stack = []
|
|
75
|
+
|
|
76
|
+
if enable_memory:
|
|
77
|
+
tracemalloc.start()
|
|
78
|
+
|
|
79
|
+
def stop(self) -> ProfileReport:
|
|
80
|
+
"""Stop profiling and generate report."""
|
|
81
|
+
self.enabled = False
|
|
82
|
+
total_time = time.time() - self.start_time
|
|
83
|
+
|
|
84
|
+
memory_peak = 0
|
|
85
|
+
if self.memory_enabled:
|
|
86
|
+
_, peak = tracemalloc.get_traced_memory()
|
|
87
|
+
memory_peak = peak
|
|
88
|
+
tracemalloc.stop()
|
|
89
|
+
|
|
90
|
+
# Calculate total calls
|
|
91
|
+
total_calls = sum(prof.calls for prof in self.functions.values())
|
|
92
|
+
|
|
93
|
+
# Identify hotspots (functions taking most time)
|
|
94
|
+
hotspots = sorted(
|
|
95
|
+
self.functions.values(),
|
|
96
|
+
key=lambda p: p.total_time,
|
|
97
|
+
reverse=True
|
|
98
|
+
)[:10] # Top 10 hotspots
|
|
99
|
+
|
|
100
|
+
return ProfileReport(
|
|
101
|
+
total_time=total_time,
|
|
102
|
+
total_calls=total_calls,
|
|
103
|
+
memory_peak=memory_peak,
|
|
104
|
+
functions=self.functions,
|
|
105
|
+
hotspots=hotspots
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def enter_function(self, name: str):
|
|
109
|
+
"""Record entering a function."""
|
|
110
|
+
if not self.enabled:
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
if name not in self.functions:
|
|
114
|
+
self.functions[name] = FunctionProfile(name=name)
|
|
115
|
+
|
|
116
|
+
profile = self.functions[name]
|
|
117
|
+
profile.calls += 1
|
|
118
|
+
|
|
119
|
+
# Record memory if enabled
|
|
120
|
+
if self.memory_enabled:
|
|
121
|
+
current, _ = tracemalloc.get_traced_memory()
|
|
122
|
+
profile.memory_allocated = current
|
|
123
|
+
|
|
124
|
+
# Push onto call stack
|
|
125
|
+
self.call_stack.append({
|
|
126
|
+
'name': name,
|
|
127
|
+
'start_time': time.time(),
|
|
128
|
+
'start_memory': profile.memory_allocated if self.memory_enabled else 0
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
def exit_function(self, name: str):
|
|
132
|
+
"""Record exiting a function."""
|
|
133
|
+
if not self.enabled or not self.call_stack:
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
# Pop from call stack
|
|
137
|
+
call_info = self.call_stack.pop()
|
|
138
|
+
|
|
139
|
+
if call_info['name'] != name:
|
|
140
|
+
# Stack mismatch - log warning
|
|
141
|
+
import logging
|
|
142
|
+
logger = logging.getLogger(__name__)
|
|
143
|
+
logger.warning(f"Profile stack mismatch. Expected {call_info['name']}, got {name}")
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
# Calculate elapsed time
|
|
147
|
+
elapsed = time.time() - call_info['start_time']
|
|
148
|
+
|
|
149
|
+
profile = self.functions[name]
|
|
150
|
+
profile.total_time += elapsed
|
|
151
|
+
profile.self_time += elapsed
|
|
152
|
+
|
|
153
|
+
# Update memory if enabled
|
|
154
|
+
if self.memory_enabled:
|
|
155
|
+
current, peak = tracemalloc.get_traced_memory()
|
|
156
|
+
profile.memory_peak = max(profile.memory_peak, peak)
|
|
157
|
+
|
|
158
|
+
# Subtract time from parent if exists
|
|
159
|
+
if self.call_stack:
|
|
160
|
+
parent_name = self.call_stack[-1]['name']
|
|
161
|
+
if parent_name in self.functions:
|
|
162
|
+
self.functions[parent_name].self_time -= elapsed
|
|
163
|
+
|
|
164
|
+
def print_report(self, report: ProfileReport, top_n: int = 20):
|
|
165
|
+
"""Print profiling report."""
|
|
166
|
+
print("\n" + "="*80)
|
|
167
|
+
print("ZEXUS PERFORMANCE PROFILE REPORT")
|
|
168
|
+
print("="*80)
|
|
169
|
+
print(f"\nTotal Time: {report.total_time:.4f} seconds")
|
|
170
|
+
print(f"Total Calls: {report.total_calls}")
|
|
171
|
+
print(f"Peak Memory: {report.memory_peak / 1024 / 1024:.2f} MB")
|
|
172
|
+
|
|
173
|
+
print(f"\n{'Function':<40} {'Calls':>10} {'Total Time':>15} {'Self Time':>15} {'Avg Time':>15}")
|
|
174
|
+
print("-"*100)
|
|
175
|
+
|
|
176
|
+
# Sort by total time
|
|
177
|
+
sorted_functions = sorted(
|
|
178
|
+
report.functions.values(),
|
|
179
|
+
key=lambda p: p.total_time,
|
|
180
|
+
reverse=True
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
for prof in sorted_functions[:top_n]:
|
|
184
|
+
avg_time = prof.total_time / prof.calls if prof.calls > 0 else 0
|
|
185
|
+
print(f"{prof.name:<40} {prof.calls:>10} {prof.total_time:>15.4f}s {prof.self_time:>15.4f}s {avg_time:>15.6f}s")
|
|
186
|
+
|
|
187
|
+
print("\n" + "="*80)
|
|
188
|
+
print("TOP HOTSPOTS (by total time)")
|
|
189
|
+
print("="*80)
|
|
190
|
+
|
|
191
|
+
for i, prof in enumerate(report.hotspots[:10], 1):
|
|
192
|
+
pct = (prof.total_time / report.total_time * 100) if report.total_time > 0 else 0
|
|
193
|
+
print(f"{i}. {prof.name}: {prof.total_time:.4f}s ({pct:.1f}%)")
|
|
194
|
+
|
|
195
|
+
print("="*80 + "\n")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
# Global profiler instance
|
|
199
|
+
_profiler = Profiler()
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def start_profiling(enable_memory: bool = True):
|
|
203
|
+
"""Start global profiler."""
|
|
204
|
+
_profiler.start(enable_memory)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def stop_profiling() -> ProfileReport:
|
|
208
|
+
"""Stop global profiler and get report."""
|
|
209
|
+
return _profiler.stop()
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def print_profile():
|
|
213
|
+
"""Print current profile."""
|
|
214
|
+
report = stop_profiling()
|
|
215
|
+
_profiler.print_report(report)
|
|
216
|
+
return report
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def profile_function(func):
|
|
220
|
+
"""Decorator to profile a function."""
|
|
221
|
+
def wrapper(*args, **kwargs):
|
|
222
|
+
_profiler.enter_function(func.__name__)
|
|
223
|
+
try:
|
|
224
|
+
result = func(*args, **kwargs)
|
|
225
|
+
return result
|
|
226
|
+
finally:
|
|
227
|
+
_profiler.exit_function(func.__name__)
|
|
228
|
+
return wrapper
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def get_profiler() -> Profiler:
|
|
232
|
+
"""Get global profiler instance."""
|
|
233
|
+
return _profiler
|