omnibase_infra 0.2.6__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 (833) hide show
  1. omnibase_infra/__init__.py +101 -0
  2. omnibase_infra/adapters/adapter_onex_tool_execution.py +451 -0
  3. omnibase_infra/capabilities/__init__.py +15 -0
  4. omnibase_infra/capabilities/capability_inference_rules.py +211 -0
  5. omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
  6. omnibase_infra/capabilities/intent_type_extractor.py +160 -0
  7. omnibase_infra/cli/__init__.py +1 -0
  8. omnibase_infra/cli/commands.py +216 -0
  9. omnibase_infra/clients/__init__.py +0 -0
  10. omnibase_infra/configs/widget_mapping.yaml +176 -0
  11. omnibase_infra/constants_topic_patterns.py +26 -0
  12. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +264 -0
  13. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +141 -0
  14. omnibase_infra/decorators/__init__.py +29 -0
  15. omnibase_infra/decorators/allow_any.py +109 -0
  16. omnibase_infra/dlq/__init__.py +90 -0
  17. omnibase_infra/dlq/constants_dlq.py +57 -0
  18. omnibase_infra/dlq/models/__init__.py +26 -0
  19. omnibase_infra/dlq/models/enum_replay_status.py +37 -0
  20. omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
  21. omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
  22. omnibase_infra/dlq/service_dlq_tracking.py +611 -0
  23. omnibase_infra/enums/__init__.py +132 -0
  24. omnibase_infra/enums/enum_any_type_violation.py +104 -0
  25. omnibase_infra/enums/enum_backend_type.py +27 -0
  26. omnibase_infra/enums/enum_capture_outcome.py +42 -0
  27. omnibase_infra/enums/enum_capture_state.py +88 -0
  28. omnibase_infra/enums/enum_chain_violation_type.py +119 -0
  29. omnibase_infra/enums/enum_circuit_state.py +51 -0
  30. omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
  31. omnibase_infra/enums/enum_consumer_group_purpose.py +92 -0
  32. omnibase_infra/enums/enum_contract_type.py +84 -0
  33. omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
  34. omnibase_infra/enums/enum_dispatch_status.py +191 -0
  35. omnibase_infra/enums/enum_environment.py +46 -0
  36. omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
  37. omnibase_infra/enums/enum_handler_error_type.py +111 -0
  38. omnibase_infra/enums/enum_handler_loader_error.py +178 -0
  39. omnibase_infra/enums/enum_handler_source_mode.py +86 -0
  40. omnibase_infra/enums/enum_handler_source_type.py +87 -0
  41. omnibase_infra/enums/enum_handler_type.py +77 -0
  42. omnibase_infra/enums/enum_handler_type_category.py +61 -0
  43. omnibase_infra/enums/enum_infra_transport_type.py +73 -0
  44. omnibase_infra/enums/enum_introspection_reason.py +154 -0
  45. omnibase_infra/enums/enum_kafka_acks.py +99 -0
  46. omnibase_infra/enums/enum_message_category.py +213 -0
  47. omnibase_infra/enums/enum_node_archetype.py +74 -0
  48. omnibase_infra/enums/enum_node_output_type.py +185 -0
  49. omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
  50. omnibase_infra/enums/enum_policy_type.py +32 -0
  51. omnibase_infra/enums/enum_registration_state.py +261 -0
  52. omnibase_infra/enums/enum_registration_status.py +33 -0
  53. omnibase_infra/enums/enum_registry_response_status.py +28 -0
  54. omnibase_infra/enums/enum_response_status.py +26 -0
  55. omnibase_infra/enums/enum_retry_error_category.py +98 -0
  56. omnibase_infra/enums/enum_security_rule_id.py +103 -0
  57. omnibase_infra/enums/enum_selection_strategy.py +91 -0
  58. omnibase_infra/enums/enum_topic_standard.py +42 -0
  59. omnibase_infra/enums/enum_validation_severity.py +78 -0
  60. omnibase_infra/errors/__init__.py +160 -0
  61. omnibase_infra/errors/error_architecture_violation.py +152 -0
  62. omnibase_infra/errors/error_binding_resolution.py +128 -0
  63. omnibase_infra/errors/error_chain_propagation.py +188 -0
  64. omnibase_infra/errors/error_compute_registry.py +95 -0
  65. omnibase_infra/errors/error_consul.py +132 -0
  66. omnibase_infra/errors/error_container_wiring.py +243 -0
  67. omnibase_infra/errors/error_event_bus_registry.py +105 -0
  68. omnibase_infra/errors/error_infra.py +610 -0
  69. omnibase_infra/errors/error_message_type_registry.py +101 -0
  70. omnibase_infra/errors/error_policy_registry.py +115 -0
  71. omnibase_infra/errors/error_vault.py +123 -0
  72. omnibase_infra/event_bus/__init__.py +72 -0
  73. omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +84 -0
  74. omnibase_infra/event_bus/event_bus_inmemory.py +797 -0
  75. omnibase_infra/event_bus/event_bus_kafka.py +1716 -0
  76. omnibase_infra/event_bus/mixin_kafka_broadcast.py +180 -0
  77. omnibase_infra/event_bus/mixin_kafka_dlq.py +771 -0
  78. omnibase_infra/event_bus/models/__init__.py +29 -0
  79. omnibase_infra/event_bus/models/config/__init__.py +20 -0
  80. omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +693 -0
  81. omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
  82. omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
  83. omnibase_infra/event_bus/models/model_event_headers.py +115 -0
  84. omnibase_infra/event_bus/models/model_event_message.py +60 -0
  85. omnibase_infra/event_bus/testing/__init__.py +26 -0
  86. omnibase_infra/event_bus/testing/adapter_protocol_event_publisher_inmemory.py +418 -0
  87. omnibase_infra/event_bus/testing/model_publisher_metrics.py +64 -0
  88. omnibase_infra/event_bus/topic_constants.py +376 -0
  89. omnibase_infra/handlers/__init__.py +82 -0
  90. omnibase_infra/handlers/filesystem/__init__.py +48 -0
  91. omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
  92. omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
  93. omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
  94. omnibase_infra/handlers/handler_consul.py +795 -0
  95. omnibase_infra/handlers/handler_db.py +1046 -0
  96. omnibase_infra/handlers/handler_filesystem.py +1478 -0
  97. omnibase_infra/handlers/handler_graph.py +2015 -0
  98. omnibase_infra/handlers/handler_http.py +926 -0
  99. omnibase_infra/handlers/handler_intent.py +387 -0
  100. omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
  101. omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
  102. omnibase_infra/handlers/handler_mcp.py +1430 -0
  103. omnibase_infra/handlers/handler_qdrant.py +1076 -0
  104. omnibase_infra/handlers/handler_vault.py +428 -0
  105. omnibase_infra/handlers/mcp/__init__.py +19 -0
  106. omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
  107. omnibase_infra/handlers/mcp/protocols.py +178 -0
  108. omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
  109. omnibase_infra/handlers/mixins/__init__.py +47 -0
  110. omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
  111. omnibase_infra/handlers/mixins/mixin_consul_kv.py +338 -0
  112. omnibase_infra/handlers/mixins/mixin_consul_service.py +542 -0
  113. omnibase_infra/handlers/mixins/mixin_consul_topic_index.py +585 -0
  114. omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
  115. omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
  116. omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
  117. omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
  118. omnibase_infra/handlers/models/__init__.py +286 -0
  119. omnibase_infra/handlers/models/consul/__init__.py +81 -0
  120. omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
  121. omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
  122. omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
  123. omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
  124. omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
  125. omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
  126. omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
  127. omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
  128. omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
  129. omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
  130. omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
  131. omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
  132. omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
  133. omnibase_infra/handlers/models/graph/__init__.py +35 -0
  134. omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
  135. omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
  136. omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
  137. omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
  138. omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
  139. omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
  140. omnibase_infra/handlers/models/http/__init__.py +50 -0
  141. omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
  142. omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
  143. omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
  144. omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
  145. omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
  146. omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
  147. omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
  148. omnibase_infra/handlers/models/mcp/__init__.py +23 -0
  149. omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
  150. omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
  151. omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
  152. omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
  153. omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
  154. omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
  155. omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
  156. omnibase_infra/handlers/models/model_db_query_response.py +60 -0
  157. omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
  158. omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
  159. omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
  160. omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
  161. omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
  162. omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
  163. omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
  164. omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
  165. omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
  166. omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
  167. omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
  168. omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
  169. omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
  170. omnibase_infra/handlers/models/model_handler_response.py +103 -0
  171. omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
  172. omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
  173. omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
  174. omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
  175. omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
  176. omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
  177. omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
  178. omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
  179. omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
  180. omnibase_infra/handlers/models/model_operation_context.py +187 -0
  181. omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
  182. omnibase_infra/handlers/models/model_retry_state.py +162 -0
  183. omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
  184. omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
  185. omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
  186. omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
  187. omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
  188. omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
  189. omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
  190. omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
  191. omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
  192. omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
  193. omnibase_infra/handlers/models/vault/__init__.py +69 -0
  194. omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
  195. omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
  196. omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
  197. omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
  198. omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
  199. omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
  200. omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
  201. omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
  202. omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
  203. omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
  204. omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
  205. omnibase_infra/handlers/registration_storage/__init__.py +43 -0
  206. omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
  207. omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +922 -0
  208. omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
  209. omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
  210. omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
  211. omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
  212. omnibase_infra/handlers/service_discovery/__init__.py +43 -0
  213. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +1051 -0
  214. omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
  215. omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
  216. omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
  217. omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
  218. omnibase_infra/handlers/service_discovery/models/model_service_info.py +109 -0
  219. omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
  220. omnibase_infra/idempotency/__init__.py +94 -0
  221. omnibase_infra/idempotency/models/__init__.py +43 -0
  222. omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
  223. omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
  224. omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
  225. omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
  226. omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
  227. omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
  228. omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
  229. omnibase_infra/idempotency/store_inmemory.py +265 -0
  230. omnibase_infra/idempotency/store_postgres.py +923 -0
  231. omnibase_infra/infrastructure/__init__.py +0 -0
  232. omnibase_infra/migrations/001_create_event_ledger.sql +166 -0
  233. omnibase_infra/migrations/001_drop_event_ledger.sql +18 -0
  234. omnibase_infra/mixins/__init__.py +71 -0
  235. omnibase_infra/mixins/mixin_async_circuit_breaker.py +656 -0
  236. omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
  237. omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
  238. omnibase_infra/mixins/mixin_node_introspection.py +2670 -0
  239. omnibase_infra/mixins/mixin_retry_execution.py +386 -0
  240. omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
  241. omnibase_infra/models/__init__.py +144 -0
  242. omnibase_infra/models/bindings/__init__.py +59 -0
  243. omnibase_infra/models/bindings/constants.py +144 -0
  244. omnibase_infra/models/bindings/model_binding_resolution_result.py +103 -0
  245. omnibase_infra/models/bindings/model_operation_binding.py +44 -0
  246. omnibase_infra/models/bindings/model_operation_bindings_subcontract.py +152 -0
  247. omnibase_infra/models/bindings/model_parsed_binding.py +52 -0
  248. omnibase_infra/models/corpus/__init__.py +17 -0
  249. omnibase_infra/models/corpus/model_capture_config.py +133 -0
  250. omnibase_infra/models/corpus/model_capture_result.py +86 -0
  251. omnibase_infra/models/discovery/__init__.py +42 -0
  252. omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
  253. omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
  254. omnibase_infra/models/discovery/model_introspection_config.py +330 -0
  255. omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
  256. omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
  257. omnibase_infra/models/dispatch/__init__.py +155 -0
  258. omnibase_infra/models/dispatch/model_debug_trace_snapshot.py +114 -0
  259. omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
  260. omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
  261. omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
  262. omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
  263. omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
  264. omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
  265. omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
  266. omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
  267. omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
  268. omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
  269. omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
  270. omnibase_infra/models/dispatch/model_materialized_dispatch.py +141 -0
  271. omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
  272. omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
  273. omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
  274. omnibase_infra/models/errors/__init__.py +45 -0
  275. omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
  276. omnibase_infra/models/errors/model_infra_error_context.py +99 -0
  277. omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
  278. omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
  279. omnibase_infra/models/handlers/__init__.py +80 -0
  280. omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
  281. omnibase_infra/models/handlers/model_contract_discovery_result.py +82 -0
  282. omnibase_infra/models/handlers/model_handler_descriptor.py +200 -0
  283. omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
  284. omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
  285. omnibase_infra/models/health/__init__.py +9 -0
  286. omnibase_infra/models/health/model_health_check_result.py +40 -0
  287. omnibase_infra/models/lifecycle/__init__.py +39 -0
  288. omnibase_infra/models/logging/__init__.py +51 -0
  289. omnibase_infra/models/logging/model_log_context.py +756 -0
  290. omnibase_infra/models/mcp/__init__.py +15 -0
  291. omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
  292. omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
  293. omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
  294. omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
  295. omnibase_infra/models/model_node_identity.py +126 -0
  296. omnibase_infra/models/model_retry_error_classification.py +78 -0
  297. omnibase_infra/models/projection/__init__.py +43 -0
  298. omnibase_infra/models/projection/model_capability_fields.py +112 -0
  299. omnibase_infra/models/projection/model_registration_projection.py +434 -0
  300. omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
  301. omnibase_infra/models/projection/model_sequence_info.py +182 -0
  302. omnibase_infra/models/projection/model_snapshot_topic_config.py +591 -0
  303. omnibase_infra/models/projectors/__init__.py +41 -0
  304. omnibase_infra/models/projectors/model_projector_column.py +289 -0
  305. omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
  306. omnibase_infra/models/projectors/model_projector_index.py +270 -0
  307. omnibase_infra/models/projectors/model_projector_schema.py +415 -0
  308. omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
  309. omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
  310. omnibase_infra/models/registration/__init__.py +68 -0
  311. omnibase_infra/models/registration/commands/__init__.py +15 -0
  312. omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
  313. omnibase_infra/models/registration/events/__init__.py +56 -0
  314. omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
  315. omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
  316. omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
  317. omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
  318. omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
  319. omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
  320. omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
  321. omnibase_infra/models/registration/model_event_bus_topic_entry.py +59 -0
  322. omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
  323. omnibase_infra/models/registration/model_node_capabilities.py +190 -0
  324. omnibase_infra/models/registration/model_node_event_bus_config.py +99 -0
  325. omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
  326. omnibase_infra/models/registration/model_node_introspection_event.py +195 -0
  327. omnibase_infra/models/registration/model_node_metadata.py +79 -0
  328. omnibase_infra/models/registration/model_node_registration.py +162 -0
  329. omnibase_infra/models/registration/model_node_registration_record.py +162 -0
  330. omnibase_infra/models/registry/__init__.py +29 -0
  331. omnibase_infra/models/registry/model_domain_constraint.py +202 -0
  332. omnibase_infra/models/registry/model_message_type_entry.py +271 -0
  333. omnibase_infra/models/resilience/__init__.py +9 -0
  334. omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
  335. omnibase_infra/models/routing/__init__.py +25 -0
  336. omnibase_infra/models/routing/model_routing_entry.py +52 -0
  337. omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
  338. omnibase_infra/models/runtime/__init__.py +49 -0
  339. omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
  340. omnibase_infra/models/runtime/model_discovery_error.py +81 -0
  341. omnibase_infra/models/runtime/model_discovery_result.py +162 -0
  342. omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
  343. omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
  344. omnibase_infra/models/runtime/model_handler_contract.py +296 -0
  345. omnibase_infra/models/runtime/model_loaded_handler.py +129 -0
  346. omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
  347. omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
  348. omnibase_infra/models/security/__init__.py +50 -0
  349. omnibase_infra/models/security/classification_levels.py +99 -0
  350. omnibase_infra/models/security/model_environment_policy.py +145 -0
  351. omnibase_infra/models/security/model_handler_security_policy.py +107 -0
  352. omnibase_infra/models/security/model_security_error.py +81 -0
  353. omnibase_infra/models/security/model_security_validation_result.py +328 -0
  354. omnibase_infra/models/security/model_security_warning.py +67 -0
  355. omnibase_infra/models/snapshot/__init__.py +27 -0
  356. omnibase_infra/models/snapshot/model_field_change.py +65 -0
  357. omnibase_infra/models/snapshot/model_snapshot.py +270 -0
  358. omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
  359. omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
  360. omnibase_infra/models/types/__init__.py +71 -0
  361. omnibase_infra/models/validation/__init__.py +89 -0
  362. omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
  363. omnibase_infra/models/validation/model_any_type_violation.py +141 -0
  364. omnibase_infra/models/validation/model_category_match_result.py +345 -0
  365. omnibase_infra/models/validation/model_chain_violation.py +166 -0
  366. omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
  367. omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
  368. omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
  369. omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
  370. omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
  371. omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
  372. omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
  373. omnibase_infra/models/validation/model_output_validation_params.py +74 -0
  374. omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
  375. omnibase_infra/models/validation/model_validation_error_params.py +84 -0
  376. omnibase_infra/models/validation/model_validation_outcome.py +287 -0
  377. omnibase_infra/nodes/__init__.py +57 -0
  378. omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
  379. omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
  380. omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +203 -0
  381. omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
  382. omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
  383. omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
  384. omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
  385. omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
  386. omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
  387. omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
  388. omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
  389. omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
  390. omnibase_infra/nodes/architecture_validator/node.py +262 -0
  391. omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
  392. omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
  393. omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
  394. omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
  395. omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +106 -0
  396. omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
  397. omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
  398. omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
  399. omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
  400. omnibase_infra/nodes/contract_registry_reducer/__init__.py +29 -0
  401. omnibase_infra/nodes/contract_registry_reducer/contract.yaml +255 -0
  402. omnibase_infra/nodes/contract_registry_reducer/models/__init__.py +38 -0
  403. omnibase_infra/nodes/contract_registry_reducer/models/model_contract_registry_state.py +266 -0
  404. omnibase_infra/nodes/contract_registry_reducer/models/model_payload_cleanup_topic_references.py +55 -0
  405. omnibase_infra/nodes/contract_registry_reducer/models/model_payload_deactivate_contract.py +58 -0
  406. omnibase_infra/nodes/contract_registry_reducer/models/model_payload_mark_stale.py +49 -0
  407. omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_heartbeat.py +71 -0
  408. omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_topic.py +66 -0
  409. omnibase_infra/nodes/contract_registry_reducer/models/model_payload_upsert_contract.py +92 -0
  410. omnibase_infra/nodes/contract_registry_reducer/node.py +121 -0
  411. omnibase_infra/nodes/contract_registry_reducer/reducer.py +784 -0
  412. omnibase_infra/nodes/contract_registry_reducer/registry/__init__.py +9 -0
  413. omnibase_infra/nodes/contract_registry_reducer/registry/registry_infra_contract_registry_reducer.py +101 -0
  414. omnibase_infra/nodes/effects/README.md +358 -0
  415. omnibase_infra/nodes/effects/__init__.py +26 -0
  416. omnibase_infra/nodes/effects/contract.yaml +167 -0
  417. omnibase_infra/nodes/effects/models/__init__.py +32 -0
  418. omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
  419. omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
  420. omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
  421. omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
  422. omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
  423. omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
  424. omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
  425. omnibase_infra/nodes/effects/registry_effect.py +525 -0
  426. omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
  427. omnibase_infra/nodes/handlers/consul/contract.yaml +85 -0
  428. omnibase_infra/nodes/handlers/db/contract.yaml +72 -0
  429. omnibase_infra/nodes/handlers/graph/contract.yaml +127 -0
  430. omnibase_infra/nodes/handlers/http/contract.yaml +74 -0
  431. omnibase_infra/nodes/handlers/intent/contract.yaml +66 -0
  432. omnibase_infra/nodes/handlers/mcp/contract.yaml +69 -0
  433. omnibase_infra/nodes/handlers/vault/contract.yaml +91 -0
  434. omnibase_infra/nodes/node_intent_storage_effect/__init__.py +50 -0
  435. omnibase_infra/nodes/node_intent_storage_effect/contract.yaml +194 -0
  436. omnibase_infra/nodes/node_intent_storage_effect/models/__init__.py +24 -0
  437. omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_input.py +141 -0
  438. omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_output.py +130 -0
  439. omnibase_infra/nodes/node_intent_storage_effect/node.py +94 -0
  440. omnibase_infra/nodes/node_intent_storage_effect/registry/__init__.py +35 -0
  441. omnibase_infra/nodes/node_intent_storage_effect/registry/registry_infra_intent_storage.py +294 -0
  442. omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +50 -0
  443. omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +104 -0
  444. omnibase_infra/nodes/node_ledger_projection_compute/node.py +284 -0
  445. omnibase_infra/nodes/node_ledger_projection_compute/registry/__init__.py +29 -0
  446. omnibase_infra/nodes/node_ledger_projection_compute/registry/registry_infra_ledger_projection.py +118 -0
  447. omnibase_infra/nodes/node_ledger_write_effect/__init__.py +82 -0
  448. omnibase_infra/nodes/node_ledger_write_effect/contract.yaml +200 -0
  449. omnibase_infra/nodes/node_ledger_write_effect/handlers/__init__.py +22 -0
  450. omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_append.py +372 -0
  451. omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_query.py +597 -0
  452. omnibase_infra/nodes/node_ledger_write_effect/models/__init__.py +31 -0
  453. omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_append_result.py +54 -0
  454. omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_entry.py +92 -0
  455. omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query.py +53 -0
  456. omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query_result.py +41 -0
  457. omnibase_infra/nodes/node_ledger_write_effect/node.py +89 -0
  458. omnibase_infra/nodes/node_ledger_write_effect/protocols/__init__.py +13 -0
  459. omnibase_infra/nodes/node_ledger_write_effect/protocols/protocol_ledger_persistence.py +127 -0
  460. omnibase_infra/nodes/node_ledger_write_effect/registry/__init__.py +9 -0
  461. omnibase_infra/nodes/node_ledger_write_effect/registry/registry_infra_ledger_write.py +121 -0
  462. omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
  463. omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
  464. omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +482 -0
  465. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
  466. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
  467. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
  468. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
  469. omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
  470. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
  471. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +694 -0
  472. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
  473. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
  474. omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
  475. omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
  476. omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
  477. omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
  478. omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
  479. omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
  480. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
  481. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
  482. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
  483. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
  484. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
  485. omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
  486. omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
  487. omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
  488. omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
  489. omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
  490. omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
  491. omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
  492. omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
  493. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +528 -0
  494. omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +393 -0
  495. omnibase_infra/nodes/node_registration_orchestrator/wiring.py +743 -0
  496. omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
  497. omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
  498. omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
  499. omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
  500. omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
  501. omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
  502. omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
  503. omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
  504. omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +220 -0
  505. omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
  506. omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
  507. omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
  508. omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
  509. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
  510. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
  511. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
  512. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
  513. omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
  514. omnibase_infra/nodes/node_registration_storage_effect/node.py +112 -0
  515. omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
  516. omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
  517. omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
  518. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +215 -0
  519. omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
  520. omnibase_infra/nodes/node_registry_effect/contract.yaml +677 -0
  521. omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
  522. omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
  523. omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
  524. omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +417 -0
  525. omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
  526. omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
  527. omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
  528. omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
  529. omnibase_infra/nodes/node_registry_effect/node.py +165 -0
  530. omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
  531. omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
  532. omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
  533. omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
  534. omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
  535. omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
  536. omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
  537. omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
  538. omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
  539. omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
  540. omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
  541. omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
  542. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
  543. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
  544. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
  545. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
  546. omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
  547. omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
  548. omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
  549. omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
  550. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +222 -0
  551. omnibase_infra/nodes/reducers/__init__.py +30 -0
  552. omnibase_infra/nodes/reducers/models/__init__.py +37 -0
  553. omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +87 -0
  554. omnibase_infra/nodes/reducers/models/model_payload_ledger_append.py +133 -0
  555. omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
  556. omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
  557. omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
  558. omnibase_infra/nodes/reducers/registration_reducer.py +1138 -0
  559. omnibase_infra/observability/__init__.py +143 -0
  560. omnibase_infra/observability/constants_metrics.py +91 -0
  561. omnibase_infra/observability/factory_observability_sink.py +525 -0
  562. omnibase_infra/observability/handlers/__init__.py +118 -0
  563. omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
  564. omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
  565. omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
  566. omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
  567. omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
  568. omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
  569. omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
  570. omnibase_infra/observability/hooks/__init__.py +74 -0
  571. omnibase_infra/observability/hooks/hook_observability.py +1223 -0
  572. omnibase_infra/observability/models/__init__.py +30 -0
  573. omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
  574. omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
  575. omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
  576. omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
  577. omnibase_infra/observability/sinks/__init__.py +69 -0
  578. omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
  579. omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
  580. omnibase_infra/plugins/__init__.py +27 -0
  581. omnibase_infra/plugins/examples/__init__.py +28 -0
  582. omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
  583. omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
  584. omnibase_infra/plugins/models/__init__.py +21 -0
  585. omnibase_infra/plugins/models/model_plugin_context.py +76 -0
  586. omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
  587. omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
  588. omnibase_infra/plugins/plugin_compute_base.py +449 -0
  589. omnibase_infra/projectors/__init__.py +30 -0
  590. omnibase_infra/projectors/contracts/__init__.py +63 -0
  591. omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
  592. omnibase_infra/projectors/projection_reader_registration.py +1559 -0
  593. omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
  594. omnibase_infra/protocols/__init__.py +104 -0
  595. omnibase_infra/protocols/protocol_capability_projection.py +253 -0
  596. omnibase_infra/protocols/protocol_capability_query.py +251 -0
  597. omnibase_infra/protocols/protocol_container_aware.py +200 -0
  598. omnibase_infra/protocols/protocol_dispatch_engine.py +152 -0
  599. omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
  600. omnibase_infra/protocols/protocol_event_projector.py +96 -0
  601. omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
  602. omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
  603. omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
  604. omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
  605. omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
  606. omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
  607. omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
  608. omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
  609. omnibase_infra/runtime/__init__.py +445 -0
  610. omnibase_infra/runtime/binding_config_resolver.py +2771 -0
  611. omnibase_infra/runtime/binding_resolver.py +753 -0
  612. omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
  613. omnibase_infra/runtime/constants_notification.py +75 -0
  614. omnibase_infra/runtime/constants_security.py +70 -0
  615. omnibase_infra/runtime/contract_handler_discovery.py +587 -0
  616. omnibase_infra/runtime/contract_loaders/__init__.py +51 -0
  617. omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
  618. omnibase_infra/runtime/contract_loaders/operation_bindings_loader.py +789 -0
  619. omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
  620. omnibase_infra/runtime/emit_daemon/__init__.py +97 -0
  621. omnibase_infra/runtime/emit_daemon/cli.py +844 -0
  622. omnibase_infra/runtime/emit_daemon/client.py +811 -0
  623. omnibase_infra/runtime/emit_daemon/config.py +535 -0
  624. omnibase_infra/runtime/emit_daemon/daemon.py +812 -0
  625. omnibase_infra/runtime/emit_daemon/event_registry.py +477 -0
  626. omnibase_infra/runtime/emit_daemon/model_daemon_request.py +139 -0
  627. omnibase_infra/runtime/emit_daemon/model_daemon_response.py +191 -0
  628. omnibase_infra/runtime/emit_daemon/queue.py +618 -0
  629. omnibase_infra/runtime/enums/__init__.py +18 -0
  630. omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
  631. omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
  632. omnibase_infra/runtime/envelope_validator.py +179 -0
  633. omnibase_infra/runtime/event_bus_subcontract_wiring.py +466 -0
  634. omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
  635. omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
  636. omnibase_infra/runtime/handler_contract_source.py +750 -0
  637. omnibase_infra/runtime/handler_identity.py +81 -0
  638. omnibase_infra/runtime/handler_plugin_loader.py +2046 -0
  639. omnibase_infra/runtime/handler_registry.py +329 -0
  640. omnibase_infra/runtime/handler_source_resolver.py +367 -0
  641. omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
  642. omnibase_infra/runtime/kafka_contract_source.py +984 -0
  643. omnibase_infra/runtime/kernel.py +40 -0
  644. omnibase_infra/runtime/mixin_policy_validation.py +522 -0
  645. omnibase_infra/runtime/mixin_semver_cache.py +402 -0
  646. omnibase_infra/runtime/mixins/__init__.py +24 -0
  647. omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
  648. omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +778 -0
  649. omnibase_infra/runtime/models/__init__.py +229 -0
  650. omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
  651. omnibase_infra/runtime/models/model_binding_config.py +168 -0
  652. omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
  653. omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
  654. omnibase_infra/runtime/models/model_cached_secret.py +138 -0
  655. omnibase_infra/runtime/models/model_compute_key.py +138 -0
  656. omnibase_infra/runtime/models/model_compute_registration.py +97 -0
  657. omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
  658. omnibase_infra/runtime/models/model_config_ref.py +331 -0
  659. omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
  660. omnibase_infra/runtime/models/model_contract_load_result.py +224 -0
  661. omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
  662. omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
  663. omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
  664. omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
  665. omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
  666. omnibase_infra/runtime/models/model_failed_component.py +55 -0
  667. omnibase_infra/runtime/models/model_health_check_response.py +168 -0
  668. omnibase_infra/runtime/models/model_health_check_result.py +229 -0
  669. omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
  670. omnibase_infra/runtime/models/model_logging_config.py +42 -0
  671. omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
  672. omnibase_infra/runtime/models/model_optional_string.py +94 -0
  673. omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
  674. omnibase_infra/runtime/models/model_policy_context.py +100 -0
  675. omnibase_infra/runtime/models/model_policy_key.py +138 -0
  676. omnibase_infra/runtime/models/model_policy_registration.py +139 -0
  677. omnibase_infra/runtime/models/model_policy_result.py +103 -0
  678. omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
  679. omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
  680. omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
  681. omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
  682. omnibase_infra/runtime/models/model_retry_policy.py +105 -0
  683. omnibase_infra/runtime/models/model_runtime_config.py +150 -0
  684. omnibase_infra/runtime/models/model_runtime_contract_config.py +268 -0
  685. omnibase_infra/runtime/models/model_runtime_scheduler_config.py +625 -0
  686. omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
  687. omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
  688. omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
  689. omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
  690. omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
  691. omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
  692. omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
  693. omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
  694. omnibase_infra/runtime/models/model_security_config.py +109 -0
  695. omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
  696. omnibase_infra/runtime/models/model_shutdown_config.py +94 -0
  697. omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
  698. omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
  699. omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
  700. omnibase_infra/runtime/projector_plugin_loader.py +1462 -0
  701. omnibase_infra/runtime/projector_schema_manager.py +565 -0
  702. omnibase_infra/runtime/projector_shell.py +1330 -0
  703. omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
  704. omnibase_infra/runtime/protocol_contract_source.py +92 -0
  705. omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
  706. omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
  707. omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
  708. omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
  709. omnibase_infra/runtime/protocol_policy.py +366 -0
  710. omnibase_infra/runtime/protocols/__init__.py +37 -0
  711. omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
  712. omnibase_infra/runtime/publisher_topic_scoped.py +294 -0
  713. omnibase_infra/runtime/registry/__init__.py +93 -0
  714. omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
  715. omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
  716. omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
  717. omnibase_infra/runtime/registry/registry_message_type.py +542 -0
  718. omnibase_infra/runtime/registry/registry_protocol_binding.py +445 -0
  719. omnibase_infra/runtime/registry_compute.py +1143 -0
  720. omnibase_infra/runtime/registry_contract_source.py +693 -0
  721. omnibase_infra/runtime/registry_dispatcher.py +678 -0
  722. omnibase_infra/runtime/registry_policy.py +1185 -0
  723. omnibase_infra/runtime/runtime_contract_config_loader.py +406 -0
  724. omnibase_infra/runtime/runtime_scheduler.py +1070 -0
  725. omnibase_infra/runtime/secret_resolver.py +2112 -0
  726. omnibase_infra/runtime/security_metadata_validator.py +776 -0
  727. omnibase_infra/runtime/service_kernel.py +1651 -0
  728. omnibase_infra/runtime/service_message_dispatch_engine.py +2350 -0
  729. omnibase_infra/runtime/service_runtime_host_process.py +3493 -0
  730. omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
  731. omnibase_infra/runtime/transition_notification_publisher.py +765 -0
  732. omnibase_infra/runtime/util_container_wiring.py +1124 -0
  733. omnibase_infra/runtime/util_validation.py +314 -0
  734. omnibase_infra/runtime/util_version.py +98 -0
  735. omnibase_infra/runtime/util_wiring.py +723 -0
  736. omnibase_infra/schemas/schema_registration_projection.sql +320 -0
  737. omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
  738. omnibase_infra/services/__init__.py +89 -0
  739. omnibase_infra/services/corpus_capture.py +684 -0
  740. omnibase_infra/services/mcp/__init__.py +31 -0
  741. omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
  742. omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
  743. omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
  744. omnibase_infra/services/mcp/service_mcp_tool_sync.py +565 -0
  745. omnibase_infra/services/registry_api/__init__.py +40 -0
  746. omnibase_infra/services/registry_api/main.py +261 -0
  747. omnibase_infra/services/registry_api/models/__init__.py +66 -0
  748. omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
  749. omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
  750. omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
  751. omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
  752. omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
  753. omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
  754. omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
  755. omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
  756. omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
  757. omnibase_infra/services/registry_api/models/model_warning.py +49 -0
  758. omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
  759. omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
  760. omnibase_infra/services/registry_api/routes.py +371 -0
  761. omnibase_infra/services/registry_api/service.py +837 -0
  762. omnibase_infra/services/service_capability_query.py +945 -0
  763. omnibase_infra/services/service_health.py +898 -0
  764. omnibase_infra/services/service_node_selector.py +530 -0
  765. omnibase_infra/services/service_timeout_emitter.py +699 -0
  766. omnibase_infra/services/service_timeout_scanner.py +394 -0
  767. omnibase_infra/services/session/__init__.py +56 -0
  768. omnibase_infra/services/session/config_consumer.py +137 -0
  769. omnibase_infra/services/session/config_store.py +139 -0
  770. omnibase_infra/services/session/consumer.py +1007 -0
  771. omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
  772. omnibase_infra/services/session/store.py +997 -0
  773. omnibase_infra/services/snapshot/__init__.py +31 -0
  774. omnibase_infra/services/snapshot/service_snapshot.py +647 -0
  775. omnibase_infra/services/snapshot/store_inmemory.py +637 -0
  776. omnibase_infra/services/snapshot/store_postgres.py +1279 -0
  777. omnibase_infra/shared/__init__.py +8 -0
  778. omnibase_infra/testing/__init__.py +10 -0
  779. omnibase_infra/testing/utils.py +23 -0
  780. omnibase_infra/topics/__init__.py +45 -0
  781. omnibase_infra/topics/platform_topic_suffixes.py +140 -0
  782. omnibase_infra/topics/util_topic_composition.py +95 -0
  783. omnibase_infra/types/__init__.py +48 -0
  784. omnibase_infra/types/type_cache_info.py +49 -0
  785. omnibase_infra/types/type_dsn.py +173 -0
  786. omnibase_infra/types/type_infra_aliases.py +60 -0
  787. omnibase_infra/types/typed_dict/__init__.py +29 -0
  788. omnibase_infra/types/typed_dict/typed_dict_envelope_build_params.py +115 -0
  789. omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
  790. omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
  791. omnibase_infra/types/typed_dict_capabilities.py +64 -0
  792. omnibase_infra/utils/__init__.py +117 -0
  793. omnibase_infra/utils/correlation.py +208 -0
  794. omnibase_infra/utils/util_atomic_file.py +261 -0
  795. omnibase_infra/utils/util_consumer_group.py +232 -0
  796. omnibase_infra/utils/util_datetime.py +372 -0
  797. omnibase_infra/utils/util_db_transaction.py +239 -0
  798. omnibase_infra/utils/util_dsn_validation.py +333 -0
  799. omnibase_infra/utils/util_env_parsing.py +264 -0
  800. omnibase_infra/utils/util_error_sanitization.py +457 -0
  801. omnibase_infra/utils/util_pydantic_validators.py +477 -0
  802. omnibase_infra/utils/util_retry_optimistic.py +281 -0
  803. omnibase_infra/utils/util_semver.py +233 -0
  804. omnibase_infra/validation/__init__.py +307 -0
  805. omnibase_infra/validation/contracts/security.validation.yaml +114 -0
  806. omnibase_infra/validation/enums/__init__.py +11 -0
  807. omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
  808. omnibase_infra/validation/infra_validators.py +1514 -0
  809. omnibase_infra/validation/linter_contract.py +907 -0
  810. omnibase_infra/validation/mixin_any_type_classification.py +120 -0
  811. omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
  812. omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
  813. omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
  814. omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
  815. omnibase_infra/validation/models/__init__.py +15 -0
  816. omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
  817. omnibase_infra/validation/models/model_contract_violation.py +41 -0
  818. omnibase_infra/validation/service_validation_aggregator.py +395 -0
  819. omnibase_infra/validation/validation_exemptions.yaml +2033 -0
  820. omnibase_infra/validation/validator_any_type.py +715 -0
  821. omnibase_infra/validation/validator_chain_propagation.py +839 -0
  822. omnibase_infra/validation/validator_execution_shape.py +465 -0
  823. omnibase_infra/validation/validator_localhandler.py +261 -0
  824. omnibase_infra/validation/validator_registration_security.py +410 -0
  825. omnibase_infra/validation/validator_routing_coverage.py +1020 -0
  826. omnibase_infra/validation/validator_runtime_shape.py +915 -0
  827. omnibase_infra/validation/validator_security.py +513 -0
  828. omnibase_infra/validation/validator_topic_category.py +1152 -0
  829. omnibase_infra-0.2.6.dist-info/METADATA +197 -0
  830. omnibase_infra-0.2.6.dist-info/RECORD +833 -0
  831. omnibase_infra-0.2.6.dist-info/WHEEL +4 -0
  832. omnibase_infra-0.2.6.dist-info/entry_points.txt +5 -0
  833. omnibase_infra-0.2.6.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,1020 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Routing Coverage Validator for ONEX Message Types.
