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
@@ -76,7 +76,7 @@ See Also
76
76
  - Runtime kernel: omnibase_infra.runtime.service_kernel
77
77
  """
78
78
 
79
- __version__ = "0.3.1"
79
+ __version__ = "0.4.0"
80
80
 
81
81
  from . import (
82
82
  enums,
@@ -36,6 +36,7 @@ Exports:
36
36
  EnumNodeOutputType: Node output types for execution shape validation
37
37
  EnumNonRetryableErrorCategory: Non-retryable error categories for DLQ
38
38
  EnumPolicyType: Policy types for RegistryPolicy plugins
39
+ EnumPostgresErrorCode: PostgreSQL error codes for contract persistence operations
39
40
  EnumRegistrationState: Registration FSM states for two-way registration
40
41
  EnumRegistrationStatus: Registration workflow status (IDLE, PENDING, PARTIAL, COMPLETE, FAILED)
41
42
  EnumRegistryResponseStatus: Registry operation response status (SUCCESS, PARTIAL, FAILED)
@@ -82,6 +83,7 @@ from omnibase_infra.enums.enum_non_retryable_error_category import (
82
83
  EnumNonRetryableErrorCategory,
83
84
  )
84
85
  from omnibase_infra.enums.enum_policy_type import EnumPolicyType
86
+ from omnibase_infra.enums.enum_postgres_error_code import EnumPostgresErrorCode
85
87
  from omnibase_infra.enums.enum_registration_state import EnumRegistrationState
86
88
  from omnibase_infra.enums.enum_registration_status import EnumRegistrationStatus
87
89
  from omnibase_infra.enums.enum_registry_response_status import (
@@ -123,6 +125,7 @@ __all__: list[str] = [
123
125
  "EnumNodeOutputType",
124
126
  "EnumNonRetryableErrorCategory",
125
127
  "EnumPolicyType",
128
+ "EnumPostgresErrorCode",
126
129
  "EnumRegistrationState",
127
130
  "EnumRegistrationStatus",
128
131
  "EnumRegistryResponseStatus",
@@ -11,6 +11,7 @@ Consumer Group Purpose Categories:
11
11
  - REPLAY: Reprocess historical data from earliest offset
12
12
  - AUDIT: Compliance and read-only consumption
13
13
  - BACKFILL: One-shot bounded consumers for populating derived state
14
+ - CONTRACT_REGISTRY: Contract lifecycle events (registration, deregistration, heartbeat)
14
15
 
15
16
  The purpose determines consumer group naming conventions and default
16
17
  offset reset policies in the Kafka adapter layer.
@@ -63,6 +64,11 @@ class EnumConsumerGroupPurpose(str, Enum):
63
64
  - Naming: {base_group_id}-backfill
64
65
  - Pattern: Bounded consumption until caught up
65
66
 
67
+ CONTRACT_REGISTRY: Contract lifecycle events processing.
68
+ - Default offset reset: latest
69
+ - Naming: {base_group_id}-contract-registry
70
+ - Pattern: Continuous consumption of registration, deregistration, heartbeat events
71
+
66
72
  Example:
67
73
  >>> purpose = EnumConsumerGroupPurpose.REPLAY
68
74
  >>> f"order-processor-{purpose.value}"
@@ -84,6 +90,9 @@ class EnumConsumerGroupPurpose(str, Enum):
84
90
  BACKFILL = "backfill"
85
91
  """One-shot bounded consumers for populating derived state."""
86
92
 
93
+ CONTRACT_REGISTRY = "contract-registry"
94
+ """Contract lifecycle events (registration, deregistration, heartbeat)."""
95
+
87
96
  def __str__(self) -> str:
88
97
  """Return the string value for serialization."""
89
98
  return self.value
@@ -0,0 +1,188 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """PostgreSQL Error Code Enumeration.
4
+
5
+ Defines structured error codes for PostgreSQL persistence operations. These codes
6
+ enable precise error classification, debugging, and programmatic error handling
7
+ for contract registry persistence via NodeContractPersistenceEffect.
8
+
9
+ Error Code Categories:
10
+ - Connection errors: Connection, timeout, authentication failures
11
+ - Operation errors: Specific operation failures (upsert, topic, etc.)
12
+ - Unknown errors: Catch-all for unclassified failures
13
+
14
+ Usage:
15
+ >>> from omnibase_infra.enums import EnumPostgresErrorCode
16
+ >>> error_code = EnumPostgresErrorCode.CONNECTION_ERROR
17
+ >>> print(f"Error: {error_code.value}")
18
+ Error: POSTGRES_CONNECTION_ERROR
19
+
20
+ >>> # Check if error is retriable
21
+ >>> if error_code.is_retriable:
22
+ ... print("Will retry operation")
23
+
24
+ >>> # Categorize error type
25
+ >>> if error_code.is_connection_error:
26
+ ... print("Connection-level failure")
27
+
28
+ See Also:
29
+ - NodeContractPersistenceEffect: Effect node using these error codes
30
+ - ContractRegistryReducer: Source of intents that may trigger these errors
31
+ - contract.yaml: Error code definitions in error_handling.error_codes
32
+ """
33
+
34
+ from enum import Enum
35
+
36
+
37
+ class EnumPostgresErrorCode(str, Enum):
38
+ """Error codes for PostgreSQL persistence operations.
39
+
40
+ These codes provide structured classification for failures during
41
+ contract registry persistence operations. Each code maps to a specific
42
+ failure scenario as defined in the contract.yaml error_codes section.
43
+
44
+ Connection Errors (retriable):
45
+ CONNECTION_ERROR: Connection to PostgreSQL server failed.
46
+ The database server is unreachable or connection was refused.
47
+ Verify PostgreSQL server is running and network is accessible.
48
+
49
+ TIMEOUT_ERROR: PostgreSQL operation exceeded timeout.
50
+ The operation took longer than the configured timeout threshold.
51
+ Check database load and query performance.
52
+
53
+ Authentication Errors (non-retriable):
54
+ AUTH_ERROR: Authentication with PostgreSQL server failed.
55
+ Invalid credentials or insufficient privileges.
56
+ Verify POSTGRES_USER and POSTGRES_PASSWORD in .env.
57
+
58
+ Operation Errors (non-retriable):
59
+ UPSERT_ERROR: PostgreSQL upsert operation failed.
60
+ Insert/update of contract record failed due to constraint
61
+ violation, invalid data, or schema mismatch.
62
+
63
+ TOPIC_UPDATE_ERROR: PostgreSQL topic update failed.
64
+ Failed to update topic routing table. Check JSONB array
65
+ operations and topic table schema.
66
+
67
+ MARK_STALE_ERROR: PostgreSQL mark stale operation failed.
68
+ Batch staleness marking failed. Check is_stale column
69
+ and last_seen_at timestamp handling.
70
+
71
+ HEARTBEAT_ERROR: PostgreSQL heartbeat update failed.
72
+ Heartbeat timestamp update failed. Verify contract_id
73
+ exists and last_seen_at column is writable.
74
+
75
+ DEACTIVATE_ERROR: PostgreSQL deactivation failed.
76
+ Soft delete (is_active=false) failed. Check contract_id
77
+ validity and is_active column constraints.
78
+
79
+ CLEANUP_ERROR: PostgreSQL topic cleanup failed.
80
+ Failed to remove contract from topic arrays. Check JSONB
81
+ array manipulation and referential integrity.
82
+
83
+ Unknown Errors (non-retriable):
84
+ UNKNOWN_ERROR: Unknown error during PostgreSQL operation.
85
+ Catch-all for unclassified PostgreSQL failures.
86
+ Check logs for underlying exception details.
87
+ """
88
+
89
+ # Connection errors
90
+ CONNECTION_ERROR = "POSTGRES_CONNECTION_ERROR"
91
+ TIMEOUT_ERROR = "POSTGRES_TIMEOUT_ERROR"
92
+ AUTH_ERROR = "POSTGRES_AUTH_ERROR"
93
+
94
+ # Operation errors
95
+ UPSERT_ERROR = "POSTGRES_UPSERT_ERROR"
96
+ TOPIC_UPDATE_ERROR = "POSTGRES_TOPIC_UPDATE_ERROR"
97
+ MARK_STALE_ERROR = "POSTGRES_MARK_STALE_ERROR"
98
+ HEARTBEAT_ERROR = "POSTGRES_HEARTBEAT_ERROR"
99
+ DEACTIVATE_ERROR = "POSTGRES_DEACTIVATE_ERROR"
100
+ CLEANUP_ERROR = "POSTGRES_CLEANUP_ERROR"
101
+
102
+ # Unknown errors
103
+ UNKNOWN_ERROR = "POSTGRES_UNKNOWN_ERROR"
104
+
105
+ @property
106
+ def is_retriable(self) -> bool:
107
+ """Check if this error is retriable.
108
+
109
+ Retriable errors indicate transient failures that may succeed
110
+ on retry, such as connection issues or timeouts. Non-retriable
111
+ errors indicate permanent failures requiring intervention.
112
+
113
+ Returns:
114
+ True if the error is retriable, False otherwise.
115
+ """
116
+ return self in {
117
+ EnumPostgresErrorCode.CONNECTION_ERROR,
118
+ EnumPostgresErrorCode.TIMEOUT_ERROR,
119
+ }
120
+
121
+ @property
122
+ def is_connection_error(self) -> bool:
123
+ """Check if this is a connection-level error.
124
+
125
+ Connection errors indicate infrastructure-level failures
126
+ rather than operation-specific issues.
127
+
128
+ Returns:
129
+ True if this is a connection-level error.
130
+ """
131
+ return self in {
132
+ EnumPostgresErrorCode.CONNECTION_ERROR,
133
+ EnumPostgresErrorCode.TIMEOUT_ERROR,
134
+ EnumPostgresErrorCode.AUTH_ERROR,
135
+ }
136
+
137
+ @property
138
+ def is_operation_error(self) -> bool:
139
+ """Check if this is an operation-specific error.
140
+
141
+ Operation errors indicate failures in specific database
142
+ operations rather than infrastructure issues.
143
+
144
+ Returns:
145
+ True if this is an operation-specific error.
146
+ """
147
+ return self in {
148
+ EnumPostgresErrorCode.UPSERT_ERROR,
149
+ EnumPostgresErrorCode.TOPIC_UPDATE_ERROR,
150
+ EnumPostgresErrorCode.MARK_STALE_ERROR,
151
+ EnumPostgresErrorCode.HEARTBEAT_ERROR,
152
+ EnumPostgresErrorCode.DEACTIVATE_ERROR,
153
+ EnumPostgresErrorCode.CLEANUP_ERROR,
154
+ }
155
+
156
+ @property
157
+ def description(self) -> str:
158
+ """Get human-readable description of the error code.
159
+
160
+ Returns:
161
+ Description string for the error code.
162
+ """
163
+ descriptions = {
164
+ EnumPostgresErrorCode.CONNECTION_ERROR: (
165
+ "Connection to PostgreSQL server failed"
166
+ ),
167
+ EnumPostgresErrorCode.TIMEOUT_ERROR: (
168
+ "PostgreSQL operation exceeded timeout"
169
+ ),
170
+ EnumPostgresErrorCode.AUTH_ERROR: (
171
+ "Authentication with PostgreSQL server failed"
172
+ ),
173
+ EnumPostgresErrorCode.UPSERT_ERROR: "PostgreSQL upsert operation failed",
174
+ EnumPostgresErrorCode.TOPIC_UPDATE_ERROR: "PostgreSQL topic update failed",
175
+ EnumPostgresErrorCode.MARK_STALE_ERROR: (
176
+ "PostgreSQL mark stale operation failed"
177
+ ),
178
+ EnumPostgresErrorCode.HEARTBEAT_ERROR: "PostgreSQL heartbeat update failed",
179
+ EnumPostgresErrorCode.DEACTIVATE_ERROR: "PostgreSQL deactivation failed",
180
+ EnumPostgresErrorCode.CLEANUP_ERROR: "PostgreSQL topic cleanup failed",
181
+ EnumPostgresErrorCode.UNKNOWN_ERROR: (
182
+ "Unknown error during PostgreSQL operation"
183
+ ),
184
+ }
185
+ return descriptions.get(self, "Unknown error")
186
+
187
+
188
+ __all__ = ["EnumPostgresErrorCode"]
@@ -10,6 +10,7 @@ Exports:
10
10
  ModelInfraErrorContext: Configuration model for bundled error context
11
11
  RuntimeHostError: Base infrastructure error class
12
12
  ProtocolConfigurationError: Protocol configuration validation errors
13
+ ProtocolDependencyResolutionError: Protocol dependency resolution errors
13
14
  SecretResolutionError: Secret/credential resolution errors
14
15
  InfraConnectionError: Infrastructure connection errors
15
16
  InfraTimeoutError: Infrastructure timeout errors
@@ -115,6 +116,7 @@ from omnibase_infra.errors.error_infra import (
115
116
  InfraTimeoutError,
116
117
  InfraUnavailableError,
117
118
  ProtocolConfigurationError,
119
+ ProtocolDependencyResolutionError,
118
120
  RuntimeHostError,
119
121
  SecretResolutionError,
120
122
  UnknownHandlerTypeError,
@@ -162,6 +164,8 @@ __all__: list[str] = [
162
164
  "ModelTimeoutErrorContext",
163
165
  "PolicyRegistryError",
164
166
  "ProtocolConfigurationError",
167
+ # Protocol dependency resolution errors
168
+ "ProtocolDependencyResolutionError",
165
169
  # Repository errors
166
170
  "RepositoryContractError",
167
171
  "RepositoryError",
@@ -597,6 +597,65 @@ class UnknownHandlerTypeError(RuntimeHostError):
597
597
  )
598
598
 
599
599
 
600
+ class ProtocolDependencyResolutionError(RuntimeHostError):
601
+ """Raised when protocol dependencies cannot be resolved from container.
602
+
603
+ Used when a node's contract.yaml declares protocol dependencies that
604
+ are not registered in the container's service_registry. This is a
605
+ fail-fast error that prevents node creation with missing dependencies.
606
+
607
+ Example:
608
+ >>> context = ModelInfraErrorContext(
609
+ ... transport_type=EnumInfraTransportType.RUNTIME,
610
+ ... operation="resolve_dependencies",
611
+ ... target_name="NodeContractPersistenceEffect",
612
+ ... )
613
+ >>> raise ProtocolDependencyResolutionError(
614
+ ... "Missing required protocols for node",
615
+ ... context=context,
616
+ ... missing_protocols=["ProtocolPostgresAdapter"],
617
+ ... node_name="node_contract_persistence_effect",
618
+ ... )
619
+
620
+ .. versionadded:: 0.x.x
621
+ Part of OMN-1732 runtime dependency injection.
622
+ """
623
+
624
+ def __init__(
625
+ self,
626
+ message: str,
627
+ context: ModelInfraErrorContext | None = None,
628
+ *,
629
+ missing_protocols: list[str] | None = None,
630
+ node_name: str | None = None,
631
+ contract_path: str | None = None,
632
+ **extra_context: object,
633
+ ) -> None:
634
+ """Initialize ProtocolDependencyResolutionError.
635
+
636
+ Args:
637
+ message: Human-readable error message
638
+ context: Bundled infrastructure context
639
+ missing_protocols: List of protocol class names that could not be resolved
640
+ node_name: Name of the node requiring the protocols
641
+ contract_path: Path to the contract.yaml file (for debugging)
642
+ **extra_context: Additional context information
643
+ """
644
+ if missing_protocols is not None:
645
+ extra_context["missing_protocols"] = missing_protocols
646
+ if node_name is not None:
647
+ extra_context["node_name"] = node_name
648
+ if contract_path is not None:
649
+ extra_context["contract_path"] = contract_path
650
+
651
+ super().__init__(
652
+ message=message,
653
+ error_code=EnumCoreErrorCode.DEPENDENCY_ERROR,
654
+ context=context,
655
+ **extra_context,
656
+ )
657
+
658
+
600
659
  __all__: list[str] = [
601
660
  "EnvelopeValidationError",
602
661
  "InfraAuthenticationError",
@@ -604,6 +663,7 @@ __all__: list[str] = [
604
663
  "InfraTimeoutError",
605
664
  "InfraUnavailableError",
606
665
  "ProtocolConfigurationError",
666
+ "ProtocolDependencyResolutionError",
607
667
  "RuntimeHostError",
608
668
  "SecretResolutionError",
609
669
  "UnknownHandlerTypeError",
@@ -20,6 +20,7 @@ Available Handlers:
20
20
  - HandlerGraph: Graph database handler (Memgraph/Neo4j via Bolt protocol)
21
21
  - HandlerIntent: Intent storage and query handler wrapping HandlerGraph (demo wiring)
22
22
  - HandlerQdrant: Qdrant vector database handler (MVP: create, upsert, search, delete)
23
+ - HandlerSlackWebhook: Slack webhook handler for infrastructure alerting
23
24
 
24
25
  Response Models:
25
26
  - ModelDbQueryPayload: Database query result payload
@@ -45,6 +46,7 @@ from omnibase_infra.handlers.handler_manifest_persistence import (
45
46
  )
46
47
  from omnibase_infra.handlers.handler_mcp import HandlerMCP
47
48
  from omnibase_infra.handlers.handler_qdrant import HandlerQdrant
49
+ from omnibase_infra.handlers.handler_slack_webhook import HandlerSlackWebhook
48
50
  from omnibase_infra.handlers.handler_vault import HandlerVault
49
51
  from omnibase_infra.handlers.models import (
50
52
  ModelConsulHandlerPayload,
@@ -71,6 +73,7 @@ __all__: list[str] = [
71
73
  "HandlerManifestPersistence",
72
74
  "HandlerMCP",
73
75
  "HandlerQdrant",
76
+ "HandlerSlackWebhook",
74
77
  "HandlerVault",
75
78
  "ModelConsulHandlerPayload",
76
79
  "ModelConsulHandlerResponse",