omnibase_infra 0.2.2__py3-none-any.whl → 0.2.3__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 (77) hide show
  1. omnibase_infra/__init__.py +1 -1
  2. omnibase_infra/adapters/adapter_onex_tool_execution.py +6 -1
  3. omnibase_infra/capabilities/__init__.py +15 -0
  4. omnibase_infra/capabilities/capability_inference_rules.py +211 -0
  5. omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
  6. omnibase_infra/capabilities/intent_type_extractor.py +160 -0
  7. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +1 -1
  8. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +1 -1
  9. omnibase_infra/enums/__init__.py +6 -0
  10. omnibase_infra/enums/enum_handler_error_type.py +10 -0
  11. omnibase_infra/enums/enum_handler_source_mode.py +72 -0
  12. omnibase_infra/enums/enum_kafka_acks.py +99 -0
  13. omnibase_infra/event_bus/event_bus_kafka.py +1 -1
  14. omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +59 -10
  15. omnibase_infra/handlers/__init__.py +8 -1
  16. omnibase_infra/handlers/handler_consul.py +7 -1
  17. omnibase_infra/handlers/handler_db.py +8 -2
  18. omnibase_infra/handlers/handler_http.py +8 -2
  19. omnibase_infra/handlers/handler_intent.py +387 -0
  20. omnibase_infra/handlers/handler_mcp.py +10 -1
  21. omnibase_infra/handlers/handler_vault.py +11 -5
  22. omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +7 -0
  23. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +7 -0
  24. omnibase_infra/mixins/mixin_node_introspection.py +18 -0
  25. omnibase_infra/models/discovery/model_introspection_config.py +11 -0
  26. omnibase_infra/models/handlers/__init__.py +38 -5
  27. omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +4 -4
  28. omnibase_infra/models/handlers/model_contract_discovery_result.py +6 -4
  29. omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
  30. omnibase_infra/models/registration/model_node_introspection_event.py +9 -0
  31. omnibase_infra/models/runtime/model_handler_contract.py +25 -9
  32. omnibase_infra/models/runtime/model_loaded_handler.py +9 -0
  33. omnibase_infra/nodes/node_registration_orchestrator/plugin.py +1 -1
  34. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +7 -7
  35. omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +4 -3
  36. omnibase_infra/nodes/node_registration_storage_effect/node.py +4 -1
  37. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +1 -1
  38. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +4 -1
  39. omnibase_infra/protocols/__init__.py +2 -0
  40. omnibase_infra/protocols/protocol_container_aware.py +200 -0
  41. omnibase_infra/runtime/__init__.py +39 -0
  42. omnibase_infra/runtime/handler_bootstrap_source.py +26 -33
  43. omnibase_infra/runtime/handler_contract_config_loader.py +1 -1
  44. omnibase_infra/runtime/handler_contract_source.py +10 -51
  45. omnibase_infra/runtime/handler_identity.py +81 -0
  46. omnibase_infra/runtime/handler_plugin_loader.py +15 -0
  47. omnibase_infra/runtime/handler_registry.py +11 -3
  48. omnibase_infra/runtime/handler_source_resolver.py +326 -0
  49. omnibase_infra/runtime/protocol_lifecycle_executor.py +6 -6
  50. omnibase_infra/runtime/registry/registry_protocol_binding.py +13 -13
  51. omnibase_infra/runtime/registry_contract_source.py +693 -0
  52. omnibase_infra/runtime/service_kernel.py +1 -1
  53. omnibase_infra/runtime/service_runtime_host_process.py +463 -190
  54. omnibase_infra/runtime/util_wiring.py +12 -3
  55. omnibase_infra/services/__init__.py +21 -0
  56. omnibase_infra/services/corpus_capture.py +7 -1
  57. omnibase_infra/services/mcp/mcp_server_lifecycle.py +9 -3
  58. omnibase_infra/services/registry_api/main.py +31 -13
  59. omnibase_infra/services/registry_api/service.py +10 -19
  60. omnibase_infra/services/service_timeout_emitter.py +7 -1
  61. omnibase_infra/services/service_timeout_scanner.py +7 -3
  62. omnibase_infra/services/session/__init__.py +56 -0
  63. omnibase_infra/services/session/config_consumer.py +120 -0
  64. omnibase_infra/services/session/config_store.py +139 -0
  65. omnibase_infra/services/session/consumer.py +1007 -0
  66. omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
  67. omnibase_infra/services/session/store.py +997 -0
  68. omnibase_infra/utils/__init__.py +19 -0
  69. omnibase_infra/utils/util_atomic_file.py +261 -0
  70. omnibase_infra/utils/util_db_transaction.py +239 -0
  71. omnibase_infra/utils/util_retry_optimistic.py +281 -0
  72. omnibase_infra/validation/validation_exemptions.yaml +27 -0
  73. {omnibase_infra-0.2.2.dist-info → omnibase_infra-0.2.3.dist-info}/METADATA +3 -3
  74. {omnibase_infra-0.2.2.dist-info → omnibase_infra-0.2.3.dist-info}/RECORD +77 -56
  75. {omnibase_infra-0.2.2.dist-info → omnibase_infra-0.2.3.dist-info}/WHEEL +0 -0
  76. {omnibase_infra-0.2.2.dist-info → omnibase_infra-0.2.3.dist-info}/entry_points.txt +0 -0
  77. {omnibase_infra-0.2.2.dist-info → omnibase_infra-0.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,326 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Handler Source Resolver for Multi-Source Handler Discovery.
4
+
5
+ This module provides the HandlerSourceResolver class, which resolves handlers
6
+ from multiple sources (bootstrap, contract) based on the configured mode.
7
+
8
+ Part of OMN-1095: Handler Source Mode Hybrid Resolution.
9
+
10
+ Resolution Modes:
11
+ - BOOTSTRAP: Only use hardcoded bootstrap handlers.
12
+ - CONTRACT: Only use YAML contract-discovered handlers.
13
+ - HYBRID: Per-handler resolution with configurable precedence.
14
+
15
+ In HYBRID mode, the resolver performs per-handler identity resolution:
16
+ 1. Discovers handlers from both bootstrap and contract sources
17
+ 2. Builds a handler map keyed by handler_id
18
+ 3. Resolves conflicts based on allow_bootstrap_override:
19
+ - False (default): Contract handlers override bootstrap handlers
20
+ - True: Bootstrap handlers override contract handlers
21
+ 4. Non-conflicting handlers are included from both sources
22
+
23
+ See Also:
24
+ - EnumHandlerSourceMode: Defines the resolution modes
25
+ - HandlerBootstrapSource: Provides bootstrap handlers
26
+ - HandlerContractSource: Provides contract-discovered handlers
27
+ - ProtocolContractSource: Protocol for handler sources
28
+
29
+ .. versionadded:: 0.7.0
30
+ Created as part of OMN-1095 handler source mode hybrid resolution.
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import logging
36
+ from typing import TYPE_CHECKING
37
+
38
+ from omnibase_infra.enums.enum_handler_source_mode import EnumHandlerSourceMode
39
+
40
+ if TYPE_CHECKING:
41
+ from omnibase_infra.runtime.protocol_contract_source import ProtocolContractSource
42
+
43
+ # Import models after TYPE_CHECKING to avoid circular imports
44
+ from omnibase_infra.models.errors import ModelHandlerValidationError
45
+ from omnibase_infra.models.handlers import (
46
+ ModelContractDiscoveryResult,
47
+ ModelHandlerDescriptor,
48
+ )
49
+
50
+ # Forward Reference Resolution:
51
+ # ModelContractDiscoveryResult uses a forward reference to ModelHandlerValidationError.
52
+ # Since we import ModelHandlerValidationError above, we can call model_rebuild() here
53
+ # to resolve the forward reference. This call is idempotent - multiple calls are harmless.
54
+ ModelContractDiscoveryResult.model_rebuild()
55
+
56
+ logger = logging.getLogger(__name__)
57
+
58
+
59
+ class HandlerSourceResolver:
60
+ """Resolver for multi-source handler discovery with configurable modes.
61
+
62
+ This class resolves handlers from bootstrap and contract sources based on
63
+ the configured mode. It supports three resolution strategies:
64
+
65
+ - BOOTSTRAP: Use only bootstrap handlers, ignore contracts.
66
+ - CONTRACT: Use only contract handlers, ignore bootstrap.
67
+ - HYBRID: Per-handler resolution with configurable precedence:
68
+ - allow_bootstrap_override=False (default): Contract handlers take
69
+ precedence over bootstrap handlers with the same handler_id.
70
+ - allow_bootstrap_override=True: Bootstrap handlers take precedence
71
+ over contract handlers with the same handler_id.
72
+ In both cases, handlers without conflicts are included from both sources.
73
+
74
+ Attributes:
75
+ mode: The configured resolution mode.
76
+ allow_bootstrap_override: If True, bootstrap handlers take precedence
77
+ in HYBRID mode. Default is False (contract precedence).
78
+
79
+ Example:
80
+ >>> resolver = HandlerSourceResolver(
81
+ ... bootstrap_source=bootstrap_source,
82
+ ... contract_source=contract_source,
83
+ ... mode=EnumHandlerSourceMode.HYBRID,
84
+ ... )
85
+ >>> result = await resolver.resolve_handlers()
86
+ >>> print(f"Discovered {len(result.descriptors)} handlers")
87
+
88
+ .. versionadded:: 0.7.0
89
+ Created as part of OMN-1095 handler source mode hybrid resolution.
90
+ """
91
+
92
+ def __init__(
93
+ self,
94
+ bootstrap_source: ProtocolContractSource,
95
+ contract_source: ProtocolContractSource,
96
+ mode: EnumHandlerSourceMode,
97
+ *,
98
+ allow_bootstrap_override: bool = False,
99
+ ) -> None:
100
+ """Initialize the handler source resolver.
101
+
102
+ Args:
103
+ bootstrap_source: Source for bootstrap handlers. Must implement
104
+ ProtocolContractSource with discover_handlers() method.
105
+ contract_source: Source for contract-discovered handlers. Must
106
+ implement ProtocolContractSource with discover_handlers() method.
107
+ mode: Resolution mode determining which sources are used and how
108
+ handlers are merged.
109
+ allow_bootstrap_override: If True, bootstrap handlers override
110
+ contract handlers with the same handler_id in HYBRID mode.
111
+ Default is False (contract handlers take precedence).
112
+ Has no effect in BOOTSTRAP or CONTRACT modes.
113
+ """
114
+ self._bootstrap_source = bootstrap_source
115
+ self._contract_source = contract_source
116
+ self._mode = mode
117
+ self._allow_bootstrap_override = allow_bootstrap_override
118
+
119
+ @property
120
+ def mode(self) -> EnumHandlerSourceMode:
121
+ """Get the configured resolution mode.
122
+
123
+ Returns:
124
+ EnumHandlerSourceMode: The mode used for handler resolution.
125
+ """
126
+ return self._mode
127
+
128
+ @property
129
+ def allow_bootstrap_override(self) -> bool:
130
+ """Get the bootstrap override configuration.
131
+
132
+ Returns:
133
+ bool: True if bootstrap handlers take precedence in HYBRID mode,
134
+ False if contract handlers take precedence (default).
135
+ """
136
+ return self._allow_bootstrap_override
137
+
138
+ async def resolve_handlers(self) -> ModelContractDiscoveryResult:
139
+ """Resolve handlers based on the configured mode.
140
+
141
+ Discovers handlers from the appropriate source(s) based on mode:
142
+ - BOOTSTRAP: Only queries bootstrap source
143
+ - CONTRACT: Only queries contract source
144
+ - HYBRID: Queries both sources and merges with contract precedence
145
+
146
+ Returns:
147
+ ModelContractDiscoveryResult: Container with discovered descriptors
148
+ and any validation errors from the queried source(s).
149
+ """
150
+ if self._mode == EnumHandlerSourceMode.BOOTSTRAP:
151
+ return await self._resolve_bootstrap()
152
+ elif self._mode == EnumHandlerSourceMode.CONTRACT:
153
+ return await self._resolve_contract()
154
+ else:
155
+ # HYBRID mode
156
+ return await self._resolve_hybrid()
157
+
158
+ async def _resolve_bootstrap(self) -> ModelContractDiscoveryResult:
159
+ """Resolve handlers using only the bootstrap source.
160
+
161
+ Returns:
162
+ ModelContractDiscoveryResult: Handlers from bootstrap source only.
163
+ """
164
+ result = await self._bootstrap_source.discover_handlers()
165
+
166
+ logger.info(
167
+ "Handler resolution completed (BOOTSTRAP mode)",
168
+ extra={
169
+ "mode": self._mode.value,
170
+ "bootstrap_handler_count": len(result.descriptors),
171
+ "resolved_handler_count": len(result.descriptors),
172
+ },
173
+ )
174
+
175
+ return result
176
+
177
+ async def _resolve_contract(self) -> ModelContractDiscoveryResult:
178
+ """Resolve handlers using only the contract source.
179
+
180
+ Returns:
181
+ ModelContractDiscoveryResult: Handlers from contract source only.
182
+ """
183
+ result = await self._contract_source.discover_handlers()
184
+
185
+ logger.info(
186
+ "Handler resolution completed (CONTRACT mode)",
187
+ extra={
188
+ "mode": self._mode.value,
189
+ "contract_handler_count": len(result.descriptors),
190
+ "resolved_handler_count": len(result.descriptors),
191
+ },
192
+ )
193
+
194
+ return result
195
+
196
+ async def _resolve_hybrid(self) -> ModelContractDiscoveryResult:
197
+ """Resolve handlers using both sources with configurable precedence.
198
+
199
+ In HYBRID mode:
200
+ 1. Discover handlers from both bootstrap and contract sources
201
+ 2. Build a handler map keyed by handler_id
202
+ 3. Resolve conflicts based on allow_bootstrap_override:
203
+ - False (default): Contract handlers override bootstrap handlers
204
+ - True: Bootstrap handlers override contract handlers
205
+ 4. Non-conflicting handlers are included from both sources
206
+
207
+ Returns:
208
+ ModelContractDiscoveryResult: Merged handlers with configured
209
+ precedence and combined validation errors from both sources.
210
+ """
211
+ # Get handlers from both sources
212
+ bootstrap_result = await self._bootstrap_source.discover_handlers()
213
+ contract_result = await self._contract_source.discover_handlers()
214
+
215
+ # Build lookup maps for both sources
216
+ bootstrap_by_id: dict[str, ModelHandlerDescriptor] = {
217
+ d.handler_id: d for d in bootstrap_result.descriptors
218
+ }
219
+ contract_by_id: dict[str, ModelHandlerDescriptor] = {
220
+ d.handler_id: d for d in contract_result.descriptors
221
+ }
222
+
223
+ # Determine which source takes precedence
224
+ if self._allow_bootstrap_override:
225
+ # Bootstrap wins conflicts: add bootstrap first, then contract fallbacks
226
+ primary_source = bootstrap_result.descriptors
227
+ primary_by_id = bootstrap_by_id
228
+ secondary_source = contract_result.descriptors
229
+ secondary_by_id = contract_by_id
230
+ primary_name = "bootstrap"
231
+ secondary_name = "contract"
232
+ else:
233
+ # Contract wins conflicts (default): add contract first, then bootstrap fallbacks
234
+ primary_source = contract_result.descriptors
235
+ primary_by_id = contract_by_id
236
+ secondary_source = bootstrap_result.descriptors
237
+ secondary_by_id = bootstrap_by_id
238
+ primary_name = "contract"
239
+ secondary_name = "bootstrap"
240
+
241
+ # Build handler map - primary source handlers first (they take precedence)
242
+ handlers_by_id: dict[str, ModelHandlerDescriptor] = {}
243
+
244
+ # Add primary handlers (they win conflicts)
245
+ for descriptor in primary_source:
246
+ handlers_by_id[descriptor.handler_id] = descriptor
247
+
248
+ # Log primary-only handlers (no secondary equivalent)
249
+ if descriptor.handler_id not in secondary_by_id:
250
+ logger.debug(
251
+ f"Adding {primary_name}-only handler (no {secondary_name} equivalent)",
252
+ extra={
253
+ "handler_id": descriptor.handler_id,
254
+ "handler_name": descriptor.name,
255
+ "source": primary_name,
256
+ },
257
+ )
258
+
259
+ # Add secondary handlers only if not already present (fallback)
260
+ fallback_count = 0
261
+ override_count = 0
262
+ for descriptor in secondary_source:
263
+ if descriptor.handler_id in handlers_by_id:
264
+ # Primary handler wins - this is an override
265
+ override_count += 1
266
+ primary_handler = handlers_by_id[descriptor.handler_id]
267
+ logger.debug(
268
+ f"{primary_name.capitalize()} handler overrides {secondary_name} handler",
269
+ extra={
270
+ "handler_id": descriptor.handler_id,
271
+ "primary_name": primary_handler.name,
272
+ "secondary_name": descriptor.name,
273
+ "primary_source": primary_name,
274
+ "secondary_source": secondary_name,
275
+ "contract_path": (
276
+ primary_handler.contract_path
277
+ if primary_name == "contract"
278
+ else descriptor.contract_path
279
+ ),
280
+ },
281
+ )
282
+ else:
283
+ # No primary handler with this ID - use secondary as fallback
284
+ handlers_by_id[descriptor.handler_id] = descriptor
285
+ fallback_count += 1
286
+ logger.debug(
287
+ f"Using {secondary_name} handler as fallback (no {primary_name} match)",
288
+ extra={
289
+ "handler_id": descriptor.handler_id,
290
+ "handler_name": descriptor.name,
291
+ "source": secondary_name,
292
+ },
293
+ )
294
+
295
+ # NOTE: Validation errors from bootstrap and contract sources are intentionally
296
+ # combined WITHOUT deduplication. During migration, the same error appearing from
297
+ # BOTH sources helps distinguish handler-level issues (error in both) from
298
+ # source-specific configuration problems (error in only one). This preserves
299
+ # diagnostic signal that would be lost if we deduplicated.
300
+ all_errors: list[ModelHandlerValidationError] = list(
301
+ bootstrap_result.validation_errors
302
+ ) + list(contract_result.validation_errors)
303
+
304
+ # Log structured counts for observability
305
+ logger.info(
306
+ "Handler resolution completed (HYBRID mode)",
307
+ extra={
308
+ "mode": self._mode.value,
309
+ "allow_bootstrap_override": self._allow_bootstrap_override,
310
+ "precedence": primary_name,
311
+ "contract_handler_count": len(contract_result.descriptors),
312
+ "bootstrap_handler_count": len(bootstrap_result.descriptors),
313
+ "fallback_handler_count": fallback_count,
314
+ "override_count": override_count,
315
+ "resolved_handler_count": len(handlers_by_id),
316
+ "validation_error_count": len(all_errors),
317
+ },
318
+ )
319
+
320
+ return ModelContractDiscoveryResult(
321
+ descriptors=list(handlers_by_id.values()),
322
+ validation_errors=all_errors,
323
+ )
324
+
325
+
326
+ __all__ = ["HandlerSourceResolver"]
@@ -49,7 +49,7 @@ from omnibase_infra.runtime.models import (
49
49
  )
50
50
 
51
51
  if TYPE_CHECKING:
52
- from omnibase_spi.protocols.handlers.protocol_handler import ProtocolHandler
52
+ from omnibase_infra.protocols import ProtocolContainerAware
53
53
 
54
54
  logger = logging.getLogger(__name__)
55
55
 
@@ -172,7 +172,7 @@ class ProtocolLifecycleExecutor:
172
172
  return self._health_check_timeout_seconds
173
173
 
174
174
  @staticmethod
175
- def get_shutdown_priority(handler: ProtocolHandler) -> int:
175
+ def get_shutdown_priority(handler: ProtocolContainerAware) -> int:
176
176
  """Get shutdown priority for a handler.
177
177
 
178
178
  Returns the shutdown priority for the given handler. Handlers with higher
@@ -225,7 +225,7 @@ class ProtocolLifecycleExecutor:
225
225
  async def shutdown_handler(
226
226
  self,
227
227
  handler_type: str,
228
- handler: ProtocolHandler,
228
+ handler: ProtocolContainerAware,
229
229
  ) -> ModelLifecycleResult:
230
230
  """Shutdown a single handler with error handling.
231
231
 
@@ -267,7 +267,7 @@ class ProtocolLifecycleExecutor:
267
267
  async def check_handler_health(
268
268
  self,
269
269
  handler_type: str,
270
- handler: ProtocolHandler,
270
+ handler: ProtocolContainerAware,
271
271
  timeout_seconds: float = -1.0,
272
272
  ) -> ModelHealthCheckResult:
273
273
  """Check health of a single handler with timeout.
@@ -329,7 +329,7 @@ class ProtocolLifecycleExecutor:
329
329
 
330
330
  async def shutdown_handlers_by_priority(
331
331
  self,
332
- handlers: dict[str, ProtocolHandler],
332
+ handlers: dict[str, ProtocolContainerAware],
333
333
  ) -> ModelBatchLifecycleResult:
334
334
  """Shutdown all handlers grouped by priority (higher first, parallel within group).
335
335
 
@@ -359,7 +359,7 @@ class ProtocolLifecycleExecutor:
359
359
  return ModelBatchLifecycleResult.empty()
360
360
 
361
361
  # Group handlers by priority
362
- priority_groups: dict[int, list[tuple[str, ProtocolHandler]]] = {}
362
+ priority_groups: dict[int, list[tuple[str, ProtocolContainerAware]]] = {}
363
363
  for handler_type, handler in handlers.items():
364
364
  priority = self.get_shutdown_priority(handler)
365
365
  if priority not in priority_groups:
@@ -3,13 +3,13 @@
3
3
  """Protocol Binding Registry - SINGLE SOURCE OF TRUTH for handler registration.
4
4
 
5
5
  This module provides the RegistryProtocolBinding class which implements the
6
- ProtocolHandlerRegistry protocol from omnibase_spi. It serves as the
6
+ ProtocolContainerAwareRegistry protocol from omnibase_spi. It serves as the
7
7
  centralized location for registering and resolving protocol handlers
8
8
  in the omnibase_infra layer.
9
9
 
10
10
  The registry is responsible for:
11
- - Registering protocol handlers by protocol type identifier
12
- - Resolving handler classes for protocol types
11
+ - Registering infrastructure handlers by protocol type identifier
12
+ - Resolving handler classes for protocol types (requires ProtocolContainerAware)
13
13
  - Thread-safe registration operations
14
14
  - Listing all registered protocol types
15
15
 
@@ -70,7 +70,7 @@ from typing import TYPE_CHECKING, Any, cast
70
70
  from omnibase_infra.errors import ModelInfraErrorContext, RuntimeHostError
71
71
 
72
72
  if TYPE_CHECKING:
73
- from omnibase_spi.protocols.handlers.protocol_handler import ProtocolHandler
73
+ from omnibase_infra.protocols import ProtocolContainerAware
74
74
 
75
75
 
76
76
  # =============================================================================
@@ -131,11 +131,11 @@ class RegistryError(RuntimeHostError):
131
131
  class RegistryProtocolBinding:
132
132
  """SINGLE SOURCE OF TRUTH for handler registration in omnibase_infra.
133
133
 
134
- Thread-safe registry for protocol handlers. Implements ProtocolHandlerRegistry
134
+ Thread-safe registry for protocol handlers. Implements ProtocolContainerAwareRegistry
135
135
  protocol from omnibase_spi.
136
136
 
137
137
  The registry maintains a mapping from protocol type identifiers (strings like
138
- "http", "db", "kafka") to handler classes that implement the ProtocolHandler
138
+ "http", "db", "kafka") to handler classes that implement the ProtocolContainerAware
139
139
  protocol.