4
+
5
+ This module provides validation functionality to ensure all message types
6
+ (Events, Commands, Intents, Projections) defined in the codebase are properly
7
+ registered in the routing configuration. It supports startup fail-fast validation
8
+ and CI gate integration.
9
+
10
+ The validator performs two types of discovery:
11
+ 1. **Message Type Discovery**: Scans source code for classes following ONEX
12
+ message type naming conventions (Event, Command, Intent, Projection suffixes).
13
+ 2. **Route Registration Discovery**: Inspects the runtime registry or performs
14
+ static analysis to find registered message routes.
15
+
16
+ Usage:
17
+ # At application startup
18
+ from omnibase_infra.validation import validate_routing_coverage_on_startup
19
+
20
+ validate_routing_coverage_on_startup(
21
+ source_directory=Path("src/omnibase_infra"),
22
+ fail_on_unmapped=True,
23
+ )
24
+
25
+ # In CI pipelines
26
+ from omnibase_infra.validation import check_routing_coverage_ci
27
+
28
+ passed, violations = check_routing_coverage_ci(Path("src/omnibase_infra"))
29
+ if not passed:
30
+ for v in violations:
31
+ print(v.format_for_ci())
32
+ sys.exit(1)
33
+
34
+ Integration with ONEX Architecture:
35
+ - Supports ONEX 4-node architecture message categories
36
+ - Integrates with RegistryProtocolBinding for runtime route inspection
37
+ - Returns ModelExecutionShapeViolationResult for consistency with other validators
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ import ast
43
+ import logging
44
+ import re
45
+ import threading
46
+ from pathlib import Path
47
+ from typing import TYPE_CHECKING
48
+
49
+ from omnibase_infra.enums import (
50
+ EnumExecutionShapeViolation,
51
+ EnumMessageCategory,
52
+ EnumNodeOutputType,
53
+ EnumValidationSeverity,
54
+ )
55
+ from omnibase_infra.errors import RuntimeHostError
56
+ from omnibase_infra.models.validation.model_category_match_result import (
57
+ ModelCategoryMatchResult,
58
+ )
59
+ from omnibase_infra.models.validation.model_coverage_metrics import (
60
+ ModelCoverageMetrics,
61
+ )
62
+ from omnibase_infra.models.validation.model_execution_shape_violation import (
63
+ ModelExecutionShapeViolationResult,
64
+ )
65
+ from omnibase_infra.types import MessageOutputCategory
66
+ from omnibase_infra.validation.infra_validators import should_skip_path
67
+
68
+ if TYPE_CHECKING:
69
+ from omnibase_infra.runtime.handler_registry import RegistryProtocolBinding
70
+
71
+ logger = logging.getLogger(__name__)
72
+
73
+ # =============================================================================
74
+ # Custom Exception
75
+ # =============================================================================
76
+
77
+
78
+ class RoutingCoverageError(RuntimeHostError):
79
+ """Raised when message types are not registered in routing.
80
+
81
+ This exception is thrown during application startup if fail-fast mode
82
+ is enabled and there are unmapped message types. It provides a clear
83
+ list of all types that need routing registration.
84
+
85
+ Attributes:
86
+ unmapped_types: Set of message type class names that lack routing.
87
+ coverage_percent: Percentage of types that are properly registered.
88
+
89
+ Example:
90
+ >>> raise RoutingCoverageError(
91
+ ... unmapped_types={"OrderCreatedEvent", "PaymentCommand"},
92
+ ... total_types=10,
93
+ ... registered_types=8,
94
+ ... )
95
+ RoutingCoverageError: 2 unmapped message types (80.0% coverage):
96
+ OrderCreatedEvent, PaymentCommand
97
+ """
98
+
99
+ def __init__(
100
+ self,
101
+ unmapped_types: set[str],
102
+ total_types: int = 0,
103
+ registered_types: int = 0,
104
+ ) -> None:
105
+ """Initialize RoutingCoverageError.
106
+
107
+ Args:
108
+ unmapped_types: Set of message type class names without routing.
109
+ total_types: Total number of message types discovered.
110
+ registered_types: Number of types with registered routes.
111
+ """
112
+ self.unmapped_types = unmapped_types
113
+ self.total_types = total_types
114
+ self.registered_types = registered_types
115
+
116
+ coverage_percent = (
117
+ (registered_types / total_types * 100) if total_types > 0 else 0.0
118
+ )
119
+ self.coverage_percent = coverage_percent
120
+
121
+ types_list = ", ".join(sorted(unmapped_types))
122
+ message = (
123
+ f"{len(unmapped_types)} unmapped message types "
124
+ f"({coverage_percent:.1f}% coverage): {types_list}"
125
+ )
126
+ super().__init__(message=message)
127
+
128
+
129
+ # =============================================================================
130
+ # Message Category Detection
131
+ # =============================================================================
132
+
133
+ # Suffix patterns for message type detection
134
+ # Note: PROJECTION uses EnumNodeOutputType as it's a node output, not a message category
135
+ _MESSAGE_SUFFIX_PATTERNS: dict[str, MessageOutputCategory] = {
136
+ "Event": EnumMessageCategory.EVENT,
137
+ "Command": EnumMessageCategory.COMMAND,
138
+ "Intent": EnumMessageCategory.INTENT,
139
+ "Projection": EnumNodeOutputType.PROJECTION,
140
+ }
141
+
142
+ # Decorator patterns that indicate a message type
143
+ _MESSAGE_DECORATOR_PATTERNS: frozenset[str] = frozenset(
144
+ {
145
+ "message_type",
146
+ "event_type",
147
+ "command_type",
148
+ "intent_type",
149
+ "projection_type",
150
+ }
151
+ )
152
+
153
+ # Base class patterns indicating message inheritance
154
+ _MESSAGE_BASE_PATTERNS: frozenset[str] = frozenset(
155
+ {
156
+ "BaseEvent",
157
+ "BaseCommand",
158
+ "BaseIntent",
159
+ "BaseProjection",
160
+ "ModelEvent",
161
+ "ModelCommand",
162
+ "ModelIntent",
163
+ "ModelProjection",
164
+ "EventBase",
165
+ "CommandBase",
166
+ "IntentBase",
167
+ "ProjectionBase",
168
+ }
169
+ )
170
+
171
+
172
+ def _get_category_from_suffix(
173
+ class_name: str,
174
+ ) -> MessageOutputCategory | None:
175
+ """Determine message category or node output type from class name suffix.
176
+
177
+ Args:
178
+ class_name: The class name to analyze.
179
+
180
+ Returns:
181
+ EnumMessageCategory or EnumNodeOutputType if suffix matches, None otherwise.
182
+ """
183
+ for suffix, category in _MESSAGE_SUFFIX_PATTERNS.items():
184
+ if class_name.endswith(suffix):
185
+ return category
186
+ return None
187
+
188
+
189
+ def _get_category_from_base(
190
+ base_name: str,
191
+ ) -> MessageOutputCategory | None:
192
+ """Determine message category or node output type from base class name.
193
+
194
+ Args:
195
+ base_name: The base class name to analyze.
196
+
197
+ Returns:
198
+ EnumMessageCategory or EnumNodeOutputType if base matches, None otherwise.
199
+ """
200
+ base_lower = base_name.lower()
201
+ if "event" in base_lower:
202
+ return EnumMessageCategory.EVENT
203
+ if "command" in base_lower:
204
+ return EnumMessageCategory.COMMAND
205
+ if "intent" in base_lower:
206
+ return EnumMessageCategory.INTENT
207
+ if "projection" in base_lower:
208
+ return EnumNodeOutputType.PROJECTION
209
+ return None
210
+
211
+
212
+ def _has_message_decorator(
213
+ node: ast.ClassDef,
214
+ ) -> ModelCategoryMatchResult:
215
+ """Check if class has a message type decorator.
216
+
217
+ Args:
218
+ node: AST ClassDef node to analyze.
219
+
220
+ Returns:
221
+ ModelCategoryMatchResult indicating whether a decorator was found
222
+ and, if so, which category it represents.
223
+
224
+ Example:
225
+ >>> # For a class with @event_type decorator
226
+ >>> result = _has_message_decorator(class_node)
227
+ >>> result.matched
228
+ True
229
+ >>> result.category
230
+ <EnumMessageCategory.EVENT: 'event'>
231
+
232
+ .. versionchanged:: 0.6.1
233
+ Changed return type from tuple[bool, MessageOutputCategory | None]
234
+ to ModelCategoryMatchResult (OMN-1007).
235
+ """
236
+ for decorator in node.decorator_list:
237
+ decorator_name = ""
238
+ if isinstance(decorator, ast.Name):
239
+ decorator_name = decorator.id
240
+ elif isinstance(decorator, ast.Call):
241
+ if isinstance(decorator.func, ast.Name):
242
+ decorator_name = decorator.func.id
243
+ elif isinstance(decorator.func, ast.Attribute):
244
+ decorator_name = decorator.func.attr
245
+
246
+ if decorator_name in _MESSAGE_DECORATOR_PATTERNS:
247
+ # Try to infer category from decorator name
248
+ if "event" in decorator_name.lower():
249
+ return ModelCategoryMatchResult.matched_with_category(
250
+ EnumMessageCategory.EVENT
251
+ )
252
+ if "command" in decorator_name.lower():
253
+ return ModelCategoryMatchResult.matched_with_category(
254
+ EnumMessageCategory.COMMAND
255
+ )
256
+ if "intent" in decorator_name.lower():
257
+ return ModelCategoryMatchResult.matched_with_category(
258
+ EnumMessageCategory.INTENT
259
+ )
260
+ if "projection" in decorator_name.lower():
261
+ return ModelCategoryMatchResult.matched_with_category(
262
+ EnumNodeOutputType.PROJECTION
263
+ )
264
+ # Generic message_type decorator
265
+ return ModelCategoryMatchResult.matched_without_category()
266
+
267
+ return ModelCategoryMatchResult.not_matched()
268
+
269
+
270
+ def _get_base_classes(node: ast.ClassDef) -> list[str]:
271
+ """Extract base class names from ClassDef node.
272
+
273
+ Args:
274
+ node: AST ClassDef node to analyze.
275
+
276
+ Returns:
277
+ List of base class names as strings.
278
+ """
279
+ bases: list[str] = []
280
+ for base in node.bases:
281
+ if isinstance(base, ast.Name):
282
+ bases.append(base.id)
283
+ elif isinstance(base, ast.Attribute):
284
+ bases.append(base.attr)
285
+ return bases
286
+
287
+
288
+ # =============================================================================
289
+ # Discovery Functions
290
+ # =============================================================================
291
+
292
+
293
+ def discover_message_types(
294
+ source_directory: Path,
295
+ exclude_patterns: list[str] | None = None,
296
+ ) -> dict[str, MessageOutputCategory]:
297
+ """Discover all message types defined in source code.
298
+
299
+ Scans Python files in the source directory for classes that match
300
+ ONEX message type patterns:
301
+ - Classes ending in 'Event', 'Command', 'Intent', 'Projection'
302
+ - Classes with @message_type decorator (or variants)
303
+ - Classes inheriting from base message types
304
+
305
+ Args:
306
+ source_directory: Root directory to scan for message types.
307
+ exclude_patterns: Optional list of glob patterns to exclude.
308
+
309
+ Returns:
310
+ Dictionary mapping message class names to their categories
311
+ (EnumMessageCategory for EVENT/COMMAND/INTENT, EnumNodeOutputType for PROJECTION).
312
+ Returns empty dict if source_directory is invalid.
313
+
314
+ Example:
315
+ >>> types = discover_message_types(Path("src/omnibase_infra"))
316
+ >>> print(types)
317
+ {
318
+ 'ModelNodeHeartbeatEvent': EnumMessageCategory.EVENT,
319
+ 'ModelNodeIntrospectionEvent': EnumMessageCategory.EVENT,
320
+ ...
321
+ }
322
+ """
323
+ # Defensive type check for source_directory
324
+ if not isinstance(source_directory, Path):
325
+ try:
326
+ source_directory = Path(source_directory)
327
+ except (TypeError, ValueError):
328
+ return {}
329
+
330
+ if exclude_patterns is None:
331
+ exclude_patterns = [
332
+ "**/test_*.py",
333
+ "**/*_test.py",
334
+ "**/tests/**",
335
+ "**/__pycache__/**",
336
+ ]
337
+ # Defensive type check for exclude_patterns
338
+ elif not isinstance(exclude_patterns, list):
339
+ exclude_patterns = []
340
+
341
+ discovered_types: dict[str, MessageOutputCategory] = {}
342
+
343
+ # Collect all Python files
344
+ python_files: list[Path] = []
345
+ for pattern in ["**/*.py"]:
346
+ python_files.extend(source_directory.glob(pattern))
347
+
348
+ # Filter out excluded files
349
+ filtered_files: list[Path] = []
350
+ for file_path in python_files:
351
+ excluded = False
352
+ for exclude in exclude_patterns:
353
+ # Skip non-string exclude patterns
354
+ if not isinstance(exclude, str):
355
+ continue
356
+ if file_path.match(exclude):
357
+ excluded = True
358
+ break
359
+ if not excluded:
360
+ filtered_files.append(file_path)
361
+
362
+ # Parse each file and discover message types
363
+ for file_path in filtered_files:
364
+ try:
365
+ file_content = file_path.read_text(encoding="utf-8")
366
+ tree = ast.parse(file_content, filename=str(file_path))
367
+ except SyntaxError as e:
368
+ # Log and skip files with syntax errors
369
+ logger.debug(
370
+ "Skipping file with syntax error during message type discovery: %s "
371
+ "(line %s: %s)",
372
+ file_path,
373
+ e.lineno,
374
+ e.msg,
375
+ )
376
+ continue
377
+ except UnicodeDecodeError as e:
378
+ # Log and skip files with encoding errors
379
+ logger.debug(
380
+ "Skipping file with encoding error during message type discovery: %s "
381
+ "(%s)",
382
+ file_path,
383
+ e.reason,
384
+ )
385
+ continue
386
+
387
+ for node in ast.walk(tree):
388
+ if not isinstance(node, ast.ClassDef):
389
+ continue
390
+
391
+ class_name = node.name
392
+ category: MessageOutputCategory | None = None
393
+
394
+ # Strategy 1: Check suffix pattern (most common)
395
+ category = _get_category_from_suffix(class_name)
396
+
397
+ # Strategy 2: Check for message type decorators
398
+ if category is None:
399
+ match_result = _has_message_decorator(node)
400
+ if match_result.matched:
401
+ category = match_result.category
402
+
403
+ # Strategy 3: Check base class inheritance
404
+ if category is None:
405
+ bases = _get_base_classes(node)
406
+ for base_name in bases:
407
+ if base_name in _MESSAGE_BASE_PATTERNS:
408
+ category = _get_category_from_base(base_name)
409
+ if category is not None:
410
+ break
411
+
412
+ # If we found a category, record it
413
+ if category is not None:
414
+ discovered_types[class_name] = category
415
+
416
+ return discovered_types
417
+
418
+
419
+ def discover_registered_routes(
420
+ registry: RegistryProtocolBinding | None = None,
421
+ source_directory: Path | None = None,
422
+ ) -> set[str]:
423
+ """Discover routing registrations from registry or source code.
424
+
425
+ This function supports two discovery strategies that return DIFFERENT
426
+ types of identifiers. Understanding this distinction is critical for
427
+ correct usage.
428
+
429
+ **Strategy 1: Runtime Registry Inspection** (returns HANDLER CATEGORIES)
430
+ When `registry` is provided, inspects the RegistryProtocolBinding
431
+ to find registered protocol handlers.
432
+
433
+ Returns: Handler category strings (e.g., "http", "db", "kafka")
434
+ representing the types of protocol handlers registered in the system.
435
+
436
+ Use case: Infrastructure health checks - verifying handler infrastructure
437
+ is configured. NOT suitable for message-level routing coverage validation.
438
+
439
+ Example return: {"http", "kafka", "db", "grpc"}
440
+
441
+ **Strategy 2: Static Source Analysis** (returns MESSAGE TYPE NAMES)
442
+ When `source_directory` is provided, scans source files for message
443
+ registration patterns using regex-based static analysis.
444
+
445
+ Returns: Message type class names (e.g., "OrderCreatedEvent",
446
+ "CreateUserCommand") found in registration patterns like
447
+ @route(MessageType) or registry.register(MessageType, handler).
448
+
449
+ Use case: Routing coverage validation - discovering which specific
450
+ message types have handler registrations. This is the PREFERRED
451
+ approach for coverage validation.
452
+
453
+ Example return: {"OrderCreatedEvent", "UserRegisteredEvent", "PaymentCommand"}
454
+
455
+ **Critical Distinction**:
456
+ - Registry strategy: Returns protocol/transport categories (http, kafka)
457
+ - Source analysis: Returns message type class names (OrderCreatedEvent)
458
+
459
+ These are fundamentally different identifier spaces and should NOT
460
+ be mixed or compared. For routing coverage validation, always use
461
+ source_directory alone.
462
+
463
+ Args:
464
+ registry: Optional runtime registry instance to inspect. When used,
465
+ returns handler categories (protocol types like "http", "kafka").
466
+ Useful for infrastructure health checks, not coverage validation.
467
+ source_directory: Optional source directory for static analysis.
468
+ Returns message type class names found in registration patterns.
469
+ Preferred for routing coverage validation.
470
+
471
+ Returns:
472
+ Set of discovered route identifiers. The semantics depend on which
473
+ parameters were provided:
474
+ - Registry only: Handler categories (http, db, kafka)
475
+ - Source directory only: Message type class names (OrderEvent, etc.)
476
+ - Both: Combined set (not recommended - produces mixed identifier types)
477
+
478
+ Example:
479
+ >>> # Runtime inspection - returns handler categories (infrastructure check)
480
+ >>> routes = discover_registered_routes(registry=get_handler_registry())
481
+ >>> # Returns: {"http", "kafka", "db"}
482
+ >>> # Use case: Verify handler infrastructure is configured
483
+
484
+ >>> # Static analysis - returns message type names (coverage validation)
485
+ >>> routes = discover_registered_routes(
486
+ ... source_directory=Path("src/omnibase_infra")
487
+ ... )
488
+ >>> # Returns: {"OrderCreatedEvent", "UserRegisteredEvent", ...}
489
+ >>> # Use case: Validate message routing coverage
490
+
491
+ >>> # For coverage validation, compare with discover_message_types():
492
+ >>> message_types = discover_message_types(Path("src/omnibase_infra"))
493
+ >>> registered = discover_registered_routes(source_directory=Path("src"))
494
+ >>> unmapped = set(message_types.keys()) - registered
495
+ """
496
+ registered_types: set[str] = set()
497
+
498
+ # Strategy 1: Inspect runtime registry
499
+ if registry is not None:
500
+ # Get all registered protocol types
501
+ protocol_types = registry.list_protocols()
502
+ # Note: Protocol types are handler categories (http, db, kafka),
503
+ # not individual message types. For full message routing coverage,
504
+ # we need to inspect message-to-handler bindings separately.
505
+ # This is a placeholder for future integration with message routing.
506
+ registered_types.update(protocol_types)
507
+
508
+ # Strategy 2: Static analysis of registration calls
509
+ if source_directory is not None:
510
+ # Defensive type check - convert to Path if needed
511
+ if not isinstance(source_directory, Path):
512
+ try:
513
+ source_directory = Path(source_directory)
514
+ except (TypeError, ValueError):
515
+ pass
516
+ else:
517
+ registered_types.update(_discover_routes_static(source_directory))
518
+ else:
519
+ registered_types.update(_discover_routes_static(source_directory))
520
+
521
+ return registered_types
522
+
523
+
524
+ def _discover_routes_static(source_directory: Path) -> set[str]:
525
+ """Discover registered routes through regex-based static analysis.
526
+
527
+ Searches for patterns like:
528
+ - registry.register(MessageType, handler)
529
+ - @route(MessageType)
530
+ - handler_map[MessageType] = ...
531
+ - bind(MessageType, ...)
532
+ - subscribe(topic, MessageType)
533
+
534
+ Note:
535
+ This function uses regex patterns, not AST parsing, for discovery.
536
+ This approach is faster but has limitations:
537
+
538
+ **May produce false positives:**
539
+ - Code in comments or docstrings matching the patterns
540
+ - String literals that happen to match (e.g., error messages)
541
+ - Test fixtures or mocks that aren't real registrations
542
+
543
+ **May miss registrations:**
544
+ - Dynamically constructed registration calls
545
+ - Non-standard registration patterns
546
+ - Registrations via factory functions or metaclasses
547
+ - Registrations in configuration files (YAML, JSON)
548
+
549
+ For precise discovery, consider AST-based analysis or runtime
550
+ registry inspection.
551
+
552
+ Args:
553
+ source_directory: Root directory to scan.
554
+
555
+ Returns:
556
+ Set of message type names found in registration patterns.
557
+ Returns empty set if source_directory is invalid.
558
+ """
559
+ registered_types: set[str] = set()
560
+
561
+ # Defensive type check for source_directory
562
+ if not isinstance(source_directory, Path):
563
+ try:
564
+ source_directory = Path(source_directory)
565
+ except (TypeError, ValueError):
566
+ return registered_types
567
+
568
+ # Registration patterns to search for.
569
+ # Each pattern captures the message type name as group 1.
570
+ #
571
+ # PATTERN ORDERING: Patterns are ordered by specificity/reliability:
572
+ # 1. Decorator patterns - most explicit routing declarations
573
+ # 2. Method call patterns - programmatic registration
574
+ # 3. Dictionary patterns - mapping-based registration
575
+ #
576
+ # Note: Order doesn't affect matching (all patterns run independently),
577
+ # but documents the relative reliability of each pattern type.
578
+ registration_patterns = [
579
+ # Decorator patterns (most explicit routing declarations)
580
+ # Matches: @route(OrderEvent), @handle("OrderEvent"), @handler(OrderEvent)
581
+ # False positive risk: Low - decorators are typically for routing
582
+ r"@(?:route|handle|handler)\s*\(\s*['\"]?(\w+)['\"]?\s*\)",
583
+ # Method call patterns (programmatic registration)
584
+ # Matches: registry.register(OrderEvent, handler)
585
+ # False positive risk: Medium - .register() is a common method name
586
+ r"\.register\s*\(\s*['\"]?(\w+)['\"]?\s*,",
587
+ # Matches: event_bus.bind(OrderEvent, handler)
588
+ # False positive risk: Medium - .bind() could be used for other purposes
589
+ r"\.bind\s*\(\s*['\"]?(\w+)['\"]?\s*,",
590
+ # Matches: consumer.subscribe(topic, OrderEvent)
591
+ # False positive risk: Medium - second argument detection is heuristic
592
+ r"\.subscribe\s*\([^,]+,\s*['\"]?(\w+)['\"]?\s*\)",
593
+ # Dictionary patterns (mapping-based registration)
594
+ # Matches: handler_map[OrderEvent] = ...
595
+ # False positive risk: Low - specific to handler_map convention
596
+ r"handler_map\s*\[\s*['\"]?(\w+)['\"]?\s*\]",
597
+ ]
598
+
599
+ compiled_patterns = [re.compile(p) for p in registration_patterns]
600
+
601
+ # Scan all Python files, excluding test files to reduce false positives
602
+ for file_path in source_directory.glob("**/*.py"):
603
+ # Skip files in excluded directories (archive, archived, examples, __pycache__)
604
+ # Uses exact path component matching to avoid false positives from substring
605
+ # matching (e.g., "my__pycache__dir" should NOT be skipped)
606
+ if should_skip_path(file_path):
607
+ continue
608
+ # Skip test files - they often contain mock registrations that
609
+ # would produce false positives (e.g., `registry.register(MockEvent, ...)`)
610
+ if file_path.name.startswith("test_") or file_path.name.endswith("_test.py"):
611
+ continue
612
+ if file_path.name == "conftest.py":
613
+ continue
614
+
615
+ try:
616
+ content = file_path.read_text(encoding="utf-8")
617
+ for pattern in compiled_patterns:
618
+ matches = pattern.findall(content)
619
+ registered_types.update(matches)
620
+ except UnicodeDecodeError as e:
621
+ logger.debug(
622
+ "Skipping file with encoding error during route discovery: %s (%s)",
623
+ file_path,
624
+ e.reason,
625
+ )
626
+ continue
627
+ except OSError as e:
628
+ logger.debug(
629
+ "Skipping file with OS error during route discovery: %s (%s)",
630
+ file_path,
631
+ e.strerror,
632
+ )
633
+ continue
634
+
635
+ return registered_types
636
+
637
+
638
+ # =============================================================================
639
+ # Routing Coverage Validator
640
+ # =============================================================================
641
+
642
+
643
+ class RoutingCoverageValidator:
644
+ """Validator for ensuring all message types have registered routes.
645
+
646
+ This validator checks that every message type discovered in the source code
647
+ has a corresponding route registration. It supports both runtime inspection
648
+ and static analysis modes.
649
+
650
+ Attributes:
651
+ source_directory: Root directory to scan for message types.
652
+ registry: Optional runtime registry for route inspection.
653
+
654
+ Thread Safety:
655
+ This validator uses lazy initialization with double-checked locking.
656
+ The first call to validate_coverage() or get_unmapped_types() triggers
657
+ discovery, which is protected by a threading.Lock. Subsequent calls
658
+ use cached results without locking overhead.
659
+
660
+ Multiple threads can safely call validation methods concurrently.
661
+ The cached discovery results are immutable after initialization.
662
+
663
+ Performance:
664
+ **Lazy Initialization**: Discovery is deferred until first validation
665
+ call. This allows creating validators early without blocking on I/O.
666
+
667
+ **Caching**: After first discovery, results are cached. Repeated calls
668
+ to validate_coverage() reuse cached data without re-scanning.
669
+
670
+ **Refresh**: If source files change, call refresh() to clear cache
671
+ and re-discover on next validation call.
672
+
673
+ **When to create new instances vs reuse**:
674
+ - Reuse: Within a single application run for consistent results
675
+ - New instance: After source code changes, or for different directories
676
+ - CI pipelines: Typically create fresh instance per run
677
+
678
+ For startup validation, use validate_routing_coverage_on_startup()
679
+ which creates a fresh validator and performs immediate validation.
680
+
681
+ Example:
682
+ >>> validator = RoutingCoverageValidator(Path("src/omnibase_infra"))
683
+ >>> violations = validator.validate_coverage()
684
+ >>> if violations:
685
+ ... for v in violations:
686
+ ... print(v.format_for_ci())
687
+
688
+ >>> # Get coverage statistics
689
+ >>> report = validator.get_coverage_report()
690
+ >>> print(f"Coverage: {report.coverage_percent:.1f}%")
691
+
692
+ >>> # After source changes, refresh the cache
693
+ >>> validator.refresh()
694
+ >>> violations = validator.validate_coverage() # Re-discovers
695
+ """
696
+
697
+ def __init__(
698
+ self,
699
+ source_directory: Path,
700
+ registry: RegistryProtocolBinding | None = None,
701
+ ) -> None:
702
+ """Initialize the routing coverage validator.
703
+
704
+ Args:
705
+ source_directory: Root directory to scan for message types.
706
+ registry: Optional runtime registry for route inspection.
707
+ """
708
+ self.source_directory = source_directory
709
+ self.registry = registry
710
+ self._lock = threading.Lock()
711
+ # Explicit initialization flag - more robust than checking data fields
712
+ # See _ensure_discovery() docstring for thread safety rationale
713
+ self._initialized = False
714
+ self._discovered_types: dict[str, MessageOutputCategory] | None = None
715
+ self._registered_routes: set[str] | None = None
716
+
717
+ def _ensure_discovery(self) -> None:
718
+ """Ensure discovery has been performed (lazy initialization).
719
+
720
+ Thread Safety:
721
+ Uses double-checked locking with an explicit _initialized flag.
722
+
723
+ Why a separate flag instead of checking data fields?
724
+ - Eliminates ordering dependency between field assignments
725
+ - Future refactoring can't accidentally break the invariant
726
+ - The flag is only set True AFTER all fields are fully populated
727
+ - Any thread seeing _initialized=True is guaranteed to see
728
+ both _discovered_types and _registered_routes populated
729
+
730
+ The pattern:
731
+ 1. Check _initialized without lock (fast path for already-initialized)
732
+ 2. Acquire lock and re-check (prevents duplicate initialization)
733
+ 3. Set all data fields first
734
+ 4. Set _initialized=True last (makes state visible atomically)
735
+ """
736
+ if not self._initialized:
737
+ with self._lock:
738
+ if not self._initialized:
739
+ self._discovered_types = discover_message_types(
740
+ self.source_directory
741
+ )
742
+ self._registered_routes = discover_registered_routes(
743
+ registry=self.registry,
744
+ source_directory=self.source_directory,
745
+ )
746
+ # CRITICAL: Set _initialized LAST to ensure all fields
747
+ # are visible to other threads before they skip the lock
748
+ self._initialized = True
749
+
750
+ def validate_coverage(self) -> list[ModelExecutionShapeViolationResult]:
751
+ """Validate all message types are registered.
752
+
753
+ Returns:
754
+ List of violations for unmapped types. Empty if all types are mapped.
755
+
756
+ Example:
757
+ >>> validator = RoutingCoverageValidator(Path("src"))
758
+ >>> violations = validator.validate_coverage()
759
+ >>> for v in violations:
760
+ ... print(f"{v.file_path}:{v.line_number}: {v.message}")
761
+ """
762
+ self._ensure_discovery()
763
+ assert self._discovered_types is not None
764
+ assert self._registered_routes is not None
765
+
766
+ violations: list[ModelExecutionShapeViolationResult] = []
767
+ unmapped = self.get_unmapped_types()
768
+
769
+ for type_name in sorted(unmapped):
770
+ category = self._discovered_types.get(type_name)
771
+ category_name = category.value if category else "unknown"
772
+
773
+ # Routing coverage is a configuration issue, not specific to any node archetype.
774
+ # node_archetype is None because this violation is about missing routing
775
+ # registration, not about a specific handler's behavior.
776
+ # Use UNMAPPED_MESSAGE_ROUTE for semantic correctness - this is a routing
777
+ # configuration issue, not a topic/category mismatch.
778
+ violation = ModelExecutionShapeViolationResult(
779
+ violation_type=EnumExecutionShapeViolation.UNMAPPED_MESSAGE_ROUTE,
780
+ node_archetype=None, # Routing coverage is not archetype-specific
781
+ file_path=str(self.source_directory),
782
+ line_number=1,
783
+ message=(
784
+ f"Message type '{type_name}' ({category_name}) is not registered "
785
+ f"in routing configuration"
786
+ ),
787
+ severity=EnumValidationSeverity.ERROR,
788
+ )
789
+ violations.append(violation)
790
+
791
+ return violations
792
+
793
+ def get_unmapped_types(self) -> set[str]:
794
+ """Get message types that are not registered.
795
+
796
+ Returns:
797
+ Set of message type class names without routing registration.
798
+ """
799
+ self._ensure_discovery()
800
+ assert self._discovered_types is not None
801
+ assert self._registered_routes is not None
802
+
803
+ discovered_names = set(self._discovered_types.keys())
804
+ return discovered_names - self._registered_routes
805
+
806
+ def get_coverage_report(self) -> ModelCoverageMetrics:
807
+ """Get coverage statistics.
808
+
809
+ Returns:
810
+ ModelCoverageMetrics containing:
811
+ - total_types: Total number of discovered message types
812
+ - registered_types: Number of types with registered routes
813
+ - unmapped_types: List of type names without routes
814
+ - coverage_percent: Percentage of types with routes
815
+ """
816
+ self._ensure_discovery()
817
+ assert self._discovered_types is not None
818
+ assert self._registered_routes is not None
819
+
820
+ return ModelCoverageMetrics.from_discovery(
821
+ discovered_types=self._discovered_types,
822
+ registered_routes=self._registered_routes,
823
+ )
824
+
825
+ def fail_fast_on_unmapped(self) -> None:
826
+ """Raise exception if any message types are unmapped.
827
+
828
+ This method is intended for use during application startup to ensure
829
+ all message types have routing configured before the application
830
+ accepts requests.
831
+
832
+ Raises:
833
+ RoutingCoverageError: If any message types are unmapped.
834
+
835
+ Example:
836
+ >>> validator = RoutingCoverageValidator(Path("src"))
837
+ >>> try:
838
+ ... validator.fail_fast_on_unmapped()
839
+ ... except RoutingCoverageError as e:
840
+ ... print(f"Missing routes for: {e.unmapped_types}")
841
+ ... sys.exit(1)
842
+ """
843
+ self._ensure_discovery()
844
+ assert self._discovered_types is not None
845
+
846
+ unmapped = self.get_unmapped_types()
847
+ if unmapped:
848
+ total = len(self._discovered_types)
849
+ registered = total - len(unmapped)
850
+ raise RoutingCoverageError(
851
+ unmapped_types=unmapped,
852
+ total_types=total,
853
+ registered_types=registered,
854
+ )
855
+
856
+ def refresh(self) -> None:
857
+ """Clear cached discovery results and re-scan.
858
+
859
+ Call this method if source files have changed and you need
860
+ to re-discover message types and routes.
861
+
862
+ Thread Safety:
863
+ Clears _initialized FIRST to ensure any concurrent readers
864
+ see the invalidated state and wait for the lock.
865
+ """
866
+ with self._lock:
867
+ # CRITICAL: Clear _initialized FIRST to invalidate
868
+ # Any thread checking this will then acquire the lock
869
+ self._initialized = False
870
+ self._discovered_types = None
871
+ self._registered_routes = None
872
+
873
+
874
+ # =============================================================================
875
+ # Integration Functions
876
+ # =============================================================================
877
+
878
+
879
+ def validate_routing_coverage_on_startup(
880
+ source_directory: Path,
881
+ fail_on_unmapped: bool = True,
882
+ registry: RegistryProtocolBinding | None = None,
883
+ ) -> bool:
884
+ """Validate routing coverage at application startup.
885
+
886
+ This function is designed to be called during application initialization
887
+ to ensure all message types have routing configured. If fail_on_unmapped
888
+ is True, the application will fail fast with a clear error message.
889
+
890
+ Args:
891
+ source_directory: Root directory to scan for message types.
892
+ fail_on_unmapped: If True, raise exception on unmapped types.
893
+ registry: Optional runtime registry for route inspection.
894
+
895
+ Returns:
896
+ True if all types are mapped, False otherwise.
897
+
898
+ Raises:
899
+ RoutingCoverageError: If fail_on_unmapped and types are unmapped.
900
+
901
+ Example:
902
+ >>> # In your application startup code
903
+ >>> from omnibase_infra.validation import validate_routing_coverage_on_startup
904
+ >>>
905
+ >>> def main():
906
+ ... # Validate routing before accepting requests
907
+ ... validate_routing_coverage_on_startup(
908
+ ... source_directory=Path("src/myapp"),
909
+ ... fail_on_unmapped=True,
910
+ ... )
911
+ ...
912
+ ... # Continue with application startup
913
+ ... app.run()
914
+ """
915
+ validator = RoutingCoverageValidator(
916
+ source_directory=source_directory,
917
+ registry=registry,
918
+ )
919
+
920
+ if fail_on_unmapped:
921
+ validator.fail_fast_on_unmapped()
922
+ return True
923
+
924
+ unmapped = validator.get_unmapped_types()
925
+ return len(unmapped) == 0
926
+
927
+
928
+ def check_routing_coverage_ci(
929
+ source_directory: Path,
930
+ registry: RegistryProtocolBinding | None = None,
931
+ ) -> tuple[bool, list[ModelExecutionShapeViolationResult]]:
932
+ """CI gate for routing coverage.
933
+
934
+ This function is designed for CI/CD pipeline integration. It returns
935
+ both a pass/fail status and a list of violations that can be formatted
936
+ for CI output (e.g., GitHub Actions annotations).
937
+
938
+ Args:
939
+ source_directory: Root directory to scan for message types.
940
+ registry: Optional runtime registry for route inspection.
941
+
942
+ Returns:
943
+ Tuple of (passed, violations) where:
944
+ - passed: True if all types have routes
945
+ - violations: List of ModelExecutionShapeViolationResult for CI output
946
+
947
+ Example:
948
+ >>> # In your CI script
949
+ >>> from omnibase_infra.validation import check_routing_coverage_ci
950
+ >>>
951
+ >>> passed, violations = check_routing_coverage_ci(Path("src"))
952
+ >>>
953
+ >>> # Output in GitHub Actions format
954
+ >>> for v in violations:
955
+ ... print(v.format_for_ci())
956
+ >>>
957
+ >>> sys.exit(0 if passed else 1)
958
+ """
959
+ validator = RoutingCoverageValidator(
960
+ source_directory=source_directory,
961
+ registry=registry,
962
+ )
963
+
964
+ violations = validator.validate_coverage()
965
+ passed = len(violations) == 0
966
+
967
+ return passed, violations
968
+
969
+
970
+ # =============================================================================
971
+ # Design Note: Why No Module-Level Singleton
972
+ # =============================================================================
973
+ #
974
+ # Unlike other validators (ExecutionShapeValidator, RuntimeShapeValidator,
975
+ # TopicCategoryValidator), the RoutingCoverageValidator is NOT cached as a
976
+ # module-level singleton. This is an intentional design decision:
977
+ #
978
+ # 1. **Parameterized Construction**: Each RoutingCoverageValidator requires a
979
+ # source_directory parameter. Different callers may validate different
980
+ # directories (e.g., "src/handlers" vs "src/events").
981
+ #
982
+ # 2. **Stateful Discovery**: The validator caches discovered message types
983
+ # and routes internally. This state is tied to the specific source_directory.
984
+ # A singleton would only work for one directory.
985
+ #
986
+ # 3. **Built-in Caching**: The validator already implements lazy initialization
987
+ # with thread-safe locking (_ensure_discovery). Callers who need repeated
988
+ # validation of the same directory should keep a reference to their validator
989
+ # instance rather than relying on a module-level singleton.
990
+ #
991
+ # 4. **Refresh Capability**: The refresh() method allows re-scanning after
992
+ # source file changes. This per-instance state management wouldn't work
993
+ # well with a shared singleton.
994
+ #
995
+ # Performance Recommendation for Callers:
996
+ # # For repeated validation of the same directory, reuse the instance:
997
+ # validator = RoutingCoverageValidator(Path("src/handlers"))
998
+ # violations = validator.validate_coverage() # Discovery happens here
999
+ # report = validator.get_coverage_report() # Uses cached discovery
1000
+ #
1001
+ # # For one-time CI validation, the integration functions are sufficient:
1002
+ # passed, violations = check_routing_coverage_ci(Path("src/handlers"))
1003
+
1004
+ # =============================================================================
1005
+ # Module Exports
1006
+ # =============================================================================
1007
+
1008
+
1009
+ __all__: list[str] = [
1010
+ # Exception
1011
+ "RoutingCoverageError",
1012
+ # Validator class
1013
+ "RoutingCoverageValidator",
1014
+ "check_routing_coverage_ci",
1015
+ # Discovery functions
1016
+ "discover_message_types",
1017
+ "discover_registered_routes",
1018
+ # Integration functions
1019
+ "validate_routing_coverage_on_startup",
1020
+ ]