omnibase_infra 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omnibase_infra/__init__.py +101 -0
- omnibase_infra/cli/__init__.py +1 -0
- omnibase_infra/cli/commands.py +216 -0
- omnibase_infra/clients/__init__.py +0 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +261 -0
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +138 -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 +123 -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_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 +101 -0
- omnibase_infra/enums/enum_handler_loader_error.py +178 -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_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 +156 -0
- omnibase_infra/errors/error_architecture_violation.py +152 -0
- omnibase_infra/errors/error_chain_propagation.py +188 -0
- omnibase_infra/errors/error_compute_registry.py +92 -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 +102 -0
- omnibase_infra/errors/error_infra.py +608 -0
- omnibase_infra/errors/error_message_type_registry.py +101 -0
- omnibase_infra/errors/error_policy_registry.py +112 -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 +86 -0
- omnibase_infra/event_bus/event_bus_inmemory.py +743 -0
- omnibase_infra/event_bus/event_bus_kafka.py +1658 -0
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +184 -0
- omnibase_infra/event_bus/mixin_kafka_dlq.py +765 -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 +725 -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/topic_constants.py +376 -0
- omnibase_infra/handlers/__init__.py +75 -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 +787 -0
- omnibase_infra/handlers/handler_db.py +1039 -0
- omnibase_infra/handlers/handler_filesystem.py +1478 -0
- omnibase_infra/handlers/handler_graph.py +1154 -0
- omnibase_infra/handlers/handler_http.py +920 -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 +748 -0
- omnibase_infra/handlers/handler_qdrant.py +1076 -0
- omnibase_infra/handlers/handler_vault.py +422 -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 +42 -0
- omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +337 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +277 -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 +915 -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 +747 -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 +99 -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/mixins/__init__.py +71 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +655 -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 +2465 -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 +136 -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 +311 -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 +147 -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_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 +37 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +80 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +185 -0
- omnibase_infra/models/handlers/model_handler_identifier.py +215 -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/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 +590 -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 +59 -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_introspection_metrics.py +253 -0
- omnibase_infra/models/registration/model_node_capabilities.py +179 -0
- omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +175 -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 +40 -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 +280 -0
- omnibase_infra/models/runtime/model_loaded_handler.py +120 -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 +48 -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 +208 -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 +99 -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/effects/README.md +358 -0
- omnibase_infra/nodes/effects/__init__.py +26 -0
- omnibase_infra/nodes/effects/contract.yaml +172 -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/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 +475 -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 +609 -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 +525 -0
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +392 -0
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +742 -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 +225 -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 +109 -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 +194 -0
- omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
- omnibase_infra/nodes/node_registry_effect/contract.yaml +682 -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 +416 -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 +214 -0
- omnibase_infra/nodes/reducers/__init__.py +30 -0
- omnibase_infra/nodes/reducers/models/__init__.py +32 -0
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +76 -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 +1137 -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 +435 -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 +99 -0
- omnibase_infra/protocols/protocol_capability_projection.py +253 -0
- omnibase_infra/protocols/protocol_capability_query.py +251 -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 +296 -0
- omnibase_infra/runtime/binding_config_resolver.py +2706 -0
- omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
- omnibase_infra/runtime/contract_handler_discovery.py +582 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +42 -0
- omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
- omnibase_infra/runtime/dispatch_context_enforcer.py +427 -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/handler_contract_source.py +669 -0
- omnibase_infra/runtime/handler_plugin_loader.py +2029 -0
- omnibase_infra/runtime/handler_registry.py +321 -0
- omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
- omnibase_infra/runtime/kernel.py +40 -0
- omnibase_infra/runtime/mixin_policy_validation.py +522 -0
- omnibase_infra/runtime/mixin_semver_cache.py +378 -0
- omnibase_infra/runtime/mixins/__init__.py +17 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +757 -0
- omnibase_infra/runtime/models/__init__.py +192 -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_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 +228 -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_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_scheduler_config.py +624 -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_shutdown_batch_result.py +75 -0
- omnibase_infra/runtime/models/model_shutdown_config.py +94 -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 +1102 -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 +27 -0
- omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -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 +444 -0
- omnibase_infra/runtime/registry_compute.py +1143 -0
- omnibase_infra/runtime/registry_dispatcher.py +678 -0
- omnibase_infra/runtime/registry_policy.py +1502 -0
- omnibase_infra/runtime/runtime_scheduler.py +1070 -0
- omnibase_infra/runtime/secret_resolver.py +2110 -0
- omnibase_infra/runtime/security_metadata_validator.py +776 -0
- omnibase_infra/runtime/service_kernel.py +1573 -0
- omnibase_infra/runtime/service_message_dispatch_engine.py +1805 -0
- omnibase_infra/runtime/service_runtime_host_process.py +2260 -0
- omnibase_infra/runtime/util_container_wiring.py +1123 -0
- omnibase_infra/runtime/util_validation.py +314 -0
- omnibase_infra/runtime/util_version.py +98 -0
- omnibase_infra/runtime/util_wiring.py +566 -0
- omnibase_infra/schemas/schema_registration_projection.sql +320 -0
- omnibase_infra/services/__init__.py +68 -0
- omnibase_infra/services/corpus_capture.py +678 -0
- omnibase_infra/services/service_capability_query.py +945 -0
- omnibase_infra/services/service_health.py +897 -0
- omnibase_infra/services/service_node_selector.py +530 -0
- omnibase_infra/services/service_timeout_emitter.py +682 -0
- omnibase_infra/services/service_timeout_scanner.py +390 -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/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 +21 -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 +89 -0
- omnibase_infra/utils/correlation.py +208 -0
- omnibase_infra/utils/util_datetime.py +372 -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_semver.py +233 -0
- omnibase_infra/validation/__init__.py +307 -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 +1486 -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 +1710 -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 +410 -0
- omnibase_infra/validation/validator_topic_category.py +1152 -0
- omnibase_infra-0.2.1.dist-info/METADATA +197 -0
- omnibase_infra-0.2.1.dist-info/RECORD +675 -0
- omnibase_infra-0.2.1.dist-info/WHEEL +4 -0
- omnibase_infra-0.2.1.dist-info/entry_points.txt +4 -0
- omnibase_infra-0.2.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Chain Propagation Validator for Correlation and Causation Chain Validation.
|
|
4
|
+
|
|
5
|
+
Validates that messages properly maintain correlation and causation chains
|
|
6
|
+
during propagation through the ONEX event-driven system. This ensures
|
|
7
|
+
workflow traceability and supports distributed debugging.
|
|
8
|
+
|
|
9
|
+
Design Principles:
|
|
10
|
+
- **Workflow Traceability**: All messages in a workflow share the same
|
|
11
|
+
correlation_id for end-to-end trace visibility.
|
|
12
|
+
- **Causation Chain Integrity**: Each message's causation_id must reference
|
|
13
|
+
its direct parent's message_id, forming an unbroken lineage.
|
|
14
|
+
- **Fail-Open Architecture**: Follows ONEX validation philosophy - validation
|
|
15
|
+
failures are reported but don't block by default. Use enforce_chain_propagation()
|
|
16
|
+
for strict enforcement.
|
|
17
|
+
|
|
18
|
+
Chain Rules:
|
|
19
|
+
1. **Correlation Propagation**: Child messages must inherit the parent's
|
|
20
|
+
correlation_id exactly. A mismatch breaks trace correlation.
|
|
21
|
+
2. **Causation Chain**: Every produced message's causation_id must equal
|
|
22
|
+
its direct parent's message_id. This creates parent-child relationships.
|
|
23
|
+
3. **No Skipped Ancestors** (strict mode only): In strict pairwise validation
|
|
24
|
+
via ``validate_chain()``, causation chains must be continuous - a message
|
|
25
|
+
cannot skip its direct parent to reference a grandparent.
|
|
26
|
+
|
|
27
|
+
Note: ``validate_workflow_chain()`` intentionally relaxes Rule 3 to allow
|
|
28
|
+
ancestor skipping for workflow flexibility (fan-out patterns, aggregation,
|
|
29
|
+
partial chain reconstruction). See its docstring for details.
|
|
30
|
+
|
|
31
|
+
Message ID Semantics:
|
|
32
|
+
In ONEX, the ModelEventEnvelope uses:
|
|
33
|
+
- envelope_id: Unique identifier for each message (serves as message_id)
|
|
34
|
+
- correlation_id: Shared across all messages in a workflow
|
|
35
|
+
- causation_id: Optional field referencing parent's envelope_id
|
|
36
|
+
|
|
37
|
+
For envelopes without an explicit causation_id field, the validator
|
|
38
|
+
checks the metadata for a 'causation_id' key.
|
|
39
|
+
|
|
40
|
+
Causation ID Semantics:
|
|
41
|
+
**Canonical Location**: When producing child messages, set causation_id in
|
|
42
|
+
``metadata.tags["causation_id"]`` as a string UUID. For HTTP transports,
|
|
43
|
+
use ``metadata.headers["x-causation-id"]``.
|
|
44
|
+
|
|
45
|
+
**Why metadata.tags?** The ModelEventEnvelope's metadata.tags dict provides
|
|
46
|
+
a flexible, schema-stable location for tracing metadata.
|
|
47
|
+
|
|
48
|
+
**Producer Responsibility**: When creating a child envelope from a parent:
|
|
49
|
+
|
|
50
|
+
.. code-block:: python
|
|
51
|
+
|
|
52
|
+
child_envelope = ModelEventEnvelope(
|
|
53
|
+
payload=child_payload,
|
|
54
|
+
correlation_id=parent_envelope.correlation_id, # Propagate correlation
|
|
55
|
+
metadata=ModelEventMetadata(
|
|
56
|
+
tags={
|
|
57
|
+
"causation_id": str(parent_envelope.envelope_id), # Canonical
|
|
58
|
+
},
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
Thread Safety:
|
|
63
|
+
The ChainPropagationValidator is stateless and thread-safe. All validation
|
|
64
|
+
methods are pure functions that produce fresh result objects.
|
|
65
|
+
|
|
66
|
+
Typing Note (ModelEventEnvelope[object]):
|
|
67
|
+
Functions in this module use ``ModelEventEnvelope[object]`` instead of ``Any``
|
|
68
|
+
per CLAUDE.md guidance: "Use ``object`` for generic payloads".
|
|
69
|
+
|
|
70
|
+
This is intentional:
|
|
71
|
+
- CLAUDE.md mandates "NEVER use ``Any``" for type annotations
|
|
72
|
+
- Chain validation operates on envelope metadata (correlation_id, causation_id,
|
|
73
|
+
envelope_id), not payload content - the payload type is irrelevant
|
|
74
|
+
- Using ``object`` signals "any object payload" while maintaining type safety
|
|
75
|
+
(unlike ``Any`` which completely disables type checking)
|
|
76
|
+
- Validators that need to inspect payload content should use ``isinstance()``
|
|
77
|
+
type guards for runtime safety
|
|
78
|
+
|
|
79
|
+
Performance Considerations:
|
|
80
|
+
The validator does not cache results. This is an intentional design decision:
|
|
81
|
+
|
|
82
|
+
- **Production Use**: Workflows are validated once per dispatch, making caching
|
|
83
|
+
unnecessary overhead. Each message passes through validation exactly once.
|
|
84
|
+
- **Stateless Design**: Caching would introduce state, complicating thread safety
|
|
85
|
+
and increasing memory footprint without meaningful performance benefit.
|
|
86
|
+
- **Testing/Debugging**: For repeated validation of the same message sets during
|
|
87
|
+
debugging, callers can implement their own memoization if needed.
|
|
88
|
+
|
|
89
|
+
If profiling reveals validation as a bottleneck (unlikely given O(n) complexity),
|
|
90
|
+
consider batching validations rather than adding caching.
|
|
91
|
+
|
|
92
|
+
Usage:
|
|
93
|
+
>>> from omnibase_infra.validation.validator_chain_propagation import (
|
|
94
|
+
... ChainPropagationValidator,
|
|
95
|
+
... validate_message_chain,
|
|
96
|
+
... enforce_chain_propagation,
|
|
97
|
+
... )
|
|
98
|
+
>>> from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
|
|
99
|
+
>>> from uuid import uuid4
|
|
100
|
+
>>>
|
|
101
|
+
>>> # Direct validation
|
|
102
|
+
>>> validator = ChainPropagationValidator()
|
|
103
|
+
>>> violations = validator.validate_chain(parent_envelope, child_envelope)
|
|
104
|
+
>>> if violations:
|
|
105
|
+
... for v in violations:
|
|
106
|
+
... print(v.format_for_logging())
|
|
107
|
+
>>>
|
|
108
|
+
>>> # Strict enforcement
|
|
109
|
+
>>> enforce_chain_propagation(parent_envelope, child_envelope)
|
|
110
|
+
|
|
111
|
+
Related:
|
|
112
|
+
- OMN-951: Enforce Correlation and Causation Chain Validation
|
|
113
|
+
- docs/patterns/correlation_id_tracking.md
|
|
114
|
+
|
|
115
|
+
.. versionadded:: 0.5.0
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
from __future__ import annotations
|
|
119
|
+
|
|
120
|
+
import logging
|
|
121
|
+
from typing import cast
|
|
122
|
+
from uuid import UUID
|
|
123
|
+
|
|
124
|
+
# ModelEventEnvelope is used at runtime in function parameter types, not just for type hints
|
|
125
|
+
from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
|
|
126
|
+
from omnibase_infra.enums import EnumChainViolationType, EnumValidationSeverity
|
|
127
|
+
from omnibase_infra.errors.error_chain_propagation import ChainPropagationError
|
|
128
|
+
from omnibase_infra.models.errors.model_infra_error_context import (
|
|
129
|
+
ModelInfraErrorContext,
|
|
130
|
+
)
|
|
131
|
+
from omnibase_infra.models.validation.model_chain_violation import ModelChainViolation
|
|
132
|
+
|
|
133
|
+
logger = logging.getLogger(__name__)
|
|
134
|
+
|
|
135
|
+
__all__ = [
|
|
136
|
+
"CAUSATION_ID_HEADER_KEYS",
|
|
137
|
+
# Causation ID lookup key constants
|
|
138
|
+
"CAUSATION_ID_TAG_KEYS",
|
|
139
|
+
"ChainPropagationError",
|
|
140
|
+
"ChainPropagationValidator",
|
|
141
|
+
"enforce_chain_propagation",
|
|
142
|
+
"get_causation_id",
|
|
143
|
+
"get_correlation_id",
|
|
144
|
+
# Helper functions for envelope field access
|
|
145
|
+
"get_message_id",
|
|
146
|
+
"validate_linear_message_chain",
|
|
147
|
+
"validate_message_chain",
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
# ==============================================================================
|
|
151
|
+
# Causation ID Lookup Keys
|
|
152
|
+
# ==============================================================================
|
|
153
|
+
# These constants define the keys checked when resolving causation_id from
|
|
154
|
+
# envelope metadata.
|
|
155
|
+
|
|
156
|
+
CAUSATION_ID_TAG_KEYS: tuple[str, ...] = ("causation_id",)
|
|
157
|
+
"""Keys checked in metadata.tags for causation_id.
|
|
158
|
+
|
|
159
|
+
The canonical location for causation_id is metadata.tags["causation_id"].
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
CAUSATION_ID_HEADER_KEYS: tuple[str, ...] = ("x-causation-id",)
|
|
163
|
+
"""Keys checked in metadata.headers for causation_id.
|
|
164
|
+
|
|
165
|
+
The canonical HTTP header for causation_id is "x-causation-id".
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
# ==============================================================================
|
|
169
|
+
# Helper Functions for Envelope Field Access
|
|
170
|
+
# ==============================================================================
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_message_id(envelope: ModelEventEnvelope[object]) -> UUID:
|
|
174
|
+
"""Get the message_id from an envelope.
|
|
175
|
+
|
|
176
|
+
In ONEX, the envelope_id serves as the unique message identifier.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
envelope: The event envelope.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
The envelope's unique identifier (envelope_id).
|
|
183
|
+
"""
|
|
184
|
+
# envelope_id is typed as UUID in ModelEventEnvelope, but mypy sees it as Any
|
|
185
|
+
# due to the generic type parameter. Cast is required for type safety.
|
|
186
|
+
return cast(UUID, envelope.envelope_id)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def get_correlation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
|
|
190
|
+
"""Get the correlation_id from an envelope.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
envelope: The event envelope.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
The envelope's correlation_id, or None if not set.
|
|
197
|
+
"""
|
|
198
|
+
# correlation_id is typed as UUID | None in ModelEventEnvelope, but mypy sees it
|
|
199
|
+
# as Any due to the generic type parameter. Cast is required for type safety.
|
|
200
|
+
correlation_id = envelope.correlation_id
|
|
201
|
+
if correlation_id is None:
|
|
202
|
+
return None
|
|
203
|
+
return cast(UUID, correlation_id)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def get_causation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
|
|
207
|
+
"""Get the causation_id from an envelope.
|
|
208
|
+
|
|
209
|
+
Canonical Locations:
|
|
210
|
+
The **canonical location** for causation_id is ``metadata.tags["causation_id"]``
|
|
211
|
+
stored as a string UUID. When creating child envelopes, producers MUST set
|
|
212
|
+
causation_id in this location for consistency across the ONEX ecosystem.
|
|
213
|
+
|
|
214
|
+
For HTTP transports, use ``metadata.headers["x-causation-id"]``.
|
|
215
|
+
|
|
216
|
+
Example of canonical usage when producing a child message::
|
|
217
|
+
|
|
218
|
+
child_envelope = ModelEventEnvelope(
|
|
219
|
+
# ... other fields ...
|
|
220
|
+
metadata=ModelEventMetadata(
|
|
221
|
+
tags={
|
|
222
|
+
"causation_id": str(parent_envelope.envelope_id),
|
|
223
|
+
},
|
|
224
|
+
),
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
Lookup Order:
|
|
228
|
+
1. **Direct attribute** ``envelope.causation_id`` (UUID) - If envelope
|
|
229
|
+
exposes causation_id as a first-class attribute.
|
|
230
|
+
|
|
231
|
+
2. **Metadata tags** ``metadata.tags["causation_id"]`` (string -> UUID) -
|
|
232
|
+
Canonical location.
|
|
233
|
+
|
|
234
|
+
3. **Metadata headers** ``metadata.headers["x-causation-id"]`` (string -> UUID) -
|
|
235
|
+
Canonical HTTP header.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
envelope: The event envelope.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
The envelope's causation_id, or None if not set in any checked location.
|
|
242
|
+
|
|
243
|
+
See Also:
|
|
244
|
+
- Module docstring "Causation ID Semantics" section for architectural context
|
|
245
|
+
- ``docs/patterns/correlation_id_tracking.md`` for full tracing patterns
|
|
246
|
+
"""
|
|
247
|
+
# Check for direct attribute
|
|
248
|
+
if hasattr(envelope, "causation_id"):
|
|
249
|
+
causation_id = envelope.causation_id
|
|
250
|
+
if isinstance(causation_id, UUID):
|
|
251
|
+
return causation_id
|
|
252
|
+
|
|
253
|
+
# Check metadata for causation_id
|
|
254
|
+
if hasattr(envelope, "metadata") and envelope.metadata is not None:
|
|
255
|
+
metadata = envelope.metadata
|
|
256
|
+
|
|
257
|
+
# Check metadata.tags for causation_id (canonical location)
|
|
258
|
+
if hasattr(metadata, "tags") and metadata.tags:
|
|
259
|
+
tags = metadata.tags
|
|
260
|
+
for key in CAUSATION_ID_TAG_KEYS:
|
|
261
|
+
if key in tags:
|
|
262
|
+
value = tags[key]
|
|
263
|
+
if isinstance(value, UUID):
|
|
264
|
+
return value
|
|
265
|
+
if isinstance(value, str):
|
|
266
|
+
try:
|
|
267
|
+
return UUID(value)
|
|
268
|
+
except ValueError:
|
|
269
|
+
logger.debug(
|
|
270
|
+
"Malformed UUID in tags key '%s': %s",
|
|
271
|
+
key,
|
|
272
|
+
value,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# Check metadata.headers for x-causation-id (HTTP transport)
|
|
276
|
+
if hasattr(metadata, "headers") and metadata.headers:
|
|
277
|
+
headers = metadata.headers
|
|
278
|
+
for key in CAUSATION_ID_HEADER_KEYS:
|
|
279
|
+
if key in headers:
|
|
280
|
+
value = headers[key]
|
|
281
|
+
if isinstance(value, str):
|
|
282
|
+
try:
|
|
283
|
+
return UUID(value)
|
|
284
|
+
except ValueError:
|
|
285
|
+
logger.debug(
|
|
286
|
+
"Malformed UUID in headers key '%s': %s",
|
|
287
|
+
key,
|
|
288
|
+
value,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
return None
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
# ==============================================================================
|
|
295
|
+
# Chain Propagation Validator
|
|
296
|
+
# ==============================================================================
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class ChainPropagationValidator:
|
|
300
|
+
"""Validates correlation and causation chain propagation.
|
|
301
|
+
|
|
302
|
+
Enforces workflow traceability rules:
|
|
303
|
+
1. All messages in a workflow share the same correlation_id
|
|
304
|
+
2. Every produced message has causation_id = parent.message_id
|
|
305
|
+
3. Causation chains are local (no skipping ancestors)
|
|
306
|
+
|
|
307
|
+
Attributes:
|
|
308
|
+
None - the validator is stateless.
|
|
309
|
+
|
|
310
|
+
Thread Safety:
|
|
311
|
+
ChainPropagationValidator instances are stateless and thread-safe.
|
|
312
|
+
All validation methods are pure functions that produce fresh result
|
|
313
|
+
objects. Multiple threads can safely call any validation method on
|
|
314
|
+
the same instance concurrently.
|
|
315
|
+
|
|
316
|
+
Example:
|
|
317
|
+
>>> validator = ChainPropagationValidator()
|
|
318
|
+
>>>
|
|
319
|
+
>>> # Validate single parent-child relationship
|
|
320
|
+
>>> violations = validator.validate_chain(parent, child)
|
|
321
|
+
>>>
|
|
322
|
+
>>> # Validate entire workflow chain
|
|
323
|
+
>>> violations = validator.validate_workflow_chain([msg1, msg2, msg3])
|
|
324
|
+
"""
|
|
325
|
+
|
|
326
|
+
def validate_correlation_propagation(
|
|
327
|
+
self,
|
|
328
|
+
parent_envelope: ModelEventEnvelope[object],
|
|
329
|
+
child_envelope: ModelEventEnvelope[object],
|
|
330
|
+
) -> list[ModelChainViolation]:
|
|
331
|
+
"""Validate that child message inherits parent's correlation_id.
|
|
332
|
+
|
|
333
|
+
All messages in a workflow must share the same correlation_id to
|
|
334
|
+
enable end-to-end distributed tracing. This method checks that
|
|
335
|
+
the child's correlation_id matches the parent's correlation_id.
|
|
336
|
+
|
|
337
|
+
Args:
|
|
338
|
+
parent_envelope: The parent message envelope.
|
|
339
|
+
child_envelope: The child message envelope produced from parent.
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
List containing a single CORRELATION_MISMATCH violation if the
|
|
343
|
+
correlation_ids don't match, or an empty list if valid.
|
|
344
|
+
|
|
345
|
+
Example:
|
|
346
|
+
>>> validator = ChainPropagationValidator()
|
|
347
|
+
>>> violations = validator.validate_correlation_propagation(parent, child)
|
|
348
|
+
>>> if violations:
|
|
349
|
+
... print("Correlation chain broken!")
|
|
350
|
+
"""
|
|
351
|
+
violations: list[ModelChainViolation] = []
|
|
352
|
+
|
|
353
|
+
parent_correlation = get_correlation_id(parent_envelope)
|
|
354
|
+
child_correlation = get_correlation_id(child_envelope)
|
|
355
|
+
|
|
356
|
+
# If parent has a correlation_id, child must have the same
|
|
357
|
+
if parent_correlation is not None:
|
|
358
|
+
if child_correlation is None:
|
|
359
|
+
violations.append(
|
|
360
|
+
ModelChainViolation(
|
|
361
|
+
violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
|
|
362
|
+
expected_value=parent_correlation,
|
|
363
|
+
actual_value=None,
|
|
364
|
+
message_id=get_message_id(child_envelope),
|
|
365
|
+
parent_message_id=get_message_id(parent_envelope),
|
|
366
|
+
violation_message=(
|
|
367
|
+
f"Child message is missing correlation_id but parent has "
|
|
368
|
+
f"correlation_id={parent_correlation}. "
|
|
369
|
+
"All messages in a workflow must share the same correlation_id."
|
|
370
|
+
),
|
|
371
|
+
severity=EnumValidationSeverity.ERROR,
|
|
372
|
+
)
|
|
373
|
+
)
|
|
374
|
+
elif child_correlation != parent_correlation:
|
|
375
|
+
violations.append(
|
|
376
|
+
ModelChainViolation(
|
|
377
|
+
violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
|
|
378
|
+
expected_value=parent_correlation,
|
|
379
|
+
actual_value=child_correlation,
|
|
380
|
+
message_id=get_message_id(child_envelope),
|
|
381
|
+
parent_message_id=get_message_id(parent_envelope),
|
|
382
|
+
violation_message=(
|
|
383
|
+
f"Correlation ID mismatch: expected={parent_correlation}, "
|
|
384
|
+
f"actual={child_correlation}. "
|
|
385
|
+
"All messages in a workflow must share the same correlation_id."
|
|
386
|
+
),
|
|
387
|
+
severity=EnumValidationSeverity.ERROR,
|
|
388
|
+
)
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
return violations
|
|
392
|
+
|
|
393
|
+
def validate_causation_chain(
|
|
394
|
+
self,
|
|
395
|
+
parent_envelope: ModelEventEnvelope[object],
|
|
396
|
+
child_envelope: ModelEventEnvelope[object],
|
|
397
|
+
) -> list[ModelChainViolation]:
|
|
398
|
+
"""Validate that child's causation_id equals parent's message_id.
|
|
399
|
+
|
|
400
|
+
Each message's causation_id must reference its direct parent's
|
|
401
|
+
message_id to form an unbroken lineage back to the workflow origin.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
parent_envelope: The parent message envelope.
|
|
405
|
+
child_envelope: The child message envelope produced from parent.
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
List containing a CAUSATION_CHAIN_BROKEN violation if the
|
|
409
|
+
causation_id doesn't match parent's message_id, or an empty
|
|
410
|
+
list if valid.
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
>>> validator = ChainPropagationValidator()
|
|
414
|
+
>>> violations = validator.validate_causation_chain(parent, child)
|
|
415
|
+
>>> if violations:
|
|
416
|
+
... print("Causation chain broken!")
|
|
417
|
+
"""
|
|
418
|
+
violations: list[ModelChainViolation] = []
|
|
419
|
+
|
|
420
|
+
parent_message_id = get_message_id(parent_envelope)
|
|
421
|
+
child_causation_id = get_causation_id(child_envelope)
|
|
422
|
+
|
|
423
|
+
# Child's causation_id must equal parent's message_id
|
|
424
|
+
if child_causation_id is None:
|
|
425
|
+
# Missing causation_id is a chain break
|
|
426
|
+
violations.append(
|
|
427
|
+
ModelChainViolation(
|
|
428
|
+
violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
|
|
429
|
+
expected_value=parent_message_id,
|
|
430
|
+
actual_value=None,
|
|
431
|
+
message_id=get_message_id(child_envelope),
|
|
432
|
+
parent_message_id=parent_message_id,
|
|
433
|
+
violation_message=(
|
|
434
|
+
f"Child message is missing causation_id. "
|
|
435
|
+
f"Expected causation_id={parent_message_id} (parent's message_id). "
|
|
436
|
+
"Every message must reference its parent's message_id "
|
|
437
|
+
"to maintain causation chain integrity."
|
|
438
|
+
),
|
|
439
|
+
severity=EnumValidationSeverity.ERROR,
|
|
440
|
+
)
|
|
441
|
+
)
|
|
442
|
+
elif child_causation_id != parent_message_id:
|
|
443
|
+
violations.append(
|
|
444
|
+
ModelChainViolation(
|
|
445
|
+
violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
|
|
446
|
+
expected_value=parent_message_id,
|
|
447
|
+
actual_value=child_causation_id,
|
|
448
|
+
message_id=get_message_id(child_envelope),
|
|
449
|
+
parent_message_id=parent_message_id,
|
|
450
|
+
violation_message=(
|
|
451
|
+
f"Causation ID mismatch: expected={parent_message_id}, "
|
|
452
|
+
f"actual={child_causation_id}. "
|
|
453
|
+
"Every message must reference its direct parent's message_id."
|
|
454
|
+
),
|
|
455
|
+
severity=EnumValidationSeverity.ERROR,
|
|
456
|
+
)
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
return violations
|
|
460
|
+
|
|
461
|
+
def validate_chain(
|
|
462
|
+
self,
|
|
463
|
+
parent_envelope: ModelEventEnvelope[object],
|
|
464
|
+
child_envelope: ModelEventEnvelope[object],
|
|
465
|
+
) -> list[ModelChainViolation]:
|
|
466
|
+
"""Validate both correlation and causation chain propagation.
|
|
467
|
+
|
|
468
|
+
Runs both correlation propagation and causation chain validation,
|
|
469
|
+
returning a combined list of all detected violations.
|
|
470
|
+
|
|
471
|
+
Args:
|
|
472
|
+
parent_envelope: The parent message envelope.
|
|
473
|
+
child_envelope: The child message envelope produced from parent.
|
|
474
|
+
|
|
475
|
+
Returns:
|
|
476
|
+
Combined list of all chain violations detected. Empty list
|
|
477
|
+
if the chain propagation is valid.
|
|
478
|
+
|
|
479
|
+
Example:
|
|
480
|
+
>>> validator = ChainPropagationValidator()
|
|
481
|
+
>>> violations = validator.validate_chain(parent, child)
|
|
482
|
+
>>> for v in violations:
|
|
483
|
+
... print(f"[{v.severity}] {v.violation_type.value}")
|
|
484
|
+
"""
|
|
485
|
+
violations: list[ModelChainViolation] = []
|
|
486
|
+
|
|
487
|
+
# Validate correlation propagation
|
|
488
|
+
violations.extend(
|
|
489
|
+
self.validate_correlation_propagation(parent_envelope, child_envelope)
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
# Validate causation chain
|
|
493
|
+
violations.extend(
|
|
494
|
+
self.validate_causation_chain(parent_envelope, child_envelope)
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
return violations
|
|
498
|
+
|
|
499
|
+
def validate_workflow_chain(
|
|
500
|
+
self,
|
|
501
|
+
envelopes: list[ModelEventEnvelope[object]],
|
|
502
|
+
) -> list[ModelChainViolation]:
|
|
503
|
+
"""Validate an entire chain of messages in a workflow.
|
|
504
|
+
|
|
505
|
+
Validates that:
|
|
506
|
+
1. All messages share the same correlation_id (if first message has one)
|
|
507
|
+
2. Each message's causation_id references an ancestor message within
|
|
508
|
+
the provided chain (not necessarily the direct predecessor)
|
|
509
|
+
3. Parent messages appear before child messages in the list order
|
|
510
|
+
|
|
511
|
+
The envelopes list should be ordered by causation (parent before child).
|
|
512
|
+
|
|
513
|
+
Ancestor Skipping (Intentional Design Decision):
|
|
514
|
+
This method validates that causation_ids reference messages **within**
|
|
515
|
+
the chain, but does NOT enforce direct parent-child ordering. A message
|
|
516
|
+
may reference any ancestor in the chain (e.g., msg3 can reference msg1
|
|
517
|
+
even if msg2 exists between them). This is an intentional design
|
|
518
|
+
decision that provides workflow flexibility for:
|
|
519
|
+
|
|
520
|
+
- **Partial chain reconstruction**: When only a subset of messages
|
|
521
|
+
is available for validation (e.g., from logs or replay)
|
|
522
|
+
- **Fan-out patterns**: When a parent spawns multiple children that
|
|
523
|
+
all reference it directly rather than forming a linear chain
|
|
524
|
+
- **Aggregation patterns**: When reducers aggregate from multiple
|
|
525
|
+
ancestors within the same correlation context
|
|
526
|
+
|
|
527
|
+
For strict direct parent-child validation (enforcing linear chains),
|
|
528
|
+
use pairwise ``validate_chain()`` calls:
|
|
529
|
+
|
|
530
|
+
.. code-block:: python
|
|
531
|
+
|
|
532
|
+
# Strict linear chain validation
|
|
533
|
+
for i in range(len(envelopes) - 1):
|
|
534
|
+
violations.extend(
|
|
535
|
+
validator.validate_chain(envelopes[i], envelopes[i + 1])
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
Args:
|
|
539
|
+
envelopes: Ordered list of message envelopes in the workflow.
|
|
540
|
+
Should be ordered such that each message's causation_id
|
|
541
|
+
references a message earlier in the list.
|
|
542
|
+
|
|
543
|
+
Returns:
|
|
544
|
+
List of all chain violations detected across the workflow.
|
|
545
|
+
Empty list if the entire workflow chain is valid.
|
|
546
|
+
|
|
547
|
+
Example:
|
|
548
|
+
>>> validator = ChainPropagationValidator()
|
|
549
|
+
>>> # Workflow with messages that may reference any ancestor
|
|
550
|
+
>>> violations = validator.validate_workflow_chain([msg1, msg2, msg3])
|
|
551
|
+
>>> blocking = [v for v in violations if v.is_blocking()]
|
|
552
|
+
>>> if blocking:
|
|
553
|
+
... raise ChainPropagationError(blocking)
|
|
554
|
+
"""
|
|
555
|
+
violations: list[ModelChainViolation] = []
|
|
556
|
+
|
|
557
|
+
if len(envelopes) < 2:
|
|
558
|
+
# Single message or empty list - no chain to validate
|
|
559
|
+
return violations
|
|
560
|
+
|
|
561
|
+
# Build message_id -> envelope and message_id -> index mappings for O(1) lookup
|
|
562
|
+
# This avoids O(n) list.index() calls inside the O(n) validation loop
|
|
563
|
+
message_id_to_envelope: dict[UUID, ModelEventEnvelope[object]] = {}
|
|
564
|
+
message_id_to_index: dict[UUID, int] = {}
|
|
565
|
+
for idx, env in enumerate(envelopes):
|
|
566
|
+
msg_id = get_message_id(env)
|
|
567
|
+
message_id_to_envelope[msg_id] = env
|
|
568
|
+
message_id_to_index[msg_id] = idx
|
|
569
|
+
|
|
570
|
+
# Get the reference correlation_id from the first message
|
|
571
|
+
reference_correlation_id = get_correlation_id(envelopes[0])
|
|
572
|
+
|
|
573
|
+
# Validate each message in the chain
|
|
574
|
+
for i, envelope in enumerate(envelopes):
|
|
575
|
+
message_id = get_message_id(envelope)
|
|
576
|
+
|
|
577
|
+
# 1. Validate correlation_id consistency
|
|
578
|
+
envelope_correlation_id = get_correlation_id(envelope)
|
|
579
|
+
if reference_correlation_id is not None:
|
|
580
|
+
if envelope_correlation_id is None:
|
|
581
|
+
violations.append(
|
|
582
|
+
ModelChainViolation(
|
|
583
|
+
violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
|
|
584
|
+
expected_value=reference_correlation_id,
|
|
585
|
+
actual_value=None,
|
|
586
|
+
message_id=message_id,
|
|
587
|
+
parent_message_id=None,
|
|
588
|
+
violation_message=(
|
|
589
|
+
f"Message at index {i} is missing correlation_id "
|
|
590
|
+
f"but workflow uses correlation_id={reference_correlation_id}. "
|
|
591
|
+
"All messages in a workflow must share the same correlation_id."
|
|
592
|
+
),
|
|
593
|
+
severity=EnumValidationSeverity.ERROR,
|
|
594
|
+
)
|
|
595
|
+
)
|
|
596
|
+
elif envelope_correlation_id != reference_correlation_id:
|
|
597
|
+
violations.append(
|
|
598
|
+
ModelChainViolation(
|
|
599
|
+
violation_type=EnumChainViolationType.CORRELATION_MISMATCH,
|
|
600
|
+
expected_value=reference_correlation_id,
|
|
601
|
+
actual_value=envelope_correlation_id,
|
|
602
|
+
message_id=message_id,
|
|
603
|
+
parent_message_id=None,
|
|
604
|
+
violation_message=(
|
|
605
|
+
f"Message at index {i} has correlation_id mismatch: "
|
|
606
|
+
f"expected={reference_correlation_id}, actual={envelope_correlation_id}. "
|
|
607
|
+
"All messages must share the same correlation_id for distributed tracing."
|
|
608
|
+
),
|
|
609
|
+
severity=EnumValidationSeverity.ERROR,
|
|
610
|
+
)
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
# 2. Validate causation chain (skip first message - it's the root)
|
|
614
|
+
if i > 0:
|
|
615
|
+
causation_id = get_causation_id(envelope)
|
|
616
|
+
|
|
617
|
+
if causation_id is None:
|
|
618
|
+
# Non-root message must have causation_id
|
|
619
|
+
violations.append(
|
|
620
|
+
ModelChainViolation(
|
|
621
|
+
violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
|
|
622
|
+
expected_value=None, # Can't determine expected without causation
|
|
623
|
+
actual_value=None,
|
|
624
|
+
message_id=message_id,
|
|
625
|
+
parent_message_id=None,
|
|
626
|
+
violation_message=(
|
|
627
|
+
f"Message at index {i} (message_id={message_id}) is missing "
|
|
628
|
+
"causation_id. Every message (except root) must reference its "
|
|
629
|
+
"parent's message_id to maintain causation chain."
|
|
630
|
+
),
|
|
631
|
+
severity=EnumValidationSeverity.ERROR,
|
|
632
|
+
)
|
|
633
|
+
)
|
|
634
|
+
# Check if causation_id references a message in the chain
|
|
635
|
+
elif causation_id not in message_id_to_envelope:
|
|
636
|
+
violations.append(
|
|
637
|
+
ModelChainViolation(
|
|
638
|
+
violation_type=EnumChainViolationType.CAUSATION_ANCESTOR_SKIPPED,
|
|
639
|
+
expected_value=None,
|
|
640
|
+
actual_value=causation_id,
|
|
641
|
+
message_id=message_id,
|
|
642
|
+
parent_message_id=causation_id,
|
|
643
|
+
violation_message=(
|
|
644
|
+
f"Message at index {i} (message_id={message_id}) has "
|
|
645
|
+
f"causation_id={causation_id} which references a message "
|
|
646
|
+
"not in this workflow chain. "
|
|
647
|
+
"Causation chains must form an unbroken sequence."
|
|
648
|
+
),
|
|
649
|
+
severity=EnumValidationSeverity.ERROR,
|
|
650
|
+
)
|
|
651
|
+
)
|
|
652
|
+
else:
|
|
653
|
+
# Check that causation_id references an earlier message
|
|
654
|
+
# Use O(1) dict lookup instead of O(n) list.index()
|
|
655
|
+
parent_idx = message_id_to_index[causation_id]
|
|
656
|
+
|
|
657
|
+
if parent_idx >= i:
|
|
658
|
+
# Parent appears after child in the list - order violation
|
|
659
|
+
violations.append(
|
|
660
|
+
ModelChainViolation(
|
|
661
|
+
violation_type=EnumChainViolationType.CAUSATION_CHAIN_BROKEN,
|
|
662
|
+
expected_value=None,
|
|
663
|
+
actual_value=causation_id,
|
|
664
|
+
message_id=message_id,
|
|
665
|
+
parent_message_id=causation_id,
|
|
666
|
+
violation_message=(
|
|
667
|
+
f"Message at index {i} (message_id={message_id}) references "
|
|
668
|
+
f"parent at index {parent_idx} (causation_id={causation_id}) "
|
|
669
|
+
"but parents must appear before children in the causation chain. "
|
|
670
|
+
"Check message ordering."
|
|
671
|
+
),
|
|
672
|
+
severity=EnumValidationSeverity.WARNING,
|
|
673
|
+
)
|
|
674
|
+
)
|
|
675
|
+
|
|
676
|
+
return violations
|
|
677
|
+
|
|
678
|
+
def validate_linear_workflow_chain(
|
|
679
|
+
self,
|
|
680
|
+
envelopes: list[ModelEventEnvelope[object]],
|
|
681
|
+
) -> list[ModelChainViolation]:
|
|
682
|
+
"""Validate strict linear chain (no ancestor skipping).
|
|
683
|
+
|
|
684
|
+
Unlike validate_workflow_chain() which allows ancestor skipping,
|
|
685
|
+
this method enforces that each message's causation_id references
|
|
686
|
+
the immediately preceding message (direct parent).
|
|
687
|
+
|
|
688
|
+
Use this method when you need to verify a strict linear workflow
|
|
689
|
+
where messages form a single unbroken chain:
|
|
690
|
+
msg1 -> msg2 -> msg3 -> msg4
|
|
691
|
+
|
|
692
|
+
For workflows with fan-out patterns or aggregation, use
|
|
693
|
+
validate_workflow_chain() instead.
|
|
694
|
+
|
|
695
|
+
Args:
|
|
696
|
+
envelopes: Ordered list of message envelopes in the workflow.
|
|
697
|
+
Each message at index i+1 must have causation_id equal to
|
|
698
|
+
the envelope_id of message at index i.
|
|
699
|
+
|
|
700
|
+
Returns:
|
|
701
|
+
List of all chain violations detected. Empty list if the
|
|
702
|
+
entire linear chain is valid.
|
|
703
|
+
|
|
704
|
+
Example:
|
|
705
|
+
>>> validator = ChainPropagationValidator()
|
|
706
|
+
>>> # Strict linear chain - each message must reference direct parent
|
|
707
|
+
>>> violations = validator.validate_linear_workflow_chain([msg1, msg2, msg3])
|
|
708
|
+
>>> if violations:
|
|
709
|
+
... print("Linear chain broken!")
|
|
710
|
+
"""
|
|
711
|
+
violations: list[ModelChainViolation] = []
|
|
712
|
+
|
|
713
|
+
if len(envelopes) < 2:
|
|
714
|
+
return violations
|
|
715
|
+
|
|
716
|
+
for i in range(len(envelopes) - 1):
|
|
717
|
+
violations.extend(self.validate_chain(envelopes[i], envelopes[i + 1]))
|
|
718
|
+
|
|
719
|
+
return violations
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
# ==============================================================================
|
|
723
|
+
# Module-Level Singleton Validator
|
|
724
|
+
# ==============================================================================
|
|
725
|
+
#
|
|
726
|
+
# Performance Optimization: ChainPropagationValidator is stateless after
|
|
727
|
+
# initialization. Creating new instances on every validation call is wasteful.
|
|
728
|
+
# Instead, we use a module-level singleton.
|
|
729
|
+
#
|
|
730
|
+
# Why a singleton is safe here:
|
|
731
|
+
# - The validator is completely stateless (no mutable state)
|
|
732
|
+
# - All validation methods are pure functions that produce new results
|
|
733
|
+
# - Multiple threads can safely use the same validator instance
|
|
734
|
+
|
|
735
|
+
_default_validator = ChainPropagationValidator()
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
# ==============================================================================
|
|
739
|
+
# Convenience Functions
|
|
740
|
+
# ==============================================================================
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
def validate_message_chain(
|
|
744
|
+
parent_envelope: ModelEventEnvelope[object],
|
|
745
|
+
child_envelope: ModelEventEnvelope[object],
|
|
746
|
+
) -> list[ModelChainViolation]:
|
|
747
|
+
"""Validate chain propagation between parent and child messages.
|
|
748
|
+
|
|
749
|
+
Convenience function that validates both correlation and causation
|
|
750
|
+
chain propagation using the default singleton validator.
|
|
751
|
+
|
|
752
|
+
Args:
|
|
753
|
+
parent_envelope: The parent message envelope.
|
|
754
|
+
child_envelope: The child message envelope produced from parent.
|
|
755
|
+
|
|
756
|
+
Returns:
|
|
757
|
+
List of chain violations detected. Empty list if valid.
|
|
758
|
+
|
|
759
|
+
Example:
|
|
760
|
+
>>> violations = validate_message_chain(parent, child)
|
|
761
|
+
>>> if violations:
|
|
762
|
+
... for v in violations:
|
|
763
|
+
... print(v.format_for_logging())
|
|
764
|
+
"""
|
|
765
|
+
return _default_validator.validate_chain(parent_envelope, child_envelope)
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
def validate_linear_message_chain(
|
|
769
|
+
envelopes: list[ModelEventEnvelope[object]],
|
|
770
|
+
) -> list[ModelChainViolation]:
|
|
771
|
+
"""Validate strict linear chain using default validator.
|
|
772
|
+
|
|
773
|
+
Convenience function for validate_linear_workflow_chain() that uses
|
|
774
|
+
the module-level singleton validator. Validates that each message
|
|
775
|
+
in the chain references its immediate predecessor.
|
|
776
|
+
|
|
777
|
+
Unlike validate_workflow_chain() which allows ancestor skipping,
|
|
778
|
+
this function enforces strict linear ordering where each message's
|
|
779
|
+
causation_id must equal the envelope_id of the immediately preceding
|
|
780
|
+
message.
|
|
781
|
+
|
|
782
|
+
Args:
|
|
783
|
+
envelopes: Ordered list of message envelopes in the workflow.
|
|
784
|
+
Each message at index i+1 must have causation_id equal to
|
|
785
|
+
the envelope_id of message at index i.
|
|
786
|
+
|
|
787
|
+
Returns:
|
|
788
|
+
List of all chain violations detected. Empty list if the
|
|
789
|
+
entire linear chain is valid.
|
|
790
|
+
|
|
791
|
+
Example:
|
|
792
|
+
>>> violations = validate_linear_message_chain([msg1, msg2, msg3])
|
|
793
|
+
>>> if violations:
|
|
794
|
+
... for v in violations:
|
|
795
|
+
... print(v.format_for_logging())
|
|
796
|
+
"""
|
|
797
|
+
return _default_validator.validate_linear_workflow_chain(envelopes)
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
def enforce_chain_propagation(
|
|
801
|
+
parent_envelope: ModelEventEnvelope[object],
|
|
802
|
+
child_envelope: ModelEventEnvelope[object],
|
|
803
|
+
) -> None:
|
|
804
|
+
"""Validate chain propagation and raise error if violations found.
|
|
805
|
+
|
|
806
|
+
Strict enforcement function that validates both correlation and causation
|
|
807
|
+
chain propagation, raising ChainPropagationError if any violations are
|
|
808
|
+
detected.
|
|
809
|
+
|
|
810
|
+
Args:
|
|
811
|
+
parent_envelope: The parent message envelope.
|
|
812
|
+
child_envelope: The child message envelope produced from parent.
|
|
813
|
+
|
|
814
|
+
Raises:
|
|
815
|
+
ChainPropagationError: If any chain violations are detected.
|
|
816
|
+
Contains the list of violations for inspection.
|
|
817
|
+
|
|
818
|
+
Example:
|
|
819
|
+
>>> try:
|
|
820
|
+
... enforce_chain_propagation(parent, child)
|
|
821
|
+
... print("Chain propagation valid")
|
|
822
|
+
... except ChainPropagationError as e:
|
|
823
|
+
... print(f"Invalid: {len(e.violations)} violations")
|
|
824
|
+
... for v in e.violations:
|
|
825
|
+
... print(f" - {v.violation_type.value}: {v.violation_message}")
|
|
826
|
+
"""
|
|
827
|
+
violations = _default_validator.validate_chain(parent_envelope, child_envelope)
|
|
828
|
+
|
|
829
|
+
if violations:
|
|
830
|
+
# Use parent's correlation_id for error tracking
|
|
831
|
+
context = ModelInfraErrorContext(
|
|
832
|
+
operation="enforce_chain_propagation",
|
|
833
|
+
correlation_id=get_correlation_id(parent_envelope),
|
|
834
|
+
)
|
|
835
|
+
raise ChainPropagationError(
|
|
836
|
+
message="Chain propagation validation failed",
|
|
837
|
+
violations=violations,
|
|
838
|
+
context=context,
|
|
839
|
+
)
|