140
140
 
141
141
  TODO(OMN-40): Migrate handler signature from tuple[str, str] to structured model.
@@ -163,13 +163,13 @@ class RegistryProtocolBinding:
163
163
 
164
164
  def __init__(self) -> None:
165
165
  """Initialize an empty handler registry with thread lock."""
166
- self._registry: dict[str, type[ProtocolHandler]] = {}
166
+ self._registry: dict[str, type[ProtocolContainerAware]] = {}
167
167
  self._lock: threading.Lock = threading.Lock()
168
168
 
169
169
  def register(
170
170
  self,
171
171
  protocol_type: str,
172
- handler_cls: type[ProtocolHandler],
172
+ handler_cls: type[ProtocolContainerAware],
173
173
  ) -> None:
174
174
  """Register a protocol handler.
175
175
 
@@ -219,10 +219,10 @@ class RegistryProtocolBinding:
219
219
  Args:
220
220
  protocol_type: Protocol type identifier (e.g., 'http', 'db', 'kafka').
221
221
  Should be one of the HANDLER_TYPE_* constants.
222
- handler_cls: Handler class implementing the ProtocolHandler protocol.
222
+ handler_cls: Handler class implementing the ProtocolContainerAware protocol.
223
223
 
224
224
  Raises:
225
- RegistryError: If handler_cls does not implement the ProtocolHandler protocol
225
+ RegistryError: If handler_cls does not implement the ProtocolContainerAware protocol
226
226
  (missing or non-callable execute()/handle() method).
227
227
 
228
228
  Example:
@@ -230,7 +230,7 @@ class RegistryProtocolBinding:
230
230
  >>> registry.register(HANDLER_TYPE_HTTP, HttpHandler)
231
231
  >>> registry.register(HANDLER_TYPE_DATABASE, PostgresHandler)
232
232
  """
