omnibase_infra 0.2.1__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 (675) hide show
  1. omnibase_infra/__init__.py +101 -0
  2. omnibase_infra/cli/__init__.py +1 -0
  3. omnibase_infra/cli/commands.py +216 -0
  4. omnibase_infra/clients/__init__.py +0 -0
  5. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +261 -0
  6. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +138 -0
  7. omnibase_infra/decorators/__init__.py +29 -0
  8. omnibase_infra/decorators/allow_any.py +109 -0
  9. omnibase_infra/dlq/__init__.py +90 -0
  10. omnibase_infra/dlq/constants_dlq.py +57 -0
  11. omnibase_infra/dlq/models/__init__.py +26 -0
  12. omnibase_infra/dlq/models/enum_replay_status.py +37 -0
  13. omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
  14. omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
  15. omnibase_infra/dlq/service_dlq_tracking.py +611 -0
  16. omnibase_infra/enums/__init__.py +123 -0
  17. omnibase_infra/enums/enum_any_type_violation.py +104 -0
  18. omnibase_infra/enums/enum_backend_type.py +27 -0
  19. omnibase_infra/enums/enum_capture_outcome.py +42 -0
  20. omnibase_infra/enums/enum_capture_state.py +88 -0
  21. omnibase_infra/enums/enum_chain_violation_type.py +119 -0
  22. omnibase_infra/enums/enum_circuit_state.py +51 -0
  23. omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
  24. omnibase_infra/enums/enum_contract_type.py +84 -0
  25. omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
  26. omnibase_infra/enums/enum_dispatch_status.py +191 -0
  27. omnibase_infra/enums/enum_environment.py +46 -0
  28. omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
  29. omnibase_infra/enums/enum_handler_error_type.py +101 -0
  30. omnibase_infra/enums/enum_handler_loader_error.py +178 -0
  31. omnibase_infra/enums/enum_handler_source_type.py +87 -0
  32. omnibase_infra/enums/enum_handler_type.py +77 -0
  33. omnibase_infra/enums/enum_handler_type_category.py +61 -0
  34. omnibase_infra/enums/enum_infra_transport_type.py +73 -0
  35. omnibase_infra/enums/enum_introspection_reason.py +154 -0
  36. omnibase_infra/enums/enum_message_category.py +213 -0
  37. omnibase_infra/enums/enum_node_archetype.py +74 -0
  38. omnibase_infra/enums/enum_node_output_type.py +185 -0
  39. omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
  40. omnibase_infra/enums/enum_policy_type.py +32 -0
  41. omnibase_infra/enums/enum_registration_state.py +261 -0
  42. omnibase_infra/enums/enum_registration_status.py +33 -0
  43. omnibase_infra/enums/enum_registry_response_status.py +28 -0
  44. omnibase_infra/enums/enum_response_status.py +26 -0
  45. omnibase_infra/enums/enum_retry_error_category.py +98 -0
  46. omnibase_infra/enums/enum_security_rule_id.py +103 -0
  47. omnibase_infra/enums/enum_selection_strategy.py +91 -0
  48. omnibase_infra/enums/enum_topic_standard.py +42 -0
  49. omnibase_infra/enums/enum_validation_severity.py +78 -0
  50. omnibase_infra/errors/__init__.py +156 -0
  51. omnibase_infra/errors/error_architecture_violation.py +152 -0
  52. omnibase_infra/errors/error_chain_propagation.py +188 -0
  53. omnibase_infra/errors/error_compute_registry.py +92 -0
  54. omnibase_infra/errors/error_consul.py +132 -0
  55. omnibase_infra/errors/error_container_wiring.py +243 -0
  56. omnibase_infra/errors/error_event_bus_registry.py +102 -0
  57. omnibase_infra/errors/error_infra.py +608 -0
  58. omnibase_infra/errors/error_message_type_registry.py +101 -0
  59. omnibase_infra/errors/error_policy_registry.py +112 -0
  60. omnibase_infra/errors/error_vault.py +123 -0
  61. omnibase_infra/event_bus/__init__.py +72 -0
  62. omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +86 -0
  63. omnibase_infra/event_bus/event_bus_inmemory.py +743 -0
  64. omnibase_infra/event_bus/event_bus_kafka.py +1658 -0
  65. omnibase_infra/event_bus/mixin_kafka_broadcast.py +184 -0
  66. omnibase_infra/event_bus/mixin_kafka_dlq.py +765 -0
  67. omnibase_infra/event_bus/models/__init__.py +29 -0
  68. omnibase_infra/event_bus/models/config/__init__.py +20 -0
  69. omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +725 -0
  70. omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
  71. omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
  72. omnibase_infra/event_bus/models/model_event_headers.py +115 -0
  73. omnibase_infra/event_bus/models/model_event_message.py +60 -0
  74. omnibase_infra/event_bus/topic_constants.py +376 -0
  75. omnibase_infra/handlers/__init__.py +75 -0
  76. omnibase_infra/handlers/filesystem/__init__.py +48 -0
  77. omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
  78. omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
  79. omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
  80. omnibase_infra/handlers/handler_consul.py +787 -0
  81. omnibase_infra/handlers/handler_db.py +1039 -0
  82. omnibase_infra/handlers/handler_filesystem.py +1478 -0
  83. omnibase_infra/handlers/handler_graph.py +1154 -0
  84. omnibase_infra/handlers/handler_http.py +920 -0
  85. omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
  86. omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
  87. omnibase_infra/handlers/handler_mcp.py +748 -0
  88. omnibase_infra/handlers/handler_qdrant.py +1076 -0
  89. omnibase_infra/handlers/handler_vault.py +422 -0
  90. omnibase_infra/handlers/mcp/__init__.py +19 -0
  91. omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
  92. omnibase_infra/handlers/mcp/protocols.py +178 -0
  93. omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
  94. omnibase_infra/handlers/mixins/__init__.py +42 -0
  95. omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
  96. omnibase_infra/handlers/mixins/mixin_consul_kv.py +337 -0
  97. omnibase_infra/handlers/mixins/mixin_consul_service.py +277 -0
  98. omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
  99. omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
  100. omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
  101. omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
  102. omnibase_infra/handlers/models/__init__.py +286 -0
  103. omnibase_infra/handlers/models/consul/__init__.py +81 -0
  104. omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
  105. omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
  106. omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
  107. omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
  108. omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
  109. omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
  110. omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
  111. omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
  112. omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
  113. omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
  114. omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
  115. omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
  116. omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
  117. omnibase_infra/handlers/models/graph/__init__.py +35 -0
  118. omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
  119. omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
  120. omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
  121. omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
  122. omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
  123. omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
  124. omnibase_infra/handlers/models/http/__init__.py +50 -0
  125. omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
  126. omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
  127. omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
  128. omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
  129. omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
  130. omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
  131. omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
  132. omnibase_infra/handlers/models/mcp/__init__.py +23 -0
  133. omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
  134. omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
  135. omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
  136. omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
  137. omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
  138. omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
  139. omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
  140. omnibase_infra/handlers/models/model_db_query_response.py +60 -0
  141. omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
  142. omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
  143. omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
  144. omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
  145. omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
  146. omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
  147. omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
  148. omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
  149. omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
  150. omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
  151. omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
  152. omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
  153. omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
  154. omnibase_infra/handlers/models/model_handler_response.py +103 -0
  155. omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
  156. omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
  157. omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
  158. omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
  159. omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
  160. omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
  161. omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
  162. omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
  163. omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
  164. omnibase_infra/handlers/models/model_operation_context.py +187 -0
  165. omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
  166. omnibase_infra/handlers/models/model_retry_state.py +162 -0
  167. omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
  168. omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
  169. omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
  170. omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
  171. omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
  172. omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
  173. omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
  174. omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
  175. omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
  176. omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
  177. omnibase_infra/handlers/models/vault/__init__.py +69 -0
  178. omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
  179. omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
  180. omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
  181. omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
  182. omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
  183. omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
  184. omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
  185. omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
  186. omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
  187. omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
  188. omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
  189. omnibase_infra/handlers/registration_storage/__init__.py +43 -0
  190. omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
  191. omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +915 -0
  192. omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
  193. omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
  194. omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
  195. omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
  196. omnibase_infra/handlers/service_discovery/__init__.py +43 -0
  197. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +747 -0
  198. omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
  199. omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
  200. omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
  201. omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
  202. omnibase_infra/handlers/service_discovery/models/model_service_info.py +99 -0
  203. omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
  204. omnibase_infra/idempotency/__init__.py +94 -0
  205. omnibase_infra/idempotency/models/__init__.py +43 -0
  206. omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
  207. omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
  208. omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
  209. omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
  210. omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
  211. omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
  212. omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
  213. omnibase_infra/idempotency/store_inmemory.py +265 -0
  214. omnibase_infra/idempotency/store_postgres.py +923 -0
  215. omnibase_infra/infrastructure/__init__.py +0 -0
  216. omnibase_infra/mixins/__init__.py +71 -0
  217. omnibase_infra/mixins/mixin_async_circuit_breaker.py +655 -0
  218. omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
  219. omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
  220. omnibase_infra/mixins/mixin_node_introspection.py +2465 -0
  221. omnibase_infra/mixins/mixin_retry_execution.py +386 -0
  222. omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
  223. omnibase_infra/models/__init__.py +136 -0
  224. omnibase_infra/models/corpus/__init__.py +17 -0
  225. omnibase_infra/models/corpus/model_capture_config.py +133 -0
  226. omnibase_infra/models/corpus/model_capture_result.py +86 -0
  227. omnibase_infra/models/discovery/__init__.py +42 -0
  228. omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
  229. omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
  230. omnibase_infra/models/discovery/model_introspection_config.py +311 -0
  231. omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
  232. omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
  233. omnibase_infra/models/dispatch/__init__.py +147 -0
  234. omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
  235. omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
  236. omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
  237. omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
  238. omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
  239. omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
  240. omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
  241. omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
  242. omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
  243. omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
  244. omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
  245. omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
  246. omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
  247. omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
  248. omnibase_infra/models/errors/__init__.py +45 -0
  249. omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
  250. omnibase_infra/models/errors/model_infra_error_context.py +99 -0
  251. omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
  252. omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
  253. omnibase_infra/models/handlers/__init__.py +37 -0
  254. omnibase_infra/models/handlers/model_contract_discovery_result.py +80 -0
  255. omnibase_infra/models/handlers/model_handler_descriptor.py +185 -0
  256. omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
  257. omnibase_infra/models/health/__init__.py +9 -0
  258. omnibase_infra/models/health/model_health_check_result.py +40 -0
  259. omnibase_infra/models/lifecycle/__init__.py +39 -0
  260. omnibase_infra/models/logging/__init__.py +51 -0
  261. omnibase_infra/models/logging/model_log_context.py +756 -0
  262. omnibase_infra/models/model_retry_error_classification.py +78 -0
  263. omnibase_infra/models/projection/__init__.py +43 -0
  264. omnibase_infra/models/projection/model_capability_fields.py +112 -0
  265. omnibase_infra/models/projection/model_registration_projection.py +434 -0
  266. omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
  267. omnibase_infra/models/projection/model_sequence_info.py +182 -0
  268. omnibase_infra/models/projection/model_snapshot_topic_config.py +590 -0
  269. omnibase_infra/models/projectors/__init__.py +41 -0
  270. omnibase_infra/models/projectors/model_projector_column.py +289 -0
  271. omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
  272. omnibase_infra/models/projectors/model_projector_index.py +270 -0
  273. omnibase_infra/models/projectors/model_projector_schema.py +415 -0
  274. omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
  275. omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
  276. omnibase_infra/models/registration/__init__.py +59 -0
  277. omnibase_infra/models/registration/commands/__init__.py +15 -0
  278. omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
  279. omnibase_infra/models/registration/events/__init__.py +56 -0
  280. omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
  281. omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
  282. omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
  283. omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
  284. omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
  285. omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
  286. omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
  287. omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
  288. omnibase_infra/models/registration/model_node_capabilities.py +179 -0
  289. omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
  290. omnibase_infra/models/registration/model_node_introspection_event.py +175 -0
  291. omnibase_infra/models/registration/model_node_metadata.py +79 -0
  292. omnibase_infra/models/registration/model_node_registration.py +162 -0
  293. omnibase_infra/models/registration/model_node_registration_record.py +162 -0
  294. omnibase_infra/models/registry/__init__.py +29 -0
  295. omnibase_infra/models/registry/model_domain_constraint.py +202 -0
  296. omnibase_infra/models/registry/model_message_type_entry.py +271 -0
  297. omnibase_infra/models/resilience/__init__.py +9 -0
  298. omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
  299. omnibase_infra/models/routing/__init__.py +25 -0
  300. omnibase_infra/models/routing/model_routing_entry.py +52 -0
  301. omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
  302. omnibase_infra/models/runtime/__init__.py +40 -0
  303. omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
  304. omnibase_infra/models/runtime/model_discovery_error.py +81 -0
  305. omnibase_infra/models/runtime/model_discovery_result.py +162 -0
  306. omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
  307. omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
  308. omnibase_infra/models/runtime/model_handler_contract.py +280 -0
  309. omnibase_infra/models/runtime/model_loaded_handler.py +120 -0
  310. omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
  311. omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
  312. omnibase_infra/models/security/__init__.py +50 -0
  313. omnibase_infra/models/security/classification_levels.py +99 -0
  314. omnibase_infra/models/security/model_environment_policy.py +145 -0
  315. omnibase_infra/models/security/model_handler_security_policy.py +107 -0
  316. omnibase_infra/models/security/model_security_error.py +81 -0
  317. omnibase_infra/models/security/model_security_validation_result.py +328 -0
  318. omnibase_infra/models/security/model_security_warning.py +67 -0
  319. omnibase_infra/models/snapshot/__init__.py +27 -0
  320. omnibase_infra/models/snapshot/model_field_change.py +65 -0
  321. omnibase_infra/models/snapshot/model_snapshot.py +270 -0
  322. omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
  323. omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
  324. omnibase_infra/models/types/__init__.py +71 -0
  325. omnibase_infra/models/validation/__init__.py +89 -0
  326. omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
  327. omnibase_infra/models/validation/model_any_type_violation.py +141 -0
  328. omnibase_infra/models/validation/model_category_match_result.py +345 -0
  329. omnibase_infra/models/validation/model_chain_violation.py +166 -0
  330. omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
  331. omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
  332. omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
  333. omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
  334. omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
  335. omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
  336. omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
  337. omnibase_infra/models/validation/model_output_validation_params.py +74 -0
  338. omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
  339. omnibase_infra/models/validation/model_validation_error_params.py +84 -0
  340. omnibase_infra/models/validation/model_validation_outcome.py +287 -0
  341. omnibase_infra/nodes/__init__.py +48 -0
  342. omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
  343. omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
  344. omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +208 -0
  345. omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
  346. omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
  347. omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
  348. omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
  349. omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
  350. omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
  351. omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
  352. omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
  353. omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
  354. omnibase_infra/nodes/architecture_validator/node.py +262 -0
  355. omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
  356. omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
  357. omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
  358. omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
  359. omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +99 -0
  360. omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
  361. omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
  362. omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
  363. omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
  364. omnibase_infra/nodes/effects/README.md +358 -0
  365. omnibase_infra/nodes/effects/__init__.py +26 -0
  366. omnibase_infra/nodes/effects/contract.yaml +172 -0
  367. omnibase_infra/nodes/effects/models/__init__.py +32 -0
  368. omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
  369. omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
  370. omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
  371. omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
  372. omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
  373. omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
  374. omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
  375. omnibase_infra/nodes/effects/registry_effect.py +525 -0
  376. omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
  377. omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
  378. omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
  379. omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +475 -0
  380. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
  381. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
  382. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
  383. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
  384. omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
  385. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
  386. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +609 -0
  387. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
  388. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
  389. omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
  390. omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
  391. omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
  392. omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
  393. omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
  394. omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
  395. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
  396. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
  397. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
  398. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
  399. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
  400. omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
  401. omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
  402. omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
  403. omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
  404. omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
  405. omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
  406. omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
  407. omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
  408. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +525 -0
  409. omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +392 -0
  410. omnibase_infra/nodes/node_registration_orchestrator/wiring.py +742 -0
  411. omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
  412. omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
  413. omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
  414. omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
  415. omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
  416. omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
  417. omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
  418. omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
  419. omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +225 -0
  420. omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
  421. omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
  422. omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
  423. omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
  424. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
  425. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
  426. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
  427. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
  428. omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
  429. omnibase_infra/nodes/node_registration_storage_effect/node.py +109 -0
  430. omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
  431. omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
  432. omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
  433. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +194 -0
  434. omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
  435. omnibase_infra/nodes/node_registry_effect/contract.yaml +682 -0
  436. omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
  437. omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
  438. omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
  439. omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +416 -0
  440. omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
  441. omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
  442. omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
  443. omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
  444. omnibase_infra/nodes/node_registry_effect/node.py +165 -0
  445. omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
  446. omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
  447. omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
  448. omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
  449. omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
  450. omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
  451. omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
  452. omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
  453. omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
  454. omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
  455. omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
  456. omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
  457. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
  458. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
  459. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
  460. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
  461. omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
  462. omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
  463. omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
  464. omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
  465. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +214 -0
  466. omnibase_infra/nodes/reducers/__init__.py +30 -0
  467. omnibase_infra/nodes/reducers/models/__init__.py +32 -0
  468. omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +76 -0
  469. omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
  470. omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
  471. omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
  472. omnibase_infra/nodes/reducers/registration_reducer.py +1137 -0
  473. omnibase_infra/observability/__init__.py +143 -0
  474. omnibase_infra/observability/constants_metrics.py +91 -0
  475. omnibase_infra/observability/factory_observability_sink.py +525 -0
  476. omnibase_infra/observability/handlers/__init__.py +118 -0
  477. omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
  478. omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
  479. omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
  480. omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
  481. omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
  482. omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
  483. omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
  484. omnibase_infra/observability/hooks/__init__.py +74 -0
  485. omnibase_infra/observability/hooks/hook_observability.py +1223 -0
  486. omnibase_infra/observability/models/__init__.py +30 -0
  487. omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
  488. omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
  489. omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
  490. omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
  491. omnibase_infra/observability/sinks/__init__.py +69 -0
  492. omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
  493. omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
  494. omnibase_infra/plugins/__init__.py +27 -0
  495. omnibase_infra/plugins/examples/__init__.py +28 -0
  496. omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
  497. omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
  498. omnibase_infra/plugins/models/__init__.py +21 -0
  499. omnibase_infra/plugins/models/model_plugin_context.py +76 -0
  500. omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
  501. omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
  502. omnibase_infra/plugins/plugin_compute_base.py +435 -0
  503. omnibase_infra/projectors/__init__.py +30 -0
  504. omnibase_infra/projectors/contracts/__init__.py +63 -0
  505. omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
  506. omnibase_infra/projectors/projection_reader_registration.py +1559 -0
  507. omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
  508. omnibase_infra/protocols/__init__.py +99 -0
  509. omnibase_infra/protocols/protocol_capability_projection.py +253 -0
  510. omnibase_infra/protocols/protocol_capability_query.py +251 -0
  511. omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
  512. omnibase_infra/protocols/protocol_event_projector.py +96 -0
  513. omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
  514. omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
  515. omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
  516. omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
  517. omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
  518. omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
  519. omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
  520. omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
  521. omnibase_infra/runtime/__init__.py +296 -0
  522. omnibase_infra/runtime/binding_config_resolver.py +2706 -0
  523. omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
  524. omnibase_infra/runtime/contract_handler_discovery.py +582 -0
  525. omnibase_infra/runtime/contract_loaders/__init__.py +42 -0
  526. omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
  527. omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
  528. omnibase_infra/runtime/enums/__init__.py +18 -0
  529. omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
  530. omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
  531. omnibase_infra/runtime/envelope_validator.py +179 -0
  532. omnibase_infra/runtime/handler_contract_source.py +669 -0
  533. omnibase_infra/runtime/handler_plugin_loader.py +2029 -0
  534. omnibase_infra/runtime/handler_registry.py +321 -0
  535. omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
  536. omnibase_infra/runtime/kernel.py +40 -0
  537. omnibase_infra/runtime/mixin_policy_validation.py +522 -0
  538. omnibase_infra/runtime/mixin_semver_cache.py +378 -0
  539. omnibase_infra/runtime/mixins/__init__.py +17 -0
  540. omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +757 -0
  541. omnibase_infra/runtime/models/__init__.py +192 -0
  542. omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
  543. omnibase_infra/runtime/models/model_binding_config.py +168 -0
  544. omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
  545. omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
  546. omnibase_infra/runtime/models/model_cached_secret.py +138 -0
  547. omnibase_infra/runtime/models/model_compute_key.py +138 -0
  548. omnibase_infra/runtime/models/model_compute_registration.py +97 -0
  549. omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
  550. omnibase_infra/runtime/models/model_config_ref.py +331 -0
  551. omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
  552. omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
  553. omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
  554. omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
  555. omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
  556. omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
  557. omnibase_infra/runtime/models/model_failed_component.py +55 -0
  558. omnibase_infra/runtime/models/model_health_check_response.py +168 -0
  559. omnibase_infra/runtime/models/model_health_check_result.py +228 -0
  560. omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
  561. omnibase_infra/runtime/models/model_logging_config.py +42 -0
  562. omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
  563. omnibase_infra/runtime/models/model_optional_string.py +94 -0
  564. omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
  565. omnibase_infra/runtime/models/model_policy_context.py +100 -0
  566. omnibase_infra/runtime/models/model_policy_key.py +138 -0
  567. omnibase_infra/runtime/models/model_policy_registration.py +139 -0
  568. omnibase_infra/runtime/models/model_policy_result.py +103 -0
  569. omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
  570. omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
  571. omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
  572. omnibase_infra/runtime/models/model_retry_policy.py +105 -0
  573. omnibase_infra/runtime/models/model_runtime_config.py +150 -0
  574. omnibase_infra/runtime/models/model_runtime_scheduler_config.py +624 -0
  575. omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
  576. omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
  577. omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
  578. omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
  579. omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
  580. omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
  581. omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
  582. omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
  583. omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
  584. omnibase_infra/runtime/models/model_shutdown_config.py +94 -0
  585. omnibase_infra/runtime/projector_plugin_loader.py +1462 -0
  586. omnibase_infra/runtime/projector_schema_manager.py +565 -0
  587. omnibase_infra/runtime/projector_shell.py +1102 -0
  588. omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
  589. omnibase_infra/runtime/protocol_contract_source.py +92 -0
  590. omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
  591. omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
  592. omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
  593. omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
  594. omnibase_infra/runtime/protocol_policy.py +366 -0
  595. omnibase_infra/runtime/protocols/__init__.py +27 -0
  596. omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
  597. omnibase_infra/runtime/registry/__init__.py +93 -0
  598. omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
  599. omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
  600. omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
  601. omnibase_infra/runtime/registry/registry_message_type.py +542 -0
  602. omnibase_infra/runtime/registry/registry_protocol_binding.py +444 -0
  603. omnibase_infra/runtime/registry_compute.py +1143 -0
  604. omnibase_infra/runtime/registry_dispatcher.py +678 -0
  605. omnibase_infra/runtime/registry_policy.py +1502 -0
  606. omnibase_infra/runtime/runtime_scheduler.py +1070 -0
  607. omnibase_infra/runtime/secret_resolver.py +2110 -0
  608. omnibase_infra/runtime/security_metadata_validator.py +776 -0
  609. omnibase_infra/runtime/service_kernel.py +1573 -0
  610. omnibase_infra/runtime/service_message_dispatch_engine.py +1805 -0
  611. omnibase_infra/runtime/service_runtime_host_process.py +2260 -0
  612. omnibase_infra/runtime/util_container_wiring.py +1123 -0
  613. omnibase_infra/runtime/util_validation.py +314 -0
  614. omnibase_infra/runtime/util_version.py +98 -0
  615. omnibase_infra/runtime/util_wiring.py +566 -0
  616. omnibase_infra/schemas/schema_registration_projection.sql +320 -0
  617. omnibase_infra/services/__init__.py +68 -0
  618. omnibase_infra/services/corpus_capture.py +678 -0
  619. omnibase_infra/services/service_capability_query.py +945 -0
  620. omnibase_infra/services/service_health.py +897 -0
  621. omnibase_infra/services/service_node_selector.py +530 -0
  622. omnibase_infra/services/service_timeout_emitter.py +682 -0
  623. omnibase_infra/services/service_timeout_scanner.py +390 -0
  624. omnibase_infra/services/snapshot/__init__.py +31 -0
  625. omnibase_infra/services/snapshot/service_snapshot.py +647 -0
  626. omnibase_infra/services/snapshot/store_inmemory.py +637 -0
  627. omnibase_infra/services/snapshot/store_postgres.py +1279 -0
  628. omnibase_infra/shared/__init__.py +8 -0
  629. omnibase_infra/testing/__init__.py +10 -0
  630. omnibase_infra/testing/utils.py +23 -0
  631. omnibase_infra/types/__init__.py +48 -0
  632. omnibase_infra/types/type_cache_info.py +49 -0
  633. omnibase_infra/types/type_dsn.py +173 -0
  634. omnibase_infra/types/type_infra_aliases.py +60 -0
  635. omnibase_infra/types/typed_dict/__init__.py +21 -0
  636. omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
  637. omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
  638. omnibase_infra/types/typed_dict_capabilities.py +64 -0
  639. omnibase_infra/utils/__init__.py +89 -0
  640. omnibase_infra/utils/correlation.py +208 -0
  641. omnibase_infra/utils/util_datetime.py +372 -0
  642. omnibase_infra/utils/util_dsn_validation.py +333 -0
  643. omnibase_infra/utils/util_env_parsing.py +264 -0
  644. omnibase_infra/utils/util_error_sanitization.py +457 -0
  645. omnibase_infra/utils/util_pydantic_validators.py +477 -0
  646. omnibase_infra/utils/util_semver.py +233 -0
  647. omnibase_infra/validation/__init__.py +307 -0
  648. omnibase_infra/validation/enums/__init__.py +11 -0
  649. omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
  650. omnibase_infra/validation/infra_validators.py +1486 -0
  651. omnibase_infra/validation/linter_contract.py +907 -0
  652. omnibase_infra/validation/mixin_any_type_classification.py +120 -0
  653. omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
  654. omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
  655. omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
  656. omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
  657. omnibase_infra/validation/models/__init__.py +15 -0
  658. omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
  659. omnibase_infra/validation/models/model_contract_violation.py +41 -0
  660. omnibase_infra/validation/service_validation_aggregator.py +395 -0
  661. omnibase_infra/validation/validation_exemptions.yaml +1710 -0
  662. omnibase_infra/validation/validator_any_type.py +715 -0
  663. omnibase_infra/validation/validator_chain_propagation.py +839 -0
  664. omnibase_infra/validation/validator_execution_shape.py +465 -0
  665. omnibase_infra/validation/validator_localhandler.py +261 -0
  666. omnibase_infra/validation/validator_registration_security.py +410 -0
  667. omnibase_infra/validation/validator_routing_coverage.py +1020 -0
  668. omnibase_infra/validation/validator_runtime_shape.py +915 -0
  669. omnibase_infra/validation/validator_security.py +410 -0
  670. omnibase_infra/validation/validator_topic_category.py +1152 -0
  671. omnibase_infra-0.2.1.dist-info/METADATA +197 -0
  672. omnibase_infra-0.2.1.dist-info/RECORD +675 -0
  673. omnibase_infra-0.2.1.dist-info/WHEEL +4 -0
  674. omnibase_infra-0.2.1.dist-info/entry_points.txt +4 -0
  675. omnibase_infra-0.2.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,839 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Chain Propagation Validator for Correlation and Causation Chain Validation.
