omnibase_infra 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (675) hide show
  1. omnibase_infra/__init__.py +101 -0
  2. omnibase_infra/cli/__init__.py +1 -0
  3. omnibase_infra/cli/commands.py +216 -0
  4. omnibase_infra/clients/__init__.py +0 -0
  5. omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +261 -0
  6. omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +138 -0
  7. omnibase_infra/decorators/__init__.py +29 -0
  8. omnibase_infra/decorators/allow_any.py +109 -0
  9. omnibase_infra/dlq/__init__.py +90 -0
  10. omnibase_infra/dlq/constants_dlq.py +57 -0
  11. omnibase_infra/dlq/models/__init__.py +26 -0
  12. omnibase_infra/dlq/models/enum_replay_status.py +37 -0
  13. omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
  14. omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
  15. omnibase_infra/dlq/service_dlq_tracking.py +611 -0
  16. omnibase_infra/enums/__init__.py +123 -0
  17. omnibase_infra/enums/enum_any_type_violation.py +104 -0
  18. omnibase_infra/enums/enum_backend_type.py +27 -0
  19. omnibase_infra/enums/enum_capture_outcome.py +42 -0
  20. omnibase_infra/enums/enum_capture_state.py +88 -0
  21. omnibase_infra/enums/enum_chain_violation_type.py +119 -0
  22. omnibase_infra/enums/enum_circuit_state.py +51 -0
  23. omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
  24. omnibase_infra/enums/enum_contract_type.py +84 -0
  25. omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
  26. omnibase_infra/enums/enum_dispatch_status.py +191 -0
  27. omnibase_infra/enums/enum_environment.py +46 -0
  28. omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
  29. omnibase_infra/enums/enum_handler_error_type.py +101 -0
  30. omnibase_infra/enums/enum_handler_loader_error.py +178 -0
  31. omnibase_infra/enums/enum_handler_source_type.py +87 -0
  32. omnibase_infra/enums/enum_handler_type.py +77 -0
  33. omnibase_infra/enums/enum_handler_type_category.py +61 -0
  34. omnibase_infra/enums/enum_infra_transport_type.py +73 -0
  35. omnibase_infra/enums/enum_introspection_reason.py +154 -0
  36. omnibase_infra/enums/enum_message_category.py +213 -0
  37. omnibase_infra/enums/enum_node_archetype.py +74 -0
  38. omnibase_infra/enums/enum_node_output_type.py +185 -0
  39. omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
  40. omnibase_infra/enums/enum_policy_type.py +32 -0
  41. omnibase_infra/enums/enum_registration_state.py +261 -0
  42. omnibase_infra/enums/enum_registration_status.py +33 -0
  43. omnibase_infra/enums/enum_registry_response_status.py +28 -0
  44. omnibase_infra/enums/enum_response_status.py +26 -0
  45. omnibase_infra/enums/enum_retry_error_category.py +98 -0
  46. omnibase_infra/enums/enum_security_rule_id.py +103 -0
  47. omnibase_infra/enums/enum_selection_strategy.py +91 -0
  48. omnibase_infra/enums/enum_topic_standard.py +42 -0
  49. omnibase_infra/enums/enum_validation_severity.py +78 -0
  50. omnibase_infra/errors/__init__.py +156 -0
  51. omnibase_infra/errors/error_architecture_violation.py +152 -0
  52. omnibase_infra/errors/error_chain_propagation.py +188 -0
  53. omnibase_infra/errors/error_compute_registry.py +92 -0
  54. omnibase_infra/errors/error_consul.py +132 -0
  55. omnibase_infra/errors/error_container_wiring.py +243 -0
  56. omnibase_infra/errors/error_event_bus_registry.py +102 -0
  57. omnibase_infra/errors/error_infra.py +608 -0
  58. omnibase_infra/errors/error_message_type_registry.py +101 -0
  59. omnibase_infra/errors/error_policy_registry.py +112 -0
  60. omnibase_infra/errors/error_vault.py +123 -0
  61. omnibase_infra/event_bus/__init__.py +72 -0
  62. omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +86 -0
  63. omnibase_infra/event_bus/event_bus_inmemory.py +743 -0
  64. omnibase_infra/event_bus/event_bus_kafka.py +1658 -0
  65. omnibase_infra/event_bus/mixin_kafka_broadcast.py +184 -0
  66. omnibase_infra/event_bus/mixin_kafka_dlq.py +765 -0
  67. omnibase_infra/event_bus/models/__init__.py +29 -0
  68. omnibase_infra/event_bus/models/config/__init__.py +20 -0
  69. omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +725 -0
  70. omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
  71. omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
  72. omnibase_infra/event_bus/models/model_event_headers.py +115 -0
  73. omnibase_infra/event_bus/models/model_event_message.py +60 -0
  74. omnibase_infra/event_bus/topic_constants.py +376 -0
  75. omnibase_infra/handlers/__init__.py +75 -0
  76. omnibase_infra/handlers/filesystem/__init__.py +48 -0
  77. omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
  78. omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
  79. omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
  80. omnibase_infra/handlers/handler_consul.py +787 -0
  81. omnibase_infra/handlers/handler_db.py +1039 -0
  82. omnibase_infra/handlers/handler_filesystem.py +1478 -0
  83. omnibase_infra/handlers/handler_graph.py +1154 -0
  84. omnibase_infra/handlers/handler_http.py +920 -0
  85. omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
  86. omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
  87. omnibase_infra/handlers/handler_mcp.py +748 -0
  88. omnibase_infra/handlers/handler_qdrant.py +1076 -0
  89. omnibase_infra/handlers/handler_vault.py +422 -0
  90. omnibase_infra/handlers/mcp/__init__.py +19 -0
  91. omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
  92. omnibase_infra/handlers/mcp/protocols.py +178 -0
  93. omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
  94. omnibase_infra/handlers/mixins/__init__.py +42 -0
  95. omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
  96. omnibase_infra/handlers/mixins/mixin_consul_kv.py +337 -0
  97. omnibase_infra/handlers/mixins/mixin_consul_service.py +277 -0
  98. omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
  99. omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
  100. omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
  101. omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
  102. omnibase_infra/handlers/models/__init__.py +286 -0
  103. omnibase_infra/handlers/models/consul/__init__.py +81 -0
  104. omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
  105. omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
  106. omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
  107. omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
  108. omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
  109. omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
  110. omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
  111. omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
  112. omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
  113. omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
  114. omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
  115. omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
  116. omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
  117. omnibase_infra/handlers/models/graph/__init__.py +35 -0
  118. omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
  119. omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
  120. omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
  121. omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
  122. omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
  123. omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
  124. omnibase_infra/handlers/models/http/__init__.py +50 -0
  125. omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
  126. omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
  127. omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
  128. omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
  129. omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
  130. omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
  131. omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
  132. omnibase_infra/handlers/models/mcp/__init__.py +23 -0
  133. omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
  134. omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
  135. omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
  136. omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
  137. omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
  138. omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
  139. omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
  140. omnibase_infra/handlers/models/model_db_query_response.py +60 -0
  141. omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
  142. omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
  143. omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
  144. omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
  145. omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
  146. omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
  147. omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
  148. omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
  149. omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
  150. omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
  151. omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
  152. omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
  153. omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
  154. omnibase_infra/handlers/models/model_handler_response.py +103 -0
  155. omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
  156. omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
  157. omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
  158. omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
  159. omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
  160. omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
  161. omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
  162. omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
  163. omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
  164. omnibase_infra/handlers/models/model_operation_context.py +187 -0
  165. omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
  166. omnibase_infra/handlers/models/model_retry_state.py +162 -0
  167. omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
  168. omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
  169. omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
  170. omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
  171. omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
  172. omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
  173. omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
  174. omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
  175. omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
  176. omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
  177. omnibase_infra/handlers/models/vault/__init__.py +69 -0
  178. omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
  179. omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
  180. omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
  181. omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
  182. omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
  183. omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
  184. omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
  185. omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
  186. omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
  187. omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
  188. omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
  189. omnibase_infra/handlers/registration_storage/__init__.py +43 -0
  190. omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
  191. omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +915 -0
  192. omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
  193. omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
  194. omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
  195. omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
  196. omnibase_infra/handlers/service_discovery/__init__.py +43 -0
  197. omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +747 -0
  198. omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
  199. omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
  200. omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
  201. omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
  202. omnibase_infra/handlers/service_discovery/models/model_service_info.py +99 -0
  203. omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
  204. omnibase_infra/idempotency/__init__.py +94 -0
  205. omnibase_infra/idempotency/models/__init__.py +43 -0
  206. omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
  207. omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
  208. omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
  209. omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
  210. omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
  211. omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
  212. omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
  213. omnibase_infra/idempotency/store_inmemory.py +265 -0
  214. omnibase_infra/idempotency/store_postgres.py +923 -0
  215. omnibase_infra/infrastructure/__init__.py +0 -0
  216. omnibase_infra/mixins/__init__.py +71 -0
  217. omnibase_infra/mixins/mixin_async_circuit_breaker.py +655 -0
  218. omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
  219. omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
  220. omnibase_infra/mixins/mixin_node_introspection.py +2465 -0
  221. omnibase_infra/mixins/mixin_retry_execution.py +386 -0
  222. omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
  223. omnibase_infra/models/__init__.py +136 -0
  224. omnibase_infra/models/corpus/__init__.py +17 -0
  225. omnibase_infra/models/corpus/model_capture_config.py +133 -0
  226. omnibase_infra/models/corpus/model_capture_result.py +86 -0
  227. omnibase_infra/models/discovery/__init__.py +42 -0
  228. omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
  229. omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
  230. omnibase_infra/models/discovery/model_introspection_config.py +311 -0
  231. omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
  232. omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
  233. omnibase_infra/models/dispatch/__init__.py +147 -0
  234. omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
  235. omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
  236. omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
  237. omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
  238. omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
  239. omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
  240. omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
  241. omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
  242. omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
  243. omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
  244. omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
  245. omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
  246. omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
  247. omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
  248. omnibase_infra/models/errors/__init__.py +45 -0
  249. omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
  250. omnibase_infra/models/errors/model_infra_error_context.py +99 -0
  251. omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
  252. omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
  253. omnibase_infra/models/handlers/__init__.py +37 -0
  254. omnibase_infra/models/handlers/model_contract_discovery_result.py +80 -0
  255. omnibase_infra/models/handlers/model_handler_descriptor.py +185 -0
  256. omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
  257. omnibase_infra/models/health/__init__.py +9 -0
  258. omnibase_infra/models/health/model_health_check_result.py +40 -0
  259. omnibase_infra/models/lifecycle/__init__.py +39 -0
  260. omnibase_infra/models/logging/__init__.py +51 -0
  261. omnibase_infra/models/logging/model_log_context.py +756 -0
  262. omnibase_infra/models/model_retry_error_classification.py +78 -0
  263. omnibase_infra/models/projection/__init__.py +43 -0
  264. omnibase_infra/models/projection/model_capability_fields.py +112 -0
  265. omnibase_infra/models/projection/model_registration_projection.py +434 -0
  266. omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
  267. omnibase_infra/models/projection/model_sequence_info.py +182 -0
  268. omnibase_infra/models/projection/model_snapshot_topic_config.py +590 -0
  269. omnibase_infra/models/projectors/__init__.py +41 -0
  270. omnibase_infra/models/projectors/model_projector_column.py +289 -0
  271. omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
  272. omnibase_infra/models/projectors/model_projector_index.py +270 -0
  273. omnibase_infra/models/projectors/model_projector_schema.py +415 -0
  274. omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
  275. omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
  276. omnibase_infra/models/registration/__init__.py +59 -0
  277. omnibase_infra/models/registration/commands/__init__.py +15 -0
  278. omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
  279. omnibase_infra/models/registration/events/__init__.py +56 -0
  280. omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
  281. omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
  282. omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
  283. omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
  284. omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
  285. omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
  286. omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
  287. omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
  288. omnibase_infra/models/registration/model_node_capabilities.py +179 -0
  289. omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
  290. omnibase_infra/models/registration/model_node_introspection_event.py +175 -0
  291. omnibase_infra/models/registration/model_node_metadata.py +79 -0
  292. omnibase_infra/models/registration/model_node_registration.py +162 -0
  293. omnibase_infra/models/registration/model_node_registration_record.py +162 -0
  294. omnibase_infra/models/registry/__init__.py +29 -0
  295. omnibase_infra/models/registry/model_domain_constraint.py +202 -0
  296. omnibase_infra/models/registry/model_message_type_entry.py +271 -0
  297. omnibase_infra/models/resilience/__init__.py +9 -0
  298. omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
  299. omnibase_infra/models/routing/__init__.py +25 -0
  300. omnibase_infra/models/routing/model_routing_entry.py +52 -0
  301. omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
  302. omnibase_infra/models/runtime/__init__.py +40 -0
  303. omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
  304. omnibase_infra/models/runtime/model_discovery_error.py +81 -0
  305. omnibase_infra/models/runtime/model_discovery_result.py +162 -0
  306. omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
  307. omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
  308. omnibase_infra/models/runtime/model_handler_contract.py +280 -0
  309. omnibase_infra/models/runtime/model_loaded_handler.py +120 -0
  310. omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
  311. omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
  312. omnibase_infra/models/security/__init__.py +50 -0
  313. omnibase_infra/models/security/classification_levels.py +99 -0
  314. omnibase_infra/models/security/model_environment_policy.py +145 -0
  315. omnibase_infra/models/security/model_handler_security_policy.py +107 -0
  316. omnibase_infra/models/security/model_security_error.py +81 -0
  317. omnibase_infra/models/security/model_security_validation_result.py +328 -0
  318. omnibase_infra/models/security/model_security_warning.py +67 -0
  319. omnibase_infra/models/snapshot/__init__.py +27 -0
  320. omnibase_infra/models/snapshot/model_field_change.py +65 -0
  321. omnibase_infra/models/snapshot/model_snapshot.py +270 -0
  322. omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
  323. omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
  324. omnibase_infra/models/types/__init__.py +71 -0
  325. omnibase_infra/models/validation/__init__.py +89 -0
  326. omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
  327. omnibase_infra/models/validation/model_any_type_violation.py +141 -0
  328. omnibase_infra/models/validation/model_category_match_result.py +345 -0
  329. omnibase_infra/models/validation/model_chain_violation.py +166 -0
  330. omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
  331. omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
  332. omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
  333. omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
  334. omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
  335. omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
  336. omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
  337. omnibase_infra/models/validation/model_output_validation_params.py +74 -0
  338. omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
  339. omnibase_infra/models/validation/model_validation_error_params.py +84 -0
  340. omnibase_infra/models/validation/model_validation_outcome.py +287 -0
  341. omnibase_infra/nodes/__init__.py +48 -0
  342. omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
  343. omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
  344. omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +208 -0
  345. omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
  346. omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
  347. omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
  348. omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
  349. omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
  350. omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
  351. omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
  352. omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
  353. omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
  354. omnibase_infra/nodes/architecture_validator/node.py +262 -0
  355. omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
  356. omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
  357. omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
  358. omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
  359. omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +99 -0
  360. omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
  361. omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
  362. omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
  363. omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
  364. omnibase_infra/nodes/effects/README.md +358 -0
  365. omnibase_infra/nodes/effects/__init__.py +26 -0
  366. omnibase_infra/nodes/effects/contract.yaml +172 -0
  367. omnibase_infra/nodes/effects/models/__init__.py +32 -0
  368. omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
  369. omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
  370. omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
  371. omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
  372. omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
  373. omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
  374. omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
  375. omnibase_infra/nodes/effects/registry_effect.py +525 -0
  376. omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
  377. omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
  378. omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
  379. omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +475 -0
  380. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
  381. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
  382. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
  383. omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
  384. omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
  385. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
  386. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +609 -0
  387. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
  388. omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
  389. omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
  390. omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
  391. omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
  392. omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
  393. omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
  394. omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
  395. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
  396. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
  397. omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
  398. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
  399. omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
  400. omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
  401. omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
  402. omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
  403. omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
  404. omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
  405. omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
  406. omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
  407. omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
  408. omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +525 -0
  409. omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +392 -0
  410. omnibase_infra/nodes/node_registration_orchestrator/wiring.py +742 -0
  411. omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
  412. omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
  413. omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
  414. omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
  415. omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
  416. omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
  417. omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
  418. omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
  419. omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +225 -0
  420. omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
  421. omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
  422. omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
  423. omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
  424. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
  425. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
  426. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
  427. omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
  428. omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
  429. omnibase_infra/nodes/node_registration_storage_effect/node.py +109 -0
  430. omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
  431. omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
  432. omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
  433. omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +194 -0
  434. omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
  435. omnibase_infra/nodes/node_registry_effect/contract.yaml +682 -0
  436. omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
  437. omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
  438. omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
  439. omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +416 -0
  440. omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
  441. omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
  442. omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
  443. omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
  444. omnibase_infra/nodes/node_registry_effect/node.py +165 -0
  445. omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
  446. omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
  447. omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
  448. omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
  449. omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
  450. omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
  451. omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
  452. omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
  453. omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
  454. omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
  455. omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
  456. omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
  457. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
  458. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
  459. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
  460. omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
  461. omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
  462. omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
  463. omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
  464. omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
  465. omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +214 -0
  466. omnibase_infra/nodes/reducers/__init__.py +30 -0
  467. omnibase_infra/nodes/reducers/models/__init__.py +32 -0
  468. omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +76 -0
  469. omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
  470. omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
  471. omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
  472. omnibase_infra/nodes/reducers/registration_reducer.py +1137 -0
  473. omnibase_infra/observability/__init__.py +143 -0
  474. omnibase_infra/observability/constants_metrics.py +91 -0
  475. omnibase_infra/observability/factory_observability_sink.py +525 -0
  476. omnibase_infra/observability/handlers/__init__.py +118 -0
  477. omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
  478. omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
  479. omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
  480. omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
  481. omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
  482. omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
  483. omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
  484. omnibase_infra/observability/hooks/__init__.py +74 -0
  485. omnibase_infra/observability/hooks/hook_observability.py +1223 -0
  486. omnibase_infra/observability/models/__init__.py +30 -0
  487. omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
  488. omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
  489. omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
  490. omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
  491. omnibase_infra/observability/sinks/__init__.py +69 -0
  492. omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
  493. omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
  494. omnibase_infra/plugins/__init__.py +27 -0
  495. omnibase_infra/plugins/examples/__init__.py +28 -0
  496. omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
  497. omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
  498. omnibase_infra/plugins/models/__init__.py +21 -0
  499. omnibase_infra/plugins/models/model_plugin_context.py +76 -0
  500. omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
  501. omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
  502. omnibase_infra/plugins/plugin_compute_base.py +435 -0
  503. omnibase_infra/projectors/__init__.py +30 -0
  504. omnibase_infra/projectors/contracts/__init__.py +63 -0
  505. omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
  506. omnibase_infra/projectors/projection_reader_registration.py +1559 -0
  507. omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
  508. omnibase_infra/protocols/__init__.py +99 -0
  509. omnibase_infra/protocols/protocol_capability_projection.py +253 -0
  510. omnibase_infra/protocols/protocol_capability_query.py +251 -0
  511. omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
  512. omnibase_infra/protocols/protocol_event_projector.py +96 -0
  513. omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
  514. omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
  515. omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
  516. omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
  517. omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
  518. omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
  519. omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
  520. omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
  521. omnibase_infra/runtime/__init__.py +296 -0
  522. omnibase_infra/runtime/binding_config_resolver.py +2706 -0
  523. omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
  524. omnibase_infra/runtime/contract_handler_discovery.py +582 -0
  525. omnibase_infra/runtime/contract_loaders/__init__.py +42 -0
  526. omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
  527. omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
  528. omnibase_infra/runtime/enums/__init__.py +18 -0
  529. omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
  530. omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
  531. omnibase_infra/runtime/envelope_validator.py +179 -0
  532. omnibase_infra/runtime/handler_contract_source.py +669 -0
  533. omnibase_infra/runtime/handler_plugin_loader.py +2029 -0
  534. omnibase_infra/runtime/handler_registry.py +321 -0
  535. omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
  536. omnibase_infra/runtime/kernel.py +40 -0
  537. omnibase_infra/runtime/mixin_policy_validation.py +522 -0
  538. omnibase_infra/runtime/mixin_semver_cache.py +378 -0
  539. omnibase_infra/runtime/mixins/__init__.py +17 -0
  540. omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +757 -0
  541. omnibase_infra/runtime/models/__init__.py +192 -0
  542. omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
  543. omnibase_infra/runtime/models/model_binding_config.py +168 -0
  544. omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
  545. omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
  546. omnibase_infra/runtime/models/model_cached_secret.py +138 -0
  547. omnibase_infra/runtime/models/model_compute_key.py +138 -0
  548. omnibase_infra/runtime/models/model_compute_registration.py +97 -0
  549. omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
  550. omnibase_infra/runtime/models/model_config_ref.py +331 -0
  551. omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
  552. omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
  553. omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
  554. omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
  555. omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
  556. omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
  557. omnibase_infra/runtime/models/model_failed_component.py +55 -0
  558. omnibase_infra/runtime/models/model_health_check_response.py +168 -0
  559. omnibase_infra/runtime/models/model_health_check_result.py +228 -0
  560. omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
  561. omnibase_infra/runtime/models/model_logging_config.py +42 -0
  562. omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
  563. omnibase_infra/runtime/models/model_optional_string.py +94 -0
  564. omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
  565. omnibase_infra/runtime/models/model_policy_context.py +100 -0
  566. omnibase_infra/runtime/models/model_policy_key.py +138 -0
  567. omnibase_infra/runtime/models/model_policy_registration.py +139 -0
  568. omnibase_infra/runtime/models/model_policy_result.py +103 -0
  569. omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
  570. omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
  571. omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
  572. omnibase_infra/runtime/models/model_retry_policy.py +105 -0
  573. omnibase_infra/runtime/models/model_runtime_config.py +150 -0
  574. omnibase_infra/runtime/models/model_runtime_scheduler_config.py +624 -0
  575. omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
  576. omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
  577. omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
  578. omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
  579. omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
  580. omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
  581. omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
  582. omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
  583. omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
  584. omnibase_infra/runtime/models/model_shutdown_config.py +94 -0
  585. omnibase_infra/runtime/projector_plugin_loader.py +1462 -0
  586. omnibase_infra/runtime/projector_schema_manager.py +565 -0
  587. omnibase_infra/runtime/projector_shell.py +1102 -0
  588. omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
  589. omnibase_infra/runtime/protocol_contract_source.py +92 -0
  590. omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
  591. omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
  592. omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
  593. omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
  594. omnibase_infra/runtime/protocol_policy.py +366 -0
  595. omnibase_infra/runtime/protocols/__init__.py +27 -0
  596. omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
  597. omnibase_infra/runtime/registry/__init__.py +93 -0
  598. omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
  599. omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
  600. omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
  601. omnibase_infra/runtime/registry/registry_message_type.py +542 -0
  602. omnibase_infra/runtime/registry/registry_protocol_binding.py +444 -0
  603. omnibase_infra/runtime/registry_compute.py +1143 -0
  604. omnibase_infra/runtime/registry_dispatcher.py +678 -0
  605. omnibase_infra/runtime/registry_policy.py +1502 -0
  606. omnibase_infra/runtime/runtime_scheduler.py +1070 -0
  607. omnibase_infra/runtime/secret_resolver.py +2110 -0
  608. omnibase_infra/runtime/security_metadata_validator.py +776 -0
  609. omnibase_infra/runtime/service_kernel.py +1573 -0
  610. omnibase_infra/runtime/service_message_dispatch_engine.py +1805 -0
  611. omnibase_infra/runtime/service_runtime_host_process.py +2260 -0
  612. omnibase_infra/runtime/util_container_wiring.py +1123 -0
  613. omnibase_infra/runtime/util_validation.py +314 -0
  614. omnibase_infra/runtime/util_version.py +98 -0
  615. omnibase_infra/runtime/util_wiring.py +566 -0
  616. omnibase_infra/schemas/schema_registration_projection.sql +320 -0
  617. omnibase_infra/services/__init__.py +68 -0
  618. omnibase_infra/services/corpus_capture.py +678 -0
  619. omnibase_infra/services/service_capability_query.py +945 -0
  620. omnibase_infra/services/service_health.py +897 -0
  621. omnibase_infra/services/service_node_selector.py +530 -0
  622. omnibase_infra/services/service_timeout_emitter.py +682 -0
  623. omnibase_infra/services/service_timeout_scanner.py +390 -0
  624. omnibase_infra/services/snapshot/__init__.py +31 -0
  625. omnibase_infra/services/snapshot/service_snapshot.py +647 -0
  626. omnibase_infra/services/snapshot/store_inmemory.py +637 -0
  627. omnibase_infra/services/snapshot/store_postgres.py +1279 -0
  628. omnibase_infra/shared/__init__.py +8 -0
  629. omnibase_infra/testing/__init__.py +10 -0
  630. omnibase_infra/testing/utils.py +23 -0
  631. omnibase_infra/types/__init__.py +48 -0
  632. omnibase_infra/types/type_cache_info.py +49 -0
  633. omnibase_infra/types/type_dsn.py +173 -0
  634. omnibase_infra/types/type_infra_aliases.py +60 -0
  635. omnibase_infra/types/typed_dict/__init__.py +21 -0
  636. omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
  637. omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
  638. omnibase_infra/types/typed_dict_capabilities.py +64 -0
  639. omnibase_infra/utils/__init__.py +89 -0
  640. omnibase_infra/utils/correlation.py +208 -0
  641. omnibase_infra/utils/util_datetime.py +372 -0
  642. omnibase_infra/utils/util_dsn_validation.py +333 -0
  643. omnibase_infra/utils/util_env_parsing.py +264 -0
  644. omnibase_infra/utils/util_error_sanitization.py +457 -0
  645. omnibase_infra/utils/util_pydantic_validators.py +477 -0
  646. omnibase_infra/utils/util_semver.py +233 -0
  647. omnibase_infra/validation/__init__.py +307 -0
  648. omnibase_infra/validation/enums/__init__.py +11 -0
  649. omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
  650. omnibase_infra/validation/infra_validators.py +1486 -0
  651. omnibase_infra/validation/linter_contract.py +907 -0
  652. omnibase_infra/validation/mixin_any_type_classification.py +120 -0
  653. omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
  654. omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
  655. omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
  656. omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
  657. omnibase_infra/validation/models/__init__.py +15 -0
  658. omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
  659. omnibase_infra/validation/models/model_contract_violation.py +41 -0
  660. omnibase_infra/validation/service_validation_aggregator.py +395 -0
  661. omnibase_infra/validation/validation_exemptions.yaml +1710 -0
  662. omnibase_infra/validation/validator_any_type.py +715 -0
  663. omnibase_infra/validation/validator_chain_propagation.py +839 -0
  664. omnibase_infra/validation/validator_execution_shape.py +465 -0
  665. omnibase_infra/validation/validator_localhandler.py +261 -0
  666. omnibase_infra/validation/validator_registration_security.py +410 -0
  667. omnibase_infra/validation/validator_routing_coverage.py +1020 -0
  668. omnibase_infra/validation/validator_runtime_shape.py +915 -0
  669. omnibase_infra/validation/validator_security.py +410 -0
  670. omnibase_infra/validation/validator_topic_category.py +1152 -0
  671. omnibase_infra-0.2.1.dist-info/METADATA +197 -0
  672. omnibase_infra-0.2.1.dist-info/RECORD +675 -0
  673. omnibase_infra-0.2.1.dist-info/WHEEL +4 -0
  674. omnibase_infra-0.2.1.dist-info/entry_points.txt +4 -0
  675. omnibase_infra-0.2.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,915 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """PostgreSQL Registration Storage Handler.
4
+
5
+ This module provides a PostgreSQL-backed implementation of the registration
6
+ storage handler protocol, wrapping existing PostgreSQL functionality with
7
+ circuit breaker resilience.
8
+
9
+ Connection Pooling:
10
+ - Uses asyncpg connection pool for efficient database access
11
+ - Configurable pool size (default: 10)
12
+ - Pool gracefully closed on handler shutdown
13
+
14
+ Circuit Breaker:
15
+ - Uses MixinAsyncCircuitBreaker for consistent resilience
16
+ - Three states: CLOSED (normal), OPEN (blocking), HALF_OPEN (testing)
17
+ - Configurable failure threshold and reset timeout
18
+
19
+ SQL Security:
20
+ All SQL queries in this module use parameterized queries with positional
21
+ placeholders ($1, $2, etc.) to prevent SQL injection attacks. The asyncpg
22
+ library handles proper escaping and type conversion for all parameters.
23
+
24
+ Query parameters are ALWAYS passed as separate arguments to execute/fetch
25
+ methods, never interpolated into SQL strings:
26
+
27
+ SAFE:
28
+ await conn.execute("SELECT * FROM users WHERE id = $1", user_id)
29
+
30
+ UNSAFE (never do this):
31
+ await conn.execute(f"SELECT * FROM users WHERE id = {user_id}") # WRONG!
32
+
33
+ Dynamic WHERE clauses (e.g., in query_registrations) are built by appending
34
+ conditions with parameterized placeholders, not by string interpolation of
35
+ user values.
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ import asyncio
41
+ import json
42
+ import logging
43
+ import time
44
+ from datetime import UTC, datetime
45
+ from typing import TYPE_CHECKING
46
+ from uuid import UUID, uuid4
47
+
48
+ # Import asyncpg at module level to avoid redundant imports inside methods
49
+ import asyncpg
50
+
51
+ from omnibase_core.enums.enum_node_kind import EnumNodeKind
52
+ from omnibase_infra.enums import EnumInfraTransportType
53
+ from omnibase_infra.errors import (
54
+ InfraConnectionError,
55
+ InfraTimeoutError,
56
+ ModelInfraErrorContext,
57
+ ModelTimeoutErrorContext,
58
+ )
59
+ from omnibase_infra.handlers.registration_storage.models import (
60
+ ModelDeleteRegistrationRequest,
61
+ ModelUpdateRegistrationRequest,
62
+ )
63
+ from omnibase_infra.mixins import MixinAsyncCircuitBreaker
64
+ from omnibase_infra.models.resilience import ModelCircuitBreakerConfig
65
+ from omnibase_infra.nodes.node_registration_storage_effect.models import (
66
+ ModelDeleteResult,
67
+ ModelRegistrationRecord,
68
+ ModelStorageHealthCheckDetails,
69
+ ModelStorageHealthCheckResult,
70
+ ModelStorageQuery,
71
+ ModelStorageResult,
72
+ ModelUpsertResult,
73
+ )
74
+
75
+ if TYPE_CHECKING:
76
+ from omnibase_infra.nodes.effects.protocol_postgres_adapter import (
77
+ ProtocolPostgresAdapter,
78
+ )
79
+
80
+ logger = logging.getLogger(__name__)
81
+
82
+ # Default configuration values
83
+ DEFAULT_CIRCUIT_BREAKER_THRESHOLD = 5
84
+ DEFAULT_CIRCUIT_BREAKER_RESET_TIMEOUT = 30.0
85
+ DEFAULT_POOL_SIZE = 10
86
+ DEFAULT_TIMEOUT_SECONDS = 30.0
87
+
88
+ # SQL statements
89
+ SQL_CREATE_TABLE = """
90
+ CREATE TABLE IF NOT EXISTS node_registrations (
91
+ node_id UUID PRIMARY KEY,
92
+ node_type VARCHAR(64) NOT NULL,
93
+ node_version VARCHAR(32) NOT NULL,
94
+ capabilities JSONB NOT NULL DEFAULT '[]',
95
+ endpoints JSONB NOT NULL DEFAULT '{}',
96
+ metadata JSONB NOT NULL DEFAULT '{}',
97
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
98
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
99
+ );
100
+ """
101
+
102
+ SQL_UPSERT = """
103
+ INSERT INTO node_registrations (node_id, node_type, node_version, capabilities, endpoints, metadata, created_at, updated_at)
104
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
105
+ ON CONFLICT (node_id) DO UPDATE SET
106
+ node_type = EXCLUDED.node_type,
107
+ node_version = EXCLUDED.node_version,
108
+ capabilities = EXCLUDED.capabilities,
109
+ endpoints = EXCLUDED.endpoints,
110
+ metadata = EXCLUDED.metadata,
111
+ updated_at = EXCLUDED.updated_at
112
+ RETURNING (xmax = 0) AS was_insert;
113
+ """
114
+
115
+ SQL_QUERY_BASE = """
116
+ SELECT node_id, node_type, node_version, capabilities, endpoints, metadata, created_at, updated_at
117
+ FROM node_registrations
118
+ """
119
+
120
+ SQL_QUERY_COUNT = """
121
+ SELECT COUNT(*) FROM node_registrations
122
+ """
123
+
124
+ SQL_UPDATE = """
125
+ UPDATE node_registrations SET
126
+ capabilities = COALESCE($2, capabilities),
127
+ endpoints = COALESCE($3, endpoints),
128
+ metadata = COALESCE($4, metadata),
129
+ node_version = COALESCE($5, node_version),
130
+ updated_at = NOW()
131
+ WHERE node_id = $1
132
+ RETURNING node_id;
133
+ """
134
+
135
+ SQL_DELETE = """
136
+ DELETE FROM node_registrations WHERE node_id = $1 RETURNING node_id;
137
+ """
138
+
139
+
140
+ class HandlerRegistrationStoragePostgres(MixinAsyncCircuitBreaker):
141
+ """PostgreSQL implementation of ProtocolRegistrationStorageHandler.
142
+
143
+ Wraps existing PostgreSQL adapter functionality with circuit breaker
144
+ resilience and proper error handling.
145
+
146
+ Thread Safety:
147
+ This handler is coroutine-safe. All database operations use
148
+ asyncpg's connection pool, and circuit breaker state is protected
149
+ by asyncio.Lock.
150
+
151
+ Attributes:
152
+ handler_type: Returns "postgresql" identifier.
153
+
154
+ Example:
155
+ >>> handler = HandlerRegistrationStoragePostgres(
156
+ ... postgres_adapter=postgres_adapter,
157
+ ... circuit_breaker_config={"threshold": 5, "reset_timeout": 30.0},
158
+ ... )
159
+ >>> result = await handler.store_registration(record)
160
+ """
161
+
162
+ def __init__(
163
+ self,
164
+ postgres_adapter: ProtocolPostgresAdapter | None = None,
165
+ dsn: str | None = None,
166
+ host: str = "localhost",
167
+ port: int = 5432,
168
+ database: str = "omninode_bridge",
169
+ user: str = "postgres",
170
+ password: str | None = None,
171
+ pool_size: int = DEFAULT_POOL_SIZE,
172
+ circuit_breaker_config: ModelCircuitBreakerConfig
173
+ | dict[str, object]
174
+ | None = None,
175
+ timeout_seconds: float = DEFAULT_TIMEOUT_SECONDS,
176
+ auto_create_schema: bool = False,
177
+ ) -> None:
178
+ """Initialize HandlerRegistrationStoragePostgres.
179
+
180
+ Args:
181
+ postgres_adapter: Optional existing PostgreSQL adapter (ProtocolPostgresAdapter).
182
+ If not provided, a new asyncpg connection pool will be created.
183
+ dsn: Optional PostgreSQL connection DSN (overrides host/port/etc).
184
+ host: PostgreSQL server hostname (default: "localhost").
185
+ port: PostgreSQL server port (default: 5432).
186
+ database: Database name (default: "omninode_bridge").
187
+ user: Database user (default: "postgres").
188
+ password: Optional database password.
189
+ pool_size: Connection pool size (default: 10).
190
+ circuit_breaker_config: Optional circuit breaker configuration.
191
+ Accepts ModelCircuitBreakerConfig or dict with keys:
192
+ - threshold: Max failures before opening (default: 5)
193
+ - reset_timeout_seconds: Seconds before reset (default: 60.0)
194
+ - service_name: Service identifier (default: "postgres.storage")
195
+ timeout_seconds: Operation timeout in seconds (default: 30.0).
196
+ auto_create_schema: If True, automatically create the node_registrations
197
+ table on first connection. Default is False. Production deployments
198
+ should use database migrations instead of auto-creation.
199
+ """
200
+ # Normalize circuit breaker config to ModelCircuitBreakerConfig
201
+ if isinstance(circuit_breaker_config, ModelCircuitBreakerConfig):
202
+ cb_config = circuit_breaker_config
203
+ elif circuit_breaker_config is not None:
204
+ # Handle dict with legacy key names (reset_timeout -> reset_timeout_seconds)
205
+ config_dict = dict(circuit_breaker_config)
206
+ if (
207
+ "reset_timeout" in config_dict
208
+ and "reset_timeout_seconds" not in config_dict
209
+ ):
210
+ config_dict["reset_timeout_seconds"] = config_dict.pop("reset_timeout")
211
+ # Set defaults for service_name and transport_type if not provided
212
+ config_dict.setdefault("service_name", "postgres.storage")
213
+ config_dict.setdefault("transport_type", EnumInfraTransportType.DATABASE)
214
+ cb_config = ModelCircuitBreakerConfig(**config_dict)
215
+ else:
216
+ cb_config = ModelCircuitBreakerConfig(
217
+ service_name="postgres.storage",
218
+ transport_type=EnumInfraTransportType.DATABASE,
219
+ )
220
+
221
+ self._init_circuit_breaker(
222
+ threshold=cb_config.threshold,
223
+ reset_timeout=cb_config.reset_timeout_seconds,
224
+ service_name=cb_config.service_name,
225
+ transport_type=cb_config.transport_type,
226
+ )
227
+
228
+ # Store configuration
229
+ self._dsn = dsn
230
+ self._host = host
231
+ self._port = port
232
+ self._database = database
233
+ self._user = user
234
+ self._password = password
235
+ self._pool_size = pool_size
236
+ self._timeout_seconds = timeout_seconds
237
+ self._auto_create_schema = auto_create_schema
238
+
239
+ # Connection pool (initialized on first use)
240
+ self._pool: asyncpg.Pool | None = None
241
+ self._pool_lock = asyncio.Lock()
242
+ self._initialized = False
243
+
244
+ # External adapter (if provided)
245
+ self._postgres_adapter = postgres_adapter
246
+
247
+ logger.info(
248
+ "HandlerRegistrationStoragePostgres created",
249
+ extra={
250
+ "host": host,
251
+ "port": port,
252
+ "database": database,
253
+ "pool_size": pool_size,
254
+ },
255
+ )
256
+
257
+ @property
258
+ def handler_type(self) -> str:
259
+ """Return the handler type identifier.
260
+
261
+ Returns:
262
+ "postgresql" identifier string.
263
+ """
264
+ return "postgresql"
265
+
266
+ async def _ensure_pool(
267
+ self,
268
+ correlation_id: UUID | None = None,
269
+ ) -> asyncpg.Pool:
270
+ """Ensure connection pool is initialized.
271
+
272
+ Args:
273
+ correlation_id: Optional correlation ID for tracing.
274
+
275
+ Returns:
276
+ The asyncpg connection pool.
277
+
278
+ Raises:
279
+ InfraConnectionError: If pool creation fails.
280
+ """
281
+ if self._pool is not None:
282
+ return self._pool
283
+
284
+ async with self._pool_lock:
285
+ # Double-check after acquiring lock
286
+ if self._pool is not None:
287
+ return self._pool
288
+
289
+ try:
290
+ if self._dsn:
291
+ self._pool = await asyncpg.create_pool(
292
+ dsn=self._dsn,
293
+ min_size=1,
294
+ max_size=self._pool_size,
295
+ )
296
+ else:
297
+ self._pool = await asyncpg.create_pool(
298
+ host=self._host,
299
+ port=self._port,
300
+ database=self._database,
301
+ user=self._user,
302
+ password=self._password,
303
+ min_size=1,
304
+ max_size=self._pool_size,
305
+ )
306
+
307
+ # Create table only if auto_create_schema is enabled
308
+ # Production deployments should use database migrations
309
+ if self._auto_create_schema:
310
+ async with self._pool.acquire() as conn:
311
+ await conn.execute(SQL_CREATE_TABLE)
312
+
313
+ self._initialized = True
314
+
315
+ logger.info(
316
+ "PostgreSQL connection pool initialized",
317
+ extra={
318
+ "host": self._host,
319
+ "port": self._port,
320
+ "database": self._database,
321
+ "auto_create_schema": self._auto_create_schema,
322
+ },
323
+ )
324
+
325
+ return self._pool
326
+
327
+ except Exception as e:
328
+ context = ModelInfraErrorContext(
329
+ transport_type=EnumInfraTransportType.DATABASE,
330
+ operation="initialize_pool",
331
+ target_name="postgres.storage",
332
+ correlation_id=correlation_id,
333
+ )
334
+ raise InfraConnectionError(
335
+ f"Failed to initialize PostgreSQL pool: {type(e).__name__}",
336
+ context=context,
337
+ ) from e
338
+
339
+ async def store_registration(
340
+ self,
341
+ record: ModelRegistrationRecord,
342
+ correlation_id: UUID | None = None,
343
+ ) -> ModelUpsertResult:
344
+ """Store a registration record in PostgreSQL.
345
+
346
+ Args:
347
+ record: Registration record to store.
348
+ correlation_id: Optional correlation ID for tracing.
349
+
350
+ Returns:
351
+ ModelUpsertResult with upsert outcome.
352
+
353
+ Raises:
354
+ InfraConnectionError: If connection to PostgreSQL fails.
355
+ InfraTimeoutError: If operation times out.
356
+ InfraUnavailableError: If circuit breaker is open.
357
+ """
358
+ correlation_id = correlation_id or uuid4()
359
+ start_time = time.monotonic()
360
+
361
+ # Check circuit breaker
362
+ async with self._circuit_breaker_lock:
363
+ await self._check_circuit_breaker(
364
+ operation="store_registration",
365
+ correlation_id=correlation_id,
366
+ )
367
+
368
+ try:
369
+ pool = await self._ensure_pool(correlation_id=correlation_id)
370
+
371
+ now = datetime.now(UTC)
372
+ capabilities_json = json.dumps(record.capabilities)
373
+ endpoints_json = json.dumps(record.endpoints)
374
+ metadata_json = json.dumps(record.metadata)
375
+
376
+ async with pool.acquire() as conn:
377
+ result = await asyncio.wait_for(
378
+ conn.fetchrow(
379
+ SQL_UPSERT,
380
+ record.node_id,
381
+ record.node_type.value,
382
+ record.node_version,
383
+ capabilities_json,
384
+ endpoints_json,
385
+ metadata_json,
386
+ record.created_at or now,
387
+ now,
388
+ ),
389
+ timeout=self._timeout_seconds,
390
+ )
391
+
392
+ # Reset circuit breaker on success
393
+ async with self._circuit_breaker_lock:
394
+ await self._reset_circuit_breaker()
395
+
396
+ was_insert = result["was_insert"] if result else False
397
+ operation = "insert" if was_insert else "update"
398
+ duration_ms = (time.monotonic() - start_time) * 1000
399
+
400
+ logger.info(
401
+ "Registration stored in PostgreSQL",
402
+ extra={
403
+ "node_id": str(record.node_id),
404
+ "operation": operation,
405
+ "duration_ms": duration_ms,
406
+ "correlation_id": str(correlation_id),
407
+ },
408
+ )
409
+
410
+ return ModelUpsertResult(
411
+ success=True,
412
+ node_id=record.node_id,
413
+ operation=operation,
414
+ duration_ms=duration_ms,
415
+ backend_type=self.handler_type,
416
+ correlation_id=correlation_id,
417
+ )
418
+
419
+ except TimeoutError as e:
420
+ async with self._circuit_breaker_lock:
421
+ await self._record_circuit_failure(
422
+ operation="store_registration",
423
+ correlation_id=correlation_id,
424
+ )
425
+ duration_ms = (time.monotonic() - start_time) * 1000
426
+ raise InfraTimeoutError(
427
+ f"PostgreSQL upsert timed out after {self._timeout_seconds}s",
428
+ context=ModelTimeoutErrorContext(
429
+ transport_type=EnumInfraTransportType.DATABASE,
430
+ operation="store_registration",
431
+ target_name="postgres.storage",
432
+ correlation_id=correlation_id,
433
+ timeout_seconds=self._timeout_seconds,
434
+ ),
435
+ ) from e
436
+
437
+ except Exception as e:
438
+ async with self._circuit_breaker_lock:
439
+ await self._record_circuit_failure(
440
+ operation="store_registration",
441
+ correlation_id=correlation_id,
442
+ )
443
+ duration_ms = (time.monotonic() - start_time) * 1000
444
+ context = ModelInfraErrorContext(
445
+ transport_type=EnumInfraTransportType.DATABASE,
446
+ operation="store_registration",
447
+ target_name="postgres.storage",
448
+ correlation_id=correlation_id,
449
+ )
450
+ raise InfraConnectionError(
451
+ f"PostgreSQL upsert failed: {type(e).__name__}",
452
+ context=context,
453
+ ) from e
454
+
455
+ async def query_registrations(
456
+ self,
457
+ query: ModelStorageQuery,
458
+ correlation_id: UUID | None = None,
459
+ ) -> ModelStorageResult:
460
+ """Query registration records from PostgreSQL.
461
+
462
+ Args:
463
+ query: ModelStorageQuery containing filter and pagination parameters.
464
+ correlation_id: Optional correlation ID for tracing.
465
+
466
+ Returns:
467
+ ModelStorageResult with list of matching records.
468
+
469
+ Raises:
470
+ InfraConnectionError: If connection to PostgreSQL fails.
471
+ InfraTimeoutError: If operation times out.
472
+ InfraUnavailableError: If circuit breaker is open.
473
+ """
474
+ correlation_id = correlation_id or uuid4()
475
+ start_time = time.monotonic()
476
+
477
+ # Check circuit breaker
478
+ async with self._circuit_breaker_lock:
479
+ await self._check_circuit_breaker(
480
+ operation="query_registrations",
481
+ correlation_id=correlation_id,
482
+ )
483
+
484
+ try:
485
+ pool = await self._ensure_pool(correlation_id=correlation_id)
486
+
487
+ # Build query with parameterized filters
488
+ # NOTE: All filter values use positional parameters ($1, $2, etc.)
489
+ # to prevent SQL injection. The param_idx tracks parameter positions.
490
+ # User values are NEVER interpolated into SQL strings.
491
+ conditions: list[str] = []
492
+ params: list[object] = []
493
+ param_idx = 1
494
+
495
+ # Filter by node_id if specified (exact match)
496
+ if query.node_id is not None:
497
+ conditions.append(f"node_id = ${param_idx}")
498
+ params.append(query.node_id)
499
+ param_idx += 1
500
+
501
+ # Filter by node_type if specified
502
+ if query.node_type is not None:
503
+ conditions.append(f"node_type = ${param_idx}")
504
+ params.append(query.node_type.value)
505
+ param_idx += 1
506
+
507
+ # Filter by capability (JSONB array contains match)
508
+ if query.capability_filter is not None:
509
+ # Use JSONB containment operator to check if capability exists in array
510
+ conditions.append(f"capabilities @> ${param_idx}::jsonb")
511
+ params.append(json.dumps([query.capability_filter]))
512
+ param_idx += 1
513
+
514
+ where_clause = ""
515
+ if conditions:
516
+ where_clause = " WHERE " + " AND ".join(conditions)
517
+
518
+ # Query for records with pagination
519
+ sql_query = f"{SQL_QUERY_BASE}{where_clause} ORDER BY updated_at DESC LIMIT ${param_idx} OFFSET ${param_idx + 1}"
520
+ params.extend([query.limit, query.offset])
521
+
522
+ # Query for total count
523
+ count_query = f"{SQL_QUERY_COUNT}{where_clause}"
524
+ count_params = params[:-2] # Exclude limit and offset
525
+
526
+ async with pool.acquire() as conn:
527
+ rows, count_result = await asyncio.gather(
528
+ asyncio.wait_for(
529
+ conn.fetch(sql_query, *params),
530
+ timeout=self._timeout_seconds,
531
+ ),
532
+ asyncio.wait_for(
533
+ conn.fetchval(count_query, *count_params),
534
+ timeout=self._timeout_seconds,
535
+ ),
536
+ )
537
+
538
+ # Reset circuit breaker on success
539
+ async with self._circuit_breaker_lock:
540
+ await self._reset_circuit_breaker()
541
+
542
+ # Convert rows to records
543
+ records: list[ModelRegistrationRecord] = []
544
+ for row in rows:
545
+ capabilities = (
546
+ json.loads(row["capabilities"]) if row["capabilities"] else []
547
+ )
548
+ endpoints = json.loads(row["endpoints"]) if row["endpoints"] else {}
549
+ metadata = json.loads(row["metadata"]) if row["metadata"] else {}
550
+
551
+ records.append(
552
+ ModelRegistrationRecord(
553
+ node_id=row["node_id"],
554
+ node_type=EnumNodeKind(row["node_type"]),
555
+ node_version=row["node_version"],
556
+ capabilities=capabilities,
557
+ endpoints=endpoints,
558
+ metadata=metadata,
559
+ created_at=row["created_at"],
560
+ updated_at=row["updated_at"],
561
+ correlation_id=correlation_id,
562
+ )
563
+ )
564
+
565
+ duration_ms = (time.monotonic() - start_time) * 1000
566
+ total_count = count_result or 0
567
+
568
+ logger.info(
569
+ "Registration query completed",
570
+ extra={
571
+ "record_count": len(records),
572
+ "total_count": total_count,
573
+ "duration_ms": duration_ms,
574
+ "correlation_id": str(correlation_id),
575
+ },
576
+ )
577
+
578
+ return ModelStorageResult(
579
+ success=True,
580
+ records=tuple(records),
581
+ total_count=total_count,
582
+ duration_ms=duration_ms,
583
+ backend_type=self.handler_type,
584
+ correlation_id=correlation_id,
585
+ )
586
+
587
+ except TimeoutError as e:
588
+ async with self._circuit_breaker_lock:
589
+ await self._record_circuit_failure(
590
+ operation="query_registrations",
591
+ correlation_id=correlation_id,
592
+ )
593
+ duration_ms = (time.monotonic() - start_time) * 1000
594
+ raise InfraTimeoutError(
595
+ f"PostgreSQL query timed out after {self._timeout_seconds}s",
596
+ context=ModelTimeoutErrorContext(
597
+ transport_type=EnumInfraTransportType.DATABASE,
598
+ operation="query_registrations",
599
+ target_name="postgres.storage",
600
+ correlation_id=correlation_id,
601
+ timeout_seconds=self._timeout_seconds,
602
+ ),
603
+ ) from e
604
+
605
+ except Exception as e:
606
+ async with self._circuit_breaker_lock:
607
+ await self._record_circuit_failure(
608
+ operation="query_registrations",
609
+ correlation_id=correlation_id,
610
+ )
611
+ duration_ms = (time.monotonic() - start_time) * 1000
612
+ context = ModelInfraErrorContext(
613
+ transport_type=EnumInfraTransportType.DATABASE,
614
+ operation="query_registrations",
615
+ target_name="postgres.storage",
616
+ correlation_id=correlation_id,
617
+ )
618
+ raise InfraConnectionError(
619
+ f"PostgreSQL query failed: {type(e).__name__}",
620
+ context=context,
621
+ ) from e
622
+
623
+ async def update_registration(
624
+ self,
625
+ request: ModelUpdateRegistrationRequest,
626
+ ) -> ModelUpsertResult:
627
+ """Update an existing registration record.
628
+
629
+ Args:
630
+ request: ModelUpdateRegistrationRequest containing:
631
+ - node_id: ID of the node to update
632
+ - updates: ModelRegistrationUpdate with fields to update
633
+ (only non-None fields will be applied)
634
+ - correlation_id: Optional correlation ID for tracing
635
+
636
+ Returns:
637
+ ModelUpsertResult with update outcome.
638
+
639
+ Raises:
640
+ InfraConnectionError: If connection to PostgreSQL fails.
641
+ InfraTimeoutError: If operation times out.
642
+ InfraUnavailableError: If circuit breaker is open.
643
+ """
644
+ # Extract fields from request model
645
+ node_id = request.node_id
646
+ updates = request.updates
647
+ correlation_id = request.correlation_id or uuid4()
648
+ start_time = time.monotonic()
649
+
650
+ # Check circuit breaker
651
+ async with self._circuit_breaker_lock:
652
+ await self._check_circuit_breaker(
653
+ operation="update_registration",
654
+ correlation_id=correlation_id,
655
+ )
656
+
657
+ try:
658
+ pool = await self._ensure_pool(correlation_id=correlation_id)
659
+
660
+ # Extract fields from the update model
661
+ # Use `is not None` checks to allow explicitly clearing fields with empty
662
+ # lists/dicts. Truthiness checks would treat [] and {} as "no update".
663
+ capabilities_json = (
664
+ json.dumps(updates.capabilities)
665
+ if updates.capabilities is not None
666
+ else None
667
+ )
668
+ endpoints_json = (
669
+ json.dumps(updates.endpoints) if updates.endpoints is not None else None
670
+ )
671
+ metadata_json = (
672
+ json.dumps(updates.metadata) if updates.metadata is not None else None
673
+ )
674
+ node_version = updates.node_version
675
+
676
+ async with pool.acquire() as conn:
677
+ result = await asyncio.wait_for(
678
+ conn.fetchval(
679
+ SQL_UPDATE,
680
+ node_id,
681
+ capabilities_json,
682
+ endpoints_json,
683
+ metadata_json,
684
+ node_version,
685
+ ),
686
+ timeout=self._timeout_seconds,
687
+ )
688
+
689
+ # Reset circuit breaker on success
690
+ async with self._circuit_breaker_lock:
691
+ await self._reset_circuit_breaker()
692
+
693
+ success = result is not None
694
+ duration_ms = (time.monotonic() - start_time) * 1000
695
+
696
+ logger.info(
697
+ "Registration updated",
698
+ extra={
699
+ "node_id": str(node_id),
700
+ "success": success,
701
+ "duration_ms": duration_ms,
702
+ "correlation_id": str(correlation_id),
703
+ },
704
+ )
705
+
706
+ return ModelUpsertResult(
707
+ success=success,
708
+ node_id=node_id,
709
+ operation="update",
710
+ error="Record not found" if not success else None,
711
+ duration_ms=duration_ms,
712
+ backend_type=self.handler_type,
713
+ correlation_id=correlation_id,
714
+ )
715
+
716
+ except TimeoutError as e:
717
+ async with self._circuit_breaker_lock:
718
+ await self._record_circuit_failure(
719
+ operation="update_registration",
720
+ correlation_id=correlation_id,
721
+ )
722
+ duration_ms = (time.monotonic() - start_time) * 1000
723
+ raise InfraTimeoutError(
724
+ f"PostgreSQL update timed out after {self._timeout_seconds}s",
725
+ context=ModelTimeoutErrorContext(
726
+ transport_type=EnumInfraTransportType.DATABASE,
727
+ operation="update_registration",
728
+ target_name="postgres.storage",
729
+ correlation_id=correlation_id,
730
+ timeout_seconds=self._timeout_seconds,
731
+ ),
732
+ ) from e
733
+
734
+ except Exception as e:
735
+ async with self._circuit_breaker_lock:
736
+ await self._record_circuit_failure(
737
+ operation="update_registration",
738
+ correlation_id=correlation_id,
739
+ )
740
+ duration_ms = (time.monotonic() - start_time) * 1000
741
+ context = ModelInfraErrorContext(
742
+ transport_type=EnumInfraTransportType.DATABASE,
743
+ operation="update_registration",
744
+ target_name="postgres.storage",
745
+ correlation_id=correlation_id,
746
+ )
747
+ raise InfraConnectionError(
748
+ f"PostgreSQL update failed: {type(e).__name__}",
749
+ context=context,
750
+ ) from e
751
+
752
+ async def delete_registration(
753
+ self,
754
+ request: ModelDeleteRegistrationRequest,
755
+ ) -> ModelDeleteResult:
756
+ """Delete a registration record from PostgreSQL.
757
+
758
+ Args:
759
+ request: ModelDeleteRegistrationRequest containing:
760
+ - node_id: ID of the node to delete
761
+ - correlation_id: Optional correlation ID for tracing
762
+
763
+ Returns:
764
+ ModelDeleteResult with deletion outcome.
765
+
766
+ Raises:
767
+ InfraConnectionError: If connection to PostgreSQL fails.
768
+ InfraTimeoutError: If operation times out.
769
+ InfraUnavailableError: If circuit breaker is open.
770
+ """
771
+ # Extract fields from request model
772
+ node_id = request.node_id
773
+ correlation_id = request.correlation_id or uuid4()
774
+ start_time = time.monotonic()
775
+
776
+ # Check circuit breaker
777
+ async with self._circuit_breaker_lock:
778
+ await self._check_circuit_breaker(
779
+ operation="delete_registration",
780
+ correlation_id=correlation_id,
781
+ )
782
+
783
+ try:
784
+ pool = await self._ensure_pool(correlation_id=correlation_id)
785
+
786
+ async with pool.acquire() as conn:
787
+ result = await asyncio.wait_for(
788
+ conn.fetchval(SQL_DELETE, node_id),
789
+ timeout=self._timeout_seconds,
790
+ )
791
+
792
+ # Reset circuit breaker on success
793
+ async with self._circuit_breaker_lock:
794
+ await self._reset_circuit_breaker()
795
+
796
+ deleted = result is not None
797
+ duration_ms = (time.monotonic() - start_time) * 1000
798
+
799
+ logger.info(
800
+ "Registration deletion completed",
801
+ extra={
802
+ "node_id": str(node_id),
803
+ "deleted": deleted,
804
+ "duration_ms": duration_ms,
805
+ "correlation_id": str(correlation_id),
806
+ },
807
+ )
808
+
809
+ return ModelDeleteResult(
810
+ success=True,
811
+ node_id=node_id,
812
+ deleted=deleted,
813
+ duration_ms=duration_ms,
814
+ backend_type=self.handler_type,
815
+ correlation_id=correlation_id,
816
+ )
817
+
818
+ except TimeoutError as e:
819
+ async with self._circuit_breaker_lock:
820
+ await self._record_circuit_failure(
821
+ operation="delete_registration",
822
+ correlation_id=correlation_id,
823
+ )
824
+ raise InfraTimeoutError(
825
+ f"PostgreSQL delete timed out after {self._timeout_seconds}s",
826
+ context=ModelTimeoutErrorContext(
827
+ transport_type=EnumInfraTransportType.DATABASE,
828
+ operation="delete_registration",
829
+ target_name="postgres.storage",
830
+ correlation_id=correlation_id,
831
+ timeout_seconds=self._timeout_seconds,
832
+ ),
833
+ ) from e
834
+
835
+ except Exception as e:
836
+ async with self._circuit_breaker_lock:
837
+ await self._record_circuit_failure(
838
+ operation="delete_registration",
839
+ correlation_id=correlation_id,
840
+ )
841
+ context = ModelInfraErrorContext(
842
+ transport_type=EnumInfraTransportType.DATABASE,
843
+ operation="delete_registration",
844
+ target_name="postgres.storage",
845
+ correlation_id=correlation_id,
846
+ )
847
+ raise InfraConnectionError(
848
+ f"PostgreSQL delete failed: {type(e).__name__}",
849
+ context=context,
850
+ ) from e
851
+
852
+ async def health_check(
853
+ self,
854
+ correlation_id: UUID | None = None,
855
+ ) -> ModelStorageHealthCheckResult:
856
+ """Perform a health check on the PostgreSQL connection.
857
+
858
+ Args:
859
+ correlation_id: Optional correlation ID for tracing.
860
+
861
+ Returns:
862
+ ModelStorageHealthCheckResult with health status information.
863
+ """
864
+ correlation_id = correlation_id or uuid4()
865
+ start_time = time.monotonic()
866
+
867
+ try:
868
+ pool = await self._ensure_pool(correlation_id=correlation_id)
869
+
870
+ async with pool.acquire() as conn:
871
+ await asyncio.wait_for(
872
+ conn.fetchval("SELECT 1"),
873
+ timeout=5.0, # Short timeout for health check
874
+ )
875
+
876
+ duration_ms = (time.monotonic() - start_time) * 1000
877
+
878
+ return ModelStorageHealthCheckResult(
879
+ healthy=True,
880
+ backend_type=self.handler_type,
881
+ latency_ms=duration_ms,
882
+ reason="ok",
883
+ details=ModelStorageHealthCheckDetails(
884
+ pool_size=self._pool_size,
885
+ database_name=self._database,
886
+ ),
887
+ correlation_id=correlation_id,
888
+ )
889
+
890
+ except Exception as e:
891
+ duration_ms = (time.monotonic() - start_time) * 1000
892
+ return ModelStorageHealthCheckResult(
893
+ healthy=False,
894
+ backend_type=self.handler_type,
895
+ latency_ms=duration_ms,
896
+ reason=f"Health check failed: {type(e).__name__}",
897
+ error_type=type(e).__name__,
898
+ details=ModelStorageHealthCheckDetails(
899
+ pool_size=self._pool_size,
900
+ database_name=self._database,
901
+ ),
902
+ correlation_id=correlation_id,
903
+ )
904
+
905
+ async def shutdown(self) -> None:
906
+ """Shutdown the handler and release resources."""
907
+ if self._pool is not None:
908
+ await self._pool.close()
909
+ self._pool = None
910
+
911
+ self._initialized = False
912
+ logger.info("HandlerRegistrationStoragePostgres shutdown complete")
913
+
914
+
915
+ __all__ = ["HandlerRegistrationStoragePostgres"]