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,750 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Handler Contract Source for Filesystem Discovery.
|
|
4
|
+
|
|
5
|
+
This module provides HandlerContractSource, which discovers handler contracts
|
|
6
|
+
from the filesystem by recursively scanning configured paths for
|
|
7
|
+
handler_contract.yaml files, parsing them, and transforming them into
|
|
8
|
+
ModelHandlerDescriptor instances wrapped in ModelContractDiscoveryResult.
|
|
9
|
+
|
|
10
|
+
Part of OMN-1097: HandlerContractSource + Filesystem Discovery.
|
|
11
|
+
|
|
12
|
+
The source implements ProtocolContractSource and supports two operation modes:
|
|
13
|
+
- Strict mode (default): Raises on first error encountered
|
|
14
|
+
- Graceful mode: Collects errors, continues discovery
|
|
15
|
+
|
|
16
|
+
Both modes return ModelContractDiscoveryResult for a consistent interface.
|
|
17
|
+
In strict mode, validation_errors will be empty since errors raise exceptions.
|
|
18
|
+
|
|
19
|
+
See Also:
|
|
20
|
+
- ProtocolContractSource: Protocol definition for handler sources
|
|
21
|
+
- ModelHandlerContract: Contract model from omnibase_core
|
|
22
|
+
- ModelHandlerValidationError: Structured error model for validation failures
|
|
23
|
+
- ModelContractDiscoveryResult: Result model containing descriptors and errors
|
|
24
|
+
|
|
25
|
+
.. versionadded:: 0.6.2
|
|
26
|
+
Created as part of OMN-1097 filesystem handler discovery.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import logging
|
|
32
|
+
import time
|
|
33
|
+
from pathlib import Path
|
|
34
|
+
from typing import cast
|
|
35
|
+
|
|
36
|
+
import yaml
|
|
37
|
+
from pydantic import ValidationError
|
|
38
|
+
|
|
39
|
+
from omnibase_core.models.contracts.model_handler_contract import ModelHandlerContract
|
|
40
|
+
from omnibase_core.models.errors.model_onex_error import ModelOnexError
|
|
41
|
+
from omnibase_core.models.primitives import ModelSemVer
|
|
42
|
+
from omnibase_infra.enums import EnumHandlerErrorType, EnumHandlerSourceType
|
|
43
|
+
from omnibase_infra.models.errors import ModelHandlerValidationError
|
|
44
|
+
from omnibase_infra.models.handlers import (
|
|
45
|
+
LiteralHandlerKind,
|
|
46
|
+
ModelContractDiscoveryResult,
|
|
47
|
+
ModelHandlerDescriptor,
|
|
48
|
+
ModelHandlerIdentifier,
|
|
49
|
+
)
|
|
50
|
+
from omnibase_infra.runtime.protocol_contract_source import ProtocolContractSource
|
|
51
|
+
|
|
52
|
+
# Forward Reference Resolution:
|
|
53
|
+
# ModelContractDiscoveryResult uses a forward reference to ModelHandlerValidationError.
|
|
54
|
+
# Since we import ModelHandlerValidationError above, we can call model_rebuild() here
|
|
55
|
+
# to resolve the forward reference. This call is idempotent - multiple calls are harmless.
|
|
56
|
+
# This ensures the model is fully defined before we create instances in discover_handlers().
|
|
57
|
+
ModelContractDiscoveryResult.model_rebuild()
|
|
58
|
+
|
|
59
|
+
logger = logging.getLogger(__name__)
|
|
60
|
+
|
|
61
|
+
# File pattern for handler contracts
|
|
62
|
+
HANDLER_CONTRACT_FILENAME = "handler_contract.yaml"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# Maximum contract file size (10MB) to prevent memory exhaustion
|
|
66
|
+
MAX_CONTRACT_SIZE = 10 * 1024 * 1024
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# =============================================================================
|
|
70
|
+
# Module-Level Helper Functions
|
|
71
|
+
# =============================================================================
|
|
72
|
+
#
|
|
73
|
+
# These functions are extracted from HandlerContractSource to reduce method count
|
|
74
|
+
# while maintaining the same functionality. They are pure functions that operate
|
|
75
|
+
# on their inputs without requiring instance state.
|
|
76
|
+
# =============================================================================
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _sanitize_path_for_logging(path: Path) -> str:
|
|
80
|
+
"""Sanitize a file path for safe inclusion in logs and error messages.
|
|
81
|
+
|
|
82
|
+
In production environments, full paths may leak sensitive information
|
|
83
|
+
about directory structure. This function returns only the filename and
|
|
84
|
+
parent directory to provide context without exposing full paths.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
path: The full path to sanitize.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Sanitized path string showing only parent/filename.
|
|
91
|
+
For example: "/home/user/code/handlers/handler_contract.yaml"
|
|
92
|
+
becomes "handlers/handler_contract.yaml".
|
|
93
|
+
"""
|
|
94
|
+
# Return parent directory name + filename for context
|
|
95
|
+
# This provides enough info for debugging without full path exposure
|
|
96
|
+
try:
|
|
97
|
+
return str(Path(path.parent.name) / path.name)
|
|
98
|
+
except (ValueError, AttributeError):
|
|
99
|
+
# Fallback to just filename if parent extraction fails
|
|
100
|
+
return path.name
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _create_parse_error(
|
|
104
|
+
contract_path: Path,
|
|
105
|
+
error: yaml.YAMLError,
|
|
106
|
+
) -> ModelHandlerValidationError:
|
|
107
|
+
"""Create a validation error for YAML parse failures.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
contract_path: Path to the failing contract file.
|
|
111
|
+
error: The YAML parsing error.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
ModelHandlerValidationError with parse error details.
|
|
115
|
+
"""
|
|
116
|
+
handler_identity = ModelHandlerIdentifier.from_handler_id(
|
|
117
|
+
f"unknown@{contract_path.name}"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
return ModelHandlerValidationError(
|
|
121
|
+
error_type=EnumHandlerErrorType.CONTRACT_PARSE_ERROR,
|
|
122
|
+
rule_id="CONTRACT-001",
|
|
123
|
+
handler_identity=handler_identity,
|
|
124
|
+
source_type=EnumHandlerSourceType.CONTRACT,
|
|
125
|
+
message=f"Failed to parse YAML in {_sanitize_path_for_logging(contract_path)}: {error}",
|
|
126
|
+
remediation_hint="Check YAML syntax and ensure proper indentation",
|
|
127
|
+
file_path=str(contract_path),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _create_validation_error(
|
|
132
|
+
contract_path: Path,
|
|
133
|
+
error: ValidationError,
|
|
134
|
+
) -> ModelHandlerValidationError:
|
|
135
|
+
"""Create a validation error for contract validation failures.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
contract_path: Path to the failing contract file.
|
|
139
|
+
error: The Pydantic validation error.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
ModelHandlerValidationError with validation details.
|
|
143
|
+
"""
|
|
144
|
+
handler_identity = ModelHandlerIdentifier.from_handler_id(
|
|
145
|
+
f"unknown@{contract_path.name}"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Extract first error detail for remediation hint
|
|
149
|
+
error_details = error.errors()
|
|
150
|
+
if error_details:
|
|
151
|
+
first_error = error_details[0]
|
|
152
|
+
field_loc = " -> ".join(str(x) for x in first_error.get("loc", ()))
|
|
153
|
+
error_msg = str(first_error.get("msg", "validation failed"))
|
|
154
|
+
else:
|
|
155
|
+
field_loc = "unknown"
|
|
156
|
+
error_msg = "validation failed"
|
|
157
|
+
|
|
158
|
+
return ModelHandlerValidationError(
|
|
159
|
+
error_type=EnumHandlerErrorType.CONTRACT_VALIDATION_ERROR,
|
|
160
|
+
rule_id="CONTRACT-002",
|
|
161
|
+
handler_identity=handler_identity,
|
|
162
|
+
source_type=EnumHandlerSourceType.CONTRACT,
|
|
163
|
+
message=f"Contract validation failed in {_sanitize_path_for_logging(contract_path)}: {error_msg} at {field_loc}",
|
|
164
|
+
remediation_hint=f"Check the '{field_loc}' field in the contract",
|
|
165
|
+
file_path=str(contract_path),
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _create_size_limit_error(
|
|
170
|
+
contract_path: Path,
|
|
171
|
+
file_size: int,
|
|
172
|
+
) -> ModelHandlerValidationError:
|
|
173
|
+
"""Create a validation error for file size limit violations.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
contract_path: Path to the oversized contract file.
|
|
177
|
+
file_size: The actual file size in bytes.
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
ModelHandlerValidationError with size limit details.
|
|
181
|
+
"""
|
|
182
|
+
handler_identity = ModelHandlerIdentifier.from_handler_id(
|
|
183
|
+
f"unknown@{contract_path.name}"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return ModelHandlerValidationError(
|
|
187
|
+
error_type=EnumHandlerErrorType.CONTRACT_VALIDATION_ERROR,
|
|
188
|
+
rule_id="CONTRACT-003",
|
|
189
|
+
handler_identity=handler_identity,
|
|
190
|
+
source_type=EnumHandlerSourceType.CONTRACT,
|
|
191
|
+
message=(
|
|
192
|
+
f"Contract file {_sanitize_path_for_logging(contract_path)} exceeds size limit: "
|
|
193
|
+
f"{file_size} bytes (max: {MAX_CONTRACT_SIZE} bytes)"
|
|
194
|
+
),
|
|
195
|
+
remediation_hint=(
|
|
196
|
+
f"Reduce contract file size to under {MAX_CONTRACT_SIZE // (1024 * 1024)}MB. "
|
|
197
|
+
"Consider splitting into multiple contracts if needed."
|
|
198
|
+
),
|
|
199
|
+
file_path=str(contract_path),
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _create_io_error(
|
|
204
|
+
contract_path: Path,
|
|
205
|
+
error: OSError,
|
|
206
|
+
) -> ModelHandlerValidationError:
|
|
207
|
+
"""Create a validation error for I/O failures.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
contract_path: Path to the contract file that failed to read.
|
|
211
|
+
error: The I/O error encountered.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
ModelHandlerValidationError with I/O error details.
|
|
215
|
+
"""
|
|
216
|
+
handler_identity = ModelHandlerIdentifier.from_handler_id(
|
|
217
|
+
f"unknown@{contract_path.name}"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# OSError.strerror may be None for some error types (e.g., custom subclasses),
|
|
221
|
+
# so use str(error) as a fallback to ensure we always have an error message
|
|
222
|
+
error_message = error.strerror or str(error)
|
|
223
|
+
|
|
224
|
+
return ModelHandlerValidationError(
|
|
225
|
+
error_type=EnumHandlerErrorType.CONTRACT_PARSE_ERROR,
|
|
226
|
+
rule_id="CONTRACT-004",
|
|
227
|
+
handler_identity=handler_identity,
|
|
228
|
+
source_type=EnumHandlerSourceType.CONTRACT,
|
|
229
|
+
message=f"Failed to read contract file: {error_message}",
|
|
230
|
+
remediation_hint="Check file permissions and ensure the file exists",
|
|
231
|
+
file_path=str(contract_path),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _create_version_parse_error(
|
|
236
|
+
contract_path: Path,
|
|
237
|
+
error_message: str,
|
|
238
|
+
) -> ModelHandlerValidationError:
|
|
239
|
+
"""Create a validation error for version string parse failures.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
contract_path: Path to the contract file with invalid version.
|
|
243
|
+
error_message: The error message describing the version parse failure.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
ModelHandlerValidationError with version parse error details.
|
|
247
|
+
"""
|
|
248
|
+
handler_identity = ModelHandlerIdentifier.from_handler_id(
|
|
249
|
+
f"unknown@{contract_path.name}"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
return ModelHandlerValidationError(
|
|
253
|
+
error_type=EnumHandlerErrorType.CONTRACT_VALIDATION_ERROR,
|
|
254
|
+
rule_id="CONTRACT-005",
|
|
255
|
+
handler_identity=handler_identity,
|
|
256
|
+
source_type=EnumHandlerSourceType.CONTRACT,
|
|
257
|
+
message=(
|
|
258
|
+
f"Invalid version string in contract "
|
|
259
|
+
f"{_sanitize_path_for_logging(contract_path)}: {error_message}"
|
|
260
|
+
),
|
|
261
|
+
remediation_hint=(
|
|
262
|
+
"Ensure the 'version' field uses semantic versioning format "
|
|
263
|
+
"(e.g., '1.0.0', '2.1.3-beta.1'). "
|
|
264
|
+
"Version components must be non-negative integers."
|
|
265
|
+
),
|
|
266
|
+
file_path=str(contract_path),
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
# =============================================================================
|
|
271
|
+
# HandlerContractSource Implementation
|
|
272
|
+
# =============================================================================
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
class HandlerContractSource(ProtocolContractSource):
|
|
276
|
+
"""Handler source that discovers contracts from the filesystem.
|
|
277
|
+
|
|
278
|
+
This class implements ProtocolContractSource by recursively scanning
|
|
279
|
+
configured paths for handler_contract.yaml files, parsing them with
|
|
280
|
+
YAML and validating against ModelHandlerContract from omnibase_core.
|
|
281
|
+
|
|
282
|
+
Protocol Compliance:
|
|
283
|
+
This class explicitly inherits from ProtocolContractSource and implements
|
|
284
|
+
all required protocol methods: discover_handlers() async method and
|
|
285
|
+
source_type property. Protocol compliance is verified at runtime through
|
|
286
|
+
Python's structural subtyping and enforced by type checkers (mypy/pyright).
|
|
287
|
+
|
|
288
|
+
The source supports two operation modes:
|
|
289
|
+
- Strict mode (default): Raises ModelOnexError on first error
|
|
290
|
+
- Graceful mode: Collects all errors, continues discovery
|
|
291
|
+
|
|
292
|
+
Both modes return ModelContractDiscoveryResult for a consistent interface.
|
|
293
|
+
In strict mode, validation_errors will always be empty since errors raise
|
|
294
|
+
exceptions instead of being collected.
|
|
295
|
+
|
|
296
|
+
Attributes:
|
|
297
|
+
source_type: Returns "CONTRACT" as the source type identifier.
|
|
298
|
+
|
|
299
|
+
Example:
|
|
300
|
+
>>> # Strict mode discovery (raises on error)
|
|
301
|
+
>>> source = HandlerContractSource(contract_paths=[Path("./handlers")])
|
|
302
|
+
>>> result = await source.discover_handlers()
|
|
303
|
+
>>> print(f"Found {len(result.descriptors)} handlers")
|
|
304
|
+
>>> # result.validation_errors is always empty in strict mode
|
|
305
|
+
|
|
306
|
+
>>> # Graceful mode with error collection
|
|
307
|
+
>>> source = HandlerContractSource(
|
|
308
|
+
... contract_paths=[Path("./handlers")],
|
|
309
|
+
... graceful_mode=True,
|
|
310
|
+
... )
|
|
311
|
+
>>> result = await source.discover_handlers()
|
|
312
|
+
>>> print(f"Found {len(result.descriptors)} handlers")
|
|
313
|
+
>>> print(f"Encountered {len(result.validation_errors)} errors")
|
|
314
|
+
|
|
315
|
+
Performance Characteristics:
|
|
316
|
+
- File system scanning is O(n) where n is total files in paths
|
|
317
|
+
- YAML parsing is synchronous (consider aiofiles for high-throughput)
|
|
318
|
+
- Typical performance: 100-500 contracts/second on SSD
|
|
319
|
+
- Memory: ~1KB per contract descriptor retained
|
|
320
|
+
|
|
321
|
+
.. versionadded:: 0.6.2
|
|
322
|
+
Created as part of OMN-1097 filesystem handler discovery.
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
def __init__(
|
|
326
|
+
self,
|
|
327
|
+
contract_paths: list[Path],
|
|
328
|
+
graceful_mode: bool = False,
|
|
329
|
+
) -> None:
|
|
330
|
+
"""Initialize the handler contract source.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
contract_paths: List of paths to scan for handler_contract.yaml files.
|
|
334
|
+
Must not be empty.
|
|
335
|
+
graceful_mode: If True, collect errors and continue discovery.
|
|
336
|
+
If False (default), raise on first error.
|
|
337
|
+
|
|
338
|
+
Raises:
|
|
339
|
+
ModelOnexError: If contract_paths is empty.
|
|
340
|
+
"""
|
|
341
|
+
if not contract_paths:
|
|
342
|
+
raise ModelOnexError(
|
|
343
|
+
"contract_paths is required and cannot be empty",
|
|
344
|
+
error_code="HANDLER_SOURCE_001",
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
self._contract_paths = contract_paths
|
|
348
|
+
self._graceful_mode = graceful_mode
|
|
349
|
+
|
|
350
|
+
@property
|
|
351
|
+
def source_type(self) -> str:
|
|
352
|
+
"""Return the source type identifier.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
"CONTRACT" as the source type.
|
|
356
|
+
"""
|
|
357
|
+
return "CONTRACT"
|
|
358
|
+
|
|
359
|
+
async def discover_handlers(
|
|
360
|
+
self,
|
|
361
|
+
) -> ModelContractDiscoveryResult:
|
|
362
|
+
"""Discover handler contracts from configured paths.
|
|
363
|
+
|
|
364
|
+
Recursively scans all configured paths for handler_contract.yaml files,
|
|
365
|
+
parses them, validates against ModelHandlerContract, and transforms
|
|
366
|
+
them into ModelHandlerDescriptor instances.
|
|
367
|
+
|
|
368
|
+
In strict mode (default), raises on the first error encountered.
|
|
369
|
+
In graceful mode, collects all errors and continues discovery.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
ModelContractDiscoveryResult containing discovered descriptors and
|
|
373
|
+
any validation errors. In strict mode, validation_errors will be
|
|
374
|
+
empty (errors raise exceptions instead of being collected).
|
|
375
|
+
|
|
376
|
+
Raises:
|
|
377
|
+
ModelOnexError: In strict mode, if a path doesn't exist or
|
|
378
|
+
a contract fails to parse/validate.
|
|
379
|
+
|
|
380
|
+
Performance:
|
|
381
|
+
Discovery is synchronous and scales linearly with the number
|
|
382
|
+
of files. Telemetry is logged including duration_seconds and
|
|
383
|
+
contracts_per_second for monitoring.
|
|
384
|
+
"""
|
|
385
|
+
start_time = time.perf_counter()
|
|
386
|
+
descriptors: list[ModelHandlerDescriptor] = []
|
|
387
|
+
validation_errors: list[ModelHandlerValidationError] = []
|
|
388
|
+
# Track discovered files to avoid duplicates when paths overlap
|
|
389
|
+
discovered_paths: set[Path] = set()
|
|
390
|
+
|
|
391
|
+
logger.debug(
|
|
392
|
+
"Starting handler contract discovery",
|
|
393
|
+
extra={
|
|
394
|
+
"paths_scanned": len(self._contract_paths),
|
|
395
|
+
"graceful_mode": self._graceful_mode,
|
|
396
|
+
"contract_paths": [str(p) for p in self._contract_paths],
|
|
397
|
+
},
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
for base_path in self._contract_paths:
|
|
401
|
+
# Check if path exists (strict mode raises, graceful collects)
|
|
402
|
+
if not base_path.exists():
|
|
403
|
+
error_msg = f"Contract path does not exist: {base_path}"
|
|
404
|
+
if not self._graceful_mode:
|
|
405
|
+
raise ModelOnexError(
|
|
406
|
+
error_msg,
|
|
407
|
+
error_code="HANDLER_SOURCE_002",
|
|
408
|
+
)
|
|
409
|
+
# In graceful mode, log and continue
|
|
410
|
+
logger.warning(
|
|
411
|
+
"Contract path does not exist, skipping: %s",
|
|
412
|
+
base_path,
|
|
413
|
+
extra={
|
|
414
|
+
"path": str(base_path),
|
|
415
|
+
"graceful_mode": self._graceful_mode,
|
|
416
|
+
"paths_scanned": len(self._contract_paths),
|
|
417
|
+
},
|
|
418
|
+
)
|
|
419
|
+
continue
|
|
420
|
+
|
|
421
|
+
# Discover contract files
|
|
422
|
+
contract_files = self._find_contract_files(base_path)
|
|
423
|
+
logger.debug(
|
|
424
|
+
"Scanned path for contracts: %s",
|
|
425
|
+
base_path,
|
|
426
|
+
extra={
|
|
427
|
+
"base_path": str(base_path),
|
|
428
|
+
"contracts_found": len(contract_files),
|
|
429
|
+
"graceful_mode": self._graceful_mode,
|
|
430
|
+
"paths_scanned": len(self._contract_paths),
|
|
431
|
+
},
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
for contract_file in contract_files:
|
|
435
|
+
# Deduplicate using resolved path to handle overlapping search paths
|
|
436
|
+
resolved_path = contract_file.resolve()
|
|
437
|
+
if resolved_path in discovered_paths:
|
|
438
|
+
continue
|
|
439
|
+
|
|
440
|
+
# Symlink protection: verify resolved path is within configured paths
|
|
441
|
+
# This prevents symlink-based path traversal attacks where a symlink
|
|
442
|
+
# inside a configured path points to files outside allowed directories
|
|
443
|
+
is_within_allowed = any(
|
|
444
|
+
resolved_path.is_relative_to(base.resolve())
|
|
445
|
+
for base in self._contract_paths
|
|
446
|
+
)
|
|
447
|
+
if not is_within_allowed:
|
|
448
|
+
logger.warning(
|
|
449
|
+
"Skipping contract file outside allowed paths: %s (resolved to %s)",
|
|
450
|
+
contract_file,
|
|
451
|
+
resolved_path,
|
|
452
|
+
extra={
|
|
453
|
+
"contract_file": str(contract_file),
|
|
454
|
+
"resolved_path": str(resolved_path),
|
|
455
|
+
"graceful_mode": self._graceful_mode,
|
|
456
|
+
"reason": "symlink_outside_allowed_paths",
|
|
457
|
+
},
|
|
458
|
+
)
|
|
459
|
+
continue
|
|
460
|
+
|
|
461
|
+
discovered_paths.add(resolved_path)
|
|
462
|
+
|
|
463
|
+
try:
|
|
464
|
+
descriptor = self._parse_contract_file(contract_file)
|
|
465
|
+
descriptors.append(descriptor)
|
|
466
|
+
logger.debug(
|
|
467
|
+
"Successfully parsed contract: %s",
|
|
468
|
+
contract_file,
|
|
469
|
+
extra={
|
|
470
|
+
"contract_file": str(contract_file),
|
|
471
|
+
"handler_id": descriptor.handler_id,
|
|
472
|
+
"handler_name": descriptor.name,
|
|
473
|
+
"handler_version": descriptor.version,
|
|
474
|
+
"graceful_mode": self._graceful_mode,
|
|
475
|
+
},
|
|
476
|
+
)
|
|
477
|
+
except yaml.YAMLError as e:
|
|
478
|
+
error = _create_parse_error(contract_file, e)
|
|
479
|
+
if not self._graceful_mode:
|
|
480
|
+
raise ModelOnexError(
|
|
481
|
+
f"Failed to parse YAML contract at {contract_file}: {e}",
|
|
482
|
+
error_code="HANDLER_SOURCE_003",
|
|
483
|
+
) from e
|
|
484
|
+
logger.warning(
|
|
485
|
+
"Failed to parse YAML contract in %s, continuing in graceful mode",
|
|
486
|
+
_sanitize_path_for_logging(contract_file),
|
|
487
|
+
extra={
|
|
488
|
+
"contract_file": str(contract_file),
|
|
489
|
+
"error_type": "yaml_parse_error",
|
|
490
|
+
"graceful_mode": self._graceful_mode,
|
|
491
|
+
"paths_scanned": len(self._contract_paths),
|
|
492
|
+
},
|
|
493
|
+
)
|
|
494
|
+
validation_errors.append(error)
|
|
495
|
+
except ValidationError as e:
|
|
496
|
+
error = _create_validation_error(contract_file, e)
|
|
497
|
+
if not self._graceful_mode:
|
|
498
|
+
raise ModelOnexError(
|
|
499
|
+
f"Contract validation failed at {contract_file}: {e}",
|
|
500
|
+
error_code="HANDLER_SOURCE_004",
|
|
501
|
+
) from e
|
|
502
|
+
logger.warning(
|
|
503
|
+
"Contract validation failed in %s, continuing in graceful mode",
|
|
504
|
+
_sanitize_path_for_logging(contract_file),
|
|
505
|
+
extra={
|
|
506
|
+
"contract_file": str(contract_file),
|
|
507
|
+
"error_type": "validation_error",
|
|
508
|
+
"error_count": len(e.errors()),
|
|
509
|
+
"graceful_mode": self._graceful_mode,
|
|
510
|
+
"paths_scanned": len(self._contract_paths),
|
|
511
|
+
},
|
|
512
|
+
)
|
|
513
|
+
validation_errors.append(error)
|
|
514
|
+
except ModelOnexError as e:
|
|
515
|
+
# Handle known ModelOnexError types in graceful mode
|
|
516
|
+
if not self._graceful_mode:
|
|
517
|
+
raise
|
|
518
|
+
|
|
519
|
+
# Handle specific error codes gracefully:
|
|
520
|
+
# - HANDLER_SOURCE_005: File size limit exceeded
|
|
521
|
+
# - HANDLER_SOURCE_007: Invalid version string
|
|
522
|
+
# Other ModelOnexError types should be re-raised as they may indicate
|
|
523
|
+
# more serious issues (e.g., configuration errors, programming errors)
|
|
524
|
+
# Defensive check: error_code should always exist on ModelOnexError,
|
|
525
|
+
# but handle the case where it might be None
|
|
526
|
+
error_code = getattr(e, "error_code", None)
|
|
527
|
+
if error_code == "HANDLER_SOURCE_005":
|
|
528
|
+
# Get file size defensively - the original stat() that triggered
|
|
529
|
+
# this error may have succeeded, but the file could have changed
|
|
530
|
+
# (TOCTOU race). Use 0 as fallback if stat() fails now.
|
|
531
|
+
try:
|
|
532
|
+
file_size = contract_file.stat().st_size
|
|
533
|
+
except OSError:
|
|
534
|
+
file_size = 0 # File may have been deleted/changed
|
|
535
|
+
error = _create_size_limit_error(
|
|
536
|
+
contract_file,
|
|
537
|
+
file_size,
|
|
538
|
+
)
|
|
539
|
+
logger.warning(
|
|
540
|
+
"Contract file %s exceeds size limit, continuing in graceful mode",
|
|
541
|
+
_sanitize_path_for_logging(contract_file),
|
|
542
|
+
extra={
|
|
543
|
+
"contract_file": str(contract_file),
|
|
544
|
+
"error_type": "size_limit_error",
|
|
545
|
+
"error_code": error_code,
|
|
546
|
+
"graceful_mode": self._graceful_mode,
|
|
547
|
+
"paths_scanned": len(self._contract_paths),
|
|
548
|
+
},
|
|
549
|
+
)
|
|
550
|
+
validation_errors.append(error)
|
|
551
|
+
elif error_code == "HANDLER_SOURCE_007":
|
|
552
|
+
# Invalid version string - extract version from error message
|
|
553
|
+
error = _create_version_parse_error(
|
|
554
|
+
contract_file,
|
|
555
|
+
str(e),
|
|
556
|
+
)
|
|
557
|
+
logger.warning(
|
|
558
|
+
"Contract file %s has invalid version string, "
|
|
559
|
+
"continuing in graceful mode",
|
|
560
|
+
_sanitize_path_for_logging(contract_file),
|
|
561
|
+
extra={
|
|
562
|
+
"contract_file": str(contract_file),
|
|
563
|
+
"error_type": "version_parse_error",
|
|
564
|
+
"error_code": error_code,
|
|
565
|
+
"error_message": str(e),
|
|
566
|
+
"graceful_mode": self._graceful_mode,
|
|
567
|
+
"paths_scanned": len(self._contract_paths),
|
|
568
|
+
},
|
|
569
|
+
)
|
|
570
|
+
validation_errors.append(error)
|
|
571
|
+
else:
|
|
572
|
+
# Re-raise unexpected ModelOnexError types even in graceful mode
|
|
573
|
+
# These may indicate configuration or programming errors
|
|
574
|
+
raise
|
|
575
|
+
except OSError as e:
|
|
576
|
+
# Handle file I/O errors (permission denied, file not found, etc.)
|
|
577
|
+
if not self._graceful_mode:
|
|
578
|
+
raise ModelOnexError(
|
|
579
|
+
f"Failed to read contract file at {contract_file}: {e}",
|
|
580
|
+
error_code="HANDLER_SOURCE_006",
|
|
581
|
+
) from e
|
|
582
|
+
error = _create_io_error(contract_file, e)
|
|
583
|
+
logger.warning(
|
|
584
|
+
"Failed to read contract file, continuing in graceful mode: %s",
|
|
585
|
+
_sanitize_path_for_logging(contract_file),
|
|
586
|
+
extra={
|
|
587
|
+
"contract_file": str(contract_file),
|
|
588
|
+
"error_type": "io_error",
|
|
589
|
+
"error_message": str(e),
|
|
590
|
+
"graceful_mode": self._graceful_mode,
|
|
591
|
+
},
|
|
592
|
+
)
|
|
593
|
+
validation_errors.append(error)
|
|
594
|
+
|
|
595
|
+
# Calculate duration and log results
|
|
596
|
+
duration_seconds = time.perf_counter() - start_time
|
|
597
|
+
self._log_discovery_results(
|
|
598
|
+
len(descriptors), len(validation_errors), duration_seconds
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
return ModelContractDiscoveryResult(
|
|
602
|
+
descriptors=descriptors,
|
|
603
|
+
validation_errors=validation_errors,
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
def _find_contract_files(self, base_path: Path) -> list[Path]:
|
|
607
|
+
"""Find all handler_contract.yaml files under a base path.
|
|
608
|
+
|
|
609
|
+
Args:
|
|
610
|
+
base_path: Directory to scan recursively.
|
|
611
|
+
|
|
612
|
+
Returns:
|
|
613
|
+
List of paths to handler_contract.yaml files.
|
|
614
|
+
"""
|
|
615
|
+
if base_path.is_file():
|
|
616
|
+
# Exact case-sensitive match for file names
|
|
617
|
+
if base_path.name == HANDLER_CONTRACT_FILENAME:
|
|
618
|
+
return [base_path]
|
|
619
|
+
return []
|
|
620
|
+
|
|
621
|
+
# Use rglob and filter for exact case-sensitive match
|
|
622
|
+
# This ensures we don't pick up HANDLER_CONTRACT.yaml or handler_contract.yml
|
|
623
|
+
return [
|
|
624
|
+
f
|
|
625
|
+
for f in base_path.rglob(HANDLER_CONTRACT_FILENAME)
|
|
626
|
+
if f.name == HANDLER_CONTRACT_FILENAME
|
|
627
|
+
]
|
|
628
|
+
|
|
629
|
+
def _parse_contract_file(self, contract_path: Path) -> ModelHandlerDescriptor:
|
|
630
|
+
"""Parse a contract file and return a descriptor.
|
|
631
|
+
|
|
632
|
+
Args:
|
|
633
|
+
contract_path: Path to the handler_contract.yaml file.
|
|
634
|
+
|
|
635
|
+
Returns:
|
|
636
|
+
ModelHandlerDescriptor created from the contract.
|
|
637
|
+
|
|
638
|
+
Raises:
|
|
639
|
+
ModelOnexError: If contract file exceeds MAX_CONTRACT_SIZE (10MB),
|
|
640
|
+
or if the version string in the contract is invalid.
|
|
641
|
+
yaml.YAMLError: If YAML parsing fails.
|
|
642
|
+
ValidationError: If contract validation fails.
|
|
643
|
+
"""
|
|
644
|
+
# TODO [OMN-1352]: Replace direct file I/O with FileRegistry abstraction
|
|
645
|
+
#
|
|
646
|
+
# Why direct file operations are used here:
|
|
647
|
+
# RegistryFileBased (or FileRegistry) does not yet exist in omnibase_core.
|
|
648
|
+
# This is a temporary implementation that will be replaced once the
|
|
649
|
+
# registry abstraction is available, providing:
|
|
650
|
+
# - Consistent file loading across the codebase
|
|
651
|
+
# - Caching and performance optimizations
|
|
652
|
+
# - Unified error handling for file operations
|
|
653
|
+
#
|
|
654
|
+
# See: docs/architecture/RUNTIME_HOST_IMPLEMENTATION_PLAN.md
|
|
655
|
+
|
|
656
|
+
# Validate file size before reading to prevent memory exhaustion
|
|
657
|
+
file_size = contract_path.stat().st_size
|
|
658
|
+
if file_size > MAX_CONTRACT_SIZE:
|
|
659
|
+
raise ModelOnexError(
|
|
660
|
+
f"Contract file exceeds size limit: {file_size} bytes "
|
|
661
|
+
f"(max: {MAX_CONTRACT_SIZE} bytes)",
|
|
662
|
+
error_code="HANDLER_SOURCE_005",
|
|
663
|
+
)
|
|
664
|
+
|
|
665
|
+
with contract_path.open("r", encoding="utf-8") as f:
|
|
666
|
+
raw_data = yaml.safe_load(f)
|
|
667
|
+
|
|
668
|
+
# Validate against ModelHandlerContract
|
|
669
|
+
contract = ModelHandlerContract.model_validate(raw_data)
|
|
670
|
+
|
|
671
|
+
# TODO [OMN-1420]: Extract handler_class from ModelHandlerContract
|
|
672
|
+
#
|
|
673
|
+
# handler_contract.yaml files include a `handler_class` field for dynamic import
|
|
674
|
+
# (e.g., "omnibase_infra.handlers.handler_consul.HandlerConsul"), but
|
|
675
|
+
# ModelHandlerContract from omnibase_core does not have this field yet.
|
|
676
|
+
#
|
|
677
|
+
# Once ModelHandlerContract is updated to include handler_class, this code
|
|
678
|
+
# should be changed from:
|
|
679
|
+
# handler_class=raw_data.get("handler_class")
|
|
680
|
+
# to:
|
|
681
|
+
# handler_class=contract.handler_class
|
|
682
|
+
#
|
|
683
|
+
# For now, extract directly from raw YAML data to support dynamic handler loading.
|
|
684
|
+
# See: https://linear.app/omninode/issue/OMN-1420
|
|
685
|
+
handler_class = (
|
|
686
|
+
raw_data.get("handler_class") if isinstance(raw_data, dict) else None
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
# Use contract_version directly - it's already a ModelSemVer from Pydantic validation
|
|
690
|
+
# Transform to descriptor
|
|
691
|
+
return ModelHandlerDescriptor(
|
|
692
|
+
handler_id=contract.handler_id,
|
|
693
|
+
name=contract.name,
|
|
694
|
+
version=contract.contract_version,
|
|
695
|
+
handler_kind=cast(
|
|
696
|
+
"LiteralHandlerKind", contract.descriptor.node_archetype.value
|
|
697
|
+
),
|
|
698
|
+
input_model=contract.input_model,
|
|
699
|
+
output_model=contract.output_model,
|
|
700
|
+
description=contract.description,
|
|
701
|
+
handler_class=handler_class,
|
|
702
|
+
contract_path=str(contract_path),
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
def _log_discovery_results(
|
|
706
|
+
self,
|
|
707
|
+
discovered_count: int,
|
|
708
|
+
failure_count: int,
|
|
709
|
+
duration_seconds: float,
|
|
710
|
+
) -> None:
|
|
711
|
+
"""Log the discovery results with structured counts and timing.
|
|
712
|
+
|
|
713
|
+
Args:
|
|
714
|
+
discovered_count: Number of successfully discovered contracts.
|
|
715
|
+
failure_count: Number of validation failures.
|
|
716
|
+
duration_seconds: Total discovery duration in seconds.
|
|
717
|
+
"""
|
|
718
|
+
contracts_per_sec = (
|
|
719
|
+
discovered_count / duration_seconds if duration_seconds > 0 else 0.0
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
logger.info(
|
|
723
|
+
"Handler contract discovery completed: "
|
|
724
|
+
"discovered_contract_count=%d, validation_failure_count=%d, "
|
|
725
|
+
"paths_scanned=%d, graceful_mode=%s, "
|
|
726
|
+
"duration_seconds=%.3f, contracts_per_second=%.1f",
|
|
727
|
+
discovered_count,
|
|
728
|
+
failure_count,
|
|
729
|
+
len(self._contract_paths),
|
|
730
|
+
self._graceful_mode,
|
|
731
|
+
duration_seconds,
|
|
732
|
+
contracts_per_sec,
|
|
733
|
+
extra={
|
|
734
|
+
"discovered_contract_count": discovered_count,
|
|
735
|
+
"validation_failure_count": failure_count,
|
|
736
|
+
"paths_scanned": len(self._contract_paths),
|
|
737
|
+
"graceful_mode": self._graceful_mode,
|
|
738
|
+
"contract_paths": [str(p) for p in self._contract_paths],
|
|
739
|
+
"duration_seconds": duration_seconds,
|
|
740
|
+
"contracts_per_second": contracts_per_sec,
|
|
741
|
+
},
|
|
742
|
+
)
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
__all__ = [
|
|
746
|
+
"HandlerContractSource",
|
|
747
|
+
"MAX_CONTRACT_SIZE",
|
|
748
|
+
"ModelContractDiscoveryResult",
|
|
749
|
+
"ModelHandlerDescriptor",
|
|
750
|
+
]
|