omnibase_infra 0.2.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omnibase_infra/__init__.py +101 -0
- omnibase_infra/adapters/adapter_onex_tool_execution.py +451 -0
- omnibase_infra/capabilities/__init__.py +15 -0
- omnibase_infra/capabilities/capability_inference_rules.py +211 -0
- omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
- omnibase_infra/capabilities/intent_type_extractor.py +160 -0
- omnibase_infra/cli/__init__.py +1 -0
- omnibase_infra/cli/commands.py +216 -0
- omnibase_infra/clients/__init__.py +0 -0
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/constants_topic_patterns.py +26 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +264 -0
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +141 -0
- omnibase_infra/decorators/__init__.py +29 -0
- omnibase_infra/decorators/allow_any.py +109 -0
- omnibase_infra/dlq/__init__.py +90 -0
- omnibase_infra/dlq/constants_dlq.py +57 -0
- omnibase_infra/dlq/models/__init__.py +26 -0
- omnibase_infra/dlq/models/enum_replay_status.py +37 -0
- omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
- omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
- omnibase_infra/dlq/service_dlq_tracking.py +611 -0
- omnibase_infra/enums/__init__.py +132 -0
- omnibase_infra/enums/enum_any_type_violation.py +104 -0
- omnibase_infra/enums/enum_backend_type.py +27 -0
- omnibase_infra/enums/enum_capture_outcome.py +42 -0
- omnibase_infra/enums/enum_capture_state.py +88 -0
- omnibase_infra/enums/enum_chain_violation_type.py +119 -0
- omnibase_infra/enums/enum_circuit_state.py +51 -0
- omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
- omnibase_infra/enums/enum_consumer_group_purpose.py +92 -0
- omnibase_infra/enums/enum_contract_type.py +84 -0
- omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
- omnibase_infra/enums/enum_dispatch_status.py +191 -0
- omnibase_infra/enums/enum_environment.py +46 -0
- omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
- omnibase_infra/enums/enum_handler_error_type.py +111 -0
- omnibase_infra/enums/enum_handler_loader_error.py +178 -0
- omnibase_infra/enums/enum_handler_source_mode.py +86 -0
- omnibase_infra/enums/enum_handler_source_type.py +87 -0
- omnibase_infra/enums/enum_handler_type.py +77 -0
- omnibase_infra/enums/enum_handler_type_category.py +61 -0
- omnibase_infra/enums/enum_infra_transport_type.py +73 -0
- omnibase_infra/enums/enum_introspection_reason.py +154 -0
- omnibase_infra/enums/enum_kafka_acks.py +99 -0
- omnibase_infra/enums/enum_message_category.py +213 -0
- omnibase_infra/enums/enum_node_archetype.py +74 -0
- omnibase_infra/enums/enum_node_output_type.py +185 -0
- omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
- omnibase_infra/enums/enum_policy_type.py +32 -0
- omnibase_infra/enums/enum_registration_state.py +261 -0
- omnibase_infra/enums/enum_registration_status.py +33 -0
- omnibase_infra/enums/enum_registry_response_status.py +28 -0
- omnibase_infra/enums/enum_response_status.py +26 -0
- omnibase_infra/enums/enum_retry_error_category.py +98 -0
- omnibase_infra/enums/enum_security_rule_id.py +103 -0
- omnibase_infra/enums/enum_selection_strategy.py +91 -0
- omnibase_infra/enums/enum_topic_standard.py +42 -0
- omnibase_infra/enums/enum_validation_severity.py +78 -0
- omnibase_infra/errors/__init__.py +160 -0
- omnibase_infra/errors/error_architecture_violation.py +152 -0
- omnibase_infra/errors/error_binding_resolution.py +128 -0
- omnibase_infra/errors/error_chain_propagation.py +188 -0
- omnibase_infra/errors/error_compute_registry.py +95 -0
- omnibase_infra/errors/error_consul.py +132 -0
- omnibase_infra/errors/error_container_wiring.py +243 -0
- omnibase_infra/errors/error_event_bus_registry.py +105 -0
- omnibase_infra/errors/error_infra.py +610 -0
- omnibase_infra/errors/error_message_type_registry.py +101 -0
- omnibase_infra/errors/error_policy_registry.py +115 -0
- omnibase_infra/errors/error_vault.py +123 -0
- omnibase_infra/event_bus/__init__.py +72 -0
- omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +84 -0
- omnibase_infra/event_bus/event_bus_inmemory.py +797 -0
- omnibase_infra/event_bus/event_bus_kafka.py +1716 -0
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +180 -0
- omnibase_infra/event_bus/mixin_kafka_dlq.py +771 -0
- omnibase_infra/event_bus/models/__init__.py +29 -0
- omnibase_infra/event_bus/models/config/__init__.py +20 -0
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +693 -0
- omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
- omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
- omnibase_infra/event_bus/models/model_event_headers.py +115 -0
- omnibase_infra/event_bus/models/model_event_message.py +60 -0
- omnibase_infra/event_bus/testing/__init__.py +26 -0
- omnibase_infra/event_bus/testing/adapter_protocol_event_publisher_inmemory.py +418 -0
- omnibase_infra/event_bus/testing/model_publisher_metrics.py +64 -0
- omnibase_infra/event_bus/topic_constants.py +376 -0
- omnibase_infra/handlers/__init__.py +82 -0
- omnibase_infra/handlers/filesystem/__init__.py +48 -0
- omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
- omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
- omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
- omnibase_infra/handlers/handler_consul.py +795 -0
- omnibase_infra/handlers/handler_db.py +1046 -0
- omnibase_infra/handlers/handler_filesystem.py +1478 -0
- omnibase_infra/handlers/handler_graph.py +2015 -0
- omnibase_infra/handlers/handler_http.py +926 -0
- omnibase_infra/handlers/handler_intent.py +387 -0
- omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
- omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
- omnibase_infra/handlers/handler_mcp.py +1430 -0
- omnibase_infra/handlers/handler_qdrant.py +1076 -0
- omnibase_infra/handlers/handler_vault.py +428 -0
- omnibase_infra/handlers/mcp/__init__.py +19 -0
- omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
- omnibase_infra/handlers/mcp/protocols.py +178 -0
- omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
- omnibase_infra/handlers/mixins/__init__.py +47 -0
- omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +338 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +542 -0
- omnibase_infra/handlers/mixins/mixin_consul_topic_index.py +585 -0
- omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
- omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
- omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
- omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
- omnibase_infra/handlers/models/__init__.py +286 -0
- omnibase_infra/handlers/models/consul/__init__.py +81 -0
- omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
- omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
- omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
- omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
- omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
- omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
- omnibase_infra/handlers/models/graph/__init__.py +35 -0
- omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
- omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
- omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
- omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
- omnibase_infra/handlers/models/http/__init__.py +50 -0
- omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
- omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
- omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
- omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
- omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
- omnibase_infra/handlers/models/mcp/__init__.py +23 -0
- omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
- omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
- omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
- omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
- omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
- omnibase_infra/handlers/models/model_db_query_response.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
- omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
- omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
- omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
- omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
- omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
- omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
- omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_handler_response.py +103 -0
- omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
- omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
- omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
- omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
- omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
- omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
- omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
- omnibase_infra/handlers/models/model_operation_context.py +187 -0
- omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_retry_state.py +162 -0
- omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
- omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
- omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
- omnibase_infra/handlers/models/vault/__init__.py +69 -0
- omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
- omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
- omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
- omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
- omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
- omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
- omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
- omnibase_infra/handlers/registration_storage/__init__.py +43 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +922 -0
- omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
- omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
- omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
- omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
- omnibase_infra/handlers/service_discovery/__init__.py +43 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +1051 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
- omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
- omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
- omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +109 -0
- omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
- omnibase_infra/idempotency/__init__.py +94 -0
- omnibase_infra/idempotency/models/__init__.py +43 -0
- omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
- omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
- omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
- omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
- omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
- omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
- omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
- omnibase_infra/idempotency/store_inmemory.py +265 -0
- omnibase_infra/idempotency/store_postgres.py +923 -0
- omnibase_infra/infrastructure/__init__.py +0 -0
- omnibase_infra/migrations/001_create_event_ledger.sql +166 -0
- omnibase_infra/migrations/001_drop_event_ledger.sql +18 -0
- omnibase_infra/mixins/__init__.py +71 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +656 -0
- omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
- omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
- omnibase_infra/mixins/mixin_node_introspection.py +2670 -0
- omnibase_infra/mixins/mixin_retry_execution.py +386 -0
- omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
- omnibase_infra/models/__init__.py +144 -0
- omnibase_infra/models/bindings/__init__.py +59 -0
- omnibase_infra/models/bindings/constants.py +144 -0
- omnibase_infra/models/bindings/model_binding_resolution_result.py +103 -0
- omnibase_infra/models/bindings/model_operation_binding.py +44 -0
- omnibase_infra/models/bindings/model_operation_bindings_subcontract.py +152 -0
- omnibase_infra/models/bindings/model_parsed_binding.py +52 -0
- omnibase_infra/models/corpus/__init__.py +17 -0
- omnibase_infra/models/corpus/model_capture_config.py +133 -0
- omnibase_infra/models/corpus/model_capture_result.py +86 -0
- omnibase_infra/models/discovery/__init__.py +42 -0
- omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
- omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
- omnibase_infra/models/discovery/model_introspection_config.py +330 -0
- omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
- omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
- omnibase_infra/models/dispatch/__init__.py +155 -0
- omnibase_infra/models/dispatch/model_debug_trace_snapshot.py +114 -0
- omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
- omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
- omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
- omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
- omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
- omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
- omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
- omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
- omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
- omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
- omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
- omnibase_infra/models/dispatch/model_materialized_dispatch.py +141 -0
- omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
- omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
- omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
- omnibase_infra/models/errors/__init__.py +45 -0
- omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
- omnibase_infra/models/errors/model_infra_error_context.py +99 -0
- omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
- omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
- omnibase_infra/models/handlers/__init__.py +80 -0
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +82 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +200 -0
- omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
- omnibase_infra/models/health/__init__.py +9 -0
- omnibase_infra/models/health/model_health_check_result.py +40 -0
- omnibase_infra/models/lifecycle/__init__.py +39 -0
- omnibase_infra/models/logging/__init__.py +51 -0
- omnibase_infra/models/logging/model_log_context.py +756 -0
- omnibase_infra/models/mcp/__init__.py +15 -0
- omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
- omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
- omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
- omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
- omnibase_infra/models/model_node_identity.py +126 -0
- omnibase_infra/models/model_retry_error_classification.py +78 -0
- omnibase_infra/models/projection/__init__.py +43 -0
- omnibase_infra/models/projection/model_capability_fields.py +112 -0
- omnibase_infra/models/projection/model_registration_projection.py +434 -0
- omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
- omnibase_infra/models/projection/model_sequence_info.py +182 -0
- omnibase_infra/models/projection/model_snapshot_topic_config.py +591 -0
- omnibase_infra/models/projectors/__init__.py +41 -0
- omnibase_infra/models/projectors/model_projector_column.py +289 -0
- omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
- omnibase_infra/models/projectors/model_projector_index.py +270 -0
- omnibase_infra/models/projectors/model_projector_schema.py +415 -0
- omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
- omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
- omnibase_infra/models/registration/__init__.py +68 -0
- omnibase_infra/models/registration/commands/__init__.py +15 -0
- omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
- omnibase_infra/models/registration/events/__init__.py +56 -0
- omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
- omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
- omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
- omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
- omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
- omnibase_infra/models/registration/model_event_bus_topic_entry.py +59 -0
- omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
- omnibase_infra/models/registration/model_node_capabilities.py +190 -0
- omnibase_infra/models/registration/model_node_event_bus_config.py +99 -0
- omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +195 -0
- omnibase_infra/models/registration/model_node_metadata.py +79 -0
- omnibase_infra/models/registration/model_node_registration.py +162 -0
- omnibase_infra/models/registration/model_node_registration_record.py +162 -0
- omnibase_infra/models/registry/__init__.py +29 -0
- omnibase_infra/models/registry/model_domain_constraint.py +202 -0
- omnibase_infra/models/registry/model_message_type_entry.py +271 -0
- omnibase_infra/models/resilience/__init__.py +9 -0
- omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
- omnibase_infra/models/routing/__init__.py +25 -0
- omnibase_infra/models/routing/model_routing_entry.py +52 -0
- omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
- omnibase_infra/models/runtime/__init__.py +49 -0
- omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
- omnibase_infra/models/runtime/model_discovery_error.py +81 -0
- omnibase_infra/models/runtime/model_discovery_result.py +162 -0
- omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
- omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
- omnibase_infra/models/runtime/model_handler_contract.py +296 -0
- omnibase_infra/models/runtime/model_loaded_handler.py +129 -0
- omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
- omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
- omnibase_infra/models/security/__init__.py +50 -0
- omnibase_infra/models/security/classification_levels.py +99 -0
- omnibase_infra/models/security/model_environment_policy.py +145 -0
- omnibase_infra/models/security/model_handler_security_policy.py +107 -0
- omnibase_infra/models/security/model_security_error.py +81 -0
- omnibase_infra/models/security/model_security_validation_result.py +328 -0
- omnibase_infra/models/security/model_security_warning.py +67 -0
- omnibase_infra/models/snapshot/__init__.py +27 -0
- omnibase_infra/models/snapshot/model_field_change.py +65 -0
- omnibase_infra/models/snapshot/model_snapshot.py +270 -0
- omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
- omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
- omnibase_infra/models/types/__init__.py +71 -0
- omnibase_infra/models/validation/__init__.py +89 -0
- omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
- omnibase_infra/models/validation/model_any_type_violation.py +141 -0
- omnibase_infra/models/validation/model_category_match_result.py +345 -0
- omnibase_infra/models/validation/model_chain_violation.py +166 -0
- omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
- omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
- omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
- omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
- omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
- omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
- omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
- omnibase_infra/models/validation/model_output_validation_params.py +74 -0
- omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
- omnibase_infra/models/validation/model_validation_error_params.py +84 -0
- omnibase_infra/models/validation/model_validation_outcome.py +287 -0
- omnibase_infra/nodes/__init__.py +57 -0
- omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
- omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +203 -0
- omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
- omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
- omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
- omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
- omnibase_infra/nodes/architecture_validator/node.py +262 -0
- omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
- omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
- omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
- omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +106 -0
- omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
- omnibase_infra/nodes/contract_registry_reducer/__init__.py +29 -0
- omnibase_infra/nodes/contract_registry_reducer/contract.yaml +255 -0
- omnibase_infra/nodes/contract_registry_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_contract_registry_state.py +266 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_cleanup_topic_references.py +55 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_deactivate_contract.py +58 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_mark_stale.py +49 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_heartbeat.py +71 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_topic.py +66 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_upsert_contract.py +92 -0
- omnibase_infra/nodes/contract_registry_reducer/node.py +121 -0
- omnibase_infra/nodes/contract_registry_reducer/reducer.py +784 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/registry_infra_contract_registry_reducer.py +101 -0
- omnibase_infra/nodes/effects/README.md +358 -0
- omnibase_infra/nodes/effects/__init__.py +26 -0
- omnibase_infra/nodes/effects/contract.yaml +167 -0
- omnibase_infra/nodes/effects/models/__init__.py +32 -0
- omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
- omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
- omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
- omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
- omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
- omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
- omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
- omnibase_infra/nodes/effects/registry_effect.py +525 -0
- omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
- omnibase_infra/nodes/handlers/consul/contract.yaml +85 -0
- omnibase_infra/nodes/handlers/db/contract.yaml +72 -0
- omnibase_infra/nodes/handlers/graph/contract.yaml +127 -0
- omnibase_infra/nodes/handlers/http/contract.yaml +74 -0
- omnibase_infra/nodes/handlers/intent/contract.yaml +66 -0
- omnibase_infra/nodes/handlers/mcp/contract.yaml +69 -0
- omnibase_infra/nodes/handlers/vault/contract.yaml +91 -0
- omnibase_infra/nodes/node_intent_storage_effect/__init__.py +50 -0
- omnibase_infra/nodes/node_intent_storage_effect/contract.yaml +194 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/__init__.py +24 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_input.py +141 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_output.py +130 -0
- omnibase_infra/nodes/node_intent_storage_effect/node.py +94 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/__init__.py +35 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/registry_infra_intent_storage.py +294 -0
- omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +50 -0
- omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +104 -0
- omnibase_infra/nodes/node_ledger_projection_compute/node.py +284 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/__init__.py +29 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/registry_infra_ledger_projection.py +118 -0
- omnibase_infra/nodes/node_ledger_write_effect/__init__.py +82 -0
- omnibase_infra/nodes/node_ledger_write_effect/contract.yaml +200 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/__init__.py +22 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_append.py +372 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_query.py +597 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/__init__.py +31 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_append_result.py +54 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_entry.py +92 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query.py +53 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query_result.py +41 -0
- omnibase_infra/nodes/node_ledger_write_effect/node.py +89 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/__init__.py +13 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/protocol_ledger_persistence.py +127 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/registry_infra_ledger_write.py +121 -0
- omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
- omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +482 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +694 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
- omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
- omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
- omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +528 -0
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +393 -0
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +743 -0
- omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
- omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
- omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
- omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
- omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
- omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +220 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
- omnibase_infra/nodes/node_registration_storage_effect/node.py +112 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +215 -0
- omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
- omnibase_infra/nodes/node_registry_effect/contract.yaml +677 -0
- omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +417 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
- omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
- omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
- omnibase_infra/nodes/node_registry_effect/node.py +165 -0
- omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
- omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
- omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +222 -0
- omnibase_infra/nodes/reducers/__init__.py +30 -0
- omnibase_infra/nodes/reducers/models/__init__.py +37 -0
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +87 -0
- omnibase_infra/nodes/reducers/models/model_payload_ledger_append.py +133 -0
- omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
- omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
- omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
- omnibase_infra/nodes/reducers/registration_reducer.py +1138 -0
- omnibase_infra/observability/__init__.py +143 -0
- omnibase_infra/observability/constants_metrics.py +91 -0
- omnibase_infra/observability/factory_observability_sink.py +525 -0
- omnibase_infra/observability/handlers/__init__.py +118 -0
- omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
- omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
- omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
- omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
- omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
- omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
- omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
- omnibase_infra/observability/hooks/__init__.py +74 -0
- omnibase_infra/observability/hooks/hook_observability.py +1223 -0
- omnibase_infra/observability/models/__init__.py +30 -0
- omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
- omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
- omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
- omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
- omnibase_infra/observability/sinks/__init__.py +69 -0
- omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
- omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
- omnibase_infra/plugins/__init__.py +27 -0
- omnibase_infra/plugins/examples/__init__.py +28 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
- omnibase_infra/plugins/models/__init__.py +21 -0
- omnibase_infra/plugins/models/model_plugin_context.py +76 -0
- omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
- omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
- omnibase_infra/plugins/plugin_compute_base.py +449 -0
- omnibase_infra/projectors/__init__.py +30 -0
- omnibase_infra/projectors/contracts/__init__.py +63 -0
- omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
- omnibase_infra/projectors/projection_reader_registration.py +1559 -0
- omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
- omnibase_infra/protocols/__init__.py +104 -0
- omnibase_infra/protocols/protocol_capability_projection.py +253 -0
- omnibase_infra/protocols/protocol_capability_query.py +251 -0
- omnibase_infra/protocols/protocol_container_aware.py +200 -0
- omnibase_infra/protocols/protocol_dispatch_engine.py +152 -0
- omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
- omnibase_infra/protocols/protocol_event_projector.py +96 -0
- omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
- omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
- omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
- omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
- omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
- omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
- omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
- omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
- omnibase_infra/runtime/__init__.py +445 -0
- omnibase_infra/runtime/binding_config_resolver.py +2771 -0
- omnibase_infra/runtime/binding_resolver.py +753 -0
- omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/constants_security.py +70 -0
- omnibase_infra/runtime/contract_handler_discovery.py +587 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +51 -0
- omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
- omnibase_infra/runtime/contract_loaders/operation_bindings_loader.py +789 -0
- omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
- omnibase_infra/runtime/emit_daemon/__init__.py +97 -0
- omnibase_infra/runtime/emit_daemon/cli.py +844 -0
- omnibase_infra/runtime/emit_daemon/client.py +811 -0
- omnibase_infra/runtime/emit_daemon/config.py +535 -0
- omnibase_infra/runtime/emit_daemon/daemon.py +812 -0
- omnibase_infra/runtime/emit_daemon/event_registry.py +477 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_request.py +139 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_response.py +191 -0
- omnibase_infra/runtime/emit_daemon/queue.py +618 -0
- omnibase_infra/runtime/enums/__init__.py +18 -0
- omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
- omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
- omnibase_infra/runtime/envelope_validator.py +179 -0
- omnibase_infra/runtime/event_bus_subcontract_wiring.py +466 -0
- omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
- omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
- omnibase_infra/runtime/handler_contract_source.py +750 -0
- omnibase_infra/runtime/handler_identity.py +81 -0
- omnibase_infra/runtime/handler_plugin_loader.py +2046 -0
- omnibase_infra/runtime/handler_registry.py +329 -0
- omnibase_infra/runtime/handler_source_resolver.py +367 -0
- omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
- omnibase_infra/runtime/kafka_contract_source.py +984 -0
- omnibase_infra/runtime/kernel.py +40 -0
- omnibase_infra/runtime/mixin_policy_validation.py +522 -0
- omnibase_infra/runtime/mixin_semver_cache.py +402 -0
- omnibase_infra/runtime/mixins/__init__.py +24 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +778 -0
- omnibase_infra/runtime/models/__init__.py +229 -0
- omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
- omnibase_infra/runtime/models/model_binding_config.py +168 -0
- omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
- omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
- omnibase_infra/runtime/models/model_cached_secret.py +138 -0
- omnibase_infra/runtime/models/model_compute_key.py +138 -0
- omnibase_infra/runtime/models/model_compute_registration.py +97 -0
- omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
- omnibase_infra/runtime/models/model_config_ref.py +331 -0
- omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
- omnibase_infra/runtime/models/model_contract_load_result.py +224 -0
- omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
- omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
- omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
- omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
- omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
- omnibase_infra/runtime/models/model_failed_component.py +55 -0
- omnibase_infra/runtime/models/model_health_check_response.py +168 -0
- omnibase_infra/runtime/models/model_health_check_result.py +229 -0
- omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
- omnibase_infra/runtime/models/model_logging_config.py +42 -0
- omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
- omnibase_infra/runtime/models/model_optional_string.py +94 -0
- omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
- omnibase_infra/runtime/models/model_policy_context.py +100 -0
- omnibase_infra/runtime/models/model_policy_key.py +138 -0
- omnibase_infra/runtime/models/model_policy_registration.py +139 -0
- omnibase_infra/runtime/models/model_policy_result.py +103 -0
- omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
- omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
- omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
- omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
- omnibase_infra/runtime/models/model_retry_policy.py +105 -0
- omnibase_infra/runtime/models/model_runtime_config.py +150 -0
- omnibase_infra/runtime/models/model_runtime_contract_config.py +268 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_config.py +625 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
- omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
- omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
- omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
- omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
- omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
- omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
- omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
- omnibase_infra/runtime/models/model_security_config.py +109 -0
- omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
- omnibase_infra/runtime/models/model_shutdown_config.py +94 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
- omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
- omnibase_infra/runtime/projector_plugin_loader.py +1462 -0
- omnibase_infra/runtime/projector_schema_manager.py +565 -0
- omnibase_infra/runtime/projector_shell.py +1330 -0
- omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
- omnibase_infra/runtime/protocol_contract_source.py +92 -0
- omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
- omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
- omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
- omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
- omnibase_infra/runtime/protocol_policy.py +366 -0
- omnibase_infra/runtime/protocols/__init__.py +37 -0
- omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
- omnibase_infra/runtime/publisher_topic_scoped.py +294 -0
- omnibase_infra/runtime/registry/__init__.py +93 -0
- omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
- omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
- omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
- omnibase_infra/runtime/registry/registry_message_type.py +542 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +445 -0
- omnibase_infra/runtime/registry_compute.py +1143 -0
- omnibase_infra/runtime/registry_contract_source.py +693 -0
- omnibase_infra/runtime/registry_dispatcher.py +678 -0
- omnibase_infra/runtime/registry_policy.py +1185 -0
- omnibase_infra/runtime/runtime_contract_config_loader.py +406 -0
- omnibase_infra/runtime/runtime_scheduler.py +1070 -0
- omnibase_infra/runtime/secret_resolver.py +2112 -0
- omnibase_infra/runtime/security_metadata_validator.py +776 -0
- omnibase_infra/runtime/service_kernel.py +1651 -0
- omnibase_infra/runtime/service_message_dispatch_engine.py +2350 -0
- omnibase_infra/runtime/service_runtime_host_process.py +3493 -0
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +765 -0
- omnibase_infra/runtime/util_container_wiring.py +1124 -0
- omnibase_infra/runtime/util_validation.py +314 -0
- omnibase_infra/runtime/util_version.py +98 -0
- omnibase_infra/runtime/util_wiring.py +723 -0
- omnibase_infra/schemas/schema_registration_projection.sql +320 -0
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/__init__.py +89 -0
- omnibase_infra/services/corpus_capture.py +684 -0
- omnibase_infra/services/mcp/__init__.py +31 -0
- omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
- omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
- omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +565 -0
- omnibase_infra/services/registry_api/__init__.py +40 -0
- omnibase_infra/services/registry_api/main.py +261 -0
- omnibase_infra/services/registry_api/models/__init__.py +66 -0
- omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
- omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
- omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
- omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
- omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
- omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
- omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
- omnibase_infra/services/registry_api/models/model_warning.py +49 -0
- omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
- omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
- omnibase_infra/services/registry_api/routes.py +371 -0
- omnibase_infra/services/registry_api/service.py +837 -0
- omnibase_infra/services/service_capability_query.py +945 -0
- omnibase_infra/services/service_health.py +898 -0
- omnibase_infra/services/service_node_selector.py +530 -0
- omnibase_infra/services/service_timeout_emitter.py +699 -0
- omnibase_infra/services/service_timeout_scanner.py +394 -0
- omnibase_infra/services/session/__init__.py +56 -0
- omnibase_infra/services/session/config_consumer.py +137 -0
- omnibase_infra/services/session/config_store.py +139 -0
- omnibase_infra/services/session/consumer.py +1007 -0
- omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
- omnibase_infra/services/session/store.py +997 -0
- omnibase_infra/services/snapshot/__init__.py +31 -0
- omnibase_infra/services/snapshot/service_snapshot.py +647 -0
- omnibase_infra/services/snapshot/store_inmemory.py +637 -0
- omnibase_infra/services/snapshot/store_postgres.py +1279 -0
- omnibase_infra/shared/__init__.py +8 -0
- omnibase_infra/testing/__init__.py +10 -0
- omnibase_infra/testing/utils.py +23 -0
- omnibase_infra/topics/__init__.py +45 -0
- omnibase_infra/topics/platform_topic_suffixes.py +140 -0
- omnibase_infra/topics/util_topic_composition.py +95 -0
- omnibase_infra/types/__init__.py +48 -0
- omnibase_infra/types/type_cache_info.py +49 -0
- omnibase_infra/types/type_dsn.py +173 -0
- omnibase_infra/types/type_infra_aliases.py +60 -0
- omnibase_infra/types/typed_dict/__init__.py +29 -0
- omnibase_infra/types/typed_dict/typed_dict_envelope_build_params.py +115 -0
- omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
- omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
- omnibase_infra/types/typed_dict_capabilities.py +64 -0
- omnibase_infra/utils/__init__.py +117 -0
- omnibase_infra/utils/correlation.py +208 -0
- omnibase_infra/utils/util_atomic_file.py +261 -0
- omnibase_infra/utils/util_consumer_group.py +232 -0
- omnibase_infra/utils/util_datetime.py +372 -0
- omnibase_infra/utils/util_db_transaction.py +239 -0
- omnibase_infra/utils/util_dsn_validation.py +333 -0
- omnibase_infra/utils/util_env_parsing.py +264 -0
- omnibase_infra/utils/util_error_sanitization.py +457 -0
- omnibase_infra/utils/util_pydantic_validators.py +477 -0
- omnibase_infra/utils/util_retry_optimistic.py +281 -0
- omnibase_infra/utils/util_semver.py +233 -0
- omnibase_infra/validation/__init__.py +307 -0
- omnibase_infra/validation/contracts/security.validation.yaml +114 -0
- omnibase_infra/validation/enums/__init__.py +11 -0
- omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
- omnibase_infra/validation/infra_validators.py +1514 -0
- omnibase_infra/validation/linter_contract.py +907 -0
- omnibase_infra/validation/mixin_any_type_classification.py +120 -0
- omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
- omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
- omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
- omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
- omnibase_infra/validation/models/__init__.py +15 -0
- omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
- omnibase_infra/validation/models/model_contract_violation.py +41 -0
- omnibase_infra/validation/service_validation_aggregator.py +395 -0
- omnibase_infra/validation/validation_exemptions.yaml +2033 -0
- omnibase_infra/validation/validator_any_type.py +715 -0
- omnibase_infra/validation/validator_chain_propagation.py +839 -0
- omnibase_infra/validation/validator_execution_shape.py +465 -0
- omnibase_infra/validation/validator_localhandler.py +261 -0
- omnibase_infra/validation/validator_registration_security.py +410 -0
- omnibase_infra/validation/validator_routing_coverage.py +1020 -0
- omnibase_infra/validation/validator_runtime_shape.py +915 -0
- omnibase_infra/validation/validator_security.py +513 -0
- omnibase_infra/validation/validator_topic_category.py +1152 -0
- omnibase_infra-0.2.6.dist-info/METADATA +197 -0
- omnibase_infra-0.2.6.dist-info/RECORD +833 -0
- omnibase_infra-0.2.6.dist-info/WHEEL +4 -0
- omnibase_infra-0.2.6.dist-info/entry_points.txt +5 -0
- omnibase_infra-0.2.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Kafka-Based Contract Source for Event-Driven Discovery.
|
|
4
|
+
|
|
5
|
+
This module provides KafkaContractSource for discovering handler contracts
|
|
6
|
+
via Kafka events instead of filesystem or registry polling.
|
|
7
|
+
|
|
8
|
+
Part of OMN-1654: KafkaContractSource (cache + discovery).
|
|
9
|
+
|
|
10
|
+
**Beta Implementation**: Cache-only model. Does NOT wire business subscriptions
|
|
11
|
+
dynamically. Discovered contracts take effect on next restart.
|
|
12
|
+
|
|
13
|
+
Contract Event Flow:
|
|
14
|
+
1. External system publishes ModelContractRegisteredEvent to platform topic
|
|
15
|
+
2. KafkaContractSource receives event via baseline-wired subscription
|
|
16
|
+
3. Contract YAML is parsed and cached as ModelHandlerDescriptor
|
|
17
|
+
4. Next call to discover_handlers() returns cached descriptors
|
|
18
|
+
5. Runtime restart applies new handler configuration
|
|
19
|
+
|
|
20
|
+
Event Topics (Platform Reserved):
|
|
21
|
+
- Registration: {env}.{TOPIC_SUFFIX_CONTRACT_REGISTERED}
|
|
22
|
+
- Deregistration: {env}.{TOPIC_SUFFIX_CONTRACT_DEREGISTERED}
|
|
23
|
+
|
|
24
|
+
Topic suffixes are imported from omnibase_core.constants for single source of truth.
|
|
25
|
+
|
|
26
|
+
See Also:
|
|
27
|
+
- HandlerContractSource: Filesystem-based discovery
|
|
28
|
+
- RegistryContractSource: Consul KV-based discovery
|
|
29
|
+
- ProtocolContractSource: Protocol definition
|
|
30
|
+
|
|
31
|
+
Error Codes:
|
|
32
|
+
This module uses structured error codes for precise error classification:
|
|
33
|
+
|
|
34
|
+
**Parse Errors (KAFKA_CONTRACT_001)**:
|
|
35
|
+
- ``KAFKA_CONTRACT_001`` (PARSE_FAILURE_STRICT_MODE): Contract parsing failed
|
|
36
|
+
in strict mode (graceful_mode=False). Raised when YAML parsing, Pydantic
|
|
37
|
+
validation, or contract schema validation fails.
|
|
38
|
+
|
|
39
|
+
**When Raised**: Only in strict mode. In graceful mode, parse errors are
|
|
40
|
+
logged and cached as ``ModelParseError`` instead of raising.
|
|
41
|
+
|
|
42
|
+
**Remediation**:
|
|
43
|
+
1. Check contract YAML syntax with a YAML linter
|
|
44
|
+
2. Validate contract against ``ModelHandlerContract`` schema
|
|
45
|
+
3. Enable ``graceful_mode=True`` if partial failures are acceptable
|
|
46
|
+
4. Check logs for the underlying error (YAML, validation, etc.)
|
|
47
|
+
|
|
48
|
+
**Size Limit Errors (KAFKA_CONTRACT_002)**:
|
|
49
|
+
- ``KAFKA_CONTRACT_002`` (CONTRACT_SIZE_EXCEEDED): Contract YAML exceeds
|
|
50
|
+
the 10MB size limit. This is a hard limit applied before YAML parsing
|
|
51
|
+
to prevent memory exhaustion attacks.
|
|
52
|
+
|
|
53
|
+
**When Raised**: During contract parsing when the UTF-8 encoded contract
|
|
54
|
+
exceeds ``MAX_CONTRACT_SIZE`` (10,485,760 bytes).
|
|
55
|
+
|
|
56
|
+
**Remediation**:
|
|
57
|
+
1. Reduce contract size by removing unnecessary fields
|
|
58
|
+
2. Split large handler configurations into multiple contracts
|
|
59
|
+
3. Move large static data (e.g., schemas) to external files
|
|
60
|
+
4. Verify the contract isn't corrupted or duplicated
|
|
61
|
+
|
|
62
|
+
Error codes are accessible via ``error.error_code`` on raised ``ModelOnexError``
|
|
63
|
+
exceptions. Include the correlation ID from logs when reporting errors.
|
|
64
|
+
|
|
65
|
+
.. versionadded:: 0.8.0
|
|
66
|
+
Created as part of OMN-1654 Kafka-based contract discovery.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
from __future__ import annotations
|
|
70
|
+
|
|
71
|
+
import logging
|
|
72
|
+
import threading
|
|
73
|
+
from typing import Protocol, cast, get_args, runtime_checkable
|
|
74
|
+
from uuid import UUID, uuid4
|
|
75
|
+
|
|
76
|
+
import yaml
|
|
77
|
+
from pydantic import ValidationError
|
|
78
|
+
|
|
79
|
+
from omnibase_core.constants import (
|
|
80
|
+
TOPIC_SUFFIX_CONTRACT_DEREGISTERED,
|
|
81
|
+
TOPIC_SUFFIX_CONTRACT_REGISTERED,
|
|
82
|
+
)
|
|
83
|
+
from omnibase_core.models.contracts.model_handler_contract import ModelHandlerContract
|
|
84
|
+
from omnibase_core.models.errors import ModelOnexError
|
|
85
|
+
from omnibase_core.models.events import (
|
|
86
|
+
ModelContractDeregisteredEvent,
|
|
87
|
+
ModelContractRegisteredEvent,
|
|
88
|
+
)
|
|
89
|
+
from omnibase_infra.enums import EnumHandlerErrorType, EnumHandlerSourceType
|
|
90
|
+
from omnibase_infra.models.errors import ModelHandlerValidationError
|
|
91
|
+
from omnibase_infra.models.handlers import (
|
|
92
|
+
LiteralHandlerKind,
|
|
93
|
+
ModelContractDiscoveryResult,
|
|
94
|
+
ModelHandlerDescriptor,
|
|
95
|
+
ModelHandlerIdentifier,
|
|
96
|
+
)
|
|
97
|
+
from omnibase_infra.runtime.protocol_contract_source import ProtocolContractSource
|
|
98
|
+
|
|
99
|
+
logger = logging.getLogger(__name__)
|
|
100
|
+
|
|
101
|
+
# Forward Reference Resolution:
|
|
102
|
+
# ModelContractDiscoveryResult uses a forward reference to ModelHandlerValidationError.
|
|
103
|
+
# Since we import ModelHandlerValidationError above, we can call model_rebuild() here
|
|
104
|
+
# to resolve the forward reference. This call is idempotent - multiple calls are harmless.
|
|
105
|
+
ModelContractDiscoveryResult.model_rebuild()
|
|
106
|
+
|
|
107
|
+
# Maximum contract size (same as other sources)
|
|
108
|
+
MAX_CONTRACT_SIZE = 10 * 1024 * 1024 # 10MB
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class ContractYamlParser:
|
|
112
|
+
"""Parse contract YAML into ModelHandlerDescriptor.
|
|
113
|
+
|
|
114
|
+
This class handles YAML parsing, validation, and error creation
|
|
115
|
+
for contract documents received via Kafka events. It encapsulates
|
|
116
|
+
all YAML-to-descriptor conversion logic in a single responsibility
|
|
117
|
+
class.
|
|
118
|
+
|
|
119
|
+
Attributes:
|
|
120
|
+
environment: The environment name used for constructing contract paths.
|
|
121
|
+
|
|
122
|
+
Example:
|
|
123
|
+
>>> parser = ContractYamlParser(environment="dev")
|
|
124
|
+
>>> descriptor = parser.parse("my.node", yaml_content, correlation_id)
|
|
125
|
+
>>> print(descriptor.handler_id)
|
|
126
|
+
|
|
127
|
+
.. versionadded:: 0.8.0
|
|
128
|
+
Extracted from KafkaContractSource for single-responsibility.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
__slots__ = ("_environment",)
|
|
132
|
+
|
|
133
|
+
def __init__(self, environment: str = "dev") -> None:
|
|
134
|
+
"""Initialize the parser.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
environment: Environment name for topic prefix (e.g., "dev", "prod").
|
|
138
|
+
Used for constructing contract_path URIs.
|
|
139
|
+
"""
|
|
140
|
+
self._environment = environment
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def environment(self) -> str:
|
|
144
|
+
"""Return the environment name.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
The environment name (e.g., "dev", "prod").
|
|
148
|
+
"""
|
|
149
|
+
return self._environment
|
|
150
|
+
|
|
151
|
+
def parse(
|
|
152
|
+
self,
|
|
153
|
+
node_name: str,
|
|
154
|
+
contract_yaml: str,
|
|
155
|
+
correlation_id: UUID,
|
|
156
|
+
) -> ModelHandlerDescriptor:
|
|
157
|
+
"""Parse contract YAML into ModelHandlerDescriptor.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
node_name: Node identifier (used for error context and path).
|
|
161
|
+
contract_yaml: Full YAML content of the handler contract.
|
|
162
|
+
correlation_id: Correlation ID for tracing.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
ModelHandlerDescriptor parsed from the contract.
|
|
166
|
+
|
|
167
|
+
Raises:
|
|
168
|
+
yaml.YAMLError: If YAML parsing fails.
|
|
169
|
+
ValidationError: If Pydantic validation fails.
|
|
170
|
+
ModelOnexError: If contract exceeds size limit.
|
|
171
|
+
ValueError: If contract data is invalid.
|
|
172
|
+
"""
|
|
173
|
+
# Check size limit
|
|
174
|
+
contract_bytes = contract_yaml.encode("utf-8")
|
|
175
|
+
if len(contract_bytes) > MAX_CONTRACT_SIZE:
|
|
176
|
+
raise ModelOnexError(
|
|
177
|
+
f"Contract exceeds size limit: {len(contract_bytes)} bytes "
|
|
178
|
+
f"(max: {MAX_CONTRACT_SIZE} bytes)",
|
|
179
|
+
error_code="KAFKA_CONTRACT_002",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Parse YAML
|
|
183
|
+
contract_data = yaml.safe_load(contract_yaml)
|
|
184
|
+
if not contract_data:
|
|
185
|
+
raise ValueError("Contract YAML is empty or invalid")
|
|
186
|
+
|
|
187
|
+
# Validate against ModelHandlerContract
|
|
188
|
+
contract = ModelHandlerContract.model_validate(contract_data)
|
|
189
|
+
|
|
190
|
+
# Extract handler_class from metadata section
|
|
191
|
+
# NOTE: handler_class must be in metadata per ModelHandlerContract schema
|
|
192
|
+
# (root-level extra fields are forbidden by Pydantic extra='forbid')
|
|
193
|
+
# TODO [OMN-1420]: Use contract.handler_class once available in schema
|
|
194
|
+
handler_class = None
|
|
195
|
+
if isinstance(contract_data, dict):
|
|
196
|
+
metadata = contract_data.get("metadata", {})
|
|
197
|
+
if isinstance(metadata, dict):
|
|
198
|
+
handler_class = metadata.get("handler_class")
|
|
199
|
+
|
|
200
|
+
if handler_class is None:
|
|
201
|
+
logger.debug(
|
|
202
|
+
"handler_class missing from contract, handler may not be loadable",
|
|
203
|
+
extra={
|
|
204
|
+
"node_name": node_name,
|
|
205
|
+
"handler_id": contract.handler_id,
|
|
206
|
+
"correlation_id": str(correlation_id),
|
|
207
|
+
},
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# Build descriptor - validate handler_kind before casting
|
|
211
|
+
archetype_value = contract.descriptor.node_archetype.value
|
|
212
|
+
valid_handler_kinds = get_args(LiteralHandlerKind)
|
|
213
|
+
if archetype_value not in valid_handler_kinds:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
f"Invalid node_archetype value '{archetype_value}'. "
|
|
216
|
+
f"Expected one of: {valid_handler_kinds}"
|
|
217
|
+
)
|
|
218
|
+
# Value validated above, cast is now safe
|
|
219
|
+
handler_kind = cast("LiteralHandlerKind", archetype_value)
|
|
220
|
+
|
|
221
|
+
return ModelHandlerDescriptor(
|
|
222
|
+
handler_id=contract.handler_id,
|
|
223
|
+
name=contract.name,
|
|
224
|
+
version=contract.contract_version,
|
|
225
|
+
handler_kind=handler_kind,
|
|
226
|
+
input_model=contract.input_model,
|
|
227
|
+
output_model=contract.output_model,
|
|
228
|
+
description=contract.description,
|
|
229
|
+
handler_class=handler_class,
|
|
230
|
+
contract_path=f"kafka://{self._environment}/contracts/{node_name}",
|
|
231
|
+
contract_config=contract_data,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
def create_parse_error(
|
|
235
|
+
self,
|
|
236
|
+
node_name: str,
|
|
237
|
+
error: Exception,
|
|
238
|
+
correlation_id: UUID,
|
|
239
|
+
) -> ModelHandlerValidationError:
|
|
240
|
+
"""Create a validation error for contract parse failures.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
node_name: The node identifier.
|
|
244
|
+
error: The parsing error.
|
|
245
|
+
correlation_id: Correlation ID for tracing.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
ModelHandlerValidationError with parse error details.
|
|
249
|
+
"""
|
|
250
|
+
handler_identity = ModelHandlerIdentifier.from_handler_id(
|
|
251
|
+
f"kafka://{node_name}"
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
return ModelHandlerValidationError(
|
|
255
|
+
error_type=EnumHandlerErrorType.CONTRACT_PARSE_ERROR,
|
|
256
|
+
rule_id="KAFKA-001",
|
|
257
|
+
handler_identity=handler_identity,
|
|
258
|
+
source_type=EnumHandlerSourceType.CONTRACT,
|
|
259
|
+
message=f"Failed to parse contract from Kafka event for node '{node_name}': {error}",
|
|
260
|
+
remediation_hint="Check YAML syntax and required contract fields in the registration event",
|
|
261
|
+
correlation_id=correlation_id,
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class KafkaContractCache:
|
|
266
|
+
"""Thread-safe cache for contract descriptors and validation errors.
|
|
267
|
+
|
|
268
|
+
This class manages the in-memory storage of handler descriptors discovered
|
|
269
|
+
from Kafka contract registration events. All operations are thread-safe
|
|
270
|
+
and can be called concurrently from multiple Kafka consumer threads.
|
|
271
|
+
|
|
272
|
+
The cache provides atomic operations for:
|
|
273
|
+
- Adding/removing handler descriptors by node name
|
|
274
|
+
- Collecting validation errors during event processing
|
|
275
|
+
- Retrieving all cached data with proper thread synchronization
|
|
276
|
+
|
|
277
|
+
Attributes:
|
|
278
|
+
count: Number of cached descriptors (thread-safe read).
|
|
279
|
+
error_count: Number of pending validation errors (thread-safe read).
|
|
280
|
+
|
|
281
|
+
Example:
|
|
282
|
+
>>> cache = KafkaContractCache()
|
|
283
|
+
>>> cache.add("my.node", descriptor)
|
|
284
|
+
>>> assert cache.count == 1
|
|
285
|
+
>>> removed = cache.remove("my.node")
|
|
286
|
+
>>> assert removed is not None
|
|
287
|
+
|
|
288
|
+
.. versionadded:: 0.8.0
|
|
289
|
+
Extracted from KafkaContractSource for single-responsibility.
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
__slots__ = ("_descriptors", "_errors", "_lock")
|
|
293
|
+
|
|
294
|
+
def __init__(self) -> None:
|
|
295
|
+
"""Initialize an empty cache with thread-safe locking."""
|
|
296
|
+
self._descriptors: dict[str, ModelHandlerDescriptor] = {}
|
|
297
|
+
self._errors: list[ModelHandlerValidationError] = []
|
|
298
|
+
self._lock = threading.Lock()
|
|
299
|
+
|
|
300
|
+
@property
|
|
301
|
+
def count(self) -> int:
|
|
302
|
+
"""Return the number of cached descriptors.
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Number of handler descriptors currently in the cache.
|
|
306
|
+
"""
|
|
307
|
+
with self._lock:
|
|
308
|
+
return len(self._descriptors)
|
|
309
|
+
|
|
310
|
+
@property
|
|
311
|
+
def error_count(self) -> int:
|
|
312
|
+
"""Return the number of pending validation errors.
|
|
313
|
+
|
|
314
|
+
Returns:
|
|
315
|
+
Number of validation errors awaiting retrieval.
|
|
316
|
+
"""
|
|
317
|
+
with self._lock:
|
|
318
|
+
return len(self._errors)
|
|
319
|
+
|
|
320
|
+
def add(self, node_name: str, descriptor: ModelHandlerDescriptor) -> None:
|
|
321
|
+
"""Add or update a descriptor in the cache.
|
|
322
|
+
|
|
323
|
+
If a descriptor with the same node_name exists, it is replaced.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
node_name: Unique identifier for the node (cache key).
|
|
327
|
+
descriptor: The handler descriptor to cache.
|
|
328
|
+
"""
|
|
329
|
+
with self._lock:
|
|
330
|
+
self._descriptors[node_name] = descriptor
|
|
331
|
+
|
|
332
|
+
def remove(self, node_name: str) -> ModelHandlerDescriptor | None:
|
|
333
|
+
"""Remove a descriptor from the cache.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
node_name: Unique identifier for the node to remove.
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
The removed descriptor if found, None otherwise.
|
|
340
|
+
"""
|
|
341
|
+
with self._lock:
|
|
342
|
+
return self._descriptors.pop(node_name, None)
|
|
343
|
+
|
|
344
|
+
def get_all(self) -> list[ModelHandlerDescriptor]:
|
|
345
|
+
"""Return all cached descriptors.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
A copy of all cached descriptors. Modifying the returned
|
|
349
|
+
list does not affect the cache.
|
|
350
|
+
"""
|
|
351
|
+
with self._lock:
|
|
352
|
+
return list(self._descriptors.values())
|
|
353
|
+
|
|
354
|
+
def add_error(self, error: ModelHandlerValidationError) -> None:
|
|
355
|
+
"""Add a validation error to the pending errors list.
|
|
356
|
+
|
|
357
|
+
Args:
|
|
358
|
+
error: The validation error to add.
|
|
359
|
+
"""
|
|
360
|
+
with self._lock:
|
|
361
|
+
self._errors.append(error)
|
|
362
|
+
|
|
363
|
+
def get_errors(self) -> list[ModelHandlerValidationError]:
|
|
364
|
+
"""Return pending errors WITHOUT clearing them.
|
|
365
|
+
|
|
366
|
+
This method provides read-only access to pending errors for
|
|
367
|
+
inspection without consuming them.
|
|
368
|
+
|
|
369
|
+
Returns:
|
|
370
|
+
A copy of the pending validation errors.
|
|
371
|
+
"""
|
|
372
|
+
with self._lock:
|
|
373
|
+
return list(self._errors)
|
|
374
|
+
|
|
375
|
+
def get_and_clear_errors(self) -> list[ModelHandlerValidationError]:
|
|
376
|
+
"""Atomically get and clear all pending errors.
|
|
377
|
+
|
|
378
|
+
This method returns the current errors and clears the internal
|
|
379
|
+
list in a single atomic operation, ensuring no errors are lost
|
|
380
|
+
in concurrent access scenarios.
|
|
381
|
+
|
|
382
|
+
Returns:
|
|
383
|
+
The list of pending errors that were cleared.
|
|
384
|
+
"""
|
|
385
|
+
with self._lock:
|
|
386
|
+
errors = list(self._errors)
|
|
387
|
+
self._errors.clear()
|
|
388
|
+
return errors
|
|
389
|
+
|
|
390
|
+
def clear(self) -> int:
|
|
391
|
+
"""Clear all cached descriptors and pending errors.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
Number of descriptors that were cleared.
|
|
395
|
+
"""
|
|
396
|
+
with self._lock:
|
|
397
|
+
count = len(self._descriptors)
|
|
398
|
+
self._descriptors.clear()
|
|
399
|
+
self._errors.clear()
|
|
400
|
+
return count
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@runtime_checkable
|
|
404
|
+
class ProtocolContractEventCallbacks(Protocol):
|
|
405
|
+
"""Protocol defining callbacks for contract registration events.
|
|
406
|
+
|
|
407
|
+
This protocol defines the interface required by MixinTypedContractEvents
|
|
408
|
+
for delegating typed event handling to the host class. Any class using
|
|
409
|
+
MixinTypedContractEvents must implement these methods.
|
|
410
|
+
|
|
411
|
+
The protocol enables type-safe cross-mixin method access without
|
|
412
|
+
inheritance conflicts or type: ignore comments.
|
|
413
|
+
|
|
414
|
+
Methods:
|
|
415
|
+
on_contract_registered: Process a contract registration event.
|
|
416
|
+
on_contract_deregistered: Process a contract deregistration event.
|
|
417
|
+
|
|
418
|
+
Example:
|
|
419
|
+
>>> class MySource(MixinTypedContractEvents, ProtocolContractSource):
|
|
420
|
+
... def on_contract_registered(
|
|
421
|
+
... self, node_name: str, contract_yaml: str, correlation_id: UUID | None
|
|
422
|
+
... ) -> bool:
|
|
423
|
+
... # Implementation here
|
|
424
|
+
... return True
|
|
425
|
+
...
|
|
426
|
+
... def on_contract_deregistered(
|
|
427
|
+
... self, node_name: str, correlation_id: UUID | None
|
|
428
|
+
... ) -> bool:
|
|
429
|
+
... # Implementation here
|
|
430
|
+
... return True
|
|
431
|
+
|
|
432
|
+
.. versionadded:: 0.8.0
|
|
433
|
+
Created for type-safe mixin composition in MixinTypedContractEvents.
|
|
434
|
+
"""
|
|
435
|
+
|
|
436
|
+
def on_contract_registered(
|
|
437
|
+
self,
|
|
438
|
+
node_name: str,
|
|
439
|
+
contract_yaml: str,
|
|
440
|
+
correlation_id: UUID | None = None,
|
|
441
|
+
) -> bool:
|
|
442
|
+
"""Cache descriptor from contract registration event.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
node_name: Unique identifier for the node (used as cache key).
|
|
446
|
+
contract_yaml: Full YAML content of the handler contract.
|
|
447
|
+
correlation_id: Optional correlation ID from the event for tracing.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
True if the contract was successfully cached, False if parsing failed.
|
|
451
|
+
"""
|
|
452
|
+
...
|
|
453
|
+
|
|
454
|
+
def on_contract_deregistered(
|
|
455
|
+
self,
|
|
456
|
+
node_name: str,
|
|
457
|
+
correlation_id: UUID | None = None,
|
|
458
|
+
) -> bool:
|
|
459
|
+
"""Remove descriptor from cache on deregistration event.
|
|
460
|
+
|
|
461
|
+
Args:
|
|
462
|
+
node_name: Unique identifier for the node to remove.
|
|
463
|
+
correlation_id: Optional correlation ID from the event for tracing.
|
|
464
|
+
|
|
465
|
+
Returns:
|
|
466
|
+
True if a descriptor was removed, False if not found in cache.
|
|
467
|
+
"""
|
|
468
|
+
...
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class MixinTypedContractEvents:
|
|
472
|
+
"""Mixin providing typed event handler and error inspection methods.
|
|
473
|
+
|
|
474
|
+
This mixin provides convenience methods for handling typed contract
|
|
475
|
+
events from omnibase_core and inspecting pending validation errors.
|
|
476
|
+
It delegates to the primitive methods (on_contract_registered,
|
|
477
|
+
on_contract_deregistered) and the cache which must be available
|
|
478
|
+
in the class using this mixin.
|
|
479
|
+
|
|
480
|
+
This mixin reduces method count in KafkaContractSource by extracting
|
|
481
|
+
the typed event handling and error inspection into a separate concern.
|
|
482
|
+
|
|
483
|
+
Requirements:
|
|
484
|
+
Classes using this mixin MUST implement ProtocolContractEventCallbacks
|
|
485
|
+
(i.e., provide on_contract_registered and on_contract_deregistered methods).
|
|
486
|
+
|
|
487
|
+
.. versionadded:: 0.8.0
|
|
488
|
+
Extracted from KafkaContractSource for single-responsibility.
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
# Type hints for mixin - these must be provided by the using class
|
|
492
|
+
_cache: KafkaContractCache
|
|
493
|
+
|
|
494
|
+
def _as_event_handler(self) -> ProtocolContractEventCallbacks:
|
|
495
|
+
"""Cast self to ProtocolContractEventCallbacks for type-safe method access.
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
Self cast as ProtocolContractEventCallbacks for type checker.
|
|
499
|
+
|
|
500
|
+
Note:
|
|
501
|
+
Only call this method when the host class implements
|
|
502
|
+
ProtocolContractEventCallbacks (provides on_contract_registered
|
|
503
|
+
and on_contract_deregistered methods).
|
|
504
|
+
"""
|
|
505
|
+
return cast("ProtocolContractEventCallbacks", self)
|
|
506
|
+
|
|
507
|
+
def get_pending_errors(self) -> list[ModelHandlerValidationError]:
|
|
508
|
+
"""Return pending validation errors WITHOUT clearing them.
|
|
509
|
+
|
|
510
|
+
This method provides read-only access to pending errors for inspection
|
|
511
|
+
purposes. Unlike ``discover_handlers()`` which clears errors after
|
|
512
|
+
returning them (one-shot behavior), this method allows repeated
|
|
513
|
+
inspection of the same errors.
|
|
514
|
+
|
|
515
|
+
Use this method when you need to:
|
|
516
|
+
- Check error state without consuming errors
|
|
517
|
+
- Log or display errors before a discover_handlers() call
|
|
518
|
+
- Implement custom error handling before the next discovery cycle
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
A copy of the pending validation errors list. Modifying the
|
|
522
|
+
returned list does not affect the internal state.
|
|
523
|
+
|
|
524
|
+
Thread Safety:
|
|
525
|
+
This method is thread-safe. The returned list is a copy created
|
|
526
|
+
while holding the internal lock.
|
|
527
|
+
|
|
528
|
+
Example:
|
|
529
|
+
>>> source = KafkaContractSource()
|
|
530
|
+
>>> # Inspect errors without consuming
|
|
531
|
+
>>> errors = source.get_pending_errors()
|
|
532
|
+
>>> print(f"Found {len(errors)} pending errors")
|
|
533
|
+
>>>
|
|
534
|
+
>>> # Errors are still available for discover_handlers()
|
|
535
|
+
>>> result = await source.discover_handlers()
|
|
536
|
+
>>> assert len(result.validation_errors) == len(errors)
|
|
537
|
+
>>>
|
|
538
|
+
>>> # Now errors are cleared (one-shot)
|
|
539
|
+
>>> assert source.pending_error_count == 0
|
|
540
|
+
|
|
541
|
+
See Also:
|
|
542
|
+
- ``pending_error_count``: Quick count check without list copy.
|
|
543
|
+
- ``discover_handlers()``: Consumes errors (one-shot retrieval).
|
|
544
|
+
"""
|
|
545
|
+
return self._cache.get_errors()
|
|
546
|
+
|
|
547
|
+
def handle_registered_event(
|
|
548
|
+
self,
|
|
549
|
+
event: ModelContractRegisteredEvent,
|
|
550
|
+
) -> bool:
|
|
551
|
+
"""Handle a typed contract registration event.
|
|
552
|
+
|
|
553
|
+
This is the preferred method for processing registration events when
|
|
554
|
+
using the typed event models from omnibase_core. It extracts the
|
|
555
|
+
relevant fields and delegates to on_contract_registered().
|
|
556
|
+
|
|
557
|
+
Args:
|
|
558
|
+
event: The typed contract registration event from Kafka.
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
True if the contract was successfully cached, False if parsing failed.
|
|
562
|
+
|
|
563
|
+
Example:
|
|
564
|
+
>>> source = KafkaContractSource()
|
|
565
|
+
>>> event = ModelContractRegisteredEvent(
|
|
566
|
+
... node_name="my.handler",
|
|
567
|
+
... contract_yaml="...",
|
|
568
|
+
... # ... other fields
|
|
569
|
+
... )
|
|
570
|
+
>>> success = source.handle_registered_event(event)
|
|
571
|
+
"""
|
|
572
|
+
return self._as_event_handler().on_contract_registered(
|
|
573
|
+
node_name=event.node_name,
|
|
574
|
+
contract_yaml=event.contract_yaml,
|
|
575
|
+
correlation_id=event.correlation_id,
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
def handle_deregistered_event(
|
|
579
|
+
self,
|
|
580
|
+
event: ModelContractDeregisteredEvent,
|
|
581
|
+
) -> bool:
|
|
582
|
+
"""Handle a typed contract deregistration event.
|
|
583
|
+
|
|
584
|
+
This is the preferred method for processing deregistration events when
|
|
585
|
+
using the typed event models from omnibase_core. It extracts the
|
|
586
|
+
relevant fields and delegates to on_contract_deregistered().
|
|
587
|
+
|
|
588
|
+
Args:
|
|
589
|
+
event: The typed contract deregistration event from Kafka.
|
|
590
|
+
|
|
591
|
+
Returns:
|
|
592
|
+
True if a descriptor was removed, False if not found in cache.
|
|
593
|
+
|
|
594
|
+
Example:
|
|
595
|
+
>>> source = KafkaContractSource()
|
|
596
|
+
>>> event = ModelContractDeregisteredEvent(
|
|
597
|
+
... node_name="my.handler",
|
|
598
|
+
... reason=EnumDeregistrationReason.SHUTDOWN,
|
|
599
|
+
... # ... other fields
|
|
600
|
+
... )
|
|
601
|
+
>>> removed = source.handle_deregistered_event(event)
|
|
602
|
+
"""
|
|
603
|
+
return self._as_event_handler().on_contract_deregistered(
|
|
604
|
+
node_name=event.node_name,
|
|
605
|
+
correlation_id=event.correlation_id,
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
class KafkaContractSource(MixinTypedContractEvents, ProtocolContractSource):
|
|
610
|
+
"""Kafka-based contract source - cache + discovery only.
|
|
611
|
+
|
|
612
|
+
Subscribes to platform-reserved contract topics (baseline-wired).
|
|
613
|
+
Maintains in-memory cache of descriptors derived from contract YAML.
|
|
614
|
+
|
|
615
|
+
Does NOT wire business subscriptions dynamically.
|
|
616
|
+
For beta: discover + next restart applies.
|
|
617
|
+
|
|
618
|
+
This source maintains an in-memory cache of handler descriptors that is
|
|
619
|
+
populated by contract registration events received via Kafka. The cache
|
|
620
|
+
is read-only from the discover_handlers() perspective - it simply returns
|
|
621
|
+
whatever has been cached from events.
|
|
622
|
+
|
|
623
|
+
Thread Safety:
|
|
624
|
+
This class is thread-safe. All access to the internal cache
|
|
625
|
+
(``_cached_descriptors``) and error list (``_pending_errors``) is
|
|
626
|
+
protected by a ``threading.Lock``. Multiple Kafka consumer threads
|
|
627
|
+
may safely call ``on_contract_registered()`` and
|
|
628
|
+
``on_contract_deregistered()`` concurrently.
|
|
629
|
+
|
|
630
|
+
Attributes:
|
|
631
|
+
source_type: Returns "KAFKA_EVENTS" as the source type identifier.
|
|
632
|
+
|
|
633
|
+
Example:
|
|
634
|
+
>>> source = KafkaContractSource(environment="dev")
|
|
635
|
+
>>>
|
|
636
|
+
>>> # Event handler wiring (done by runtime)
|
|
637
|
+
>>> source.on_contract_registered(event)
|
|
638
|
+
>>>
|
|
639
|
+
>>> # Discovery returns cached descriptors
|
|
640
|
+
>>> result = await source.discover_handlers()
|
|
641
|
+
>>> for desc in result.descriptors:
|
|
642
|
+
... print(f"Cached: {desc.handler_id}")
|
|
643
|
+
|
|
644
|
+
Note:
|
|
645
|
+
This class does NOT handle Kafka subscription setup. The runtime is
|
|
646
|
+
responsible for wiring the platform-reserved contract topics to the
|
|
647
|
+
on_contract_registered/on_contract_deregistered methods.
|
|
648
|
+
|
|
649
|
+
.. versionadded:: 0.8.0
|
|
650
|
+
Created as part of OMN-1654 Kafka-based contract discovery.
|
|
651
|
+
"""
|
|
652
|
+
|
|
653
|
+
__slots__ = (
|
|
654
|
+
"_cache",
|
|
655
|
+
"_correlation_id",
|
|
656
|
+
"_environment",
|
|
657
|
+
"_graceful_mode",
|
|
658
|
+
"_parser",
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
def __init__(
|
|
662
|
+
self,
|
|
663
|
+
environment: str = "dev",
|
|
664
|
+
graceful_mode: bool = True,
|
|
665
|
+
) -> None:
|
|
666
|
+
"""Initialize the Kafka contract source.
|
|
667
|
+
|
|
668
|
+
Args:
|
|
669
|
+
environment: Environment name for topic prefix (e.g., "dev", "prod").
|
|
670
|
+
Used for observability logging only - actual topic wiring is
|
|
671
|
+
done by the runtime.
|
|
672
|
+
graceful_mode: If True (default), collect errors instead of raising.
|
|
673
|
+
For cache-based sources, graceful mode is typically preferred
|
|
674
|
+
since individual event failures should not crash the runtime.
|
|
675
|
+
"""
|
|
676
|
+
self._environment = environment
|
|
677
|
+
self._graceful_mode = graceful_mode
|
|
678
|
+
self._correlation_id = uuid4()
|
|
679
|
+
self._cache = KafkaContractCache()
|
|
680
|
+
self._parser = ContractYamlParser(environment=environment)
|
|
681
|
+
|
|
682
|
+
logger.info(
|
|
683
|
+
"KafkaContractSource initialized",
|
|
684
|
+
extra={
|
|
685
|
+
"environment": environment,
|
|
686
|
+
"graceful_mode": graceful_mode,
|
|
687
|
+
"correlation_id": str(self._correlation_id),
|
|
688
|
+
},
|
|
689
|
+
)
|
|
690
|
+
|
|
691
|
+
@property
|
|
692
|
+
def source_type(self) -> str:
|
|
693
|
+
"""Return source type identifier.
|
|
694
|
+
|
|
695
|
+
Returns:
|
|
696
|
+
"KAFKA_EVENTS" as the source type.
|
|
697
|
+
"""
|
|
698
|
+
return "KAFKA_EVENTS"
|
|
699
|
+
|
|
700
|
+
@property
|
|
701
|
+
def cached_count(self) -> int:
|
|
702
|
+
"""Return the number of cached descriptors.
|
|
703
|
+
|
|
704
|
+
Returns:
|
|
705
|
+
Number of handler descriptors currently cached.
|
|
706
|
+
"""
|
|
707
|
+
return self._cache.count
|
|
708
|
+
|
|
709
|
+
@property
|
|
710
|
+
def environment(self) -> str:
|
|
711
|
+
"""Return the environment name.
|
|
712
|
+
|
|
713
|
+
Returns:
|
|
714
|
+
The environment name (e.g., "dev", "prod").
|
|
715
|
+
"""
|
|
716
|
+
return self._environment
|
|
717
|
+
|
|
718
|
+
@property
|
|
719
|
+
def graceful_mode(self) -> bool:
|
|
720
|
+
"""Return whether graceful mode is enabled.
|
|
721
|
+
|
|
722
|
+
Returns:
|
|
723
|
+
True if graceful mode is enabled, False otherwise.
|
|
724
|
+
"""
|
|
725
|
+
return self._graceful_mode
|
|
726
|
+
|
|
727
|
+
@property
|
|
728
|
+
def correlation_id(self) -> UUID:
|
|
729
|
+
"""Return the source correlation ID.
|
|
730
|
+
|
|
731
|
+
Returns:
|
|
732
|
+
The unique correlation ID for this source instance.
|
|
733
|
+
"""
|
|
734
|
+
return self._correlation_id
|
|
735
|
+
|
|
736
|
+
@property
|
|
737
|
+
def pending_error_count(self) -> int:
|
|
738
|
+
"""Return the number of pending validation errors.
|
|
739
|
+
|
|
740
|
+
This property provides a quick way to check if there are pending
|
|
741
|
+
errors without consuming them. Use ``get_pending_errors()`` to
|
|
742
|
+
inspect errors without clearing, or ``discover_handlers()`` to
|
|
743
|
+
consume errors (one-shot retrieval).
|
|
744
|
+
|
|
745
|
+
Returns:
|
|
746
|
+
Number of validation errors currently pending.
|
|
747
|
+
|
|
748
|
+
Example:
|
|
749
|
+
>>> source = KafkaContractSource()
|
|
750
|
+
>>> if source.pending_error_count > 0:
|
|
751
|
+
... errors = source.get_pending_errors()
|
|
752
|
+
... for err in errors:
|
|
753
|
+
... print(f"Pending error: {err.message}")
|
|
754
|
+
"""
|
|
755
|
+
return self._cache.error_count
|
|
756
|
+
|
|
757
|
+
async def discover_handlers(self) -> ModelContractDiscoveryResult:
|
|
758
|
+
"""Return cached descriptors from contract events.
|
|
759
|
+
|
|
760
|
+
This method returns whatever descriptors have been cached from
|
|
761
|
+
contract registration events. It does not perform any I/O or
|
|
762
|
+
network operations - it simply returns the current cache state.
|
|
763
|
+
|
|
764
|
+
Warning:
|
|
765
|
+
**One-Shot Error Retrieval**: Validation errors are cleared after
|
|
766
|
+
being returned. Calling this method twice will return an empty
|
|
767
|
+
error list on the second call (unless new errors occurred between
|
|
768
|
+
calls). Use ``get_pending_errors()`` to inspect errors without
|
|
769
|
+
consuming them, or ``pending_error_count`` for a quick count check.
|
|
770
|
+
|
|
771
|
+
Returns:
|
|
772
|
+
ModelContractDiscoveryResult with cached descriptors and any
|
|
773
|
+
validation errors encountered during event processing. Errors
|
|
774
|
+
are cleared from internal state after this call returns.
|
|
775
|
+
|
|
776
|
+
Example:
|
|
777
|
+
>>> source = KafkaContractSource()
|
|
778
|
+
>>> # First call returns accumulated errors
|
|
779
|
+
>>> result1 = await source.discover_handlers()
|
|
780
|
+
>>> print(f"Errors: {len(result1.validation_errors)}")
|
|
781
|
+
>>>
|
|
782
|
+
>>> # Second call has empty errors (already consumed)
|
|
783
|
+
>>> result2 = await source.discover_handlers()
|
|
784
|
+
>>> assert len(result2.validation_errors) == 0
|
|
785
|
+
|
|
786
|
+
Implementation Detail:
|
|
787
|
+
This method uses a two-step retrieval pattern: errors are cleared
|
|
788
|
+
first, then descriptors are fetched. Each step is individually
|
|
789
|
+
atomic (protected by the cache lock), but there is a brief window
|
|
790
|
+
between the two operations where new events could arrive.
|
|
791
|
+
|
|
792
|
+
If a contract event fails parsing between ``get_and_clear_errors()``
|
|
793
|
+
and ``get_all()``, the resulting error will NOT be included in this
|
|
794
|
+
discovery result - it will appear in the next ``discover_handlers()``
|
|
795
|
+
call. Similarly, a successful registration between the two calls
|
|
796
|
+
will include the new descriptor but any error from a concurrent
|
|
797
|
+
failed registration will be deferred.
|
|
798
|
+
|
|
799
|
+
This eventual consistency is acceptable for the cache-only beta
|
|
800
|
+
model where discovered contracts take effect on the next restart
|
|
801
|
+
anyway. The design prioritizes simplicity over perfect atomicity,
|
|
802
|
+
avoiding the complexity of a single lock spanning both operations
|
|
803
|
+
(which would increase lock contention with concurrent Kafka
|
|
804
|
+
consumer threads).
|
|
805
|
+
|
|
806
|
+
See Also:
|
|
807
|
+
- ``get_pending_errors()``: Inspect errors without clearing.
|
|
808
|
+
- ``pending_error_count``: Quick count check.
|
|
809
|
+
"""
|
|
810
|
+
# Two-step retrieval: errors cleared first, then descriptors fetched.
|
|
811
|
+
# See "Implementation Detail" in docstring for timing window behavior.
|
|
812
|
+
errors = self._cache.get_and_clear_errors()
|
|
813
|
+
descriptors = self._cache.get_all()
|
|
814
|
+
|
|
815
|
+
logger.info(
|
|
816
|
+
"Handler discovery completed (KAFKA_EVENTS mode)",
|
|
817
|
+
extra={
|
|
818
|
+
"cached_descriptor_count": len(descriptors),
|
|
819
|
+
"validation_error_count": len(errors),
|
|
820
|
+
"environment": self._environment,
|
|
821
|
+
"correlation_id": str(self._correlation_id),
|
|
822
|
+
},
|
|
823
|
+
)
|
|
824
|
+
|
|
825
|
+
return ModelContractDiscoveryResult(
|
|
826
|
+
descriptors=descriptors,
|
|
827
|
+
validation_errors=errors,
|
|
828
|
+
)
|
|
829
|
+
|
|
830
|
+
def on_contract_registered(
|
|
831
|
+
self,
|
|
832
|
+
node_name: str,
|
|
833
|
+
contract_yaml: str,
|
|
834
|
+
correlation_id: UUID | None = None,
|
|
835
|
+
) -> bool:
|
|
836
|
+
"""Cache descriptor from contract registration event.
|
|
837
|
+
|
|
838
|
+
Called by the runtime when a contract registration event is received
|
|
839
|
+
on the platform-reserved contract topic.
|
|
840
|
+
|
|
841
|
+
Args:
|
|
842
|
+
node_name: Unique identifier for the node (used as cache key).
|
|
843
|
+
contract_yaml: Full YAML content of the handler contract.
|
|
844
|
+
correlation_id: Optional correlation ID from the event for tracing.
|
|
845
|
+
|
|
846
|
+
Returns:
|
|
847
|
+
True if the contract was successfully cached, False if parsing failed.
|
|
848
|
+
|
|
849
|
+
Note:
|
|
850
|
+
In graceful mode, parsing errors are collected in pending_errors
|
|
851
|
+
and returned on the next discover_handlers() call. In strict mode,
|
|
852
|
+
errors are raised immediately.
|
|
853
|
+
"""
|
|
854
|
+
event_correlation = correlation_id or uuid4()
|
|
855
|
+
|
|
856
|
+
logger.debug(
|
|
857
|
+
"Processing contract registration event",
|
|
858
|
+
extra={
|
|
859
|
+
"node_name": node_name,
|
|
860
|
+
"contract_size": len(contract_yaml),
|
|
861
|
+
"correlation_id": str(event_correlation),
|
|
862
|
+
"source_correlation_id": str(self._correlation_id),
|
|
863
|
+
},
|
|
864
|
+
)
|
|
865
|
+
|
|
866
|
+
try:
|
|
867
|
+
descriptor = self._parser.parse(
|
|
868
|
+
node_name=node_name,
|
|
869
|
+
contract_yaml=contract_yaml,
|
|
870
|
+
correlation_id=event_correlation,
|
|
871
|
+
)
|
|
872
|
+
self._cache.add(node_name, descriptor)
|
|
873
|
+
|
|
874
|
+
logger.info(
|
|
875
|
+
"Contract registered and cached",
|
|
876
|
+
extra={
|
|
877
|
+
"node_name": node_name,
|
|
878
|
+
"handler_id": descriptor.handler_id,
|
|
879
|
+
"handler_version": str(descriptor.version),
|
|
880
|
+
"correlation_id": str(event_correlation),
|
|
881
|
+
},
|
|
882
|
+
)
|
|
883
|
+
return True
|
|
884
|
+
|
|
885
|
+
except (yaml.YAMLError, ValidationError, ModelOnexError, ValueError) as e:
|
|
886
|
+
error = self._parser.create_parse_error(
|
|
887
|
+
node_name=node_name,
|
|
888
|
+
error=e,
|
|
889
|
+
correlation_id=event_correlation,
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
if self._graceful_mode:
|
|
893
|
+
self._cache.add_error(error)
|
|
894
|
+
logger.warning(
|
|
895
|
+
"Contract registration failed (graceful mode)",
|
|
896
|
+
extra={
|
|
897
|
+
"node_name": node_name,
|
|
898
|
+
"error": str(e),
|
|
899
|
+
"error_type": type(e).__name__,
|
|
900
|
+
"correlation_id": str(event_correlation),
|
|
901
|
+
},
|
|
902
|
+
)
|
|
903
|
+
return False
|
|
904
|
+
else:
|
|
905
|
+
raise ModelOnexError(
|
|
906
|
+
f"Failed to parse contract for node '{node_name}': {e}",
|
|
907
|
+
error_code="KAFKA_CONTRACT_001",
|
|
908
|
+
correlation_id=event_correlation,
|
|
909
|
+
) from e
|
|
910
|
+
|
|
911
|
+
def on_contract_deregistered(
|
|
912
|
+
self,
|
|
913
|
+
node_name: str,
|
|
914
|
+
correlation_id: UUID | None = None,
|
|
915
|
+
) -> bool:
|
|
916
|
+
"""Remove descriptor from cache on deregistration event.
|
|
917
|
+
|
|
918
|
+
Called by the runtime when a contract deregistration event is received
|
|
919
|
+
on the platform-reserved contract topic.
|
|
920
|
+
|
|
921
|
+
Args:
|
|
922
|
+
node_name: Unique identifier for the node to remove.
|
|
923
|
+
correlation_id: Optional correlation ID from the event for tracing.
|
|
924
|
+
|
|
925
|
+
Returns:
|
|
926
|
+
True if a descriptor was removed, False if not found in cache.
|
|
927
|
+
"""
|
|
928
|
+
event_correlation = correlation_id or uuid4()
|
|
929
|
+
|
|
930
|
+
removed = self._cache.remove(node_name)
|
|
931
|
+
|
|
932
|
+
if removed is not None:
|
|
933
|
+
logger.info(
|
|
934
|
+
"Contract deregistered and removed from cache",
|
|
935
|
+
extra={
|
|
936
|
+
"node_name": node_name,
|
|
937
|
+
"handler_id": removed.handler_id,
|
|
938
|
+
"correlation_id": str(event_correlation),
|
|
939
|
+
},
|
|
940
|
+
)
|
|
941
|
+
return True
|
|
942
|
+
else:
|
|
943
|
+
logger.debug(
|
|
944
|
+
"Contract deregistration for unknown node (no-op)",
|
|
945
|
+
extra={
|
|
946
|
+
"node_name": node_name,
|
|
947
|
+
"correlation_id": str(event_correlation),
|
|
948
|
+
},
|
|
949
|
+
)
|
|
950
|
+
return False
|
|
951
|
+
|
|
952
|
+
def clear_cache(self) -> int:
|
|
953
|
+
"""Clear all cached descriptors.
|
|
954
|
+
|
|
955
|
+
Utility method for testing and runtime reset scenarios.
|
|
956
|
+
|
|
957
|
+
Returns:
|
|
958
|
+
Number of descriptors that were cleared.
|
|
959
|
+
"""
|
|
960
|
+
count = self._cache.clear()
|
|
961
|
+
|
|
962
|
+
logger.info(
|
|
963
|
+
"Contract cache cleared",
|
|
964
|
+
extra={
|
|
965
|
+
"cleared_count": count,
|
|
966
|
+
"correlation_id": str(self._correlation_id),
|
|
967
|
+
},
|
|
968
|
+
)
|
|
969
|
+
return count
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
__all__ = [
|
|
973
|
+
"ContractYamlParser",
|
|
974
|
+
"KafkaContractCache",
|
|
975
|
+
"KafkaContractSource",
|
|
976
|
+
"MAX_CONTRACT_SIZE",
|
|
977
|
+
"MixinTypedContractEvents",
|
|
978
|
+
"ProtocolContractEventCallbacks",
|
|
979
|
+
# Re-exported from omnibase_core for convenience
|
|
980
|
+
"ModelContractDeregisteredEvent",
|
|
981
|
+
"ModelContractRegisteredEvent",
|
|
982
|
+
"TOPIC_SUFFIX_CONTRACT_DEREGISTERED",
|
|
983
|
+
"TOPIC_SUFFIX_CONTRACT_REGISTERED",
|
|
984
|
+
]
|