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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/enums/__init__.py +3 -0
  3. omnibase_infra/enums/enum_consumer_group_purpose.py +9 -0
  4. omnibase_infra/enums/enum_postgres_error_code.py +188 -0
  5. omnibase_infra/errors/__init__.py +4 -0
  6. omnibase_infra/errors/error_infra.py +60 -0
  7. omnibase_infra/handlers/__init__.py +3 -0
  8. omnibase_infra/handlers/handler_slack_webhook.py +426 -0
  9. omnibase_infra/handlers/models/__init__.py +14 -0
  10. omnibase_infra/handlers/models/enum_alert_severity.py +36 -0
  11. omnibase_infra/handlers/models/model_slack_alert.py +24 -0
  12. omnibase_infra/handlers/models/model_slack_alert_payload.py +77 -0
  13. omnibase_infra/handlers/models/model_slack_alert_result.py +73 -0
  14. omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +29 -20
  15. omnibase_infra/mixins/__init__.py +14 -0
  16. omnibase_infra/mixins/mixin_node_introspection.py +42 -20
  17. omnibase_infra/mixins/mixin_postgres_error_response.py +314 -0
  18. omnibase_infra/mixins/mixin_postgres_op_executor.py +298 -0
  19. omnibase_infra/models/__init__.py +3 -0
  20. omnibase_infra/models/discovery/model_dependency_spec.py +1 -0
  21. omnibase_infra/models/discovery/model_discovered_capabilities.py +1 -1
  22. omnibase_infra/models/discovery/model_introspection_config.py +28 -1
  23. omnibase_infra/models/discovery/model_introspection_performance_metrics.py +1 -0
  24. omnibase_infra/models/discovery/model_introspection_task_config.py +1 -0
  25. omnibase_infra/{nodes/effects/models → models}/model_backend_result.py +22 -6
  26. omnibase_infra/models/projection/__init__.py +11 -0
  27. omnibase_infra/models/projection/model_contract_projection.py +170 -0
  28. omnibase_infra/models/projection/model_topic_projection.py +148 -0
  29. omnibase_infra/models/runtime/__init__.py +4 -0
  30. omnibase_infra/models/runtime/model_resolved_dependencies.py +116 -0
  31. omnibase_infra/nodes/contract_registry_reducer/__init__.py +5 -0
  32. omnibase_infra/nodes/contract_registry_reducer/contract.yaml +6 -5
  33. omnibase_infra/nodes/contract_registry_reducer/contract_registration_event_router.py +689 -0
  34. omnibase_infra/nodes/contract_registry_reducer/reducer.py +9 -26
  35. omnibase_infra/nodes/effects/__init__.py +1 -1
  36. omnibase_infra/nodes/effects/models/__init__.py +6 -4
  37. omnibase_infra/nodes/effects/models/model_registry_response.py +1 -1
  38. omnibase_infra/nodes/effects/protocol_consul_client.py +1 -1
  39. omnibase_infra/nodes/effects/protocol_postgres_adapter.py +1 -1
  40. omnibase_infra/nodes/effects/registry_effect.py +1 -1
  41. omnibase_infra/nodes/node_contract_persistence_effect/__init__.py +101 -0
  42. omnibase_infra/nodes/node_contract_persistence_effect/contract.yaml +490 -0
  43. omnibase_infra/nodes/node_contract_persistence_effect/handlers/__init__.py +74 -0
  44. omnibase_infra/nodes/node_contract_persistence_effect/handlers/handler_postgres_cleanup_topics.py +217 -0
  45. omnibase_infra/nodes/node_contract_persistence_effect/handlers/handler_postgres_contract_upsert.py +242 -0
  46. omnibase_infra/nodes/node_contract_persistence_effect/handlers/handler_postgres_deactivate.py +194 -0
  47. omnibase_infra/nodes/node_contract_persistence_effect/handlers/handler_postgres_heartbeat.py +243 -0
  48. omnibase_infra/nodes/node_contract_persistence_effect/handlers/handler_postgres_mark_stale.py +208 -0
  49. omnibase_infra/nodes/node_contract_persistence_effect/handlers/handler_postgres_topic_update.py +298 -0
  50. omnibase_infra/nodes/node_contract_persistence_effect/models/__init__.py +15 -0
  51. omnibase_infra/nodes/node_contract_persistence_effect/models/model_persistence_result.py +52 -0
  52. omnibase_infra/nodes/node_contract_persistence_effect/node.py +131 -0
  53. omnibase_infra/nodes/node_contract_persistence_effect/registry/__init__.py +27 -0
  54. omnibase_infra/nodes/node_contract_persistence_effect/registry/registry_infra_contract_persistence_effect.py +251 -0
  55. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +8 -12
  56. omnibase_infra/nodes/node_registry_effect/models/__init__.py +2 -2
  57. omnibase_infra/nodes/node_slack_alerter_effect/__init__.py +33 -0
  58. omnibase_infra/nodes/node_slack_alerter_effect/contract.yaml +291 -0
  59. omnibase_infra/nodes/node_slack_alerter_effect/node.py +106 -0
  60. omnibase_infra/projectors/__init__.py +6 -0
  61. omnibase_infra/projectors/projection_reader_contract.py +1301 -0
  62. omnibase_infra/runtime/__init__.py +12 -0
  63. omnibase_infra/runtime/baseline_subscriptions.py +13 -6
  64. omnibase_infra/runtime/contract_dependency_resolver.py +455 -0
  65. omnibase_infra/runtime/contract_registration_event_router.py +500 -0
  66. omnibase_infra/runtime/db/__init__.py +4 -0
  67. omnibase_infra/runtime/db/models/__init__.py +15 -10
  68. omnibase_infra/runtime/db/models/model_db_operation.py +40 -0
  69. omnibase_infra/runtime/db/models/model_db_param.py +24 -0
  70. omnibase_infra/runtime/db/models/model_db_repository_contract.py +40 -0
  71. omnibase_infra/runtime/db/models/model_db_return.py +26 -0
  72. omnibase_infra/runtime/db/models/model_db_safety_policy.py +32 -0
  73. omnibase_infra/runtime/emit_daemon/event_registry.py +34 -22
  74. omnibase_infra/runtime/event_bus_subcontract_wiring.py +63 -23
  75. omnibase_infra/runtime/intent_execution_router.py +430 -0
  76. omnibase_infra/runtime/models/__init__.py +6 -0
  77. omnibase_infra/runtime/models/model_contract_registry_config.py +41 -0
  78. omnibase_infra/runtime/models/model_intent_execution_summary.py +79 -0
  79. omnibase_infra/runtime/models/model_runtime_config.py +8 -0
  80. omnibase_infra/runtime/protocols/__init__.py +16 -0
  81. omnibase_infra/runtime/protocols/protocol_intent_executor.py +107 -0
  82. omnibase_infra/runtime/publisher_topic_scoped.py +16 -11
  83. omnibase_infra/runtime/registry_policy.py +29 -15
  84. omnibase_infra/runtime/request_response_wiring.py +793 -0
  85. omnibase_infra/runtime/service_kernel.py +295 -8
  86. omnibase_infra/runtime/service_runtime_host_process.py +149 -5
  87. omnibase_infra/runtime/util_version.py +5 -1
  88. omnibase_infra/schemas/schema_latency_baseline.sql +135 -0
  89. omnibase_infra/services/contract_publisher/config.py +4 -4
  90. omnibase_infra/services/contract_publisher/service.py +8 -5
  91. omnibase_infra/services/observability/injection_effectiveness/__init__.py +67 -0
  92. omnibase_infra/services/observability/injection_effectiveness/config.py +295 -0
  93. omnibase_infra/services/observability/injection_effectiveness/consumer.py +1461 -0
  94. omnibase_infra/services/observability/injection_effectiveness/models/__init__.py +32 -0
  95. omnibase_infra/services/observability/injection_effectiveness/models/model_agent_match.py +79 -0
  96. omnibase_infra/services/observability/injection_effectiveness/models/model_context_utilization.py +118 -0
  97. omnibase_infra/services/observability/injection_effectiveness/models/model_latency_breakdown.py +107 -0
  98. omnibase_infra/services/observability/injection_effectiveness/models/model_pattern_utilization.py +46 -0
  99. omnibase_infra/services/observability/injection_effectiveness/writer_postgres.py +596 -0
  100. omnibase_infra/services/registry_api/models/__init__.py +25 -0
  101. omnibase_infra/services/registry_api/models/model_contract_ref.py +44 -0
  102. omnibase_infra/services/registry_api/models/model_contract_view.py +81 -0
  103. omnibase_infra/services/registry_api/models/model_response_contracts.py +50 -0
  104. omnibase_infra/services/registry_api/models/model_response_topics.py +50 -0
  105. omnibase_infra/services/registry_api/models/model_topic_summary.py +57 -0
  106. omnibase_infra/services/registry_api/models/model_topic_view.py +63 -0
  107. omnibase_infra/services/registry_api/routes.py +205 -6
  108. omnibase_infra/services/registry_api/service.py +528 -1
  109. omnibase_infra/utils/__init__.py +7 -0
  110. omnibase_infra/utils/util_db_error_context.py +292 -0
  111. omnibase_infra/validation/infra_validators.py +3 -1
  112. omnibase_infra/validation/validation_exemptions.yaml +65 -0
  113. {omnibase_infra-0.3.1.dist-info → omnibase_infra-0.4.0.dist-info}/METADATA +3 -3
  114. {omnibase_infra-0.3.1.dist-info → omnibase_infra-0.4.0.dist-info}/RECORD +117 -58
  115. {omnibase_infra-0.3.1.dist-info → omnibase_infra-0.4.0.dist-info}/WHEEL +0 -0
  116. {omnibase_infra-0.3.1.dist-info → omnibase_infra-0.4.0.dist-info}/entry_points.txt +0 -0
  117. {omnibase_infra-0.3.1.dist-info → omnibase_infra-0.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,170 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Contract Projection Model.
4
+
5
+ Provides the Pydantic model for contract projections stored in PostgreSQL.
6
+ Used by the Registry API to query registered contracts and their metadata.
7
+
8
+ The contracts table stores registered ONEX contracts with full YAML content
9
+ for replay capability and Kafka position tracking for exactly-once semantics.
10
+
11
+ Related Tickets:
12
+ - OMN-1845: Create ProjectionReaderContract for contract/topic queries
13
+ - OMN-1653: Contract registry state materialization
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from datetime import datetime
19
+
20
+ from pydantic import BaseModel, ConfigDict, Field
21
+
22
+
23
+ class ModelContractProjection(BaseModel):
24
+ """Contract projection for Registry API queries.
25
+
26
+ Represents a registered ONEX contract stored in PostgreSQL. This model
27
+ maps to the contracts table created by migration 005.
28
+
29
+ Primary Key:
30
+ contract_id - derived natural key: node_name:major.minor.patch
31
+
32
+ Attributes:
33
+ contract_id: Derived natural key (e.g., "my-node:1.0.0")
34
+ node_name: ONEX node name from contract metadata
35
+ version_major: Semantic version major component
36
+ version_minor: Semantic version minor component
37
+ version_patch: Semantic version patch component
38
+ contract_hash: SHA-256 hash of contract YAML for change detection
39
+ contract_yaml: Full contract YAML content for replay capability
40
+ registered_at: Timestamp when contract was first registered
41
+ deregistered_at: Timestamp when contract was deregistered (None if active)
42
+ last_seen_at: Timestamp of most recent heartbeat or registration event
43
+ is_active: Whether contract is currently active (soft delete)
44
+ last_event_topic: Kafka topic of last processed event (for dedupe)
45
+ last_event_partition: Kafka partition of last processed event (for dedupe)
46
+ last_event_offset: Kafka offset of last processed event (for dedupe)
47
+ created_at: Timestamp when row was created
48
+ updated_at: Timestamp when row was last updated
49
+
50
+ Example:
51
+ >>> from datetime import datetime, UTC
52
+ >>> now = datetime.now(UTC)
53
+ >>> projection = ModelContractProjection(
54
+ ... contract_id="node-registry-effect:1.0.0",
55
+ ... node_name="node-registry-effect",
56
+ ... version_major=1,
57
+ ... version_minor=0,
58
+ ... version_patch=0,
59
+ ... contract_hash="abc123...",
60
+ ... contract_yaml="name: node-registry-effect\\n...",
61
+ ... registered_at=now,
62
+ ... last_seen_at=now,
63
+ ... is_active=True,
64
+ ... )
65
+ """
66
+
67
+ model_config = ConfigDict(
68
+ frozen=True,
69
+ extra="forbid",
70
+ from_attributes=True,
71
+ )
72
+
73
+ # Identity
74
+ # ONEX_EXCLUDE: pattern_validator - contract_id is a derived natural key (name:version), not UUID
75
+ contract_id: str = Field(
76
+ ...,
77
+ min_length=1,
78
+ description="Derived natural key: node_name:major.minor.patch",
79
+ )
80
+ # ONEX_EXCLUDE: pattern_validator - node_name is the contract name, not an entity reference
81
+ node_name: str = Field(
82
+ ...,
83
+ min_length=1,
84
+ description="ONEX node name from contract metadata",
85
+ )
86
+ version_major: int = Field(
87
+ ...,
88
+ ge=0,
89
+ description="Semantic version major component",
90
+ )
91
+ version_minor: int = Field(
92
+ ...,
93
+ ge=0,
94
+ description="Semantic version minor component",
95
+ )
96
+ version_patch: int = Field(
97
+ ...,
98
+ ge=0,
99
+ description="Semantic version patch component",
100
+ )
101
+
102
+ # Contract content
103
+ contract_hash: str = Field(
104
+ ...,
105
+ min_length=1,
106
+ description="SHA-256 hash of contract YAML for change detection",
107
+ )
108
+ contract_yaml: str = Field(
109
+ ...,
110
+ description="Full contract YAML content for replay capability",
111
+ )
112
+
113
+ # Lifecycle
114
+ registered_at: datetime = Field(
115
+ ...,
116
+ description="Timestamp when contract was first registered",
117
+ )
118
+ deregistered_at: datetime | None = Field(
119
+ default=None,
120
+ description="Timestamp when contract was deregistered (None if active)",
121
+ )
122
+ last_seen_at: datetime = Field(
123
+ ...,
124
+ description="Timestamp of most recent heartbeat or registration event",
125
+ )
126
+ is_active: bool = Field(
127
+ default=True,
128
+ description="Whether contract is currently active (soft delete)",
129
+ )
130
+
131
+ # Kafka position tracking (for exactly-once semantics)
132
+ last_event_topic: str | None = Field(
133
+ default=None,
134
+ description="Kafka topic of last processed event (for dedupe)",
135
+ )
136
+ last_event_partition: int | None = Field(
137
+ default=None,
138
+ description="Kafka partition of last processed event (for dedupe)",
139
+ )
140
+ last_event_offset: int | None = Field(
141
+ default=None,
142
+ description="Kafka offset of last processed event (for dedupe)",
143
+ )
144
+
145
+ # Audit timestamps
146
+ created_at: datetime | None = Field(
147
+ default=None,
148
+ description="Timestamp when row was created",
149
+ )
150
+ updated_at: datetime | None = Field(
151
+ default=None,
152
+ description="Timestamp when row was last updated",
153
+ )
154
+
155
+ @property
156
+ def version_string(self) -> str:
157
+ """Return semantic version as string.
158
+
159
+ Returns:
160
+ Semantic version string (e.g., "1.0.0")
161
+
162
+ Example:
163
+ >>> proj = ModelContractProjection(version_major=1, version_minor=2, version_patch=3, ...)
164
+ >>> proj.version_string
165
+ '1.2.3'
166
+ """
167
+ return f"{self.version_major}.{self.version_minor}.{self.version_patch}"
168
+
169
+
170
+ __all__: list[str] = ["ModelContractProjection"]
@@ -0,0 +1,148 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Topic Projection Model.
4
+
5
+ Provides the Pydantic model for topic projections stored in PostgreSQL.
6
+ Used by the Registry API to query topic suffixes referenced by contracts
7
+ for routing discovery.
8
+
9
+ Topics use 5-segment naming (e.g., onex.evt.platform.contract-registered.v1)
10
+ and store SUFFIXES only - environment prefix is applied at runtime.
11
+
12
+ Related Tickets:
13
+ - OMN-1845: Create ProjectionReaderContract for contract/topic queries
14
+ - OMN-1653: Contract registry state materialization
15
+ - OMN-1709: Topic orphan handling documentation
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from datetime import datetime
21
+ from typing import Literal
22
+
23
+ from pydantic import BaseModel, ConfigDict, Field
24
+
25
+ # Valid direction values for topic routing
26
+ TopicDirection = Literal["publish", "subscribe"]
27
+
28
+
29
+ class ModelTopicProjection(BaseModel):
30
+ """Topic projection for Registry API queries.
31
+
32
+ Represents a topic suffix referenced by contracts for routing discovery.
33
+ This model maps to the topics table created by migration 005.
34
+
35
+ Primary Key:
36
+ (topic_suffix, direction) - composite key allowing same topic with
37
+ both publish and subscribe directions
38
+
39
+ Topic Orphan Handling (OMN-1709):
40
+ When all contracts referencing a topic are deregistered, the topic
41
+ record remains with an empty contract_ids list. This is intentional:
42
+ - Preserves topic routing history for auditing and debugging
43
+ - Allows topic reactivation if a new contract references the same topic
44
+ - Avoids complex cascading deletes during high-volume deregistration
45
+
46
+ Attributes:
47
+ topic_suffix: Topic suffix without environment prefix
48
+ direction: Whether contracts publish to or subscribe from this topic
49
+ contract_ids: List of contract_id strings that reference this topic
50
+ first_seen_at: Timestamp when topic was first seen in any contract
51
+ last_seen_at: Timestamp when topic was last seen in any contract
52
+ is_active: Whether topic is currently referenced by any active contract
53
+ created_at: Timestamp when row was created
54
+ updated_at: Timestamp when row was last updated
55
+
56
+ Example:
57
+ >>> from datetime import datetime, UTC
58
+ >>> now = datetime.now(UTC)
59
+ >>> projection = ModelTopicProjection(
60
+ ... topic_suffix="onex.evt.platform.contract-registered.v1",
61
+ ... direction="publish",
62
+ ... contract_ids=["node-registry-effect:1.0.0"],
63
+ ... first_seen_at=now,
64
+ ... last_seen_at=now,
65
+ ... is_active=True,
66
+ ... )
67
+ """
68
+
69
+ model_config = ConfigDict(
70
+ frozen=True,
71
+ extra="forbid",
72
+ from_attributes=True,
73
+ )
74
+
75
+ # Identity (composite primary key)
76
+ topic_suffix: str = Field(
77
+ ...,
78
+ min_length=1,
79
+ description=(
80
+ "Topic suffix without environment prefix, "
81
+ "e.g., onex.evt.platform.contract-registered.v1"
82
+ ),
83
+ )
84
+ direction: TopicDirection = Field(
85
+ ...,
86
+ description="Whether contracts publish to or subscribe from this topic",
87
+ )
88
+
89
+ # Contract references (JSONB array in database)
90
+ contract_ids: list[str] = Field(
91
+ default_factory=list,
92
+ description="List of contract_id strings that reference this topic",
93
+ )
94
+
95
+ # Lifecycle
96
+ first_seen_at: datetime = Field(
97
+ ...,
98
+ description="Timestamp when topic was first seen in any contract",
99
+ )
100
+ last_seen_at: datetime = Field(
101
+ ...,
102
+ description="Timestamp when topic was last seen in any contract",
103
+ )
104
+ is_active: bool = Field(
105
+ default=True,
106
+ description="Whether topic is currently referenced by any active contract",
107
+ )
108
+
109
+ # Audit timestamps
110
+ created_at: datetime | None = Field(
111
+ default=None,
112
+ description="Timestamp when row was created",
113
+ )
114
+ updated_at: datetime | None = Field(
115
+ default=None,
116
+ description="Timestamp when row was last updated",
117
+ )
118
+
119
+ @property
120
+ def contract_count(self) -> int:
121
+ """Return number of contracts referencing this topic.
122
+
123
+ Returns:
124
+ Count of contract IDs
125
+
126
+ Example:
127
+ >>> proj = ModelTopicProjection(contract_ids=["a:1.0.0", "b:1.0.0"], ...)
128
+ >>> proj.contract_count
129
+ 2
130
+ """
131
+ return len(self.contract_ids)
132
+
133
+ @property
134
+ def is_orphaned(self) -> bool:
135
+ """Check if topic is orphaned (no contracts reference it).
136
+
137
+ Returns:
138
+ True if contract_ids is empty and topic is inactive
139
+
140
+ Example:
141
+ >>> proj = ModelTopicProjection(contract_ids=[], is_active=False, ...)
142
+ >>> proj.is_orphaned
143
+ True
144
+ """
145
+ return len(self.contract_ids) == 0 and not self.is_active
146
+
147
+
148
+ __all__: list[str] = ["ModelTopicProjection", "TopicDirection"]
@@ -26,6 +26,9 @@ from omnibase_infra.models.runtime.model_plugin_load_context import (
26
26
  from omnibase_infra.models.runtime.model_plugin_load_summary import (
27
27
  ModelPluginLoadSummary,
28
28
  )
29
+ from omnibase_infra.models.runtime.model_resolved_dependencies import (
30
+ ModelResolvedDependencies,
31
+ )
29
32
 
30
33
  # ModelContractLoadResult and ModelRuntimeContractConfig are exported from
31
34
  # omnibase_infra.runtime.models (canonical location for runtime loader models)
@@ -45,5 +48,6 @@ __all__ = [
45
48
  "ModelLoadedHandler",
46
49
  "ModelPluginLoadContext",
47
50
  "ModelPluginLoadSummary",
51
+ "ModelResolvedDependencies",
48
52
  "ModelRuntimeContractConfig",
49
53
  ]
@@ -0,0 +1,116 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Model for resolved protocol dependencies.
4
+
5
+ This module provides ModelResolvedDependencies, a container for protocol
6
+ instances resolved from the container service_registry at node creation time.
7
+
8
+ Part of OMN-1732: Runtime dependency injection for zero-code nodes.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from typing import Any
14
+
15
+ from pydantic import BaseModel, ConfigDict, Field
16
+
17
+
18
+ class ModelResolvedDependencies(BaseModel):
19
+ """Container for resolved protocol dependencies.
20
+
21
+ Holds protocol instances resolved from ModelONEXContainer.service_registry
22
+ for injection into node constructors. This model is immutable after creation.
23
+
24
+ The protocols dict maps protocol class names to their resolved instances:
25
+ - Key: Protocol class name (e.g., "ProtocolPostgresAdapter")
26
+ - Value: Resolved instance from container
27
+
28
+ Example:
29
+ >>> resolved = ModelResolvedDependencies(
30
+ ... protocols={
31
+ ... "ProtocolPostgresAdapter": postgres_adapter,
32
+ ... "ProtocolCircuitBreakerAware": circuit_breaker,
33
+ ... }
34
+ ... )
35
+ >>> adapter = resolved.get("ProtocolPostgresAdapter")
36
+
37
+ .. versionadded:: 0.x.x
38
+ Part of OMN-1732 runtime dependency injection.
39
+ """
40
+
41
+ model_config = ConfigDict(
42
+ frozen=True,
43
+ extra="forbid",
44
+ arbitrary_types_allowed=True, # Required for protocol instances
45
+ )
46
+
47
+ # ONEX_EXCLUDE: any_type - dict[str, Any] required for heterogeneous protocol instances
48
+ # resolved from container.service_registry. Type varies by protocol (ProtocolPostgresAdapter,
49
+ # ProtocolCircuitBreakerAware, etc.). Cannot use Union as protocols are open-ended.
50
+ protocols: dict[str, Any] = Field(
51
+ default_factory=dict,
52
+ description="Map of protocol class names to resolved instances",
53
+ )
54
+
55
+ # ONEX_EXCLUDE: any_type - returns heterogeneous protocol instance from protocols dict
56
+ def get(self, protocol_name: str) -> Any:
57
+ """Get a resolved protocol by name.
58
+
59
+ Args:
60
+ protocol_name: The protocol class name (e.g., "ProtocolPostgresAdapter")
61
+
62
+ Returns:
63
+ The resolved protocol instance.
64
+
65
+ Raises:
66
+ KeyError: If protocol_name is not in the resolved protocols.
67
+
68
+ Example:
69
+ >>> adapter = resolved.get("ProtocolPostgresAdapter")
70
+ """
71
+ if protocol_name not in self.protocols:
72
+ raise KeyError(
73
+ f"Protocol '{protocol_name}' not found in resolved dependencies. "
74
+ f"Available: {list(self.protocols.keys())}"
75
+ )
76
+ return self.protocols[protocol_name]
77
+
78
+ # ONEX_EXCLUDE: any_type - returns heterogeneous protocol instance, default can be any type
79
+ def get_optional(self, protocol_name: str, default: Any = None) -> Any:
80
+ """Get a resolved protocol by name, returning default if not found.
81
+
82
+ Args:
83
+ protocol_name: The protocol class name
84
+ default: Value to return if protocol not found
85
+
86
+ Returns:
87
+ The resolved protocol instance or default.
88
+ """
89
+ return self.protocols.get(protocol_name, default)
90
+
91
+ def has(self, protocol_name: str) -> bool:
92
+ """Check if a protocol is available.
93
+
94
+ Args:
95
+ protocol_name: The protocol class name
96
+
97
+ Returns:
98
+ True if protocol is resolved, False otherwise.
99
+ """
100
+ return protocol_name in self.protocols
101
+
102
+ def __len__(self) -> int:
103
+ """Return number of resolved protocols."""
104
+ return len(self.protocols)
105
+
106
+ def __bool__(self) -> bool:
107
+ """Return True if any protocols are resolved.
108
+
109
+ Warning:
110
+ **Non-standard __bool__ behavior**: Returns True only when
111
+ at least one protocol is resolved.
112
+ """
113
+ return len(self.protocols) > 0
114
+
115
+
116
+ __all__ = ["ModelResolvedDependencies"]
@@ -9,9 +9,13 @@ the ONEX declarative pattern.
9
9
  Exports:
10
10
  NodeContractRegistryReducer: Declarative reducer node shell.
11
11
  ContractRegistryReducer: Pure function reducer class.
12
+ ContractRegistrationEventRouter: Event router for Kafka messages.
12
13
  ModelContractRegistryState: Immutable state model for the reducer.
13
14
  """
14
15
 
16
+ from omnibase_infra.nodes.contract_registry_reducer.contract_registration_event_router import (
17
+ ContractRegistrationEventRouter,
18
+ )
15
19
  from omnibase_infra.nodes.contract_registry_reducer.models import (
16
20
  ModelContractRegistryState,
17
21
  )
@@ -23,6 +27,7 @@ from omnibase_infra.nodes.contract_registry_reducer.reducer import (
23
27
  )
24
28
 
25
29
  __all__ = [
30
+ "ContractRegistrationEventRouter",
26
31
  "ContractRegistryReducer",
27
32
  "ModelContractRegistryState",
28
33
  "NodeContractRegistryReducer",
@@ -38,19 +38,20 @@ description: |
38
38
  are separated.
39
39
  # Event Consumption Configuration
40
40
  # ================================
41
- # Topics follow 5-segment naming: {env}.onex.{category}.{domain}.{event-name}.v{version}
41
+ # Topics are realm-agnostic: onex.{category}.{domain}.{event-name}.v{version}
42
42
  # Categories: evt (external events), int (internal events), cmd (commands)
43
+ # Note: Environment/realm is enforced via envelope identity, not topic naming.
43
44
  consumed_events:
44
- - topic: "{env}.onex.evt.platform.contract-registered.v1"
45
+ - topic: "onex.evt.platform.contract-registered.v1"
45
46
  event_type: "ModelContractRegisteredEvent"
46
47
  description: "Contract registration from nodes on startup"
47
- - topic: "{env}.onex.evt.platform.contract-deregistered.v1"
48
+ - topic: "onex.evt.platform.contract-deregistered.v1"
48
49
  event_type: "ModelContractDeregisteredEvent"
49
50
  description: "Explicit contract deregistration on graceful shutdown"
50
- - topic: "{env}.onex.evt.platform.node-heartbeat.v1"
51
+ - topic: "onex.evt.platform.node-heartbeat.v1"
51
52
  event_type: "ModelNodeHeartbeatEvent"
52
53
  description: "Heartbeat for liveness tracking and last_seen_at updates"
53
- - topic: "{env}.onex.int.platform.runtime-tick.v1"
54
+ - topic: "onex.int.platform.runtime-tick.v1"
54
55
  event_type: "ModelRuntimeTick"
55
56
  internal: true
56
57
  description: "Periodic tick for staleness computation - marks contracts as stale/inactive"