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,1154 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2025 OmniNode Team
3
+ """Graph Database Handler - Implements ProtocolGraphDatabaseHandler from omnibase_spi.
4
+
5
+ Provides backend-agnostic graph database operations via the neo4j async driver,
6
+ supporting Memgraph and Neo4j through Bolt protocol with Cypher queries.
7
+
8
+ Protocol Implementation:
9
+ Implements ProtocolGraphDatabaseHandler from omnibase_spi.protocols.storage,
10
+ providing typed graph operations with models from omnibase_core.models.graph.
11
+
12
+ Supported Operations:
13
+ - execute_query: Execute parameterized Cypher queries
14
+ - execute_query_batch: Transactional batch query execution
15
+ - create_node: Create nodes with labels and properties
16
+ - create_relationship: Create typed relationships between nodes
17
+ - delete_node: Delete nodes with optional cascade (DETACH DELETE)
18
+ - delete_relationship: Delete relationships by ID
19
+ - traverse: Graph traversal with configurable depth and filters
20
+ - health_check: Connection health monitoring
21
+ - describe: Handler metadata introspection
22
+
23
+ Security:
24
+ - All queries use parameterization to prevent injection attacks
25
+ - Credentials are treated as secrets and never logged
26
+ - Health check responses sanitize error messages
27
+
28
+ Circuit Breaker Pattern:
29
+ Uses MixinAsyncCircuitBreaker for fault tolerance with automatic
30
+ recovery from transient failures.
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import logging
36
+ import time
37
+ from collections.abc import Mapping
38
+ from uuid import UUID, uuid4
39
+
40
+ from neo4j import AsyncDriver, AsyncGraphDatabase
41
+ from neo4j.exceptions import (
42
+ AuthError,
43
+ ConstraintError,
44
+ Neo4jError,
45
+ ServiceUnavailable,
46
+ TransactionError,
47
+ )
48
+
49
+ from omnibase_core.container import ModelONEXContainer
50
+ from omnibase_core.models.graph import (
51
+ ModelGraphBatchResult,
52
+ ModelGraphDatabaseNode,
53
+ ModelGraphDeleteResult,
54
+ ModelGraphHandlerMetadata,
55
+ ModelGraphHealthStatus,
56
+ ModelGraphQueryCounters,
57
+ ModelGraphQueryResult,
58
+ ModelGraphQuerySummary,
59
+ ModelGraphRelationship,
60
+ ModelGraphTraversalFilters,
61
+ ModelGraphTraversalResult,
62
+ )
63
+ from omnibase_core.types import JsonType
64
+ from omnibase_infra.enums import EnumInfraTransportType
65
+ from omnibase_infra.errors import (
66
+ InfraAuthenticationError,
67
+ InfraConnectionError,
68
+ ModelInfraErrorContext,
69
+ RuntimeHostError,
70
+ )
71
+ from omnibase_infra.mixins import MixinAsyncCircuitBreaker
72
+ from omnibase_infra.utils.util_env_parsing import parse_env_float
73
+ from omnibase_spi.protocols.storage import ProtocolGraphDatabaseHandler
74
+
75
+ logger = logging.getLogger(__name__)
76
+
77
+ HANDLER_ID_GRAPH: str = "graph-handler"
78
+ _DEFAULT_TIMEOUT_SECONDS: float = parse_env_float(
79
+ "ONEX_GRAPH_TIMEOUT",
80
+ 30.0,
81
+ min_value=0.1,
82
+ max_value=3600.0,
83
+ transport_type=EnumInfraTransportType.GRAPH,
84
+ service_name="graph_handler",
85
+ )
86
+ _DEFAULT_POOL_SIZE: int = 50
87
+ _HEALTH_CACHE_SECONDS: float = 10.0
88
+
89
+
90
+ class HandlerGraph(MixinAsyncCircuitBreaker, ProtocolGraphDatabaseHandler):
91
+ """Graph database handler implementing ProtocolGraphDatabaseHandler.
92
+
93
+ Provides typed graph database operations using neo4j async driver,
94
+ supporting Memgraph and Neo4j via Bolt protocol with Cypher queries.
95
+
96
+ Protocol Compliance:
97
+ Implements all methods from ProtocolGraphDatabaseHandler:
98
+ - handler_type property returning "graph_database"
99
+ - supports_transactions property returning True
100
+ - initialize(), shutdown() lifecycle methods
101
+ - execute_query(), execute_query_batch() query methods
102
+ - create_node(), create_relationship() creation methods
103
+ - delete_node(), delete_relationship() deletion methods
104
+ - traverse() graph traversal method
105
+ - health_check(), describe() introspection methods
106
+
107
+ Security Policy:
108
+ Credentials are treated as secrets and never logged or exposed in errors.
109
+
110
+ Circuit Breaker Pattern:
111
+ Uses MixinAsyncCircuitBreaker for fault tolerance with automatic
112
+ recovery after transient failures.
113
+
114
+ Example:
115
+ ```python
116
+ handler = HandlerGraph()
117
+ await handler.initialize(
118
+ connection_uri="bolt://localhost:7687",
119
+ auth=("neo4j", "password"),
120
+ )
121
+
122
+ result = await handler.execute_query(
123
+ query="MATCH (n:Person {name: $name}) RETURN n",
124
+ parameters={"name": "Alice"},
125
+ )
126
+
127
+ await handler.shutdown()
128
+ ```
129
+ """
130
+
131
+ def __init__(self, container: ModelONEXContainer) -> None:
132
+ """Initialize HandlerGraph with ONEX container for dependency injection.
133
+
134
+ Args:
135
+ container: ONEX container providing dependency injection for
136
+ services, configuration, and runtime context.
137
+
138
+ Note:
139
+ The container is stored for interface compliance with the standard ONEX
140
+ handler pattern (def __init__(self, container: ModelONEXContainer)) and
141
+ to enable future DI-based service resolution. Currently, the handler
142
+ operates independently but the container parameter ensures API
143
+ consistency across all handlers.
144
+ """
145
+ self._container = container
146
+ self._driver: AsyncDriver | None = None
147
+ self._connection_uri: str = ""
148
+ self._database: str = "memgraph"
149
+ self._timeout: float = _DEFAULT_TIMEOUT_SECONDS
150
+ self._pool_size: int = _DEFAULT_POOL_SIZE
151
+ self._initialized: bool = False
152
+ self._cached_health: ModelGraphHealthStatus | None = None
153
+ self._health_cache_time: float = 0.0
154
+
155
+ @property
156
+ def handler_type(self) -> str:
157
+ """Return the handler type identifier.
158
+
159
+ Returns:
160
+ String "graph_database" as defined by ProtocolGraphDatabaseHandler.
161
+ """
162
+ return "graph_database"
163
+
164
+ @property
165
+ def supports_transactions(self) -> bool:
166
+ """Return whether this handler supports transactional operations.
167
+
168
+ Returns:
169
+ True - Neo4j/Memgraph support ACID transactions.
170
+ """
171
+ return True
172
+
173
+ async def initialize( # type: ignore[override]
174
+ self,
175
+ connection_uri: str,
176
+ auth: tuple[str, str] | None = None,
177
+ *,
178
+ options: Mapping[str, JsonType] | None = None,
179
+ ) -> None:
180
+ """Initialize the graph database connection.
181
+
182
+ Establishes connection to the graph database using the provided URI
183
+ and authentication credentials. Configures connection pools and
184
+ validates connectivity.
185
+
186
+ Args:
187
+ connection_uri: Database connection URI (e.g., "bolt://localhost:7687").
188
+ auth: Optional tuple of (username, password) for authentication.
189
+ options: Additional connection parameters:
190
+ - max_connection_pool_size: Maximum connections in pool (default: 50)
191
+ - database: Database name (default: "memgraph")
192
+ - timeout_seconds: Operation timeout (default: 30.0)
193
+ - encrypted: Whether to use TLS/SSL encryption
194
+
195
+ Raises:
196
+ RuntimeHostError: If configuration is invalid.
197
+ InfraConnectionError: If connection to graph database fails.
198
+ InfraAuthenticationError: If authentication fails.
199
+ """
200
+ init_correlation_id = uuid4()
201
+ logger.info(
202
+ "Initializing %s",
203
+ self.__class__.__name__,
204
+ extra={
205
+ "handler": self.__class__.__name__,
206
+ "correlation_id": str(init_correlation_id),
207
+ },
208
+ )
209
+
210
+ self._connection_uri = connection_uri
211
+ opts = dict(options) if options else {}
212
+
213
+ # Extract configuration options
214
+ pool_raw = opts.get("max_connection_pool_size", _DEFAULT_POOL_SIZE)
215
+ self._pool_size = (
216
+ int(pool_raw)
217
+ if isinstance(pool_raw, int | float | str)
218
+ else _DEFAULT_POOL_SIZE
219
+ )
220
+
221
+ timeout_raw = opts.get("timeout_seconds", _DEFAULT_TIMEOUT_SECONDS)
222
+ self._timeout = (
223
+ float(timeout_raw)
224
+ if isinstance(timeout_raw, int | float | str)
225
+ else _DEFAULT_TIMEOUT_SECONDS
226
+ )
227
+
228
+ database_raw = opts.get("database", "memgraph")
229
+ self._database = str(database_raw) if database_raw else "memgraph"
230
+
231
+ encrypted = opts.get("encrypted", False)
232
+
233
+ # Create async driver
234
+ try:
235
+ self._driver = AsyncGraphDatabase.driver(
236
+ connection_uri,
237
+ auth=auth,
238
+ max_connection_pool_size=self._pool_size,
239
+ encrypted=bool(encrypted) if encrypted else False,
240
+ )
241
+ # Verify connectivity
242
+ await self._driver.verify_connectivity()
243
+ self._initialized = True
244
+ logger.info(
245
+ "%s initialized successfully",
246
+ self.__class__.__name__,
247
+ extra={
248
+ "handler": self.__class__.__name__,
249
+ "correlation_id": str(init_correlation_id),
250
+ },
251
+ )
252
+ except AuthError as e:
253
+ ctx = ModelInfraErrorContext.with_correlation(
254
+ transport_type=EnumInfraTransportType.GRAPH,
255
+ operation="initialize",
256
+ target_name="graph_handler",
257
+ correlation_id=init_correlation_id,
258
+ )
259
+ raise InfraAuthenticationError(
260
+ "Graph database authentication failed", context=ctx
261
+ ) from e
262
+ except ServiceUnavailable as e:
263
+ ctx = ModelInfraErrorContext.with_correlation(
264
+ transport_type=EnumInfraTransportType.GRAPH,
265
+ operation="initialize",
266
+ target_name="graph_handler",
267
+ correlation_id=init_correlation_id,
268
+ )
269
+ raise InfraConnectionError(
270
+ "Failed to connect to graph database", context=ctx
271
+ ) from e
272
+ except Exception as e:
273
+ ctx = ModelInfraErrorContext.with_correlation(
274
+ transport_type=EnumInfraTransportType.GRAPH,
275
+ operation="initialize",
276
+ target_name="graph_handler",
277
+ correlation_id=init_correlation_id,
278
+ )
279
+ raise InfraConnectionError(
280
+ f"Connection failed: {type(e).__name__}", context=ctx
281
+ ) from e
282
+
283
+ # Initialize circuit breaker
284
+ self._init_circuit_breaker(
285
+ threshold=5,
286
+ reset_timeout=60.0,
287
+ service_name="graph",
288
+ transport_type=EnumInfraTransportType.GRAPH,
289
+ )
290
+
291
+ async def shutdown(self, timeout_seconds: float = 30.0) -> None:
292
+ """Close database connections and release resources.
293
+
294
+ Gracefully shuts down the handler by closing all active connections
295
+ and releasing resources.
296
+
297
+ Args:
298
+ timeout_seconds: Maximum time to wait for shutdown. Defaults to 30.0.
299
+ """
300
+ correlation_id = uuid4()
301
+ logger.info(
302
+ "Shutting down %s",
303
+ self.__class__.__name__,
304
+ extra={
305
+ "handler": self.__class__.__name__,
306
+ "correlation_id": str(correlation_id),
307
+ "timeout_seconds": timeout_seconds,
308
+ },
309
+ )
310
+
311
+ if self._driver is not None:
312
+ try:
313
+ await self._driver.close()
314
+ except Exception as e:
315
+ logger.warning(
316
+ "Error during driver close: %s",
317
+ type(e).__name__,
318
+ extra={"correlation_id": str(correlation_id)},
319
+ )
320
+ self._driver = None
321
+
322
+ self._initialized = False
323
+ self._cached_health = None
324
+ logger.info(
325
+ "%s shutdown complete",
326
+ self.__class__.__name__,
327
+ extra={"correlation_id": str(correlation_id)},
328
+ )
329
+
330
+ def _ensure_initialized(
331
+ self, operation: str, correlation_id: object
332
+ ) -> AsyncDriver:
333
+ """Ensure handler is initialized and return driver.
334
+
335
+ Args:
336
+ operation: Name of the operation being performed.
337
+ correlation_id: Correlation ID for error context.
338
+
339
+ Returns:
340
+ The initialized AsyncDriver.
341
+
342
+ Raises:
343
+ RuntimeHostError: If handler is not initialized.
344
+ """
345
+ if not self._initialized or self._driver is None:
346
+ ctx = ModelInfraErrorContext.with_correlation(
347
+ transport_type=EnumInfraTransportType.GRAPH,
348
+ operation=operation,
349
+ target_name="graph_handler",
350
+ correlation_id=correlation_id
351
+ if isinstance(correlation_id, UUID)
352
+ else None,
353
+ )
354
+ raise RuntimeHostError(
355
+ "HandlerGraph not initialized. Call initialize() first.", context=ctx
356
+ )
357
+ return self._driver
358
+
359
+ async def execute_query(
360
+ self,
361
+ query: str,
362
+ parameters: Mapping[str, JsonType] | None = None,
363
+ ) -> ModelGraphQueryResult:
364
+ """Execute a Cypher query and return typed results.
365
+
366
+ Security:
367
+ Uses parameterized queries to prevent injection attacks.
368
+ NEVER construct queries via string concatenation with user input.
369
+
370
+ Args:
371
+ query: The Cypher query string.
372
+ parameters: Optional mapping of query parameters.
373
+
374
+ Returns:
375
+ ModelGraphQueryResult with records, summary, counters, and execution time.
376
+
377
+ Raises:
378
+ RuntimeHostError: If handler not initialized or query invalid.
379
+ InfraConnectionError: If query execution fails.
380
+ """
381
+ correlation_id = uuid4()
382
+ driver = self._ensure_initialized("execute_query", correlation_id)
383
+
384
+ # Check circuit breaker
385
+ async with self._circuit_breaker_lock:
386
+ await self._check_circuit_breaker("execute_query", correlation_id)
387
+
388
+ params = dict(parameters) if parameters else {}
389
+ start_time = time.perf_counter()
390
+
391
+ try:
392
+ async with driver.session(database=self._database) as session:
393
+ result = await session.run(query, params)
394
+ records_data = await result.data()
395
+ summary = await result.consume()
396
+
397
+ execution_time_ms = (time.perf_counter() - start_time) * 1000
398
+
399
+ return ModelGraphQueryResult(
400
+ records=list(records_data),
401
+ summary=ModelGraphQuerySummary(
402
+ query_type=summary.query_type or "unknown",
403
+ database=self._database,
404
+ contains_updates=summary.counters.contains_updates,
405
+ ),
406
+ counters=ModelGraphQueryCounters(
407
+ nodes_created=summary.counters.nodes_created,
408
+ nodes_deleted=summary.counters.nodes_deleted,
409
+ relationships_created=summary.counters.relationships_created,
410
+ relationships_deleted=summary.counters.relationships_deleted,
411
+ properties_set=summary.counters.properties_set,
412
+ labels_added=summary.counters.labels_added,
413
+ labels_removed=summary.counters.labels_removed,
414
+ ),
415
+ execution_time_ms=execution_time_ms,
416
+ )
417
+ except Neo4jError as e:
418
+ ctx = ModelInfraErrorContext.with_correlation(
419
+ transport_type=EnumInfraTransportType.GRAPH,
420
+ operation="execute_query",
421
+ target_name="graph_handler",
422
+ correlation_id=correlation_id,
423
+ )
424
+ async with self._circuit_breaker_lock:
425
+ await self._record_circuit_failure("execute_query")
426
+ raise InfraConnectionError(
427
+ f"Query execution failed: {type(e).__name__}", context=ctx
428
+ ) from e
429
+
430
+ async def execute_query_batch( # type: ignore[override]
431
+ self,
432
+ queries: list[tuple[str, Mapping[str, JsonType] | None]],
433
+ transaction: bool = True,
434
+ ) -> ModelGraphBatchResult:
435
+ """Execute multiple queries, optionally within a transaction.
436
+
437
+ Args:
438
+ queries: List of (query, parameters) tuples to execute.
439
+ transaction: If True, execute all queries atomically. Defaults to True.
440
+
441
+ Returns:
442
+ ModelGraphBatchResult with individual results and success status.
443
+
444
+ Raises:
445
+ RuntimeHostError: If handler not initialized.
446
+ InfraConnectionError: If batch execution fails.
447
+ """
448
+ correlation_id = uuid4()
449
+ driver = self._ensure_initialized("execute_query_batch", correlation_id)
450
+
451
+ # Check circuit breaker
452
+ async with self._circuit_breaker_lock:
453
+ await self._check_circuit_breaker("execute_query_batch", correlation_id)
454
+
455
+ results: list[ModelGraphQueryResult] = []
456
+ rollback_occurred = False
457
+ start_time = time.perf_counter()
458
+
459
+ try:
460
+ if transaction and self.supports_transactions:
461
+ # Execute all queries in a single transaction
462
+ async with driver.session(database=self._database) as session:
463
+ tx = await session.begin_transaction()
464
+ try:
465
+ for query, params in queries:
466
+ query_start = time.perf_counter()
467
+ result = await tx.run(query, dict(params) if params else {})
468
+ records_data = await result.data()
469
+ summary = await result.consume()
470
+ query_time_ms = (time.perf_counter() - query_start) * 1000
471
+
472
+ results.append(
473
+ ModelGraphQueryResult(
474
+ records=list(records_data),
475
+ summary=ModelGraphQuerySummary(
476
+ query_type=summary.query_type or "unknown",
477
+ database=self._database,
478
+ contains_updates=summary.counters.contains_updates,
479
+ ),
480
+ counters=ModelGraphQueryCounters(
481
+ nodes_created=summary.counters.nodes_created,
482
+ nodes_deleted=summary.counters.nodes_deleted,
483
+ relationships_created=summary.counters.relationships_created,
484
+ relationships_deleted=summary.counters.relationships_deleted,
485
+ properties_set=summary.counters.properties_set,
486
+ labels_added=summary.counters.labels_added,
487
+ labels_removed=summary.counters.labels_removed,
488
+ ),
489
+ execution_time_ms=query_time_ms,
490
+ )
491
+ )
492
+ await tx.commit()
493
+ except Exception:
494
+ await tx.rollback()
495
+ rollback_occurred = True
496
+ raise
497
+ else:
498
+ # Execute queries individually without transaction
499
+ for query, params in queries:
500
+ result = await self.execute_query(query, params)
501
+ results.append(result)
502
+
503
+ return ModelGraphBatchResult(
504
+ results=results,
505
+ success=True,
506
+ transaction_id=correlation_id if transaction else None,
507
+ rollback_occurred=rollback_occurred,
508
+ )
509
+ except TransactionError as e:
510
+ ctx = ModelInfraErrorContext.with_correlation(
511
+ transport_type=EnumInfraTransportType.GRAPH,
512
+ operation="execute_query_batch",
513
+ target_name="graph_handler",
514
+ correlation_id=correlation_id,
515
+ )
516
+ async with self._circuit_breaker_lock:
517
+ await self._record_circuit_failure("execute_query_batch")
518
+ raise InfraConnectionError(
519
+ f"Batch transaction failed: {type(e).__name__}", context=ctx
520
+ ) from e
521
+ except Neo4jError as e:
522
+ ctx = ModelInfraErrorContext.with_correlation(
523
+ transport_type=EnumInfraTransportType.GRAPH,
524
+ operation="execute_query_batch",
525
+ target_name="graph_handler",
526
+ correlation_id=correlation_id,
527
+ )
528
+ async with self._circuit_breaker_lock:
529
+ await self._record_circuit_failure("execute_query_batch")
530
+ raise InfraConnectionError(
531
+ f"Batch execution failed: {type(e).__name__}", context=ctx
532
+ ) from e
533
+
534
+ async def create_node(
535
+ self,
536
+ labels: list[str],
537
+ properties: Mapping[str, JsonType],
538
+ ) -> ModelGraphDatabaseNode:
539
+ """Create a new node in the graph.
540
+
541
+ Args:
542
+ labels: List of labels to assign to the node.
543
+ properties: Mapping of property key-value pairs.
544
+
545
+ Returns:
546
+ ModelGraphDatabaseNode with the created node's details.
547
+
548
+ Raises:
549
+ RuntimeHostError: If handler not initialized or invalid input.
550
+ InfraConnectionError: If node creation fails.
551
+ """
552
+ correlation_id = uuid4()
553
+ driver = self._ensure_initialized("create_node", correlation_id)
554
+
555
+ # Check circuit breaker
556
+ async with self._circuit_breaker_lock:
557
+ await self._check_circuit_breaker("create_node", correlation_id)
558
+
559
+ # Build Cypher query with labels
560
+ labels_str = ":".join(labels) if labels else ""
561
+ label_clause = f":{labels_str}" if labels_str else ""
562
+ query = f"CREATE (n{label_clause} $props) RETURN n, elementId(n) as eid, id(n) as nid"
563
+
564
+ try:
565
+ async with driver.session(database=self._database) as session:
566
+ result = await session.run(query, {"props": dict(properties)})
567
+ record = await result.single()
568
+ await result.consume()
569
+
570
+ if record is None:
571
+ ctx = ModelInfraErrorContext.with_correlation(
572
+ transport_type=EnumInfraTransportType.GRAPH,
573
+ operation="create_node",
574
+ target_name="graph_handler",
575
+ correlation_id=correlation_id,
576
+ )
577
+ raise RuntimeHostError(
578
+ "Node creation returned no result", context=ctx
579
+ )
580
+
581
+ node = record["n"]
582
+ element_id = str(record["eid"])
583
+ node_id = str(record["nid"])
584
+
585
+ return ModelGraphDatabaseNode(
586
+ id=node_id,
587
+ element_id=element_id,
588
+ labels=list(node.labels),
589
+ properties=dict(node.items()),
590
+ )
591
+ except ConstraintError as e:
592
+ ctx = ModelInfraErrorContext.with_correlation(
593
+ transport_type=EnumInfraTransportType.GRAPH,
594
+ operation="create_node",
595
+ target_name="graph_handler",
596
+ correlation_id=correlation_id,
597
+ )
598
+ raise RuntimeHostError(
599
+ "Node creation failed: constraint violation", context=ctx
600
+ ) from e
601
+ except Neo4jError as e:
602
+ ctx = ModelInfraErrorContext.with_correlation(
603
+ transport_type=EnumInfraTransportType.GRAPH,
604
+ operation="create_node",
605
+ target_name="graph_handler",
606
+ correlation_id=correlation_id,
607
+ )
608
+ async with self._circuit_breaker_lock:
609
+ await self._record_circuit_failure("create_node")
610
+ raise InfraConnectionError(
611
+ f"Node creation failed: {type(e).__name__}", context=ctx
612
+ ) from e
613
+
614
+ async def create_relationship(
615
+ self,
616
+ from_node_id: str | int,
617
+ to_node_id: str | int,
618
+ relationship_type: str,
619
+ properties: Mapping[str, JsonType] | None = None,
620
+ ) -> ModelGraphRelationship:
621
+ """Create a relationship between two nodes.
622
+
623
+ Args:
624
+ from_node_id: Identifier of the source node.
625
+ to_node_id: Identifier of the target node.
626
+ relationship_type: Type of the relationship (e.g., "KNOWS").
627
+ properties: Optional relationship properties.
628
+
629
+ Returns:
630
+ ModelGraphRelationship with the created relationship's details.
631
+
632
+ Raises:
633
+ RuntimeHostError: If handler not initialized or nodes don't exist.
634
+ InfraConnectionError: If relationship creation fails.
635
+ """
636
+ correlation_id = uuid4()
637
+ driver = self._ensure_initialized("create_relationship", correlation_id)
638
+
639
+ # Check circuit breaker
640
+ async with self._circuit_breaker_lock:
641
+ await self._check_circuit_breaker("create_relationship", correlation_id)
642
+
643
+ # Determine if IDs are element IDs (strings with colons) or internal IDs
644
+ from_is_element_id = isinstance(from_node_id, str) and ":" in from_node_id
645
+ to_is_element_id = isinstance(to_node_id, str) and ":" in to_node_id
646
+
647
+ # Build appropriate match clauses
648
+ if from_is_element_id:
649
+ from_match = "MATCH (a) WHERE elementId(a) = $from_id"
650
+ else:
651
+ from_match = "MATCH (a) WHERE id(a) = $from_id"
652
+
653
+ if to_is_element_id:
654
+ to_match = "MATCH (b) WHERE elementId(b) = $to_id"
655
+ else:
656
+ to_match = "MATCH (b) WHERE id(b) = $to_id"
657
+
658
+ props = dict(properties) if properties else {}
659
+ query = f"""
660
+ {from_match}
661
+ {to_match}
662
+ CREATE (a)-[r:{relationship_type} $props]->(b)
663
+ RETURN r, elementId(r) as eid, id(r) as rid,
664
+ elementId(a) as start_eid, elementId(b) as end_eid
665
+ """
666
+
667
+ params: dict[str, object] = {
668
+ "from_id": int(from_node_id) if not from_is_element_id else from_node_id,
669
+ "to_id": int(to_node_id) if not to_is_element_id else to_node_id,
670
+ "props": props,
671
+ }
672
+
673
+ try:
674
+ async with driver.session(database=self._database) as session:
675
+ result = await session.run(query, params)
676
+ record = await result.single()
677
+ await result.consume()
678
+
679
+ if record is None:
680
+ ctx = ModelInfraErrorContext.with_correlation(
681
+ transport_type=EnumInfraTransportType.GRAPH,
682
+ operation="create_relationship",
683
+ target_name="graph_handler",
684
+ correlation_id=correlation_id,
685
+ )
686
+ raise RuntimeHostError(
687
+ "Relationship creation failed: nodes not found", context=ctx
688
+ )
689
+
690
+ rel = record["r"]
691
+ element_id = str(record["eid"])
692
+ rel_id = str(record["rid"])
693
+ start_eid = str(record["start_eid"])
694
+ end_eid = str(record["end_eid"])
695
+
696
+ return ModelGraphRelationship(
697
+ id=rel_id,
698
+ element_id=element_id,
699
+ type=rel.type,
700
+ properties=dict(rel.items()),
701
+ start_node_id=start_eid,
702
+ end_node_id=end_eid,
703
+ )
704
+ except Neo4jError as e:
705
+ ctx = ModelInfraErrorContext.with_correlation(
706
+ transport_type=EnumInfraTransportType.GRAPH,
707
+ operation="create_relationship",
708
+ target_name="graph_handler",
709
+ correlation_id=correlation_id,
710
+ )
711
+ async with self._circuit_breaker_lock:
712
+ await self._record_circuit_failure("create_relationship")
713
+ raise InfraConnectionError(
714
+ f"Relationship creation failed: {type(e).__name__}", context=ctx
715
+ ) from e
716
+
717
+ async def delete_node(
718
+ self,
719
+ node_id: str | int,
720
+ detach: bool = False,
721
+ ) -> ModelGraphDeleteResult:
722
+ """Delete a node from the graph.
723
+
724
+ Args:
725
+ node_id: Identifier of the node to delete.
726
+ detach: If True, delete all relationships first (DETACH DELETE).
727
+
728
+ Returns:
729
+ ModelGraphDeleteResult with deletion status and counts.
730
+
731
+ Raises:
732
+ RuntimeHostError: If handler not initialized or node has relationships.
733
+ InfraConnectionError: If deletion fails.
734
+ """
735
+ correlation_id = uuid4()
736
+ driver = self._ensure_initialized("delete_node", correlation_id)
737
+
738
+ # Check circuit breaker
739
+ async with self._circuit_breaker_lock:
740
+ await self._check_circuit_breaker("delete_node", correlation_id)
741
+
742
+ is_element_id = isinstance(node_id, str) and ":" in str(node_id)
743
+ start_time = time.perf_counter()
744
+
745
+ if is_element_id:
746
+ match_clause = "MATCH (n) WHERE elementId(n) = $node_id"
747
+ else:
748
+ match_clause = "MATCH (n) WHERE id(n) = $node_id"
749
+
750
+ # Count relationships before delete if detaching
751
+ rel_count = 0
752
+ if detach:
753
+ count_query = (
754
+ f"{match_clause} OPTIONAL MATCH (n)-[r]-() RETURN count(r) as cnt"
755
+ )
756
+ try:
757
+ async with driver.session(database=self._database) as session:
758
+ result = await session.run(
759
+ count_query,
760
+ {"node_id": node_id if is_element_id else int(node_id)},
761
+ )
762
+ record = await result.single()
763
+ await result.consume()
764
+ if record:
765
+ rel_count = record["cnt"]
766
+ except Neo4jError:
767
+ pass # Best effort count
768
+
769
+ delete_keyword = "DETACH DELETE" if detach else "DELETE"
770
+ query = f"{match_clause} {delete_keyword} n RETURN count(n) as deleted"
771
+
772
+ try:
773
+ async with driver.session(database=self._database) as session:
774
+ result = await session.run(
775
+ query,
776
+ {"node_id": node_id if is_element_id else int(node_id)},
777
+ )
778
+ record = await result.single()
779
+ await result.consume()
780
+
781
+ execution_time_ms = (time.perf_counter() - start_time) * 1000
782
+ deleted = record["deleted"] if record else 0
783
+
784
+ return ModelGraphDeleteResult(
785
+ success=deleted > 0,
786
+ node_id=str(node_id),
787
+ relationships_deleted=rel_count if detach else 0,
788
+ execution_time_ms=execution_time_ms,
789
+ )
790
+ except ConstraintError as e:
791
+ ctx = ModelInfraErrorContext.with_correlation(
792
+ transport_type=EnumInfraTransportType.GRAPH,
793
+ operation="delete_node",
794
+ target_name="graph_handler",
795
+ correlation_id=correlation_id,
796
+ )
797
+ raise RuntimeHostError(
798
+ "Cannot delete node with relationships. Use detach=True.", context=ctx
799
+ ) from e
800
+ except Neo4jError as e:
801
+ ctx = ModelInfraErrorContext.with_correlation(
802
+ transport_type=EnumInfraTransportType.GRAPH,
803
+ operation="delete_node",
804
+ target_name="graph_handler",
805
+ correlation_id=correlation_id,
806
+ )
807
+ async with self._circuit_breaker_lock:
808
+ await self._record_circuit_failure("delete_node")
809
+ raise InfraConnectionError(
810
+ f"Node deletion failed: {type(e).__name__}", context=ctx
811
+ ) from e
812
+
813
+ async def delete_relationship(
814
+ self,
815
+ relationship_id: str | int,
816
+ ) -> ModelGraphDeleteResult:
817
+ """Delete a relationship from the graph.
818
+
819
+ Args:
820
+ relationship_id: Identifier of the relationship to delete.
821
+
822
+ Returns:
823
+ ModelGraphDeleteResult with deletion status.
824
+
825
+ Raises:
826
+ RuntimeHostError: If handler not initialized.
827
+ InfraConnectionError: If deletion fails.
828
+ """
829
+ correlation_id = uuid4()
830
+ driver = self._ensure_initialized("delete_relationship", correlation_id)
831
+
832
+ # Check circuit breaker
833
+ async with self._circuit_breaker_lock:
834
+ await self._check_circuit_breaker("delete_relationship", correlation_id)
835
+
836
+ is_element_id = isinstance(relationship_id, str) and ":" in str(relationship_id)
837
+ start_time = time.perf_counter()
838
+
839
+ if is_element_id:
840
+ query = """
841
+ MATCH ()-[r]-()
842
+ WHERE elementId(r) = $rel_id
843
+ DELETE r
844
+ RETURN count(r) as deleted
845
+ """
846
+ else:
847
+ query = """
848
+ MATCH ()-[r]-()
849
+ WHERE id(r) = $rel_id
850
+ DELETE r
851
+ RETURN count(r) as deleted
852
+ """
853
+
854
+ try:
855
+ async with driver.session(database=self._database) as session:
856
+ result = await session.run(
857
+ query,
858
+ {
859
+ "rel_id": relationship_id
860
+ if is_element_id
861
+ else int(relationship_id)
862
+ },
863
+ )
864
+ record = await result.single()
865
+ await result.consume()
866
+
867
+ execution_time_ms = (time.perf_counter() - start_time) * 1000
868
+ deleted = record["deleted"] if record else 0
869
+
870
+ return ModelGraphDeleteResult(
871
+ success=deleted > 0,
872
+ node_id=None, # This is relationship deletion, not node
873
+ relationships_deleted=deleted,
874
+ execution_time_ms=execution_time_ms,
875
+ )
876
+ except Neo4jError as e:
877
+ ctx = ModelInfraErrorContext.with_correlation(
878
+ transport_type=EnumInfraTransportType.GRAPH,
879
+ operation="delete_relationship",
880
+ target_name="graph_handler",
881
+ correlation_id=correlation_id,
882
+ )
883
+ async with self._circuit_breaker_lock:
884
+ await self._record_circuit_failure("delete_relationship")
885
+ raise InfraConnectionError(
886
+ f"Relationship deletion failed: {type(e).__name__}", context=ctx
887
+ ) from e
888
+
889
+ async def traverse(
890
+ self,
891
+ start_node_id: str | int,
892
+ relationship_types: list[str] | None = None,
893
+ direction: str = "outgoing",
894
+ max_depth: int = 1,
895
+ filters: ModelGraphTraversalFilters | None = None,
896
+ ) -> ModelGraphTraversalResult:
897
+ """Traverse the graph from a starting node.
898
+
899
+ Args:
900
+ start_node_id: Identifier of the node to start from.
901
+ relationship_types: Optional list of relationship types to follow.
902
+ direction: Direction to traverse ("outgoing", "incoming", "both").
903
+ max_depth: Maximum traversal depth. Defaults to 1.
904
+ filters: Optional traversal filters for labels and properties.
905
+
906
+ Returns:
907
+ ModelGraphTraversalResult with discovered nodes, relationships, and paths.
908
+
909
+ Raises:
910
+ RuntimeHostError: If handler not initialized or invalid parameters.
911
+ InfraConnectionError: If traversal fails.
912
+ """
913
+ correlation_id = uuid4()
914
+ driver = self._ensure_initialized("traverse", correlation_id)
915
+
916
+ # Check circuit breaker
917
+ async with self._circuit_breaker_lock:
918
+ await self._check_circuit_breaker("traverse", correlation_id)
919
+
920
+ is_element_id = isinstance(start_node_id, str) and ":" in str(start_node_id)
921
+ start_time = time.perf_counter()
922
+
923
+ # Build match clause for start node
924
+ if is_element_id:
925
+ start_match = "MATCH (start) WHERE elementId(start) = $start_id"
926
+ else:
927
+ start_match = "MATCH (start) WHERE id(start) = $start_id"
928
+
929
+ # Build relationship pattern
930
+ rel_types_pattern = ""
931
+ if relationship_types:
932
+ rel_types_pattern = ":" + "|".join(relationship_types)
933
+
934
+ # Direction patterns
935
+ if direction == "incoming":
936
+ rel_pattern = f"<-[r{rel_types_pattern}*1..{max_depth}]-"
937
+ elif direction == "both":
938
+ rel_pattern = f"-[r{rel_types_pattern}*1..{max_depth}]-"
939
+ else: # outgoing (default)
940
+ rel_pattern = f"-[r{rel_types_pattern}*1..{max_depth}]->"
941
+
942
+ # Build filter conditions
943
+ filter_conditions: list[str] = []
944
+ if filters:
945
+ if filters.node_labels:
946
+ label_checks = " OR ".join(
947
+ f"'{lbl}' IN labels(n)" for lbl in filters.node_labels
948
+ )
949
+ filter_conditions.append(f"({label_checks})")
950
+ if filters.node_properties:
951
+ for key, value in filters.node_properties.items():
952
+ filter_conditions.append(f"n.{key} = ${key}")
953
+
954
+ where_clause = ""
955
+ if filter_conditions:
956
+ where_clause = "WHERE " + " AND ".join(filter_conditions)
957
+
958
+ query = f"""
959
+ {start_match}
960
+ MATCH p = (start){rel_pattern}(n)
961
+ {where_clause}
962
+ WITH DISTINCT n, relationships(p) as rels, [node in nodes(p) | elementId(node)] as path_ids
963
+ RETURN n, elementId(n) as eid, id(n) as nid, rels, path_ids
964
+ LIMIT 1000
965
+ """
966
+
967
+ params: dict[str, object] = {
968
+ "start_id": start_node_id if is_element_id else int(start_node_id),
969
+ }
970
+ if filters and filters.node_properties:
971
+ params.update(filters.node_properties)
972
+
973
+ try:
974
+ async with driver.session(database=self._database) as session:
975
+ result = await session.run(query, params)
976
+ records = await result.data()
977
+ await result.consume()
978
+
979
+ nodes: list[ModelGraphDatabaseNode] = []
980
+ relationships: list[ModelGraphRelationship] = []
981
+ paths: list[list[str]] = []
982
+ seen_node_ids: set[str] = set()
983
+ seen_rel_ids: set[str] = set()
984
+ max_depth_reached = 0
985
+
986
+ for record in records:
987
+ node = record["n"]
988
+ element_id = str(record["eid"])
989
+ node_id = str(record["nid"])
990
+
991
+ if element_id not in seen_node_ids:
992
+ seen_node_ids.add(element_id)
993
+ nodes.append(
994
+ ModelGraphDatabaseNode(
995
+ id=node_id,
996
+ element_id=element_id,
997
+ labels=list(node.labels),
998
+ properties=dict(node.items()),
999
+ )
1000
+ )
1001
+
1002
+ # Process relationships
1003
+ for rel in record.get("rels", []):
1004
+ rel_eid = rel.element_id
1005
+ if rel_eid not in seen_rel_ids:
1006
+ seen_rel_ids.add(rel_eid)
1007
+ relationships.append(
1008
+ ModelGraphRelationship(
1009
+ id=str(rel.id),
1010
+ element_id=rel_eid,
1011
+ type=rel.type,
1012
+ properties=dict(rel.items()),
1013
+ start_node_id=rel.start_node.element_id,
1014
+ end_node_id=rel.end_node.element_id,
1015
+ )
1016
+ )
1017
+
1018
+ # Process path
1019
+ path_ids = record.get("path_ids", [])
1020
+ if path_ids:
1021
+ paths.append(path_ids)
1022
+ max_depth_reached = max(max_depth_reached, len(path_ids) - 1)
1023
+
1024
+ execution_time_ms = (time.perf_counter() - start_time) * 1000
1025
+
1026
+ return ModelGraphTraversalResult(
1027
+ nodes=nodes,
1028
+ relationships=relationships,
1029
+ paths=paths,
1030
+ depth_reached=max_depth_reached,
1031
+ execution_time_ms=execution_time_ms,
1032
+ )
1033
+ except Neo4jError as e:
1034
+ ctx = ModelInfraErrorContext.with_correlation(
1035
+ transport_type=EnumInfraTransportType.GRAPH,
1036
+ operation="traverse",
1037
+ target_name="graph_handler",
1038
+ correlation_id=correlation_id,
1039
+ )
1040
+ async with self._circuit_breaker_lock:
1041
+ await self._record_circuit_failure("traverse")
1042
+ raise InfraConnectionError(
1043
+ f"Traversal failed: {type(e).__name__}", context=ctx
1044
+ ) from e
1045
+
1046
+ async def health_check(self) -> ModelGraphHealthStatus:
1047
+ """Check handler health and database connectivity.
1048
+
1049
+ Returns cached results for rapid repeated calls to prevent
1050
+ overwhelming the backend.
1051
+
1052
+ Returns:
1053
+ ModelGraphHealthStatus with health status and latency.
1054
+
1055
+ Raises:
1056
+ RuntimeHostError: If called before initialize().
1057
+ """
1058
+ correlation_id = uuid4()
1059
+
1060
+ # Return cached result if recent
1061
+ current_time = time.time()
1062
+ if (
1063
+ self._cached_health is not None
1064
+ and current_time - self._health_cache_time < _HEALTH_CACHE_SECONDS
1065
+ ):
1066
+ return self._cached_health
1067
+
1068
+ if not self._initialized or self._driver is None:
1069
+ return ModelGraphHealthStatus(
1070
+ healthy=False,
1071
+ latency_ms=0.0,
1072
+ database_version=None,
1073
+ connection_count=0,
1074
+ )
1075
+
1076
+ start_time = time.perf_counter()
1077
+
1078
+ try:
1079
+ async with self._driver.session(database=self._database) as session:
1080
+ result = await session.run("RETURN 1 as n")
1081
+ await result.consume()
1082
+
1083
+ latency_ms = (time.perf_counter() - start_time) * 1000
1084
+
1085
+ # Try to get server info
1086
+ version = None
1087
+ try:
1088
+ server_info = await self._driver.get_server_info()
1089
+ version = server_info.agent if server_info else None
1090
+ except Exception:
1091
+ pass
1092
+
1093
+ health = ModelGraphHealthStatus(
1094
+ healthy=True,
1095
+ latency_ms=latency_ms,
1096
+ database_version=version,
1097
+ connection_count=0, # Neo4j driver doesn't expose pool stats easily
1098
+ )
1099
+
1100
+ # Cache the result
1101
+ self._cached_health = health
1102
+ self._health_cache_time = current_time
1103
+
1104
+ return health
1105
+ except Exception as e:
1106
+ logger.warning(
1107
+ "Health check failed: %s",
1108
+ type(e).__name__,
1109
+ extra={"correlation_id": str(correlation_id)},
1110
+ )
1111
+ return ModelGraphHealthStatus(
1112
+ healthy=False,
1113
+ latency_ms=0.0,
1114
+ database_version=None,
1115
+ connection_count=0,
1116
+ )
1117
+
1118
+ async def describe(self) -> ModelGraphHandlerMetadata: # type: ignore[override]
1119
+ """Return handler metadata and capabilities.
1120
+
1121
+ Returns:
1122
+ ModelGraphHandlerMetadata with handler information.
1123
+
1124
+ Note:
1125
+ This method is async per protocol specification (v0.5.0+).
1126
+ """
1127
+ # Determine database type based on connection URI
1128
+ database_type = "memgraph"
1129
+ if self._connection_uri:
1130
+ uri_lower = self._connection_uri.lower()
1131
+ if "neo4j" in uri_lower:
1132
+ database_type = "neo4j"
1133
+ elif "neptune" in uri_lower:
1134
+ database_type = "neptune"
1135
+
1136
+ capabilities = [
1137
+ "cypher",
1138
+ "parameterized_queries",
1139
+ "transactions",
1140
+ "node_crud",
1141
+ "relationship_crud",
1142
+ "traversal",
1143
+ "batch_operations",
1144
+ ]
1145
+
1146
+ return ModelGraphHandlerMetadata(
1147
+ handler_type=self.handler_type,
1148
+ capabilities=capabilities,
1149
+ database_type=database_type,
1150
+ supports_transactions=self.supports_transactions,
1151
+ )
1152
+
1153
+
1154
+ __all__: list[str] = ["HandlerGraph", "HANDLER_ID_GRAPH"]