4
+
5
+ Validates that messages properly maintain correlation and causation chains
6
+ during propagation through the ONEX event-driven system. This ensures
7
+ workflow traceability and supports distributed debugging.
8
+
9
+ Design Principles:
10
+ - **Workflow Traceability**: All messages in a workflow share the same
11
+ correlation_id for end-to-end trace visibility.
12
+ - **Causation Chain Integrity**: Each message's causation_id must reference
13
+ its direct parent's message_id, forming an unbroken lineage.
14
+ - **Fail-Open Architecture**: Follows ONEX validation philosophy - validation
15
+ failures are reported but don't block by default. Use enforce_chain_propagation()
16
+ for strict enforcement.
17
+
18
+ Chain Rules:
19
+ 1. **Correlation Propagation**: Child messages must inherit the parent's
20
+ correlation_id exactly. A mismatch breaks trace correlation.
21
+ 2. **Causation Chain**: Every produced message's causation_id must equal
22
+ its direct parent's message_id. This creates parent-child relationships.
23
+ 3. **No Skipped Ancestors** (strict mode only): In strict pairwise validation
24
+ via ``validate_chain()``, causation chains must be continuous - a message
25
+ cannot skip its direct parent to reference a grandparent.
26
+
27
+ Note: ``validate_workflow_chain()`` intentionally relaxes Rule 3 to allow
28
+ ancestor skipping for workflow flexibility (fan-out patterns, aggregation,
29
+ partial chain reconstruction). See its docstring for details.
30
+
31
+ Message ID Semantics:
32
+ In ONEX, the ModelEventEnvelope uses:
33
+ - envelope_id: Unique identifier for each message (serves as message_id)
34
+ - correlation_id: Shared across all messages in a workflow
35
+ - causation_id: Optional field referencing parent's envelope_id
36
+
37
+ For envelopes without an explicit causation_id field, the validator
38
+ checks the metadata for a 'causation_id' key.
39
+
40
+ Causation ID Semantics:
41
+ **Canonical Location**: When producing child messages, set causation_id in
42
+ ``metadata.tags["causation_id"]`` as a string UUID. For HTTP transports,
43
+ use ``metadata.headers["x-causation-id"]``.
44
+
45
+ **Why metadata.tags?** The ModelEventEnvelope's metadata.tags dict provides
46
+ a flexible, schema-stable location for tracing metadata.
47
+
48
+ **Producer Responsibility**: When creating a child envelope from a parent:
49
+
50
+ .. code-block:: python
51
+
52
+ child_envelope = ModelEventEnvelope(
53
+ payload=child_payload,
54
+ correlation_id=parent_envelope.correlation_id, # Propagate correlation
55
+ metadata=ModelEventMetadata(
56
+ tags={
57
+ "causation_id": str(parent_envelope.envelope_id), # Canonical
58
+ },
59
+ ),
60
+ )
61
+
62
+ Thread Safety:
63
+ The ChainPropagationValidator is stateless and thread-safe. All validation
64
+ methods are pure functions that produce fresh result objects.
65
+
66
+ Typing Note (ModelEventEnvelope[object]):
67
+ Functions in this module use ``ModelEventEnvelope[object]`` instead of ``Any``
68
+ per CLAUDE.md guidance: "Use ``object`` for generic payloads".
69
+
70
+ This is intentional:
71
+ - CLAUDE.md mandates "NEVER use ``Any``" for type annotations
72
+ - Chain validation operates on envelope metadata (correlation_id, causation_id,
73
+ envelope_id), not payload content - the payload type is irrelevant
74
+ - Using ``object`` signals "any object payload" while maintaining type safety
75
+ (unlike ``Any`` which completely disables type checking)
76
+ - Validators that need to inspect payload content should use ``isinstance()``
77
+ type guards for runtime safety
78
+
79
+ Performance Considerations:
80
+ The validator does not cache results. This is an intentional design decision:
81
+
82
+ - **Production Use**: Workflows are validated once per dispatch, making caching
83
+ unnecessary overhead. Each message passes through validation exactly once.
84
+ - **Stateless Design**: Caching would introduce state, complicating thread safety
85
+ and increasing memory footprint without meaningful performance benefit.
86
+ - **Testing/Debugging**: For repeated validation of the same message sets during
87
+ debugging, callers can implement their own memoization if needed.
88
+
89
+ If profiling reveals validation as a bottleneck (unlikely given O(n) complexity),
90
+ consider batching validations rather than adding caching.
91
+
92
+ Usage:
93
+ >>> from omnibase_infra.validation.validator_chain_propagation import (
94
+ ... ChainPropagationValidator,
95
+ ... validate_message_chain,
96
+ ... enforce_chain_propagation,
97
+ ... )
98
+ >>> from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
99
+ >>> from uuid import uuid4
100
+ >>>
101
+ >>> # Direct validation
102
+ >>> validator = ChainPropagationValidator()
103
+ >>> violations = validator.validate_chain(parent_envelope, child_envelope)
104
+ >>> if violations:
105
+ ... for v in violations:
106
+ ... print(v.format_for_logging())
107
+ >>>
108
+ >>> # Strict enforcement
109
+ >>> enforce_chain_propagation(parent_envelope, child_envelope)
110
+
111
+ Related:
112
+ - OMN-951: Enforce Correlation and Causation Chain Validation
113
+ - docs/patterns/correlation_id_tracking.md
114
+
115
+ .. versionadded:: 0.5.0
116
+ """
117
+
118
+ from __future__ import annotations
119
+
120
+ import logging
121
+ from typing import cast
122
+ from uuid import UUID
123
+
124
+ # ModelEventEnvelope is used at runtime in function parameter types, not just for type hints
125
+ from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
126
+ from omnibase_infra.enums import EnumChainViolationType, EnumValidationSeverity
127
+ from omnibase_infra.errors.error_chain_propagation import ChainPropagationError
128
+ from omnibase_infra.models.errors.model_infra_error_context import (
129
+ ModelInfraErrorContext,
130
+ )
131
+ from omnibase_infra.models.validation.model_chain_violation import ModelChainViolation
132
+
133
+ logger = logging.getLogger(__name__)
134
+
135
+ __all__ = [
136
+ "CAUSATION_ID_HEADER_KEYS",
137
+ # Causation ID lookup key constants
138
+ "CAUSATION_ID_TAG_KEYS",
139
+ "ChainPropagationError",
140
+ "ChainPropagationValidator",
141
+ "enforce_chain_propagation",
142
+ "get_causation_id",
143
+ "get_correlation_id",
144
+ # Helper functions for envelope field access
145
+ "get_message_id",
146
+ "validate_linear_message_chain",
147
+ "validate_message_chain",
148
+ ]
149
+
150
+ # ==============================================================================
151
+ # Causation ID Lookup Keys
152
+ # ==============================================================================
153
+ # These constants define the keys checked when resolving causation_id from
154
+ # envelope metadata.
155
+
156
+ CAUSATION_ID_TAG_KEYS: tuple[str, ...] = ("causation_id",)
157
+ """Keys checked in metadata.tags for causation_id.
158
+
159
+ The canonical location for causation_id is metadata.tags["causation_id"].
160
+ """
161
+
162
+ CAUSATION_ID_HEADER_KEYS: tuple[str, ...] = ("x-causation-id",)
163
+ """Keys checked in metadata.headers for causation_id.
164
+
165
+ The canonical HTTP header for causation_id is "x-causation-id".
166
+ """
167
+
168
+ # ==============================================================================
169
+ # Helper Functions for Envelope Field Access
170
+ # ==============================================================================
171
+
172
+
173
+ def get_message_id(envelope: ModelEventEnvelope[object]) -> UUID:
174
+ """Get the message_id from an envelope.
175
+
176
+ In ONEX, the envelope_id serves as the unique message identifier.
177
+
178
+ Args:
179
+ envelope: The event envelope.
180
+
181
+ Returns:
182
+ The envelope's unique identifier (envelope_id).
183
+ """
184
+ # envelope_id is typed as UUID in ModelEventEnvelope, but mypy sees it as Any
185
+ # due to the generic type parameter. Cast is required for type safety.
186
+ return cast(UUID, envelope.envelope_id)
187
+
188
+
189
+ def get_correlation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
190
+ """Get the correlation_id from an envelope.
191
+
192
+ Args:
193
+ envelope: The event envelope.
194
+
195
+ Returns:
196
+ The envelope's correlation_id, or None if not set.
197
+ """
198
+ # correlation_id is typed as UUID | None in ModelEventEnvelope, but mypy sees it
199
+ # as Any due to the generic type parameter. Cast is required for type safety.
200
+ correlation_id = envelope.correlation_id
201
+ if correlation_id is None:
202
+ return None
203
+ return cast(UUID, correlation_id)
204
+
205
+
206
+ def get_causation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
207
+ """Get the causation_id from an envelope.
208
+
209
+ Canonical Locations:
210
+ The **canonical location** for causation_id is ``metadata.tags["causation_id"]``
211
+ stored as a string UUID. When creating child envelopes, producers MUST set
212
+ causation_id in this location for consistency across the ONEX ecosystem.
213
+
214
+ For HTTP transports, use ``metadata.headers["x-causation-id"]``.
215
+
216
+ Example of canonical usage when producing a child message::
217
+
218
+ child_envelope = ModelEventEnvelope(
219
+ # ... other fields ...
220
+ metadata=ModelEventMetadata(
221
+ tags={
222
+ "causation_id": str(parent_envelope.envelope_id),
223
+ },
224
+ ),
225
+ )
226
+
227
+ Lookup Order:
228
+ 1. **Direct attribute** ``envelope.causation_id`` (UUID) - If envelope
229
+ exposes causation_id as a first-class attribute.
230
+
231
+ 2. **Metadata tags** ``metadata.tags["causation_id"]`` (string -> UUID) -
232
+ Canonical location.
233
+
234
+ 3. **Metadata headers** ``metadata.headers["x-causation-id"]`` (string -> UUID) -
235
+ Canonical HTTP header.
236
+
237
+ Args:
238
+ envelope: The event envelope.
239
+
240
+ Returns:
241
+ The envelope's causation_id, or None if not set in any checked location.
242
+
243
+ See Also:
244
+ - Module docstring "Causation ID Semantics" section for architectural context
245
+ - ``docs/patterns/correlation_id_tracking.md`` for full tracing patterns
246
+ """
247
+ # Check for direct attribute
248
+ if hasattr(envelope, "causation_id"):
249
+ causation_id = envelope.causation_id
250
+ if isinstance(causation_id, UUID):
251
+ return causation_id
252
+
253
+ # Check metadata for causation_id
254
+ if hasattr(envelope, "metadata") and envelope.metadata is not None:
255
+ metadata = envelope.metadata
256
+
257
+ # Check metadata.tags for causation_id (canonical location)
258
+ if hasattr(metadata, "tags") and metadata.tags:
259
+ tags = metadata.tags
260
+ for key in CAUSATION_ID_TAG_KEYS:
261
+ if key in tags:
262
+ value = tags[key]
263
+ if isinstance(value, UUID):
264
+ return value
265
+ if isinstance(value, str):
266
+ try:
267
+ return UUID(value)
268
+ except ValueError:
269
+ logger.debug(
270
+ "Malformed UUID in tags key '%s': %s",
271
+ key,
272
+ value,
273
+ )
274
+
275
+ # Check metadata.headers for x-causation-id (HTTP transport)
276
+ if hasattr(metadata, "headers") and metadata.headers:
277
+ headers = metadata.headers
278
+ for key in CAUSATION_ID_HEADER_KEYS:
279
+ if key in headers:
280
+ value = headers[key]
281
+ if isinstance(value, str):
282
+ try:
283
+ return UUID(value)
284
+ except ValueError:
285
+ logger.debug(
286
+ "Malformed UUID in headers key '%s': %s",
287
+ key,
288
+ value,
289
+ )
290
+
291
+ return None
292
+
293
+
294
+ # ==============================================================================
295
+ # Chain Propagation Validator
296
+ # ==============================================================================
297
+
298
+
299
+ class ChainPropagationValidator:
300
+ """Validates correlation and causation chain propagation.
301
+
302
+ Enforces workflow traceability rules:
303
+ 1. All messages in a workflow share the same correlation_id
304
+ 2. Every produced message has causation_id = parent.message_id
305
+ 3. Causation chains are local (no skipping ancestors)
306
+
307
+ Attributes:
308
+ None - the validator is stateless.
309
+
310
+ Thread Safety:
311
+ ChainPropagationValidator instances are stateless and thread-safe.
312
+ All validation methods are pure functions that produce fresh result
313
+ objects. Multiple threads can safely call any validation method on
314
+ the same instance concurrently.
315
+
316
+ Example:
317
+ >>> validator = ChainPropagationValidator()
318
+ >>>
319
+ >>> # Validate single parent-child relationship
320
+ >>> violations = validator.validate_chain(parent, child)
321
+ >>>
322
+ >>> # Validate entire workflow chain
323
+ >>> violations = validator.validate_workflow_chain([msg1, msg2, msg3])
324
+ """
325
+
326
+ def validate_correlation_propagation(
327
+ self,
328
+ parent_envelope: ModelEventEnvelope[object],
329
+ child_envelope: ModelEventEnvelope[object],
330
+ ) -> list[ModelChainViolation]:
331
+ """Validate that child message inherits parent's correlation_id.
332
+
333
+ All messages in a workflow must share the same correlation_id to
334
+ enable end-to-end distributed tracing. This method checks that
335
+ the child's correlation_id matches the parent's correlation_id.
336
+
337
+ Args:
338
+ parent_envelope: The parent message envelope.
339
+ child_envelope: The child message envelope produced from parent.
340
+
341
+ Returns:
342
+ List containing a single CORRELATION_MISMATCH violation if the
343
+ correlation_ids don't match, or an empty list if valid.
344
+
345
+ Example:
346
+ >>> validator = ChainPropagationValidator()
347
+ >>> violations = validator.validate_correlation_propagation(parent, child)
348
+ >>> if violations:
349
+ ... print("Correlation chain broken!")
350
+ """
351
+ violations: list[ModelChainViolation] = []
352
+
353
+ parent_correlation = get_correlation_id(parent_envelope)
354
+ child_correlation = get_correlation_id(child_envelope)
355
+
356
+ # If parent has a correlation_id, child must have the same
357
+ if parent_correlation is not None:
358
+ if child_correlation is None:
359
+ violations.append(
360
+ ModelChainViolation(
361
+ violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
362
+ expected_value=parent_correlation,
363
+ actual_value=None,
364
+ message_id=get_message_id(child_envelope),
365
+ parent_message_id=get_message_id(parent_envelope),
366
+ violation_message=(
367
+ f"Child message is missing correlation_id but parent has "
368
+ f"correlation_id={parent_correlation}. "
369
+ "All messages in a workflow must share the same correlation_id."
370
+ ),
371
+ severity=EnumValidationSeverity.ERROR,
372
+ )
373
+ )
374
+ elif child_correlation != parent_correlation:
375
+ violations.append(
376
+ ModelChainViolation(
377
+ violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
378
+ expected_value=parent_correlation,
379
+ actual_value=child_correlation,
380
+ message_id=get_message_id(child_envelope),
381
+ parent_message_id=get_message_id(parent_envelope),
382
+ violation_message=(
383
+ f"Correlation ID mismatch: expected={parent_correlation}, "
384
+ f"actual={child_correlation}. "
385
+ "All messages in a workflow must share the same correlation_id."
386
+ ),
387
+ severity=EnumValidationSeverity.ERROR,
388
+ )
389
+ )
390
+
391
+ return violations
392
+
393
+ def validate_causation_chain(
394
+ self,
395
+ parent_envelope: ModelEventEnvelope[object],
396
+ child_envelope: ModelEventEnvelope[object],
397
+ ) -> list[ModelChainViolation]:
398
+ """Validate that child's causation_id equals parent's message_id.
399
+
400
+ Each message's causation_id must reference its direct parent's
401
+ message_id to form an unbroken lineage back to the workflow origin.
402
+
403
+ Args:
404
+ parent_envelope: The parent message envelope.
405
+ child_envelope: The child message envelope produced from parent.
406
+
407
+ Returns:
408
+ List containing a CAUSATION_CHAIN_BROKEN violation if the
409
+ causation_id doesn't match parent's message_id, or an empty
410
+ list if valid.
411
+
412
+ Example:
413
+ >>> validator = ChainPropagationValidator()
414
+ >>> violations = validator.validate_causation_chain(parent, child)
415
+ >>> if violations:
416
+ ... print("Causation chain broken!")
417
+ """
418
+ violations: list[ModelChainViolation] = []
419
+
420
+ parent_message_id = get_message_id(parent_envelope)
421
+ child_causation_id = get_causation_id(child_envelope)
422
+
423
+ # Child's causation_id must equal parent's message_id
424
+ if child_causation_id is None:
425
+ # Missing causation_id is a chain break
426
+ violations.append(
427
+ ModelChainViolation(
428
+ violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
429
+ expected_value=parent_message_id,
430
+ actual_value=None,
431
+ message_id=get_message_id(child_envelope),
432
+ parent_message_id=parent_message_id,
433
+ violation_message=(
434
+ f"Child message is missing causation_id. "
435
+ f"Expected causation_id={parent_message_id} (parent's message_id). "
436
+ "Every message must reference its parent's message_id "
437
+ "to maintain causation chain integrity."
438
+ ),
439
+ severity=EnumValidationSeverity.ERROR,
440
+ )
441
+ )
442
+ elif child_causation_id != parent_message_id:
443
+ violations.append(
444
+ ModelChainViolation(
445
+ violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
446
+ expected_value=parent_message_id,
447
+ actual_value=child_causation_id,
448
+ message_id=get_message_id(child_envelope),
449
+ parent_message_id=parent_message_id,
450
+ violation_message=(
451
+ f"Causation ID mismatch: expected={parent_message_id}, "
452
+ f"actual={child_causation_id}. "
453
+ "Every message must reference its direct parent's message_id."
454
+ ),
455
+ severity=EnumValidationSeverity.ERROR,
456
+ )
457
+ )
458
+
459
+ return violations
460
+
461
+ def validate_chain(
462
+ self,
463
+ parent_envelope: ModelEventEnvelope[object],
464
+ child_envelope: ModelEventEnvelope[object],
465
+ ) -> list[ModelChainViolation]:
466
+ """Validate both correlation and causation chain propagation.
467
+
468
+ Runs both correlation propagation and causation chain validation,
469
+ returning a combined list of all detected violations.
470
+
471
+ Args:
472
+ parent_envelope: The parent message envelope.
473
+ child_envelope: The child message envelope produced from parent.
474
+
475
+ Returns:
476
+ Combined list of all chain violations detected. Empty list
477
+ if the chain propagation is valid.
478
+
479
+ Example:
480
+ >>> validator = ChainPropagationValidator()
481
+ >>> violations = validator.validate_chain(parent, child)
482
+ >>> for v in violations:
483
+ ... print(f"[{v.severity}] {v.violation_type.value}")
484
+ """
485
+ violations: list[ModelChainViolation] = []
486
+
487
+ # Validate correlation propagation
488
+ violations.extend(
489
+ self.validate_correlation_propagation(parent_envelope, child_envelope)
490
+ )
491
+
492
+ # Validate causation chain
493
+ violations.extend(
494
+ self.validate_causation_chain(parent_envelope, child_envelope)
495
+ )
496
+
497
+ return violations
498
+
499
+ def validate_workflow_chain(
500
+ self,
501
+ envelopes: list[ModelEventEnvelope[object]],
502
+ ) -> list[ModelChainViolation]:
503
+ """Validate an entire chain of messages in a workflow.
504
+
505
+ Validates that:
506
+ 1. All messages share the same correlation_id (if first message has one)
507
+ 2. Each message's causation_id references an ancestor message within
508
+ the provided chain (not necessarily the direct predecessor)
509
+ 3. Parent messages appear before child messages in the list order
510
+
511
+ The envelopes list should be ordered by causation (parent before child).
512
+
513
+ Ancestor Skipping (Intentional Design Decision):
514
+ This method validates that causation_ids reference messages **within**
515
+ the chain, but does NOT enforce direct parent-child ordering. A message
516
+ may reference any ancestor in the chain (e.g., msg3 can reference msg1
517
+ even if msg2 exists between them). This is an intentional design
518
+ decision that provides workflow flexibility for:
519
+
520
+ - **Partial chain reconstruction**: When only a subset of messages
521
+ is available for validation (e.g., from logs or replay)
522
+ - **Fan-out patterns**: When a parent spawns multiple children that
523
+ all reference it directly rather than forming a linear chain
524
+ - **Aggregation patterns**: When reducers aggregate from multiple
525
+ ancestors within the same correlation context
526
+
527
+ For strict direct parent-child validation (enforcing linear chains),
528
+ use pairwise ``validate_chain()`` calls:
529
+
530
+ .. code-block:: python
531
+
532
+ # Strict linear chain validation
533
+ for i in range(len(envelopes) - 1):
534
+ violations.extend(
535
+ validator.validate_chain(envelopes[i], envelopes[i + 1])
536
+ )
537
+
538
+ Args:
539
+ envelopes: Ordered list of message envelopes in the workflow.
540
+ Should be ordered such that each message's causation_id
541
+ references a message earlier in the list.
542
+
543
+ Returns:
544
+ List of all chain violations detected across the workflow.
545
+ Empty list if the entire workflow chain is valid.
546
+
547
+ Example:
548
+ >>> validator = ChainPropagationValidator()
549
+ >>> # Workflow with messages that may reference any ancestor
550
+ >>> violations = validator.validate_workflow_chain([msg1, msg2, msg3])
551
+ >>> blocking = [v for v in violations if v.is_blocking()]
552
+ >>> if blocking:
553
+ ... raise ChainPropagationError(blocking)
554
+ """
555
+ violations: list[ModelChainViolation] = []
556
+
557
+ if len(envelopes) < 2:
558
+ # Single message or empty list - no chain to validate
559
+ return violations
560
+
561
+ # Build message_id -> envelope and message_id -> index mappings for O(1) lookup
562
+ # This avoids O(n) list.index() calls inside the O(n) validation loop
563
+ message_id_to_envelope: dict[UUID, ModelEventEnvelope[object]] = {}
564
+ message_id_to_index: dict[UUID, int] = {}
565
+ for idx, env in enumerate(envelopes):
566
+ msg_id = get_message_id(env)
567
+ message_id_to_envelope[msg_id] = env
568
+ message_id_to_index[msg_id] = idx
569
+
570
+ # Get the reference correlation_id from the first message
571
+ reference_correlation_id = get_correlation_id(envelopes[0])
572
+
573
+ # Validate each message in the chain
574
+ for i, envelope in enumerate(envelopes):
575
+ message_id = get_message_id(envelope)
576
+
577
+ # 1. Validate correlation_id consistency
578
+ envelope_correlation_id = get_correlation_id(envelope)
579
+ if reference_correlation_id is not None:
580
+ if envelope_correlation_id is None:
581
+ violations.append(
582
+ ModelChainViolation(
583
+ violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
584
+ expected_value=reference_correlation_id,
585
+ actual_value=None,
586
+ message_id=message_id,
587
+ parent_message_id=None,
588
+ violation_message=(
589
+ f"Message at index {i} is missing correlation_id "
590
+ f"but workflow uses correlation_id={reference_correlation_id}. "
591
+ "All messages in a workflow must share the same correlation_id."
592
+ ),
593
+ severity=EnumValidationSeverity.ERROR,
594
+ )
595
+ )
596
+ elif envelope_correlation_id != reference_correlation_id:
597
+ violations.append(
598
+ ModelChainViolation(
599
+ violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
600
+ expected_value=reference_correlation_id,
601
+ actual_value=envelope_correlation_id,
602
+ message_id=message_id,
603
+ parent_message_id=None,
604
+ violation_message=(
605
+ f"Message at index {i} has correlation_id mismatch: "
606
+ f"expected={reference_correlation_id}, actual={envelope_correlation_id}. "
607
+ "All messages must share the same correlation_id for distributed tracing."
608
+ ),
609
+ severity=EnumValidationSeverity.ERROR,
610
+ )
611
+ )
612
+
613
+ # 2. Validate causation chain (skip first message - it's the root)
614
+ if i > 0:
615
+ causation_id = get_causation_id(envelope)
616
+
617
+ if causation_id is None:
618
+ # Non-root message must have causation_id
619
+ violations.append(
620
+ ModelChainViolation(
621
+ violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
622
+ expected_value=None, # Can't determine expected without causation
623
+ actual_value=None,
624
+ message_id=message_id,
625
+ parent_message_id=None,
626
+ violation_message=(
627
+ f"Message at index {i} (message_id={message_id}) is missing "
628
+ "causation_id. Every message (except root) must reference its "
629
+ "parent's message_id to maintain causation chain."
630
+ ),
631
+ severity=EnumValidationSeverity.ERROR,
632
+ )
633
+ )
634
+ # Check if causation_id references a message in the chain
635
+ elif causation_id not in message_id_to_envelope:
636
+ violations.append(
637
+ ModelChainViolation(
638
+ violation_type=EnumChainViolationType.CAUSATION_ANCESTOR_SKIPPED,
639
+ expected_value=None,
640
+ actual_value=causation_id,
641
+ message_id=message_id,
642
+ parent_message_id=causation_id,
643
+ violation_message=(
644
+ f"Message at index {i} (message_id={message_id}) has "
645
+ f"causation_id={causation_id} which references a message "
646
+ "not in this workflow chain. "
647
+ "Causation chains must form an unbroken sequence."
648
+ ),
649
+ severity=EnumValidationSeverity.ERROR,
650
+ )
651
+ )
652
+ else:
653
+ # Check that causation_id references an earlier message
654
+ # Use O(1) dict lookup instead of O(n) list.index()
655
+ parent_idx = message_id_to_index[causation_id]
656
+
657
+ if parent_idx >= i:
658
+ # Parent appears after child in the list - order violation
659
+ violations.append(
660
+ ModelChainViolation(
661
+ violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
662
+ expected_value=None,
663
+ actual_value=causation_id,
664
+ message_id=message_id,
665
+ parent_message_id=causation_id,
666
+ violation_message=(
667
+ f"Message at index {i} (message_id={message_id}) references "
668
+ f"parent at index {parent_idx} (causation_id={causation_id}) "
669
+ "but parents must appear before children in the causation chain. "
670
+ "Check message ordering."
671
+ ),
672
+ severity=EnumValidationSeverity.WARNING,
673
+ )
674
+ )
675
+
676
+ return violations
677
+
678
+ def validate_linear_workflow_chain(
679
+ self,
680
+ envelopes: list[ModelEventEnvelope[object]],
681
+ ) -> list[ModelChainViolation]:
682
+ """Validate strict linear chain (no ancestor skipping).
683
+
684
+ Unlike validate_workflow_chain() which allows ancestor skipping,
685
+ this method enforces that each message's causation_id references
686
+ the immediately preceding message (direct parent).
687
+
688
+ Use this method when you need to verify a strict linear workflow
689
+ where messages form a single unbroken chain:
690
+ msg1 -> msg2 -> msg3 -> msg4
691
+
692
+ For workflows with fan-out patterns or aggregation, use
693
+ validate_workflow_chain() instead.
694
+
695
+ Args:
696
+ envelopes: Ordered list of message envelopes in the workflow.
697
+ Each message at index i+1 must have causation_id equal to
698
+ the envelope_id of message at index i.
699
+
700
+ Returns:
701
+ List of all chain violations detected. Empty list if the
702
+ entire linear chain is valid.
703
+
704
+ Example:
705
+ >>> validator = ChainPropagationValidator()
706
+ >>> # Strict linear chain - each message must reference direct parent
707
+ >>> violations = validator.validate_linear_workflow_chain([msg1, msg2, msg3])
708
+ >>> if violations:
709
+ ... print("Linear chain broken!")
710
+ """
711
+ violations: list[ModelChainViolation] = []
712
+
713
+ if len(envelopes) < 2:
714
+ return violations
715
+
716
+ for i in range(len(envelopes) - 1):
717
+ violations.extend(self.validate_chain(envelopes[i], envelopes[i + 1]))
718
+
719
+ return violations
720
+
721
+
722
+ # ==============================================================================
723
+ # Module-Level Singleton Validator
724
+ # ==============================================================================
725
+ #
726
+ # Performance Optimization: ChainPropagationValidator is stateless after
727
+ # initialization. Creating new instances on every validation call is wasteful.
728
+ # Instead, we use a module-level singleton.
729
+ #
730
+ # Why a singleton is safe here:
731
+ # - The validator is completely stateless (no mutable state)
732
+ # - All validation methods are pure functions that produce new results
733
+ # - Multiple threads can safely use the same validator instance
734
+
735
+ _default_validator = ChainPropagationValidator()
736
+
737
+
738
+ # ==============================================================================
739
+ # Convenience Functions
740
+ # ==============================================================================
741
+
742
+
743
+ def validate_message_chain(
744
+ parent_envelope: ModelEventEnvelope[object],
745
+ child_envelope: ModelEventEnvelope[object],
746
+ ) -> list[ModelChainViolation]:
747
+ """Validate chain propagation between parent and child messages.
748
+
749
+ Convenience function that validates both correlation and causation
750
+ chain propagation using the default singleton validator.
751
+
752
+ Args:
753
+ parent_envelope: The parent message envelope.
754
+ child_envelope: The child message envelope produced from parent.
755
+
756
+ Returns:
757
+ List of chain violations detected. Empty list if valid.
758
+
759
+ Example:
760
+ >>> violations = validate_message_chain(parent, child)
761
+ >>> if violations:
762
+ ... for v in violations:
763
+ ... print(v.format_for_logging())
764
+ """
765
+ return _default_validator.validate_chain(parent_envelope, child_envelope)
766
+
767
+
768
+ def validate_linear_message_chain(
769
+ envelopes: list[ModelEventEnvelope[object]],
770
+ ) -> list[ModelChainViolation]:
771
+ """Validate strict linear chain using default validator.
772
+
773
+ Convenience function for validate_linear_workflow_chain() that uses
774
+ the module-level singleton validator. Validates that each message
775
+ in the chain references its immediate predecessor.
776
+
777
+ Unlike validate_workflow_chain() which allows ancestor skipping,
778
+ this function enforces strict linear ordering where each message's
779
+ causation_id must equal the envelope_id of the immediately preceding
780
+ message.
781
+
782
+ Args:
783
+ envelopes: Ordered list of message envelopes in the workflow.
784
+ Each message at index i+1 must have causation_id equal to
785
+ the envelope_id of message at index i.
786
+
787
+ Returns:
788
+ List of all chain violations detected. Empty list if the
789
+ entire linear chain is valid.
790
+
791
+ Example:
792
+ >>> violations = validate_linear_message_chain([msg1, msg2, msg3])
793
+ >>> if violations:
794
+ ... for v in violations:
795
+ ... print(v.format_for_logging())
796
+ """
797
+ return _default_validator.validate_linear_workflow_chain(envelopes)
798
+
799
+
800
+ def enforce_chain_propagation(
801
+ parent_envelope: ModelEventEnvelope[object],
802
+ child_envelope: ModelEventEnvelope[object],
803
+ ) -> None:
804
+ """Validate chain propagation and raise error if violations found.
805
+
806
+ Strict enforcement function that validates both correlation and causation
807
+ chain propagation, raising ChainPropagationError if any violations are
808
+ detected.
809
+
810
+ Args:
811
+ parent_envelope: The parent message envelope.
812
+ child_envelope: The child message envelope produced from parent.
813
+
814
+ Raises:
815
+ ChainPropagationError: If any chain violations are detected.
816
+ Contains the list of violations for inspection.
817
+
818
+ Example:
819
+ >>> try:
820
+ ... enforce_chain_propagation(parent, child)
821
+ ... print("Chain propagation valid")
822
+ ... except ChainPropagationError as e:
823
+ ... print(f"Invalid: {len(e.violations)} violations")
824
+ ... for v in e.violations:
825
+ ... print(f" - {v.violation_type.value}: {v.violation_message}")
826
+ """
827
+ violations = _default_validator.validate_chain(parent_envelope, child_envelope)
828
+
829
+ if violations:
830
+ # Use parent's correlation_id for error tracking
831
+ context = ModelInfraErrorContext(
832
+ operation="enforce_chain_propagation",
833
+ correlation_id=get_correlation_id(parent_envelope),
834
+ )
835
+ raise ChainPropagationError(
836
+ message="Chain propagation validation failed",
837
+ violations=violations,
838
+ context=context,
839
+ )