omnibase_infra 0.2.7__py3-none-any.whl → 0.2.9__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.
- omnibase_infra/__init__.py +1 -1
- omnibase_infra/enums/__init__.py +4 -0
- omnibase_infra/enums/enum_declarative_node_violation.py +102 -0
- omnibase_infra/event_bus/adapters/__init__.py +31 -0
- omnibase_infra/event_bus/adapters/adapter_protocol_event_publisher_kafka.py +517 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +113 -1
- omnibase_infra/models/__init__.py +9 -0
- omnibase_infra/models/event_bus/__init__.py +22 -0
- omnibase_infra/models/event_bus/model_consumer_retry_config.py +367 -0
- omnibase_infra/models/event_bus/model_dlq_config.py +177 -0
- omnibase_infra/models/event_bus/model_idempotency_config.py +131 -0
- omnibase_infra/models/event_bus/model_offset_policy_config.py +107 -0
- omnibase_infra/models/resilience/model_circuit_breaker_config.py +15 -0
- omnibase_infra/models/validation/__init__.py +8 -0
- omnibase_infra/models/validation/model_declarative_node_validation_result.py +139 -0
- omnibase_infra/models/validation/model_declarative_node_violation.py +169 -0
- omnibase_infra/nodes/architecture_validator/__init__.py +28 -7
- omnibase_infra/nodes/architecture_validator/constants.py +36 -0
- omnibase_infra/nodes/architecture_validator/handlers/__init__.py +28 -0
- omnibase_infra/nodes/architecture_validator/handlers/contract.yaml +120 -0
- omnibase_infra/nodes/architecture_validator/handlers/handler_architecture_validation.py +359 -0
- omnibase_infra/nodes/architecture_validator/node.py +1 -0
- omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +48 -336
- omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +16 -2
- omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +14 -4
- omnibase_infra/nodes/node_ledger_projection_compute/handlers/__init__.py +18 -0
- omnibase_infra/nodes/node_ledger_projection_compute/handlers/contract.yaml +53 -0
- omnibase_infra/nodes/node_ledger_projection_compute/handlers/handler_ledger_projection.py +354 -0
- omnibase_infra/nodes/node_ledger_projection_compute/node.py +20 -256
- omnibase_infra/nodes/node_registry_effect/node.py +20 -73
- omnibase_infra/protocols/protocol_dispatch_engine.py +90 -0
- omnibase_infra/runtime/__init__.py +11 -0
- omnibase_infra/runtime/baseline_subscriptions.py +150 -0
- omnibase_infra/runtime/event_bus_subcontract_wiring.py +455 -24
- omnibase_infra/runtime/kafka_contract_source.py +13 -5
- omnibase_infra/runtime/service_message_dispatch_engine.py +112 -0
- omnibase_infra/runtime/service_runtime_host_process.py +6 -11
- omnibase_infra/services/__init__.py +36 -0
- omnibase_infra/services/contract_publisher/__init__.py +95 -0
- omnibase_infra/services/contract_publisher/config.py +199 -0
- omnibase_infra/services/contract_publisher/errors.py +243 -0
- omnibase_infra/services/contract_publisher/models/__init__.py +28 -0
- omnibase_infra/services/contract_publisher/models/model_contract_error.py +67 -0
- omnibase_infra/services/contract_publisher/models/model_infra_error.py +62 -0
- omnibase_infra/services/contract_publisher/models/model_publish_result.py +112 -0
- omnibase_infra/services/contract_publisher/models/model_publish_stats.py +79 -0
- omnibase_infra/services/contract_publisher/service.py +617 -0
- omnibase_infra/services/contract_publisher/sources/__init__.py +52 -0
- omnibase_infra/services/contract_publisher/sources/model_discovered.py +155 -0
- omnibase_infra/services/contract_publisher/sources/protocol.py +101 -0
- omnibase_infra/services/contract_publisher/sources/source_composite.py +309 -0
- omnibase_infra/services/contract_publisher/sources/source_filesystem.py +174 -0
- omnibase_infra/services/contract_publisher/sources/source_package.py +221 -0
- omnibase_infra/services/observability/__init__.py +40 -0
- omnibase_infra/services/observability/agent_actions/__init__.py +64 -0
- omnibase_infra/services/observability/agent_actions/config.py +209 -0
- omnibase_infra/services/observability/agent_actions/consumer.py +1320 -0
- omnibase_infra/services/observability/agent_actions/models/__init__.py +87 -0
- omnibase_infra/services/observability/agent_actions/models/model_agent_action.py +142 -0
- omnibase_infra/services/observability/agent_actions/models/model_detection_failure.py +125 -0
- omnibase_infra/services/observability/agent_actions/models/model_envelope.py +85 -0
- omnibase_infra/services/observability/agent_actions/models/model_execution_log.py +159 -0
- omnibase_infra/services/observability/agent_actions/models/model_performance_metric.py +130 -0
- omnibase_infra/services/observability/agent_actions/models/model_routing_decision.py +138 -0
- omnibase_infra/services/observability/agent_actions/models/model_transformation_event.py +124 -0
- omnibase_infra/services/observability/agent_actions/tests/__init__.py +20 -0
- omnibase_infra/services/observability/agent_actions/tests/test_consumer.py +1154 -0
- omnibase_infra/services/observability/agent_actions/tests/test_models.py +645 -0
- omnibase_infra/services/observability/agent_actions/tests/test_writer.py +709 -0
- omnibase_infra/services/observability/agent_actions/writer_postgres.py +926 -0
- omnibase_infra/validation/__init__.py +12 -0
- omnibase_infra/validation/contracts/declarative_node.validation.yaml +143 -0
- omnibase_infra/validation/validation_exemptions.yaml +93 -0
- omnibase_infra/validation/validator_declarative_node.py +850 -0
- {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/METADATA +3 -3
- {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/RECORD +79 -27
- {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/WHEEL +0 -0
- {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/entry_points.txt +0 -0
- {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,383 +1,95 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
# Copyright (c) 2025 OmniNode Team
|
|
3
|
-
"""COMPUTE_GENERIC node for
|
|
3
|
+
"""Declarative COMPUTE_GENERIC node for architecture validation.
|
|
4
4
|
|
|
5
|
-
This module implements NodeArchitectureValidatorCompute, a
|
|
6
|
-
that validates nodes and handlers against architecture rules.
|
|
7
|
-
|
|
5
|
+
This module implements NodeArchitectureValidatorCompute, a declarative compute node
|
|
6
|
+
that validates nodes and handlers against architecture rules. All validation logic
|
|
7
|
+
is delegated to HandlerArchitectureValidation via the contract-driven handler pattern.
|
|
8
8
|
|
|
9
9
|
Design Pattern:
|
|
10
|
-
NodeArchitectureValidatorCompute follows the
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- Thread-safe: can be invoked concurrently with different requests
|
|
10
|
+
NodeArchitectureValidatorCompute follows the ONEX declarative node pattern:
|
|
11
|
+
- Extends NodeCompute from omnibase_core
|
|
12
|
+
- All behavior defined in contract.yaml
|
|
13
|
+
- Handler contains actual validation logic
|
|
14
|
+
- Node is a lightweight shell with no custom methods
|
|
16
15
|
|
|
17
16
|
Thread Safety:
|
|
18
|
-
The
|
|
19
|
-
|
|
17
|
+
The node delegates all operations to the handler, which is thread-safe
|
|
18
|
+
when used with immutable rules.
|
|
20
19
|
|
|
21
20
|
Related:
|
|
22
21
|
- OMN-1138: Architecture Validator for omnibase_infra
|
|
23
|
-
- OMN-
|
|
22
|
+
- OMN-1726: Refactor to declarative pattern with contract-driven handler
|
|
24
23
|
|
|
25
24
|
Example:
|
|
26
25
|
>>> from omnibase_core.models.container import ModelONEXContainer
|
|
27
26
|
>>> from omnibase_infra.nodes.architecture_validator import (
|
|
28
27
|
... NodeArchitectureValidatorCompute,
|
|
29
|
-
...
|
|
28
|
+
... )
|
|
29
|
+
>>> from omnibase_infra.nodes.architecture_validator.handlers import (
|
|
30
|
+
... HandlerArchitectureValidation,
|
|
30
31
|
... )
|
|
31
32
|
>>>
|
|
32
|
-
>>> # Create
|
|
33
|
+
>>> # Create declarative node
|
|
33
34
|
>>> container = ModelONEXContainer()
|
|
34
|
-
>>>
|
|
35
|
-
... container=container,
|
|
36
|
-
... rules=(no_handler_publishing_rule, no_workflow_in_reducer_rule),
|
|
37
|
-
... )
|
|
35
|
+
>>> node = NodeArchitectureValidatorCompute(container)
|
|
38
36
|
>>>
|
|
39
|
-
>>> #
|
|
40
|
-
>>>
|
|
41
|
-
|
|
42
|
-
... handlers=(my_handler,),
|
|
43
|
-
... )
|
|
44
|
-
>>> result = validator.compute(request)
|
|
45
|
-
>>> if result.valid:
|
|
46
|
-
... print("All architecture rules passed")
|
|
47
|
-
... else:
|
|
48
|
-
... for v in result.violations:
|
|
49
|
-
... print(f"Violation: {v.format_for_logging()}")
|
|
37
|
+
>>> # Use handler for validation
|
|
38
|
+
>>> handler = HandlerArchitectureValidation(rules=my_rules)
|
|
39
|
+
>>> result = handler.handle(request)
|
|
50
40
|
|
|
51
41
|
.. versionadded:: 0.8.0
|
|
52
42
|
Created as part of OMN-1138 Architecture Validator implementation.
|
|
43
|
+
|
|
44
|
+
.. versionchanged:: 0.9.0
|
|
45
|
+
Refactored to declarative pattern as part of OMN-1726. All validation
|
|
46
|
+
logic moved to HandlerArchitectureValidation.
|
|
53
47
|
"""
|
|
54
48
|
|
|
55
49
|
from __future__ import annotations
|
|
56
50
|
|
|
57
|
-
from typing import TYPE_CHECKING
|
|
58
|
-
|
|
59
51
|
from omnibase_core.nodes import NodeCompute
|
|
60
|
-
from omnibase_infra.enums import EnumInfraTransportType
|
|
61
|
-
from omnibase_infra.errors import ProtocolConfigurationError
|
|
62
|
-
from omnibase_infra.models.errors.model_infra_error_context import (
|
|
63
|
-
ModelInfraErrorContext,
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
if TYPE_CHECKING:
|
|
67
|
-
from omnibase_core.models.container.model_onex_container import ModelONEXContainer
|
|
68
|
-
|
|
69
52
|
from omnibase_infra.nodes.architecture_validator.models import (
|
|
70
53
|
ModelArchitectureValidationRequest,
|
|
71
54
|
ModelArchitectureValidationResult,
|
|
72
|
-
ModelArchitectureViolation,
|
|
73
|
-
ModelRuleCheckResult,
|
|
74
|
-
)
|
|
75
|
-
from omnibase_infra.nodes.architecture_validator.protocols import (
|
|
76
|
-
ProtocolArchitectureRule,
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
# Supported rule IDs from contract_architecture_validator.yaml
|
|
80
|
-
# These are the only rules that this validator node is designed to handle.
|
|
81
|
-
# Any rule not in this set indicates a misconfiguration or version mismatch.
|
|
82
|
-
SUPPORTED_RULE_IDS: frozenset[str] = frozenset(
|
|
83
|
-
{
|
|
84
|
-
"NO_HANDLER_PUBLISHING",
|
|
85
|
-
"PURE_REDUCERS",
|
|
86
|
-
"NO_FSM_IN_ORCHESTRATORS",
|
|
87
|
-
"NO_WORKFLOW_IN_REDUCERS",
|
|
88
|
-
"NO_DIRECT_HANDLER_DISPATCH",
|
|
89
|
-
"NO_LOCAL_ONLY_PATHS",
|
|
90
|
-
}
|
|
91
55
|
)
|
|
92
56
|
|
|
93
|
-
__all__ = ["NodeArchitectureValidatorCompute"
|
|
57
|
+
__all__ = ["NodeArchitectureValidatorCompute"]
|
|
94
58
|
|
|
95
59
|
|
|
96
60
|
class NodeArchitectureValidatorCompute(
|
|
97
61
|
NodeCompute[ModelArchitectureValidationRequest, ModelArchitectureValidationResult]
|
|
98
62
|
):
|
|
99
|
-
"""COMPUTE_GENERIC node for
|
|
63
|
+
"""Declarative COMPUTE_GENERIC node for architecture validation.
|
|
64
|
+
|
|
65
|
+
This node follows the ONEX declarative pattern - all behavior is defined
|
|
66
|
+
in contract.yaml and delegated to HandlerArchitectureValidation. The node
|
|
67
|
+
itself is a lightweight shell with no custom methods.
|
|
68
|
+
|
|
69
|
+
Validation Logic:
|
|
70
|
+
All validation logic is implemented in HandlerArchitectureValidation.
|
|
71
|
+
The handler validates nodes and handlers against architecture rules
|
|
72
|
+
and returns ModelArchitectureValidationResult.
|
|
100
73
|
|
|
101
|
-
|
|
102
|
-
|
|
74
|
+
Usage:
|
|
75
|
+
For validation operations, use HandlerArchitectureValidation directly:
|
|
76
|
+
|
|
77
|
+
>>> from omnibase_infra.nodes.architecture_validator.handlers import (
|
|
78
|
+
... HandlerArchitectureValidation,
|
|
79
|
+
... )
|
|
80
|
+
>>> handler = HandlerArchitectureValidation(rules=my_rules)
|
|
81
|
+
>>> result = handler.handle(request)
|
|
103
82
|
|
|
104
83
|
Can be called:
|
|
105
84
|
- At startup (direct call, pre-runtime validation)
|
|
106
85
|
- During runtime (via orchestrator for dynamic validation)
|
|
107
86
|
- From CI/CD (standalone validation in test/build pipelines)
|
|
108
87
|
|
|
109
|
-
Attributes:
|
|
110
|
-
_rules: Tuple of architecture rules to enforce during validation.
|
|
111
|
-
|
|
112
|
-
Thread Safety:
|
|
113
|
-
This node is thread-safe when:
|
|
114
|
-
- Rules are stateless (recommended)
|
|
115
|
-
- Request objects are not shared across threads
|
|
116
|
-
- Each compute() call operates independently
|
|
117
|
-
|
|
118
|
-
Example:
|
|
119
|
-
>>> # Pre-runtime validation
|
|
120
|
-
>>> validator = NodeArchitectureValidatorCompute(container, rules=rules)
|
|
121
|
-
>>> result = validator.compute(request)
|
|
122
|
-
>>> if not result:
|
|
123
|
-
... from omnibase_infra.enums import EnumInfraTransportType
|
|
124
|
-
... from omnibase_infra.errors import (
|
|
125
|
-
... ModelInfraErrorContext,
|
|
126
|
-
... ProtocolConfigurationError,
|
|
127
|
-
... )
|
|
128
|
-
... context = ModelInfraErrorContext.with_correlation(
|
|
129
|
-
... transport_type=EnumInfraTransportType.RUNTIME,
|
|
130
|
-
... operation="architecture_validation",
|
|
131
|
-
... )
|
|
132
|
-
... raise ProtocolConfigurationError(
|
|
133
|
-
... f"Validation failed: {result.violation_count} violations",
|
|
134
|
-
... context=context,
|
|
135
|
-
... code="ARCHITECTURE_VALIDATION_FAILED",
|
|
136
|
-
... violations=[v.to_structured_dict() for v in result.violations],
|
|
137
|
-
... )
|
|
138
|
-
|
|
139
|
-
>>> # CI/CD pipeline validation
|
|
140
|
-
>>> result = validator.compute(ModelArchitectureValidationRequest(
|
|
141
|
-
... nodes=discovered_nodes,
|
|
142
|
-
... handlers=discovered_handlers,
|
|
143
|
-
... fail_fast=True, # Stop on first violation for fast feedback
|
|
144
|
-
... ))
|
|
145
|
-
|
|
146
88
|
.. versionadded:: 0.8.0
|
|
147
|
-
"""
|
|
148
|
-
|
|
149
|
-
def __init__(
|
|
150
|
-
self,
|
|
151
|
-
container: ModelONEXContainer,
|
|
152
|
-
rules: tuple[ProtocolArchitectureRule, ...] = (),
|
|
153
|
-
) -> None:
|
|
154
|
-
"""Initialize validator with container and rules.
|
|
155
|
-
|
|
156
|
-
Args:
|
|
157
|
-
container: ONEX dependency injection container for node infrastructure.
|
|
158
|
-
rules: Architecture rules to enforce. These should implement
|
|
159
|
-
ProtocolArchitectureRule. Rules from OMN-1099 validators can be
|
|
160
|
-
passed directly.
|
|
161
|
-
|
|
162
|
-
Example:
|
|
163
|
-
>>> from omnibase_core.models.container import ModelONEXContainer
|
|
164
|
-
>>> from my_rules import NoHandlerPublishingRule, NoWorkflowInReducerRule
|
|
165
|
-
>>>
|
|
166
|
-
>>> container = ModelONEXContainer()
|
|
167
|
-
>>> validator = NodeArchitectureValidatorCompute(
|
|
168
|
-
... container=container,
|
|
169
|
-
... rules=(NoHandlerPublishingRule(), NoWorkflowInReducerRule()),
|
|
170
|
-
... )
|
|
171
|
-
|
|
172
|
-
.. versionadded:: 0.8.0
|
|
173
|
-
"""
|
|
174
|
-
super().__init__(container)
|
|
175
|
-
self._validate_rules_against_contract(rules)
|
|
176
|
-
self._rules = rules
|
|
177
|
-
|
|
178
|
-
def _validate_rules_against_contract(
|
|
179
|
-
self,
|
|
180
|
-
rules: tuple[ProtocolArchitectureRule, ...],
|
|
181
|
-
) -> None:
|
|
182
|
-
"""Validate that all provided rules are in the contract's supported_rules.
|
|
183
|
-
|
|
184
|
-
This validation ensures that only rules defined in the contract's
|
|
185
|
-
supported_rules list can be used with this validator. Using unsupported
|
|
186
|
-
rules would indicate a misconfiguration or version mismatch between
|
|
187
|
-
the validator and the rules being passed.
|
|
188
|
-
|
|
189
|
-
Args:
|
|
190
|
-
rules: Tuple of architecture rules to validate against the contract.
|
|
191
89
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Includes ModelInfraErrorContext with RUNTIME transport type.
|
|
197
|
-
|
|
198
|
-
Example:
|
|
199
|
-
>>> # This is called automatically in __init__
|
|
200
|
-
>>> validator._validate_rules_against_contract((
|
|
201
|
-
... NoHandlerPublishingRule(), # Valid: in supported_rules
|
|
202
|
-
... PureReducersRule(), # Valid: in supported_rules
|
|
203
|
-
... ))
|
|
204
|
-
>>> # No error raised
|
|
205
|
-
|
|
206
|
-
>>> # Invalid rule raises ProtocolConfigurationError
|
|
207
|
-
>>> validator._validate_rules_against_contract((
|
|
208
|
-
... UnknownRule(), # rule_id="UNKNOWN_RULE"
|
|
209
|
-
... ))
|
|
210
|
-
ProtocolConfigurationError: Rule 'UNKNOWN_RULE' is not in contract...
|
|
211
|
-
|
|
212
|
-
.. versionadded:: 0.8.0
|
|
213
|
-
"""
|
|
214
|
-
for rule in rules:
|
|
215
|
-
if rule.rule_id not in SUPPORTED_RULE_IDS:
|
|
216
|
-
context = ModelInfraErrorContext.with_correlation(
|
|
217
|
-
transport_type=EnumInfraTransportType.RUNTIME,
|
|
218
|
-
operation="validate_rules_against_contract",
|
|
219
|
-
)
|
|
220
|
-
raise ProtocolConfigurationError(
|
|
221
|
-
f"Rule '{rule.rule_id}' is not in contract supported_rules. "
|
|
222
|
-
f"Supported rules: {sorted(SUPPORTED_RULE_IDS)}",
|
|
223
|
-
context=context,
|
|
224
|
-
rule_id=rule.rule_id,
|
|
225
|
-
supported_rules=sorted(SUPPORTED_RULE_IDS),
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
def compute(
|
|
229
|
-
self,
|
|
230
|
-
request: ModelArchitectureValidationRequest,
|
|
231
|
-
) -> ModelArchitectureValidationResult:
|
|
232
|
-
"""Validate architecture compliance.
|
|
233
|
-
|
|
234
|
-
Applies all registered rules to the nodes and handlers in the request.
|
|
235
|
-
Returns a result containing any violations found and summary statistics.
|
|
236
|
-
|
|
237
|
-
This is a pure transformation with no side effects:
|
|
238
|
-
- Same input always produces same output
|
|
239
|
-
- Does not modify request, rules, or external state
|
|
240
|
-
- Safe to call concurrently from multiple threads
|
|
241
|
-
|
|
242
|
-
Args:
|
|
243
|
-
request: Validation request containing:
|
|
244
|
-
- nodes: Nodes to validate
|
|
245
|
-
- handlers: Handlers to validate
|
|
246
|
-
- rule_ids: Optional filter for specific rules
|
|
247
|
-
- fail_fast: Whether to stop on first violation
|
|
248
|
-
- correlation_id: For distributed tracing
|
|
249
|
-
|
|
250
|
-
Returns:
|
|
251
|
-
ModelArchitectureValidationResult with:
|
|
252
|
-
- violations: All violations found (empty if validation passed)
|
|
253
|
-
- rules_checked: IDs of rules that were evaluated
|
|
254
|
-
- nodes_checked: Count of nodes validated
|
|
255
|
-
- handlers_checked: Count of handlers validated
|
|
256
|
-
- correlation_id: Propagated from request
|
|
257
|
-
|
|
258
|
-
Example:
|
|
259
|
-
>>> # Check all rules
|
|
260
|
-
>>> result = validator.compute(ModelArchitectureValidationRequest(
|
|
261
|
-
... nodes=all_nodes,
|
|
262
|
-
... handlers=all_handlers,
|
|
263
|
-
... ))
|
|
264
|
-
>>> print(f"Checked {result.nodes_checked} nodes, {result.handlers_checked} handlers")
|
|
265
|
-
>>> print(f"Found {result.violation_count} violations")
|
|
266
|
-
|
|
267
|
-
>>> # Check specific rules only
|
|
268
|
-
>>> result = validator.compute(ModelArchitectureValidationRequest(
|
|
269
|
-
... nodes=all_nodes,
|
|
270
|
-
... rule_ids=("NO_HANDLER_PUBLISHING", "PURE_REDUCERS"),
|
|
271
|
-
... fail_fast=True,
|
|
272
|
-
... ))
|
|
273
|
-
|
|
274
|
-
.. versionadded:: 0.8.0
|
|
275
|
-
"""
|
|
276
|
-
violations: list[ModelArchitectureViolation] = []
|
|
277
|
-
rules_to_check = self._get_rules_to_check(request.rule_ids)
|
|
278
|
-
|
|
279
|
-
# Validate nodes
|
|
280
|
-
for node in request.nodes:
|
|
281
|
-
for rule in rules_to_check:
|
|
282
|
-
result = rule.check(node)
|
|
283
|
-
if not result.passed:
|
|
284
|
-
violation = self._create_violation(rule, node, result)
|
|
285
|
-
violations.append(violation)
|
|
286
|
-
if request.fail_fast:
|
|
287
|
-
return self._build_result(violations, rules_to_check, request)
|
|
288
|
-
|
|
289
|
-
# Validate handlers
|
|
290
|
-
for handler in request.handlers:
|
|
291
|
-
for rule in rules_to_check:
|
|
292
|
-
result = rule.check(handler)
|
|
293
|
-
if not result.passed:
|
|
294
|
-
violation = self._create_violation(rule, handler, result)
|
|
295
|
-
violations.append(violation)
|
|
296
|
-
if request.fail_fast:
|
|
297
|
-
return self._build_result(violations, rules_to_check, request)
|
|
298
|
-
|
|
299
|
-
return self._build_result(violations, rules_to_check, request)
|
|
300
|
-
|
|
301
|
-
def _get_rules_to_check(
|
|
302
|
-
self,
|
|
303
|
-
rule_ids: tuple[str, ...] | None,
|
|
304
|
-
) -> tuple[ProtocolArchitectureRule, ...]:
|
|
305
|
-
"""Get rules to check based on request filter.
|
|
306
|
-
|
|
307
|
-
Args:
|
|
308
|
-
rule_ids: Optional tuple of rule IDs to filter by.
|
|
309
|
-
If None, all registered rules are returned.
|
|
310
|
-
|
|
311
|
-
Returns:
|
|
312
|
-
Tuple of rules to check. If rule_ids is provided, only
|
|
313
|
-
rules with matching IDs are included.
|
|
314
|
-
|
|
315
|
-
Example:
|
|
316
|
-
>>> # No filter - returns all rules
|
|
317
|
-
>>> rules = validator._get_rules_to_check(None)
|
|
318
|
-
>>> len(rules) == len(validator._rules)
|
|
319
|
-
True
|
|
320
|
-
|
|
321
|
-
>>> # Filter by IDs
|
|
322
|
-
>>> rules = validator._get_rules_to_check(("RULE_A", "RULE_B"))
|
|
323
|
-
>>> all(r.rule_id in ("RULE_A", "RULE_B") for r in rules)
|
|
324
|
-
True
|
|
325
|
-
"""
|
|
326
|
-
if rule_ids is None:
|
|
327
|
-
return self._rules
|
|
328
|
-
return tuple(r for r in self._rules if r.rule_id in rule_ids)
|
|
329
|
-
|
|
330
|
-
def _create_violation(
|
|
331
|
-
self,
|
|
332
|
-
rule: ProtocolArchitectureRule,
|
|
333
|
-
target: object,
|
|
334
|
-
result: ModelRuleCheckResult,
|
|
335
|
-
) -> ModelArchitectureViolation:
|
|
336
|
-
"""Create violation from rule check result.
|
|
337
|
-
|
|
338
|
-
Args:
|
|
339
|
-
rule: The rule that was violated.
|
|
340
|
-
target: The node or handler that violated the rule.
|
|
341
|
-
result: The check result with violation details.
|
|
342
|
-
|
|
343
|
-
Returns:
|
|
344
|
-
ModelArchitectureViolation with full context for debugging
|
|
345
|
-
and remediation.
|
|
346
|
-
|
|
347
|
-
Note:
|
|
348
|
-
Uses getattr for target_name to handle both class types
|
|
349
|
-
(with __name__) and instances (fallback to str()).
|
|
350
|
-
"""
|
|
351
|
-
return ModelArchitectureViolation(
|
|
352
|
-
rule_id=rule.rule_id,
|
|
353
|
-
rule_name=rule.name,
|
|
354
|
-
severity=rule.severity,
|
|
355
|
-
target_type=type(target).__name__,
|
|
356
|
-
target_name=getattr(target, "__name__", str(target)),
|
|
357
|
-
message=result.message or rule.description,
|
|
358
|
-
details=result.details,
|
|
359
|
-
)
|
|
360
|
-
|
|
361
|
-
def _build_result(
|
|
362
|
-
self,
|
|
363
|
-
violations: list[ModelArchitectureViolation],
|
|
364
|
-
rules_checked: tuple[ProtocolArchitectureRule, ...],
|
|
365
|
-
request: ModelArchitectureValidationRequest,
|
|
366
|
-
) -> ModelArchitectureValidationResult:
|
|
367
|
-
"""Build final validation result.
|
|
368
|
-
|
|
369
|
-
Args:
|
|
370
|
-
violations: All violations found during validation.
|
|
371
|
-
rules_checked: Rules that were evaluated.
|
|
372
|
-
request: Original validation request (for counts and correlation_id).
|
|
90
|
+
.. versionchanged:: 0.9.0
|
|
91
|
+
Refactored to declarative pattern. All validation logic moved to
|
|
92
|
+
HandlerArchitectureValidation.
|
|
93
|
+
"""
|
|
373
94
|
|
|
374
|
-
|
|
375
|
-
ModelArchitectureValidationResult with complete validation summary.
|
|
376
|
-
"""
|
|
377
|
-
return ModelArchitectureValidationResult(
|
|
378
|
-
violations=tuple(violations),
|
|
379
|
-
rules_checked=tuple(r.rule_id for r in rules_checked),
|
|
380
|
-
nodes_checked=len(request.nodes),
|
|
381
|
-
handlers_checked=len(request.handlers),
|
|
382
|
-
correlation_id=request.correlation_id,
|
|
383
|
-
)
|
|
95
|
+
# Declarative node - all behavior defined in contract.yaml
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
# Copyright (c) 2026 OmniNode Team
|
|
3
3
|
"""Node Ledger Projection Compute - Platform event ledger projection node.
|
|
4
4
|
|
|
5
|
-
This package provides the NodeLedgerProjectionCompute, a COMPUTE node
|
|
6
|
-
subscribes to 7 platform event topics for event ledger persistence.
|
|
5
|
+
This package provides the NodeLedgerProjectionCompute, a declarative COMPUTE node
|
|
6
|
+
that subscribes to 7 platform event topics for event ledger persistence.
|
|
7
|
+
|
|
8
|
+
Architecture:
|
|
9
|
+
This node follows the ONEX declarative pattern where:
|
|
10
|
+
- NodeLedgerProjectionCompute is a declarative shell (no custom logic)
|
|
11
|
+
- HandlerLedgerProjection contains all compute logic
|
|
12
|
+
- contract.yaml defines behavior via handler_routing
|
|
7
13
|
|
|
8
14
|
Core Purpose:
|
|
9
15
|
Projects events from the platform event bus into the audit ledger,
|
|
@@ -25,18 +31,25 @@ Consumer Configuration:
|
|
|
25
31
|
|
|
26
32
|
Related Tickets:
|
|
27
33
|
- OMN-1648: Ledger Projection Compute Node
|
|
34
|
+
- OMN-1726: Refactor to declarative pattern
|
|
28
35
|
|
|
29
36
|
Example:
|
|
30
37
|
>>> from omnibase_core.container import ModelONEXContainer
|
|
31
38
|
>>> from omnibase_infra.nodes.node_ledger_projection_compute import (
|
|
32
39
|
... NodeLedgerProjectionCompute,
|
|
40
|
+
... HandlerLedgerProjection,
|
|
33
41
|
... RegistryInfraLedgerProjection,
|
|
34
42
|
... )
|
|
35
43
|
>>>
|
|
36
44
|
>>> container = ModelONEXContainer()
|
|
37
45
|
>>> node = RegistryInfraLedgerProjection.create_node(container)
|
|
46
|
+
>>> # Handler can be used directly for unit testing
|
|
47
|
+
>>> handler = HandlerLedgerProjection(container)
|
|
38
48
|
"""
|
|
39
49
|
|
|
50
|
+
from omnibase_infra.nodes.node_ledger_projection_compute.handlers import (
|
|
51
|
+
HandlerLedgerProjection,
|
|
52
|
+
)
|
|
40
53
|
from omnibase_infra.nodes.node_ledger_projection_compute.node import (
|
|
41
54
|
NodeLedgerProjectionCompute,
|
|
42
55
|
)
|
|
@@ -45,6 +58,7 @@ from omnibase_infra.nodes.node_ledger_projection_compute.registry import (
|
|
|
45
58
|
)
|
|
46
59
|
|
|
47
60
|
__all__ = [
|
|
61
|
+
"HandlerLedgerProjection",
|
|
48
62
|
"NodeLedgerProjectionCompute",
|
|
49
63
|
"RegistryInfraLedgerProjection",
|
|
50
64
|
]
|
|
@@ -64,11 +64,21 @@ input_model:
|
|
|
64
64
|
Kafka event message containing raw bytes payload and headers. The compute node processes events from all 7 subscribed topics.
|
|
65
65
|
|
|
66
66
|
output_model:
|
|
67
|
-
name: "
|
|
68
|
-
module: "
|
|
67
|
+
name: "ModelIntent"
|
|
68
|
+
module: "omnibase_core.models.reducer.model_intent"
|
|
69
69
|
description: >
|
|
70
|
-
|
|
70
|
+
ModelIntent wrapping ModelPayloadLedgerAppend to be passed to NodeLedgerWriteEffect. Contains the event data with Kafka position for idempotent writes.
|
|
71
71
|
|
|
72
|
+
# Handler routing - delegates compute logic to handler
|
|
73
|
+
handler_routing:
|
|
74
|
+
routing_strategy: "operation_match"
|
|
75
|
+
handlers:
|
|
76
|
+
- handler_type: "ledger_projection"
|
|
77
|
+
handler:
|
|
78
|
+
name: "HandlerLedgerProjection"
|
|
79
|
+
module: "omnibase_infra.nodes.node_ledger_projection_compute.handlers.handler_ledger_projection"
|
|
80
|
+
supported_operations:
|
|
81
|
+
- "ledger.project"
|
|
72
82
|
# Capabilities provided by this node
|
|
73
83
|
capabilities:
|
|
74
84
|
- name: "ledger.projection"
|
|
@@ -94,7 +104,7 @@ metadata:
|
|
|
94
104
|
author: "OmniNode Team"
|
|
95
105
|
license: "MIT"
|
|
96
106
|
created: "2026-01-29"
|
|
97
|
-
ticket: "OMN-1648"
|
|
107
|
+
ticket: "OMN-1648, OMN-1726"
|
|
98
108
|
tags:
|
|
99
109
|
- compute
|
|
100
110
|
- ledger
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 OmniNode Team
|
|
3
|
+
"""Handlers for ledger projection compute operations.
|
|
4
|
+
|
|
5
|
+
This package provides handlers for the ledger projection compute node:
|
|
6
|
+
- HandlerLedgerProjection: Transforms ModelEventMessage to ModelIntent
|
|
7
|
+
|
|
8
|
+
The handler implements best-effort metadata extraction, ensuring events
|
|
9
|
+
are never dropped due to parsing failures.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from omnibase_infra.nodes.node_ledger_projection_compute.handlers.handler_ledger_projection import (
|
|
13
|
+
HandlerLedgerProjection,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"HandlerLedgerProjection",
|
|
18
|
+
]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 OmniNode Team
|
|
3
|
+
# Contract for Ledger Projection Handler - transforms platform events to ledger intents
|
|
4
|
+
name: "handler_ledger_projection"
|
|
5
|
+
node_type: "COMPUTE_GENERIC"
|
|
6
|
+
description: "Ledger projection handler that transforms ModelEventMessage to ModelIntent with ModelPayloadLedgerAppend for audit ledger persistence"
|
|
7
|
+
contract_version:
|
|
8
|
+
major: 1
|
|
9
|
+
minor: 0
|
|
10
|
+
patch: 0
|
|
11
|
+
node_version:
|
|
12
|
+
major: 0
|
|
13
|
+
minor: 1
|
|
14
|
+
patch: 0
|
|
15
|
+
input_model:
|
|
16
|
+
name: "ModelEventMessage"
|
|
17
|
+
module: "omnibase_infra.event_bus.models.model_event_message"
|
|
18
|
+
output_model:
|
|
19
|
+
name: "ModelIntent"
|
|
20
|
+
module: "omnibase_core.models.reducer.model_intent"
|
|
21
|
+
handler_routing:
|
|
22
|
+
routing_strategy: "operation_match"
|
|
23
|
+
handlers:
|
|
24
|
+
- handler_type: "ledger_projection"
|
|
25
|
+
handler:
|
|
26
|
+
name: "HandlerLedgerProjection"
|
|
27
|
+
module: "omnibase_infra.nodes.node_ledger_projection_compute.handlers.handler_ledger_projection"
|
|
28
|
+
supported_operations:
|
|
29
|
+
- "ledger.project"
|
|
30
|
+
operation_bindings:
|
|
31
|
+
version:
|
|
32
|
+
major: 1
|
|
33
|
+
minor: 0
|
|
34
|
+
patch: 0
|
|
35
|
+
global_bindings:
|
|
36
|
+
- parameter_name: "correlation_id"
|
|
37
|
+
expression: "${envelope.correlation_id}"
|
|
38
|
+
required: false
|
|
39
|
+
bindings:
|
|
40
|
+
"ledger.project":
|
|
41
|
+
- parameter_name: "message"
|
|
42
|
+
expression: "${payload}"
|
|
43
|
+
required: true
|
|
44
|
+
metadata:
|
|
45
|
+
handler_id: "ledger-projection-handler"
|
|
46
|
+
handler_type: "compute_handler"
|
|
47
|
+
handler_category: "compute"
|
|
48
|
+
ticket: "OMN-1648"
|
|
49
|
+
features:
|
|
50
|
+
- "Best-effort metadata extraction"
|
|
51
|
+
- "Base64 encoding for bytes serialization"
|
|
52
|
+
- "Multi-topic subscription support"
|
|
53
|
+
- "Audit-purpose event consumption"
|