233
- # Runtime type validation: Ensure handler_cls implements ProtocolHandler protocol
233
+ # Runtime type validation: Ensure handler_cls implements ProtocolContainerAware protocol
234
234
  # Check if execute() or handle() method exists and is callable
235
235
  # Following RegistryEventBusBinding pattern of supporting alternative methods
236
236
  has_execute = hasattr(handler_cls, "execute")
@@ -240,7 +240,7 @@ class RegistryProtocolBinding:
240
240
  raise RegistryError(
241
241
  f"Handler class {handler_cls.__name__!r} for protocol type "
242
242
  f"{protocol_type!r} is missing 'execute()' or 'handle()' method "
243
- f"from ProtocolHandler protocol",
243
+ f"from ProtocolContainerAware protocol",
244
244
  protocol_type=protocol_type,
245
245
  context=ModelInfraErrorContext.with_correlation(
246
246
  operation="register",
@@ -279,7 +279,7 @@ class RegistryProtocolBinding:
279
279
  def get(
280
280
  self,
281
281
  protocol_type: str,
282
- ) -> type[ProtocolHandler]:
282
+ ) -> type[ProtocolContainerAware]:
283
283
  """Get handler class for protocol type.
284
284
 
285
285
  Resolves the handler class registered for the given protocol type.