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,678 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 OmniNode Team <info@omninode.ai>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
"""
|
|
5
|
+
Corpus Capture Service for recording production executions.
|
|
6
|
+
|
|
7
|
+
This service observes live execution flow and selectively captures executions
|
|
8
|
+
based on configurable filters, building a replayable test corpus.
|
|
9
|
+
|
|
10
|
+
.. versionadded:: 0.5.0
|
|
11
|
+
Added for OMN-1203
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import hashlib
|
|
16
|
+
import json
|
|
17
|
+
import logging
|
|
18
|
+
import secrets
|
|
19
|
+
import threading
|
|
20
|
+
import warnings
|
|
21
|
+
from datetime import UTC, datetime
|
|
22
|
+
from typing import Protocol
|
|
23
|
+
from uuid import UUID
|
|
24
|
+
|
|
25
|
+
from omnibase_core.enums import EnumCoreErrorCode
|
|
26
|
+
from omnibase_core.errors import OnexError
|
|
27
|
+
from omnibase_core.models.manifest.model_execution_manifest import (
|
|
28
|
+
ModelExecutionManifest,
|
|
29
|
+
)
|
|
30
|
+
from omnibase_core.models.replay.model_execution_corpus import ModelExecutionCorpus
|
|
31
|
+
from omnibase_core.types import JsonType
|
|
32
|
+
from omnibase_infra.enums.enum_capture_outcome import EnumCaptureOutcome
|
|
33
|
+
from omnibase_infra.enums.enum_capture_state import EnumCaptureState
|
|
34
|
+
from omnibase_infra.enums.enum_dedupe_strategy import EnumDedupeStrategy
|
|
35
|
+
from omnibase_infra.models.corpus.model_capture_config import ModelCaptureConfig
|
|
36
|
+
from omnibase_infra.models.corpus.model_capture_result import ModelCaptureResult
|
|
37
|
+
|
|
38
|
+
logger = logging.getLogger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ProtocolManifestPersistence(Protocol):
|
|
42
|
+
"""Protocol for manifest persistence handlers."""
|
|
43
|
+
|
|
44
|
+
async def execute(self, envelope: JsonType) -> object:
|
|
45
|
+
"""Execute a persistence operation."""
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# =============================================================================
|
|
50
|
+
# Module-Level Helper Functions (extracted to reduce class method count)
|
|
51
|
+
# =============================================================================
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _compute_dedupe_hash(
|
|
55
|
+
manifest: ModelExecutionManifest,
|
|
56
|
+
strategy: EnumDedupeStrategy,
|
|
57
|
+
) -> str | None:
|
|
58
|
+
"""
|
|
59
|
+
Compute hash for deduplication based on configured strategy.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
manifest: The manifest to hash.
|
|
63
|
+
strategy: The deduplication strategy to apply.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
The hash string, or None if no deduplication.
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
OnexError: If strategy is unknown (CONFIGURATION_ERROR).
|
|
70
|
+
"""
|
|
71
|
+
if strategy == EnumDedupeStrategy.NONE:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
if strategy == EnumDedupeStrategy.INPUT_HASH:
|
|
75
|
+
# Hash based on handler identity (input fingerprint)
|
|
76
|
+
data = (
|
|
77
|
+
f"{manifest.node_identity.node_id}:{manifest.contract_identity.contract_id}"
|
|
78
|
+
)
|
|
79
|
+
return hashlib.sha256(data.encode()).hexdigest()[:16]
|
|
80
|
+
|
|
81
|
+
if strategy == EnumDedupeStrategy.FULL_MANIFEST_HASH:
|
|
82
|
+
# Hash based on manifest content, excluding unique identifiers
|
|
83
|
+
# (manifest_id, created_at, correlation_id) that would defeat deduplication
|
|
84
|
+
manifest_data = manifest.model_dump(mode="json")
|
|
85
|
+
# Remove unique per-execution fields to enable content-based deduplication
|
|
86
|
+
manifest_data.pop("manifest_id", None)
|
|
87
|
+
manifest_data.pop("created_at", None)
|
|
88
|
+
manifest_data.pop("correlation_id", None)
|
|
89
|
+
# Sort keys for deterministic hashing
|
|
90
|
+
data = json.dumps(manifest_data, sort_keys=True, default=str)
|
|
91
|
+
return hashlib.sha256(data.encode()).hexdigest()[:16]
|
|
92
|
+
|
|
93
|
+
# Explicit error for unknown strategies - fail fast rather than silently returning None
|
|
94
|
+
raise OnexError(
|
|
95
|
+
message=f"Unknown dedupe strategy: {strategy}",
|
|
96
|
+
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _create_capture_result(
|
|
101
|
+
manifest_id: UUID,
|
|
102
|
+
outcome: EnumCaptureOutcome,
|
|
103
|
+
start_time: datetime,
|
|
104
|
+
dedupe_hash: str | None = None,
|
|
105
|
+
error_message: str | None = None,
|
|
106
|
+
) -> ModelCaptureResult:
|
|
107
|
+
"""
|
|
108
|
+
Create a capture result with timing.
|
|
109
|
+
|
|
110
|
+
Module-level helper to keep parameter count within limits.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
manifest_id: ID of the manifest processed.
|
|
114
|
+
outcome: Result of the capture attempt.
|
|
115
|
+
start_time: When capture processing started.
|
|
116
|
+
dedupe_hash: Hash used for deduplication (if computed).
|
|
117
|
+
error_message: Error message if capture failed.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
A ModelCaptureResult with computed duration.
|
|
121
|
+
"""
|
|
122
|
+
end_time = datetime.now(UTC)
|
|
123
|
+
duration_ms = (end_time - start_time).total_seconds() * 1000
|
|
124
|
+
was_captured = outcome == EnumCaptureOutcome.CAPTURED
|
|
125
|
+
|
|
126
|
+
return ModelCaptureResult(
|
|
127
|
+
manifest_id=manifest_id,
|
|
128
|
+
outcome=outcome,
|
|
129
|
+
captured_at=end_time if was_captured else None,
|
|
130
|
+
dedupe_hash=dedupe_hash,
|
|
131
|
+
duration_ms=duration_ms,
|
|
132
|
+
error_message=error_message,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# =============================================================================
|
|
137
|
+
# State Machine Helper Class (extracted to reduce service class method count)
|
|
138
|
+
# =============================================================================
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class CaptureLifecycleFSM:
|
|
142
|
+
"""
|
|
143
|
+
Internal state machine for capture lifecycle management.
|
|
144
|
+
|
|
145
|
+
Encapsulates state transition logic to keep the main service class focused
|
|
146
|
+
on capture operations.
|
|
147
|
+
|
|
148
|
+
Note:
|
|
149
|
+
This is an internal helper class and should not be imported directly.
|
|
150
|
+
Use CorpusCapture as the public API.
|
|
151
|
+
|
|
152
|
+
.. versionadded:: 0.5.0
|
|
153
|
+
Extracted from CorpusCapture for OMN-1203 refactoring.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
# Valid state transitions map
|
|
157
|
+
_VALID_TRANSITIONS: dict[EnumCaptureState, set[EnumCaptureState]] = {
|
|
158
|
+
EnumCaptureState.IDLE: {EnumCaptureState.READY},
|
|
159
|
+
EnumCaptureState.READY: {
|
|
160
|
+
EnumCaptureState.CAPTURING,
|
|
161
|
+
EnumCaptureState.CLOSED,
|
|
162
|
+
},
|
|
163
|
+
EnumCaptureState.CAPTURING: {
|
|
164
|
+
EnumCaptureState.PAUSED,
|
|
165
|
+
EnumCaptureState.FULL,
|
|
166
|
+
EnumCaptureState.CLOSED,
|
|
167
|
+
},
|
|
168
|
+
EnumCaptureState.PAUSED: {
|
|
169
|
+
EnumCaptureState.CAPTURING,
|
|
170
|
+
EnumCaptureState.CLOSED,
|
|
171
|
+
},
|
|
172
|
+
EnumCaptureState.FULL: {EnumCaptureState.CLOSED},
|
|
173
|
+
EnumCaptureState.CLOSED: set(), # Terminal state
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
def __init__(self) -> None:
|
|
177
|
+
"""Initialize state machine in IDLE state."""
|
|
178
|
+
self._state: EnumCaptureState = EnumCaptureState.IDLE
|
|
179
|
+
|
|
180
|
+
@property
|
|
181
|
+
def state(self) -> EnumCaptureState:
|
|
182
|
+
"""Get the current capture state."""
|
|
183
|
+
return self._state
|
|
184
|
+
|
|
185
|
+
@state.setter
|
|
186
|
+
def state(self, value: EnumCaptureState) -> None:
|
|
187
|
+
"""Set state directly (for internal use in critical sections)."""
|
|
188
|
+
self._state = value
|
|
189
|
+
|
|
190
|
+
def transition_to(self, target: EnumCaptureState) -> None:
|
|
191
|
+
"""
|
|
192
|
+
Transition to a new state with validation.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
target: The target state to transition to.
|
|
196
|
+
|
|
197
|
+
Raises:
|
|
198
|
+
OnexError: If the transition is not valid (INVALID_STATE).
|
|
199
|
+
"""
|
|
200
|
+
valid_targets = self._VALID_TRANSITIONS.get(self._state, set())
|
|
201
|
+
if target not in valid_targets:
|
|
202
|
+
raise OnexError(
|
|
203
|
+
message=f"Invalid state transition: {self._state.value} -> {target.value}",
|
|
204
|
+
error_code=EnumCoreErrorCode.INVALID_STATE,
|
|
205
|
+
)
|
|
206
|
+
self._state = target
|
|
207
|
+
|
|
208
|
+
def can_capture(self) -> bool:
|
|
209
|
+
"""Check if current state allows capture."""
|
|
210
|
+
return self._state.can_capture()
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# =============================================================================
|
|
214
|
+
# Main Service Class
|
|
215
|
+
# =============================================================================
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class CorpusCapture:
|
|
219
|
+
"""
|
|
220
|
+
Engine for capturing production executions into a corpus.
|
|
221
|
+
|
|
222
|
+
This service provides:
|
|
223
|
+
- Configurable filtering (handler whitelist, time window, sample rate)
|
|
224
|
+
- Deduplication strategies (input hash, full manifest hash)
|
|
225
|
+
- Lifecycle management (create, start, pause, resume, close)
|
|
226
|
+
- Max executions enforcement with automatic state transitions
|
|
227
|
+
|
|
228
|
+
Example:
|
|
229
|
+
>>> config = ModelCaptureConfig(
|
|
230
|
+
... corpus_display_name="regression-suite-v1",
|
|
231
|
+
... max_executions=50,
|
|
232
|
+
... sample_rate=0.5,
|
|
233
|
+
... handler_filter=("compute-handler",),
|
|
234
|
+
... )
|
|
235
|
+
>>> service = CorpusCapture()
|
|
236
|
+
>>> service.create_corpus(config)
|
|
237
|
+
>>> service.start_capture()
|
|
238
|
+
>>>
|
|
239
|
+
>>> # In production pipeline callback
|
|
240
|
+
>>> def on_manifest_built(manifest: ModelExecutionManifest) -> None:
|
|
241
|
+
... service.capture(manifest)
|
|
242
|
+
>>>
|
|
243
|
+
>>> # When done
|
|
244
|
+
>>> corpus = service.close_corpus()
|
|
245
|
+
|
|
246
|
+
.. versionadded:: 0.5.0
|
|
247
|
+
Added for OMN-1203
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
def __init__(
|
|
251
|
+
self,
|
|
252
|
+
persistence: ProtocolManifestPersistence | None = None,
|
|
253
|
+
) -> None:
|
|
254
|
+
"""
|
|
255
|
+
Initialize the corpus capture service.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
persistence: Optional persistence handler for flushing manifests.
|
|
259
|
+
If provided, manifests can be persisted via flush_to_persistence()
|
|
260
|
+
or by calling close_corpus_async(flush=True). The synchronous
|
|
261
|
+
close_corpus() does NOT automatically flush.
|
|
262
|
+
"""
|
|
263
|
+
self._state_machine = CaptureLifecycleFSM()
|
|
264
|
+
self._config: ModelCaptureConfig | None = None
|
|
265
|
+
self._corpus: ModelExecutionCorpus | None = None
|
|
266
|
+
self._seen_hashes: set[str] = set()
|
|
267
|
+
self._persistence = persistence
|
|
268
|
+
|
|
269
|
+
# Lock for thread-safe access to all shared mutable state
|
|
270
|
+
# Used consistently by sync capture(), async capture_async(), and get_metrics()
|
|
271
|
+
self._sync_lock = threading.Lock()
|
|
272
|
+
|
|
273
|
+
# Metrics for monitoring
|
|
274
|
+
self._capture_count: int = 0
|
|
275
|
+
self._capture_missed_count: int = 0
|
|
276
|
+
self._capture_timeout_count: int = 0
|
|
277
|
+
|
|
278
|
+
@property
|
|
279
|
+
def state(self) -> EnumCaptureState:
|
|
280
|
+
"""Get the current capture state."""
|
|
281
|
+
with self._sync_lock:
|
|
282
|
+
return self._state_machine.state
|
|
283
|
+
|
|
284
|
+
def create_corpus(self, config: ModelCaptureConfig) -> ModelExecutionCorpus:
|
|
285
|
+
"""
|
|
286
|
+
Initialize a new corpus for capture.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
config: Configuration for the capture session.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
The newly created (empty) corpus.
|
|
293
|
+
|
|
294
|
+
Raises:
|
|
295
|
+
OnexError: If not in IDLE state (INVALID_STATE).
|
|
296
|
+
"""
|
|
297
|
+
with self._sync_lock:
|
|
298
|
+
self._state_machine.transition_to(EnumCaptureState.READY)
|
|
299
|
+
self._config = config
|
|
300
|
+
self._seen_hashes = set()
|
|
301
|
+
|
|
302
|
+
# Create empty corpus
|
|
303
|
+
self._corpus = ModelExecutionCorpus(
|
|
304
|
+
name=config.corpus_display_name,
|
|
305
|
+
version="1.0.0",
|
|
306
|
+
source="capture",
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
return self._corpus
|
|
310
|
+
|
|
311
|
+
def start_capture(self) -> None:
|
|
312
|
+
"""
|
|
313
|
+
Begin capturing executions.
|
|
314
|
+
|
|
315
|
+
Raises:
|
|
316
|
+
OnexError: If not in READY state (INVALID_STATE).
|
|
317
|
+
"""
|
|
318
|
+
with self._sync_lock:
|
|
319
|
+
self._state_machine.transition_to(EnumCaptureState.CAPTURING)
|
|
320
|
+
|
|
321
|
+
def pause_capture(self) -> None:
|
|
322
|
+
"""
|
|
323
|
+
Pause capture without closing corpus.
|
|
324
|
+
|
|
325
|
+
Raises:
|
|
326
|
+
OnexError: If not in CAPTURING state (INVALID_STATE).
|
|
327
|
+
"""
|
|
328
|
+
with self._sync_lock:
|
|
329
|
+
self._state_machine.transition_to(EnumCaptureState.PAUSED)
|
|
330
|
+
|
|
331
|
+
def resume_capture(self) -> None:
|
|
332
|
+
"""
|
|
333
|
+
Resume capture after pause.
|
|
334
|
+
|
|
335
|
+
Raises:
|
|
336
|
+
OnexError: If not in PAUSED state (INVALID_STATE).
|
|
337
|
+
"""
|
|
338
|
+
with self._sync_lock:
|
|
339
|
+
self._state_machine.transition_to(EnumCaptureState.CAPTURING)
|
|
340
|
+
|
|
341
|
+
def close_corpus(self) -> ModelExecutionCorpus:
|
|
342
|
+
"""
|
|
343
|
+
Finalize and seal the corpus.
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
The finalized corpus.
|
|
347
|
+
|
|
348
|
+
Raises:
|
|
349
|
+
OnexError: If no corpus is active (INVALID_STATE).
|
|
350
|
+
"""
|
|
351
|
+
with self._sync_lock:
|
|
352
|
+
if self._corpus is None:
|
|
353
|
+
raise OnexError(
|
|
354
|
+
message="No corpus to close",
|
|
355
|
+
error_code=EnumCoreErrorCode.INVALID_STATE,
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
self._state_machine.transition_to(EnumCaptureState.CLOSED)
|
|
359
|
+
|
|
360
|
+
corpus = self._corpus
|
|
361
|
+
self._corpus = None
|
|
362
|
+
self._config = None
|
|
363
|
+
self._seen_hashes = set()
|
|
364
|
+
|
|
365
|
+
return corpus
|
|
366
|
+
|
|
367
|
+
def get_active_corpus(self) -> ModelExecutionCorpus | None:
|
|
368
|
+
"""
|
|
369
|
+
Get the currently active corpus.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
The active corpus, or None if no corpus is active.
|
|
373
|
+
"""
|
|
374
|
+
with self._sync_lock:
|
|
375
|
+
return self._corpus
|
|
376
|
+
|
|
377
|
+
def capture(self, manifest: ModelExecutionManifest) -> ModelCaptureResult:
|
|
378
|
+
"""
|
|
379
|
+
Attempt to capture an execution.
|
|
380
|
+
|
|
381
|
+
This method applies all configured filters and deduplication
|
|
382
|
+
to determine if the manifest should be added to the corpus.
|
|
383
|
+
|
|
384
|
+
Args:
|
|
385
|
+
manifest: The execution manifest to potentially capture.
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
Result indicating whether the capture succeeded or was skipped.
|
|
389
|
+
"""
|
|
390
|
+
start_time = datetime.now(UTC)
|
|
391
|
+
|
|
392
|
+
# Snapshot config early for thread-safety - prevents race with close_corpus()
|
|
393
|
+
# which may set _config to None between our checks and usage.
|
|
394
|
+
# This read is safe because Python's GIL ensures atomic reference reads.
|
|
395
|
+
config = self._config
|
|
396
|
+
|
|
397
|
+
# Check state allows capture
|
|
398
|
+
if self._state_machine.state == EnumCaptureState.FULL:
|
|
399
|
+
return _create_capture_result(
|
|
400
|
+
manifest.manifest_id,
|
|
401
|
+
EnumCaptureOutcome.SKIPPED_CORPUS_FULL,
|
|
402
|
+
start_time,
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
if not self._state_machine.can_capture():
|
|
406
|
+
return _create_capture_result(
|
|
407
|
+
manifest.manifest_id,
|
|
408
|
+
EnumCaptureOutcome.SKIPPED_NOT_CAPTURING,
|
|
409
|
+
start_time,
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
if config is None or self._corpus is None:
|
|
413
|
+
return _create_capture_result(
|
|
414
|
+
manifest.manifest_id,
|
|
415
|
+
EnumCaptureOutcome.SKIPPED_NOT_CAPTURING,
|
|
416
|
+
start_time,
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
# Apply handler filter (using snapshot)
|
|
420
|
+
handler_id = manifest.node_identity.node_id
|
|
421
|
+
if not config.is_handler_allowed(handler_id):
|
|
422
|
+
return _create_capture_result(
|
|
423
|
+
manifest.manifest_id,
|
|
424
|
+
EnumCaptureOutcome.SKIPPED_HANDLER_FILTER,
|
|
425
|
+
start_time,
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
# Apply time window filter (using snapshot)
|
|
429
|
+
if not config.is_in_time_window(manifest.created_at):
|
|
430
|
+
return _create_capture_result(
|
|
431
|
+
manifest.manifest_id,
|
|
432
|
+
EnumCaptureOutcome.SKIPPED_TIME_WINDOW,
|
|
433
|
+
start_time,
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
# Apply sample rate filter (using snapshot)
|
|
437
|
+
# Use secrets.randbelow() for thread-safe randomness (random.random() is NOT thread-safe)
|
|
438
|
+
if config.sample_rate < 1.0:
|
|
439
|
+
if secrets.randbelow(1000000) / 1000000.0 > config.sample_rate:
|
|
440
|
+
return _create_capture_result(
|
|
441
|
+
manifest.manifest_id,
|
|
442
|
+
EnumCaptureOutcome.SKIPPED_SAMPLE_RATE,
|
|
443
|
+
start_time,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Apply deduplication - compute hash outside lock (pure computation)
|
|
447
|
+
dedupe_hash = _compute_dedupe_hash(manifest, config.dedupe_strategy)
|
|
448
|
+
|
|
449
|
+
# Thread-safe critical section for shared state access
|
|
450
|
+
# Protects: _seen_hashes (check + add), _corpus (update), _state (update)
|
|
451
|
+
with self._sync_lock:
|
|
452
|
+
# Re-check state under lock (may have changed)
|
|
453
|
+
if self._state_machine.state == EnumCaptureState.FULL:
|
|
454
|
+
return _create_capture_result(
|
|
455
|
+
manifest.manifest_id,
|
|
456
|
+
EnumCaptureOutcome.SKIPPED_CORPUS_FULL,
|
|
457
|
+
start_time,
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
# Re-check can_capture under lock (may have changed to PAUSED)
|
|
461
|
+
if not self._state_machine.can_capture():
|
|
462
|
+
return _create_capture_result(
|
|
463
|
+
manifest.manifest_id,
|
|
464
|
+
EnumCaptureOutcome.SKIPPED_NOT_CAPTURING,
|
|
465
|
+
start_time,
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
if dedupe_hash is not None and dedupe_hash in self._seen_hashes:
|
|
469
|
+
return _create_capture_result(
|
|
470
|
+
manifest.manifest_id,
|
|
471
|
+
EnumCaptureOutcome.SKIPPED_DUPLICATE,
|
|
472
|
+
start_time,
|
|
473
|
+
dedupe_hash=dedupe_hash,
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
# Add to corpus (requires _corpus not None, checked above)
|
|
477
|
+
if self._corpus is None:
|
|
478
|
+
return _create_capture_result(
|
|
479
|
+
manifest.manifest_id,
|
|
480
|
+
EnumCaptureOutcome.SKIPPED_NOT_CAPTURING,
|
|
481
|
+
start_time,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
self._corpus = self._corpus.with_execution(manifest)
|
|
485
|
+
if dedupe_hash is not None:
|
|
486
|
+
self._seen_hashes.add(dedupe_hash)
|
|
487
|
+
|
|
488
|
+
# Check if we hit max_executions (using snapshot for thread-safety)
|
|
489
|
+
if self._corpus.execution_count >= config.max_executions:
|
|
490
|
+
self._state_machine.state = EnumCaptureState.FULL
|
|
491
|
+
|
|
492
|
+
return _create_capture_result(
|
|
493
|
+
manifest.manifest_id,
|
|
494
|
+
EnumCaptureOutcome.CAPTURED,
|
|
495
|
+
start_time,
|
|
496
|
+
dedupe_hash=dedupe_hash,
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
async def capture_async(
|
|
500
|
+
self,
|
|
501
|
+
manifest: ModelExecutionManifest,
|
|
502
|
+
timeout_ms: float | None = None,
|
|
503
|
+
) -> ModelCaptureResult:
|
|
504
|
+
"""
|
|
505
|
+
Async capture with configurable timeout.
|
|
506
|
+
|
|
507
|
+
This method provides bounded latency for production use. If the capture
|
|
508
|
+
operation exceeds the timeout, it returns a SKIPPED_TIMEOUT result
|
|
509
|
+
rather than blocking the caller.
|
|
510
|
+
|
|
511
|
+
Args:
|
|
512
|
+
manifest: The execution manifest to potentially capture.
|
|
513
|
+
timeout_ms: Timeout in milliseconds. If None, uses config value.
|
|
514
|
+
Defaults to 50ms from config.
|
|
515
|
+
|
|
516
|
+
Returns:
|
|
517
|
+
Result indicating whether the capture succeeded, was skipped,
|
|
518
|
+
or timed out.
|
|
519
|
+
"""
|
|
520
|
+
start_time = datetime.now(UTC)
|
|
521
|
+
effective_timeout = timeout_ms
|
|
522
|
+
if effective_timeout is None and self._config is not None:
|
|
523
|
+
effective_timeout = self._config.capture_timeout_ms
|
|
524
|
+
if effective_timeout is None:
|
|
525
|
+
effective_timeout = 50.0 # Default 50ms
|
|
526
|
+
|
|
527
|
+
try:
|
|
528
|
+
# Run capture in executor to avoid blocking if serialization is slow
|
|
529
|
+
# Use get_running_loop() as the modern approach (get_event_loop() is deprecated)
|
|
530
|
+
loop = asyncio.get_running_loop()
|
|
531
|
+
result = await asyncio.wait_for(
|
|
532
|
+
loop.run_in_executor(None, self.capture, manifest),
|
|
533
|
+
timeout=effective_timeout / 1000.0, # Convert to seconds
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
# Use sync_lock for metrics consistency with get_metrics()
|
|
537
|
+
with self._sync_lock:
|
|
538
|
+
if result.was_captured:
|
|
539
|
+
self._capture_count += 1
|
|
540
|
+
|
|
541
|
+
return result
|
|
542
|
+
|
|
543
|
+
except TimeoutError:
|
|
544
|
+
# Use sync_lock for metrics consistency with get_metrics()
|
|
545
|
+
with self._sync_lock:
|
|
546
|
+
self._capture_timeout_count += 1
|
|
547
|
+
self._capture_missed_count += 1
|
|
548
|
+
|
|
549
|
+
warnings.warn(
|
|
550
|
+
f"Capture timed out after {effective_timeout}ms for manifest "
|
|
551
|
+
f"{manifest.manifest_id}. Consider increasing capture_timeout_ms.",
|
|
552
|
+
stacklevel=2,
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
return _create_capture_result(
|
|
556
|
+
manifest.manifest_id,
|
|
557
|
+
EnumCaptureOutcome.SKIPPED_TIMEOUT,
|
|
558
|
+
start_time,
|
|
559
|
+
error_message=f"Capture timed out after {effective_timeout}ms",
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
except Exception as e:
|
|
563
|
+
# Use sync_lock for metrics consistency with get_metrics()
|
|
564
|
+
with self._sync_lock:
|
|
565
|
+
self._capture_missed_count += 1
|
|
566
|
+
|
|
567
|
+
# Log detailed exception internally for debugging
|
|
568
|
+
logger.exception(
|
|
569
|
+
"Capture failed for manifest %s: %s",
|
|
570
|
+
manifest.manifest_id,
|
|
571
|
+
e,
|
|
572
|
+
)
|
|
573
|
+
|
|
574
|
+
# Sanitize error message for external exposure - use exception type only
|
|
575
|
+
sanitized_error = f"Capture failed: {type(e).__name__}"
|
|
576
|
+
|
|
577
|
+
return _create_capture_result(
|
|
578
|
+
manifest.manifest_id,
|
|
579
|
+
EnumCaptureOutcome.FAILED,
|
|
580
|
+
start_time,
|
|
581
|
+
error_message=sanitized_error,
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
async def flush_to_persistence(self) -> int:
|
|
585
|
+
"""
|
|
586
|
+
Flush captured manifests to persistence layer.
|
|
587
|
+
|
|
588
|
+
This method stores all captured manifests via the persistence handler
|
|
589
|
+
if one was provided. Must be called explicitly or via close_corpus_async(flush=True).
|
|
590
|
+
The synchronous close_corpus() does NOT call this method.
|
|
591
|
+
|
|
592
|
+
Returns:
|
|
593
|
+
Number of manifests successfully persisted.
|
|
594
|
+
|
|
595
|
+
Raises:
|
|
596
|
+
OnexError: If no persistence handler is configured.
|
|
597
|
+
"""
|
|
598
|
+
if self._persistence is None:
|
|
599
|
+
raise OnexError(
|
|
600
|
+
message="No persistence handler configured",
|
|
601
|
+
error_code=EnumCoreErrorCode.CONFIGURATION_ERROR,
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
# Snapshot corpus under lock to prevent race with close_corpus()
|
|
605
|
+
with self._sync_lock:
|
|
606
|
+
corpus_snapshot = self._corpus
|
|
607
|
+
if corpus_snapshot is None or corpus_snapshot.execution_count == 0:
|
|
608
|
+
return 0
|
|
609
|
+
|
|
610
|
+
# Iterate outside lock - corpus_snapshot is now a safe local reference
|
|
611
|
+
persisted_count = 0
|
|
612
|
+
for manifest in corpus_snapshot.executions:
|
|
613
|
+
try:
|
|
614
|
+
await self._persistence.execute(
|
|
615
|
+
{
|
|
616
|
+
"operation": "manifest.store",
|
|
617
|
+
"payload": {
|
|
618
|
+
"manifest": manifest.model_dump(mode="json"),
|
|
619
|
+
},
|
|
620
|
+
"correlation_id": str(manifest.correlation_id)
|
|
621
|
+
if manifest.correlation_id
|
|
622
|
+
else None,
|
|
623
|
+
}
|
|
624
|
+
)
|
|
625
|
+
persisted_count += 1
|
|
626
|
+
except Exception as e:
|
|
627
|
+
# Log detailed exception internally for debugging
|
|
628
|
+
logger.exception(
|
|
629
|
+
"Failed to persist manifest %s: %s",
|
|
630
|
+
manifest.manifest_id,
|
|
631
|
+
e,
|
|
632
|
+
)
|
|
633
|
+
# Emit sanitized warning (no raw exception details)
|
|
634
|
+
warnings.warn(
|
|
635
|
+
f"Failed to persist manifest {manifest.manifest_id}: "
|
|
636
|
+
f"{type(e).__name__}",
|
|
637
|
+
stacklevel=2,
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
return persisted_count
|
|
641
|
+
|
|
642
|
+
async def close_corpus_async(
|
|
643
|
+
self,
|
|
644
|
+
flush: bool = True,
|
|
645
|
+
) -> tuple[ModelExecutionCorpus, int]:
|
|
646
|
+
"""
|
|
647
|
+
Async close and optionally flush corpus.
|
|
648
|
+
|
|
649
|
+
Args:
|
|
650
|
+
flush: If True and persistence is configured, flush all manifests
|
|
651
|
+
before closing.
|
|
652
|
+
|
|
653
|
+
Returns:
|
|
654
|
+
Tuple of (closed corpus, number of manifests persisted).
|
|
655
|
+
"""
|
|
656
|
+
persisted_count = 0
|
|
657
|
+
|
|
658
|
+
if flush and self._persistence is not None:
|
|
659
|
+
persisted_count = await self.flush_to_persistence()
|
|
660
|
+
|
|
661
|
+
corpus = self.close_corpus()
|
|
662
|
+
return corpus, persisted_count
|
|
663
|
+
|
|
664
|
+
def get_metrics(self) -> dict[str, int | float]:
|
|
665
|
+
"""
|
|
666
|
+
Get capture metrics.
|
|
667
|
+
|
|
668
|
+
Returns:
|
|
669
|
+
Dict with capture_count, capture_missed_count, capture_timeout_count,
|
|
670
|
+
and corpus_size.
|
|
671
|
+
"""
|
|
672
|
+
with self._sync_lock:
|
|
673
|
+
return {
|
|
674
|
+
"capture_count": self._capture_count,
|
|
675
|
+
"capture_missed_count": self._capture_missed_count,
|
|
676
|
+
"capture_timeout_count": self._capture_timeout_count,
|
|
677
|
+
"corpus_size": self._corpus.execution_count if self._corpus else 0,
|
|
678
|
+
}
|