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.
Files changed (79) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/enums/__init__.py +4 -0
  3. omnibase_infra/enums/enum_declarative_node_violation.py +102 -0
  4. omnibase_infra/event_bus/adapters/__init__.py +31 -0
  5. omnibase_infra/event_bus/adapters/adapter_protocol_event_publisher_kafka.py +517 -0
  6. omnibase_infra/mixins/mixin_async_circuit_breaker.py +113 -1
  7. omnibase_infra/models/__init__.py +9 -0
  8. omnibase_infra/models/event_bus/__init__.py +22 -0
  9. omnibase_infra/models/event_bus/model_consumer_retry_config.py +367 -0
  10. omnibase_infra/models/event_bus/model_dlq_config.py +177 -0
  11. omnibase_infra/models/event_bus/model_idempotency_config.py +131 -0
  12. omnibase_infra/models/event_bus/model_offset_policy_config.py +107 -0
  13. omnibase_infra/models/resilience/model_circuit_breaker_config.py +15 -0
  14. omnibase_infra/models/validation/__init__.py +8 -0
  15. omnibase_infra/models/validation/model_declarative_node_validation_result.py +139 -0
  16. omnibase_infra/models/validation/model_declarative_node_violation.py +169 -0
  17. omnibase_infra/nodes/architecture_validator/__init__.py +28 -7
  18. omnibase_infra/nodes/architecture_validator/constants.py +36 -0
  19. omnibase_infra/nodes/architecture_validator/handlers/__init__.py +28 -0
  20. omnibase_infra/nodes/architecture_validator/handlers/contract.yaml +120 -0
  21. omnibase_infra/nodes/architecture_validator/handlers/handler_architecture_validation.py +359 -0
  22. omnibase_infra/nodes/architecture_validator/node.py +1 -0
  23. omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +48 -336
  24. omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +16 -2
  25. omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +14 -4
  26. omnibase_infra/nodes/node_ledger_projection_compute/handlers/__init__.py +18 -0
  27. omnibase_infra/nodes/node_ledger_projection_compute/handlers/contract.yaml +53 -0
  28. omnibase_infra/nodes/node_ledger_projection_compute/handlers/handler_ledger_projection.py +354 -0
  29. omnibase_infra/nodes/node_ledger_projection_compute/node.py +20 -256
  30. omnibase_infra/nodes/node_registry_effect/node.py +20 -73
  31. omnibase_infra/protocols/protocol_dispatch_engine.py +90 -0
  32. omnibase_infra/runtime/__init__.py +11 -0
  33. omnibase_infra/runtime/baseline_subscriptions.py +150 -0
  34. omnibase_infra/runtime/event_bus_subcontract_wiring.py +455 -24
  35. omnibase_infra/runtime/kafka_contract_source.py +13 -5
  36. omnibase_infra/runtime/service_message_dispatch_engine.py +112 -0
  37. omnibase_infra/runtime/service_runtime_host_process.py +6 -11
  38. omnibase_infra/services/__init__.py +36 -0
  39. omnibase_infra/services/contract_publisher/__init__.py +95 -0
  40. omnibase_infra/services/contract_publisher/config.py +199 -0
  41. omnibase_infra/services/contract_publisher/errors.py +243 -0
  42. omnibase_infra/services/contract_publisher/models/__init__.py +28 -0
  43. omnibase_infra/services/contract_publisher/models/model_contract_error.py +67 -0
  44. omnibase_infra/services/contract_publisher/models/model_infra_error.py +62 -0
  45. omnibase_infra/services/contract_publisher/models/model_publish_result.py +112 -0
  46. omnibase_infra/services/contract_publisher/models/model_publish_stats.py +79 -0
  47. omnibase_infra/services/contract_publisher/service.py +617 -0
  48. omnibase_infra/services/contract_publisher/sources/__init__.py +52 -0
  49. omnibase_infra/services/contract_publisher/sources/model_discovered.py +155 -0
  50. omnibase_infra/services/contract_publisher/sources/protocol.py +101 -0
  51. omnibase_infra/services/contract_publisher/sources/source_composite.py +309 -0
  52. omnibase_infra/services/contract_publisher/sources/source_filesystem.py +174 -0
  53. omnibase_infra/services/contract_publisher/sources/source_package.py +221 -0
  54. omnibase_infra/services/observability/__init__.py +40 -0
  55. omnibase_infra/services/observability/agent_actions/__init__.py +64 -0
  56. omnibase_infra/services/observability/agent_actions/config.py +209 -0
  57. omnibase_infra/services/observability/agent_actions/consumer.py +1320 -0
  58. omnibase_infra/services/observability/agent_actions/models/__init__.py +87 -0
  59. omnibase_infra/services/observability/agent_actions/models/model_agent_action.py +142 -0
  60. omnibase_infra/services/observability/agent_actions/models/model_detection_failure.py +125 -0
  61. omnibase_infra/services/observability/agent_actions/models/model_envelope.py +85 -0
  62. omnibase_infra/services/observability/agent_actions/models/model_execution_log.py +159 -0
  63. omnibase_infra/services/observability/agent_actions/models/model_performance_metric.py +130 -0
  64. omnibase_infra/services/observability/agent_actions/models/model_routing_decision.py +138 -0
  65. omnibase_infra/services/observability/agent_actions/models/model_transformation_event.py +124 -0
  66. omnibase_infra/services/observability/agent_actions/tests/__init__.py +20 -0
  67. omnibase_infra/services/observability/agent_actions/tests/test_consumer.py +1154 -0
  68. omnibase_infra/services/observability/agent_actions/tests/test_models.py +645 -0
  69. omnibase_infra/services/observability/agent_actions/tests/test_writer.py +709 -0
  70. omnibase_infra/services/observability/agent_actions/writer_postgres.py +926 -0
  71. omnibase_infra/validation/__init__.py +12 -0
  72. omnibase_infra/validation/contracts/declarative_node.validation.yaml +143 -0
  73. omnibase_infra/validation/validation_exemptions.yaml +93 -0
  74. omnibase_infra/validation/validator_declarative_node.py +850 -0
  75. {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/METADATA +3 -3
  76. {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/RECORD +79 -27
  77. {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/WHEEL +0 -0
  78. {omnibase_infra-0.2.7.dist-info → omnibase_infra-0.2.9.dist-info}/entry_points.txt +0 -0
  79. {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 validating architecture compliance.
3
+ """Declarative COMPUTE_GENERIC node for architecture validation.
4
4
 
5
- This module implements NodeArchitectureValidatorCompute, a pure transformation node
6
- that validates nodes and handlers against architecture rules. The validator can be
7
- invoked at startup (pre-runtime), during runtime (via orchestrator), or from CI/CD.
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 COMPUTE_GENERIC node pattern from the
11
- ONEX 4-node architecture. As a COMPUTE_GENERIC node:
12
- - Pure transformation: input -> output, no side effects
13
- - Deterministic: same input always produces same output
14
- - Stateless validation: rules are injected, not stored
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 validator is thread-safe when used with immutable rules. Each invocation
19
- of compute() is independent and does not modify shared state.
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-1099: Validators implementing ProtocolArchitectureRule
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
- ... ModelArchitectureValidationRequest,
28
+ ... )
29
+ >>> from omnibase_infra.nodes.architecture_validator.handlers import (
30
+ ... HandlerArchitectureValidation,
30
31
  ... )
31
32
  >>>
32
- >>> # Create validator with rules
33
+ >>> # Create declarative node
33
34
  >>> container = ModelONEXContainer()
34
- >>> validator = NodeArchitectureValidatorCompute(
35
- ... container=container,
36
- ... rules=(no_handler_publishing_rule, no_workflow_in_reducer_rule),
37
- ... )
35
+ >>> node = NodeArchitectureValidatorCompute(container)
38
36
  >>>
39
- >>> # Validate nodes and handlers
40
- >>> request = ModelArchitectureValidationRequest(
41
- ... nodes=(my_orchestrator, my_reducer),
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", "SUPPORTED_RULE_IDS"]
57
+ __all__ = ["NodeArchitectureValidatorCompute"]
94
58
 
95
59
 
96
60
  class NodeArchitectureValidatorCompute(
97
61
  NodeCompute[ModelArchitectureValidationRequest, ModelArchitectureValidationResult]
98
62
  ):
99
- """COMPUTE_GENERIC node for validating architecture compliance.
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
- Validates nodes and handlers against architecture rules. This is a pure
102
- transformation node: input -> output, no side effects.
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
- Raises:
193
- ProtocolConfigurationError: If any rule has a rule_id not in
194
- SUPPORTED_RULE_IDS. The error message includes the unsupported
195
- rule_id and the list of supported rules for debugging.
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
- Returns:
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 that
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: "ModelPayloadLedgerAppend"
68
- module: "omnibase_infra.nodes.reducers.models.model_payload_ledger_append"
67
+ name: "ModelIntent"
68
+ module: "omnibase_core.models.reducer.model_intent"
69
69
  description: >
70
- Ledger append payload to be passed to NodeLedgerWriteEffect. Contains the event data with Kafka position for idempotent writes.
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"