omnibase_infra 0.2.1__py3-none-any.whl → 0.2.2__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 +1 -1
- omnibase_infra/adapters/adapter_onex_tool_execution.py +446 -0
- omnibase_infra/cli/commands.py +1 -1
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +4 -1
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +4 -1
- omnibase_infra/errors/error_compute_registry.py +4 -1
- omnibase_infra/errors/error_event_bus_registry.py +4 -1
- omnibase_infra/errors/error_infra.py +3 -1
- omnibase_infra/errors/error_policy_registry.py +4 -1
- omnibase_infra/handlers/handler_db.py +2 -1
- omnibase_infra/handlers/handler_graph.py +10 -5
- omnibase_infra/handlers/handler_mcp.py +736 -63
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +4 -3
- omnibase_infra/handlers/mixins/mixin_consul_service.py +2 -1
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +301 -4
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +10 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +3 -2
- omnibase_infra/mixins/mixin_node_introspection.py +24 -7
- omnibase_infra/mixins/mixin_retry_execution.py +1 -1
- omnibase_infra/models/handlers/__init__.py +10 -0
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +15 -0
- omnibase_infra/models/mcp/__init__.py +15 -0
- omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
- omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
- omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
- omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
- omnibase_infra/models/registration/model_node_capabilities.py +11 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +0 -5
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +17 -10
- omnibase_infra/nodes/effects/contract.yaml +0 -5
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +7 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +86 -1
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +3 -3
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +9 -8
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +14 -13
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +0 -5
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +46 -25
- omnibase_infra/nodes/node_registry_effect/contract.yaml +0 -5
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +2 -1
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +24 -19
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +2 -2
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +2 -2
- omnibase_infra/plugins/plugin_compute_base.py +16 -2
- omnibase_infra/protocols/protocol_event_projector.py +1 -1
- omnibase_infra/runtime/__init__.py +51 -1
- omnibase_infra/runtime/binding_config_resolver.py +102 -37
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/contract_handler_discovery.py +6 -1
- omnibase_infra/runtime/handler_bootstrap_source.py +514 -0
- omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
- omnibase_infra/runtime/handler_contract_source.py +289 -167
- omnibase_infra/runtime/handler_plugin_loader.py +4 -2
- omnibase_infra/runtime/mixin_semver_cache.py +25 -1
- omnibase_infra/runtime/mixins/__init__.py +7 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +31 -10
- omnibase_infra/runtime/models/__init__.py +24 -0
- omnibase_infra/runtime/models/model_health_check_result.py +2 -1
- omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
- omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
- omnibase_infra/runtime/projector_plugin_loader.py +1 -1
- omnibase_infra/runtime/projector_shell.py +229 -1
- omnibase_infra/runtime/protocols/__init__.py +10 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +3 -2
- omnibase_infra/runtime/registry_policy.py +9 -326
- omnibase_infra/runtime/secret_resolver.py +4 -2
- omnibase_infra/runtime/service_kernel.py +10 -2
- omnibase_infra/runtime/service_message_dispatch_engine.py +4 -2
- omnibase_infra/runtime/service_runtime_host_process.py +225 -15
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +764 -0
- omnibase_infra/runtime/util_container_wiring.py +6 -5
- omnibase_infra/runtime/util_wiring.py +5 -1
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/mcp/__init__.py +31 -0
- omnibase_infra/services/mcp/mcp_server_lifecycle.py +443 -0
- omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
- omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +547 -0
- omnibase_infra/services/registry_api/__init__.py +40 -0
- omnibase_infra/services/registry_api/main.py +243 -0
- omnibase_infra/services/registry_api/models/__init__.py +66 -0
- omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
- omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
- omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
- omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
- omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
- omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
- omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
- omnibase_infra/services/registry_api/models/model_warning.py +49 -0
- omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
- omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
- omnibase_infra/services/registry_api/routes.py +371 -0
- omnibase_infra/services/registry_api/service.py +846 -0
- omnibase_infra/services/service_capability_query.py +4 -4
- omnibase_infra/services/service_health.py +3 -2
- omnibase_infra/services/service_timeout_emitter.py +13 -2
- omnibase_infra/utils/util_dsn_validation.py +1 -1
- omnibase_infra/validation/__init__.py +3 -19
- omnibase_infra/validation/contracts/security.validation.yaml +114 -0
- omnibase_infra/validation/infra_validators.py +35 -24
- omnibase_infra/validation/validation_exemptions.yaml +113 -9
- omnibase_infra/validation/validator_chain_propagation.py +2 -2
- omnibase_infra/validation/validator_runtime_shape.py +1 -1
- omnibase_infra/validation/validator_security.py +473 -370
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/METADATA +2 -2
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/RECORD +116 -74
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/WHEEL +0 -0
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/entry_points.txt +0 -0
- {omnibase_infra-0.2.1.dist-info → omnibase_infra-0.2.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -131,10 +131,10 @@ class ServiceCapabilityQuery(MixinAsyncCircuitBreaker):
|
|
|
131
131
|
Dependency Injection Pattern: This service is a leaf infrastructure
|
|
132
132
|
service that receives its dependencies directly via constructor
|
|
133
133
|
parameters rather than resolving them from a container. Unlike
|
|
134
|
-
orchestrators that use ``container.
|
|
135
|
-
dynamically, leaf services like this one are
|
|
136
|
-
concrete dependencies (projection_reader, node_selector)
|
|
137
|
-
themselves resolved by higher-level components.
|
|
134
|
+
orchestrators that use ``container.service_registry.resolve_service()``
|
|
135
|
+
to obtain services dynamically, leaf services like this one are
|
|
136
|
+
instantiated with concrete dependencies (projection_reader, node_selector)
|
|
137
|
+
and are themselves resolved by higher-level components.
|
|
138
138
|
"""
|
|
139
139
|
|
|
140
140
|
def __init__(
|
|
@@ -57,10 +57,11 @@ See Also:
|
|
|
57
57
|
from __future__ import annotations
|
|
58
58
|
|
|
59
59
|
import logging
|
|
60
|
-
from typing import TYPE_CHECKING, Literal
|
|
60
|
+
from typing import TYPE_CHECKING, Literal, cast
|
|
61
61
|
|
|
62
62
|
from aiohttp import web
|
|
63
63
|
|
|
64
|
+
from omnibase_core.types import JsonType
|
|
64
65
|
from omnibase_infra.enums import EnumInfraTransportType
|
|
65
66
|
from omnibase_infra.errors import (
|
|
66
67
|
ModelInfraErrorContext,
|
|
@@ -859,7 +860,7 @@ class ServiceHealth:
|
|
|
859
860
|
response = ModelHealthCheckResponse.success(
|
|
860
861
|
status=status,
|
|
861
862
|
version=self._version,
|
|
862
|
-
details=health_details,
|
|
863
|
+
details=cast("dict[str, JsonType]", health_details),
|
|
863
864
|
)
|
|
864
865
|
|
|
865
866
|
return web.Response(
|
|
@@ -36,6 +36,7 @@ from uuid import UUID
|
|
|
36
36
|
|
|
37
37
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
38
38
|
|
|
39
|
+
from omnibase_core.models.events.model_event_envelope import ModelEventEnvelope
|
|
39
40
|
from omnibase_infra.enums import EnumInfraTransportType
|
|
40
41
|
from omnibase_infra.errors import ModelInfraErrorContext, ProtocolConfigurationError
|
|
41
42
|
from omnibase_infra.models.projection import ModelRegistrationProjection
|
|
@@ -568,8 +569,13 @@ class ServiceTimeoutEmitter:
|
|
|
568
569
|
},
|
|
569
570
|
)
|
|
570
571
|
|
|
572
|
+
# Wrap event in ModelEventEnvelope for protocol compliance
|
|
573
|
+
envelope: ModelEventEnvelope[object] = ModelEventEnvelope(
|
|
574
|
+
payload=event,
|
|
575
|
+
correlation_id=correlation_id,
|
|
576
|
+
)
|
|
571
577
|
await self._event_bus.publish_envelope(
|
|
572
|
-
envelope=
|
|
578
|
+
envelope=envelope, # type: ignore[arg-type]
|
|
573
579
|
topic=topic,
|
|
574
580
|
)
|
|
575
581
|
|
|
@@ -657,8 +663,13 @@ class ServiceTimeoutEmitter:
|
|
|
657
663
|
},
|
|
658
664
|
)
|
|
659
665
|
|
|
666
|
+
# Wrap event in ModelEventEnvelope for protocol compliance
|
|
667
|
+
envelope: ModelEventEnvelope[object] = ModelEventEnvelope(
|
|
668
|
+
payload=event,
|
|
669
|
+
correlation_id=correlation_id,
|
|
670
|
+
)
|
|
660
671
|
await self._event_bus.publish_envelope(
|
|
661
|
-
envelope=
|
|
672
|
+
envelope=envelope, # type: ignore[arg-type]
|
|
662
673
|
topic=topic,
|
|
663
674
|
)
|
|
664
675
|
|
|
@@ -73,7 +73,7 @@ def _assert_postgres_scheme(scheme: str) -> Literal["postgresql", "postgres"]:
|
|
|
73
73
|
parameter="scheme",
|
|
74
74
|
value=scheme,
|
|
75
75
|
)
|
|
76
|
-
return cast(Literal[
|
|
76
|
+
return cast("Literal['postgresql', 'postgres']", scheme)
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
def parse_and_validate_dsn(dsn: object) -> ModelParsedDSN:
|
|
@@ -200,17 +200,8 @@ from omnibase_infra.validation.validator_runtime_shape import (
|
|
|
200
200
|
enforce_execution_shape,
|
|
201
201
|
)
|
|
202
202
|
|
|
203
|
-
# Security validation
|
|
204
|
-
from omnibase_infra.validation.validator_security import
|
|
205
|
-
SENSITIVE_METHOD_PATTERNS,
|
|
206
|
-
SENSITIVE_PARAMETER_NAMES,
|
|
207
|
-
SecurityRuleId,
|
|
208
|
-
convert_to_validation_error,
|
|
209
|
-
has_sensitive_parameters,
|
|
210
|
-
is_sensitive_method_name,
|
|
211
|
-
validate_handler_security,
|
|
212
|
-
validate_method_exposure,
|
|
213
|
-
)
|
|
203
|
+
# Security validation (OMN-1277) - contract-driven validator
|
|
204
|
+
from omnibase_infra.validation.validator_security import ValidatorSecurity
|
|
214
205
|
|
|
215
206
|
# Topic category validation for execution shape enforcement
|
|
216
207
|
from omnibase_infra.validation.validator_topic_category import (
|
|
@@ -229,8 +220,6 @@ __all__: list[str] = [
|
|
|
229
220
|
"EXECUTION_SHAPE_RULES", # Runtime shape validation rules
|
|
230
221
|
"INFRA_MAX_UNIONS", # Infrastructure max union threshold
|
|
231
222
|
"NODE_ARCHETYPE_EXPECTED_CATEGORIES", # Node archetype categories
|
|
232
|
-
"SENSITIVE_METHOD_PATTERNS", # Security validation patterns
|
|
233
|
-
"SENSITIVE_PARAMETER_NAMES", # Security validation names
|
|
234
223
|
"TOPIC_CATEGORY_PATTERNS", # Topic category patterns
|
|
235
224
|
"TOPIC_SUFFIXES", # Topic suffix constants
|
|
236
225
|
# Errors
|
|
@@ -239,7 +228,6 @@ __all__: list[str] = [
|
|
|
239
228
|
"RoutingCoverageError", # Routing coverage error (OMN-958)
|
|
240
229
|
# Enums
|
|
241
230
|
"EnumContractViolationSeverity", # Contract violation severity
|
|
242
|
-
"SecurityRuleId", # Security rule identifiers
|
|
243
231
|
# Models
|
|
244
232
|
"ModelAnyTypeValidationResult", # Any type validation result (OMN-1276)
|
|
245
233
|
"ModelContractLintResult", # Contract lint result
|
|
@@ -261,9 +249,9 @@ __all__: list[str] = [
|
|
|
261
249
|
"TopicCategoryASTVisitor", # Topic category AST visitor
|
|
262
250
|
"TopicCategoryValidator", # Topic category validator
|
|
263
251
|
"ValidationAggregator", # Validation error aggregation (OMN-1091)
|
|
252
|
+
"ValidatorSecurity", # Contract-driven security validator (OMN-1277)
|
|
264
253
|
# Functions
|
|
265
254
|
"check_routing_coverage_ci", # CI routing coverage check
|
|
266
|
-
"convert_to_validation_error", # Error conversion utility
|
|
267
255
|
"detect_message_category", # Message category detection
|
|
268
256
|
"discover_message_types", # Message type discovery
|
|
269
257
|
"discover_registered_routes", # Route discovery
|
|
@@ -271,9 +259,7 @@ __all__: list[str] = [
|
|
|
271
259
|
"enforce_execution_shape", # Execution shape enforcement
|
|
272
260
|
"get_execution_shape_rules", # Get shape rules
|
|
273
261
|
"get_validation_summary", # Get validation summary
|
|
274
|
-
"has_sensitive_parameters", # Sensitive parameter check
|
|
275
262
|
"is_isinstance_union", # Check if union is in isinstance() call
|
|
276
|
-
"is_sensitive_method_name", # Sensitive method check
|
|
277
263
|
"lint_contract_file", # Lint single contract file
|
|
278
264
|
"lint_contracts_ci", # CI contract linting
|
|
279
265
|
"lint_contracts_in_directory", # Directory contract linting
|
|
@@ -286,7 +272,6 @@ __all__: list[str] = [
|
|
|
286
272
|
"validate_execution_shapes", # Execution shape validation
|
|
287
273
|
"validate_execution_shapes_ci", # CI shape validation
|
|
288
274
|
"validate_handler_registration", # Handler registration validation (OMN-1098)
|
|
289
|
-
"validate_handler_security", # Handler security validation
|
|
290
275
|
"validate_infra_all", # Infrastructure validation
|
|
291
276
|
"validate_infra_architecture", # Infrastructure architecture
|
|
292
277
|
"validate_infra_circular_imports", # Circular import check
|
|
@@ -298,7 +283,6 @@ __all__: list[str] = [
|
|
|
298
283
|
"validate_localhandler_in_file", # LocalHandler file validation (OMN-743)
|
|
299
284
|
"validate_message_chain", # Message chain validation
|
|
300
285
|
"validate_message_on_topic", # Topic message validation
|
|
301
|
-
"validate_method_exposure", # Method exposure validation
|
|
302
286
|
"validate_patterns", # Re-export from omnibase_core
|
|
303
287
|
"validate_routing_coverage_on_startup", # Startup routing check
|
|
304
288
|
"validate_topic_categories_in_directory", # Directory topic validation
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
contract_kind: validation_subcontract
|
|
2
|
+
validation:
|
|
3
|
+
version:
|
|
4
|
+
major: 1
|
|
5
|
+
minor: 0
|
|
6
|
+
patch: 0
|
|
7
|
+
validator_id: security
|
|
8
|
+
validator_name: ONEX Security Validator
|
|
9
|
+
validator_description: |
|
|
10
|
+
Validates Python source files for security concerns in handler implementations.
|
|
11
|
+
Detects sensitive method names that should be private, credential exposure in
|
|
12
|
+
method signatures, and admin/internal operations exposed publicly.
|
|
13
|
+
|
|
14
|
+
This validator performs static AST analysis to identify:
|
|
15
|
+
- Public methods with sensitive names (get_password, get_secret, etc.)
|
|
16
|
+
- Method signatures containing sensitive parameter names
|
|
17
|
+
- Admin/internal methods exposed without underscore prefix
|
|
18
|
+
- Decrypt operations exposed publicly
|
|
19
|
+
|
|
20
|
+
Part of OMN-1277: Refactor validators to be Handler and contract-driven.
|
|
21
|
+
target_patterns:
|
|
22
|
+
- "**/*.py"
|
|
23
|
+
exclude_patterns:
|
|
24
|
+
- "**/node_modules/**"
|
|
25
|
+
- "**/.git/**"
|
|
26
|
+
- "**/venv/**"
|
|
27
|
+
- "**/.venv/**"
|
|
28
|
+
- "**/__pycache__/**"
|
|
29
|
+
- "**/archived/**"
|
|
30
|
+
- "**/tests/**"
|
|
31
|
+
- "**/*_test.py"
|
|
32
|
+
- "**/test_*.py"
|
|
33
|
+
- "**/conftest.py"
|
|
34
|
+
rules:
|
|
35
|
+
- rule_id: sensitive_method_exposed
|
|
36
|
+
description: |
|
|
37
|
+
Detects public methods with sensitive names that should be private.
|
|
38
|
+
Matches patterns: get_password, get_secret, get_token, get_api_key,
|
|
39
|
+
get_credential*, fetch_password, fetch_secret, fetch_token,
|
|
40
|
+
validate_password, check_password, verify_password.
|
|
41
|
+
severity: error
|
|
42
|
+
enabled: true
|
|
43
|
+
parameters:
|
|
44
|
+
patterns:
|
|
45
|
+
- "^get_password$"
|
|
46
|
+
- "^get_secret$"
|
|
47
|
+
- "^get_token$"
|
|
48
|
+
- "^get_api_key$"
|
|
49
|
+
- "^get_credential"
|
|
50
|
+
- "^fetch_password$"
|
|
51
|
+
- "^fetch_secret$"
|
|
52
|
+
- "^fetch_token$"
|
|
53
|
+
- "^validate_password$"
|
|
54
|
+
- "^check_password$"
|
|
55
|
+
- "^verify_password$"
|
|
56
|
+
- rule_id: credential_in_signature
|
|
57
|
+
description: |
|
|
58
|
+
Detects method signatures containing sensitive parameter names.
|
|
59
|
+
Matches parameters: password, secret, token, api_key, apikey,
|
|
60
|
+
access_key, private_key, credential, auth_token, bearer_token,
|
|
61
|
+
decrypt_key, encryption_key.
|
|
62
|
+
severity: error
|
|
63
|
+
enabled: true
|
|
64
|
+
parameters:
|
|
65
|
+
sensitive_params:
|
|
66
|
+
- "password"
|
|
67
|
+
- "secret"
|
|
68
|
+
- "token"
|
|
69
|
+
- "api_key"
|
|
70
|
+
- "apikey"
|
|
71
|
+
- "access_key"
|
|
72
|
+
- "private_key"
|
|
73
|
+
- "credential"
|
|
74
|
+
- "auth_token"
|
|
75
|
+
- "bearer_token"
|
|
76
|
+
- "decrypt_key"
|
|
77
|
+
- "encryption_key"
|
|
78
|
+
- rule_id: admin_method_public
|
|
79
|
+
description: |
|
|
80
|
+
Detects admin or internal methods exposed without underscore prefix.
|
|
81
|
+
Matches patterns: admin_*, internal_*.
|
|
82
|
+
severity: warning
|
|
83
|
+
enabled: true
|
|
84
|
+
parameters:
|
|
85
|
+
patterns:
|
|
86
|
+
- "^admin_"
|
|
87
|
+
- "^internal_"
|
|
88
|
+
- rule_id: decrypt_method_public
|
|
89
|
+
description: |
|
|
90
|
+
Detects decrypt operations exposed publicly.
|
|
91
|
+
Matches patterns: decrypt_*.
|
|
92
|
+
severity: warning
|
|
93
|
+
enabled: true
|
|
94
|
+
parameters:
|
|
95
|
+
patterns:
|
|
96
|
+
- "^decrypt_"
|
|
97
|
+
# ============================================================================
|
|
98
|
+
# LINE-BASED SUPPRESSION
|
|
99
|
+
# ============================================================================
|
|
100
|
+
# If ANY pattern below appears on a source line, ALL security violations
|
|
101
|
+
# on that line are suppressed.
|
|
102
|
+
#
|
|
103
|
+
# Usage example:
|
|
104
|
+
# def get_password(self) -> str: # ONEX_EXCLUDE: security - required for legacy API
|
|
105
|
+
# def admin_reset(self) -> None: # security-ok: admin endpoint with auth guard
|
|
106
|
+
# ============================================================================
|
|
107
|
+
suppression_comments:
|
|
108
|
+
- "# ONEX_EXCLUDE: security"
|
|
109
|
+
- "# security-ok:"
|
|
110
|
+
severity_default: error
|
|
111
|
+
fail_on_error: true
|
|
112
|
+
fail_on_warning: false
|
|
113
|
+
max_violations: 0
|
|
114
|
+
parallel_execution: true
|
|
@@ -37,10 +37,12 @@ from typing import TypedDict
|
|
|
37
37
|
import yaml
|
|
38
38
|
|
|
39
39
|
from omnibase_core.models.common import ModelValidationMetadata
|
|
40
|
+
from omnibase_core.models.primitives import ModelSemVer
|
|
40
41
|
from omnibase_core.models.validation.model_union_pattern import ModelUnionPattern
|
|
41
42
|
from omnibase_core.validation import (
|
|
42
43
|
CircularImportValidator,
|
|
43
44
|
ModelContractValidationResult,
|
|
45
|
+
ModelImportValidationResult,
|
|
44
46
|
ModelModuleImportResult,
|
|
45
47
|
ModelValidationResult,
|
|
46
48
|
validate_architecture,
|
|
@@ -423,7 +425,11 @@ INFRA_NODES_PATH = "src/omnibase_infra/nodes/"
|
|
|
423
425
|
# (+2 unions for EnumPolicyType | str in validate_policy_type_value)
|
|
424
426
|
# (-1 union: fix PolicyTypeInput validator coercion, changed return
|
|
425
427
|
# type from str | EnumPolicyType to EnumPolicyType)
|
|
426
|
-
|
|
428
|
+
# - 98 (2026-01-20): OMN-1277 security validator contract refactoring (+2 unions)
|
|
429
|
+
# ast.FunctionDef | ast.AsyncFunctionDef for AST method type checking
|
|
430
|
+
# - 105 (2026-01-21): Contract-driven handler config loading (+4 unions)
|
|
431
|
+
# ModelHandlerContract transport config fields and lifecycle types
|
|
432
|
+
INFRA_MAX_UNIONS = 105
|
|
427
433
|
|
|
428
434
|
# Maximum allowed architecture violations in infrastructure code.
|
|
429
435
|
# Set to 0 (strict enforcement) to ensure one-model-per-file principle is always followed.
|
|
@@ -747,13 +753,14 @@ def validate_infra_contract_deep(
|
|
|
747
753
|
return result
|
|
748
754
|
|
|
749
755
|
# If result is a different type, wrap it in ModelContractValidationResult
|
|
750
|
-
# Default to
|
|
751
|
-
# Check '
|
|
756
|
+
# Default to is_valid=False for unknown result types to avoid silently masking failures
|
|
757
|
+
# Check 'is_valid' first, then 'passed' as fallback (some validators use passed)
|
|
752
758
|
return ModelContractValidationResult(
|
|
753
|
-
|
|
759
|
+
is_valid=getattr(result, "is_valid", getattr(result, "passed", False)),
|
|
754
760
|
score=getattr(result, "score", 0.0),
|
|
755
|
-
|
|
761
|
+
violations=getattr(result, "violations", getattr(result, "errors", [])),
|
|
756
762
|
warnings=getattr(result, "warnings", []),
|
|
763
|
+
interface_version=ModelSemVer(major=1, minor=0, patch=0),
|
|
757
764
|
)
|
|
758
765
|
|
|
759
766
|
|
|
@@ -1318,29 +1325,33 @@ def validate_infra_union_usage(
|
|
|
1318
1325
|
# Note: ModelValidationMetadata uses extra="allow", so extension fields
|
|
1319
1326
|
# are accepted as int values.
|
|
1320
1327
|
# See docstring "Metadata Extension Fields" section for field documentation.
|
|
1328
|
+
#
|
|
1329
|
+
# Extension fields are passed via model_construct() to satisfy type checker
|
|
1330
|
+
# while preserving runtime behavior with extra="allow".
|
|
1331
|
+
metadata_fields: dict[str, object] = {
|
|
1332
|
+
# Standard ModelValidationMetadata fields (formally defined)
|
|
1333
|
+
"validation_type": "union_usage",
|
|
1334
|
+
"files_processed": files_processed,
|
|
1335
|
+
"violations_found": len(filtered_issues),
|
|
1336
|
+
"total_unions": total_count, # Base field: all unions found
|
|
1337
|
+
"max_unions": max_unions, # Base field: configured threshold
|
|
1338
|
+
"strict_mode": strict, # Base field: whether strict mode enabled
|
|
1339
|
+
# Extension fields (via extra="allow", typed as int)
|
|
1340
|
+
# These provide transparency into the exclusion logic:
|
|
1341
|
+
"non_optional_unions": threshold_count, # What threshold actually checks
|
|
1342
|
+
"optional_unions_excluded": optional_count, # X | None patterns
|
|
1343
|
+
"isinstance_unions_excluded": isinstance_count, # isinstance(x, A | B) patterns
|
|
1344
|
+
}
|
|
1321
1345
|
return ModelValidationResult(
|
|
1322
1346
|
is_valid=is_valid,
|
|
1323
1347
|
errors=filtered_issues,
|
|
1324
|
-
metadata=ModelValidationMetadata(
|
|
1325
|
-
# Standard ModelValidationMetadata fields (formally defined)
|
|
1326
|
-
validation_type="union_usage",
|
|
1327
|
-
files_processed=files_processed,
|
|
1328
|
-
violations_found=len(filtered_issues),
|
|
1329
|
-
total_unions=total_count, # Base field: all unions found
|
|
1330
|
-
max_unions=max_unions, # Base field: configured threshold
|
|
1331
|
-
strict_mode=strict, # Base field: whether strict mode enabled
|
|
1332
|
-
# Extension fields (via extra="allow", typed as int)
|
|
1333
|
-
# These provide transparency into the exclusion logic:
|
|
1334
|
-
non_optional_unions=threshold_count, # What threshold actually checks
|
|
1335
|
-
optional_unions_excluded=optional_count, # X | None patterns
|
|
1336
|
-
isinstance_unions_excluded=isinstance_count, # isinstance(x, A | B) patterns
|
|
1337
|
-
),
|
|
1348
|
+
metadata=ModelValidationMetadata.model_construct(**metadata_fields), # type: ignore[arg-type]
|
|
1338
1349
|
)
|
|
1339
1350
|
|
|
1340
1351
|
|
|
1341
1352
|
def validate_infra_circular_imports(
|
|
1342
1353
|
directory: PathInput = INFRA_SRC_PATH,
|
|
1343
|
-
) ->
|
|
1354
|
+
) -> ModelImportValidationResult:
|
|
1344
1355
|
"""
|
|
1345
1356
|
Check for circular imports in infrastructure code.
|
|
1346
1357
|
|
|
@@ -1351,7 +1362,7 @@ def validate_infra_circular_imports(
|
|
|
1351
1362
|
directory: Directory to check. Defaults to infrastructure source.
|
|
1352
1363
|
|
|
1353
1364
|
Returns:
|
|
1354
|
-
|
|
1365
|
+
ModelImportValidationResult with detailed import validation results.
|
|
1355
1366
|
Use result.has_circular_imports to check for issues.
|
|
1356
1367
|
"""
|
|
1357
1368
|
validator = CircularImportValidator(source_path=Path(directory))
|
|
@@ -1361,7 +1372,7 @@ def validate_infra_circular_imports(
|
|
|
1361
1372
|
def validate_infra_all(
|
|
1362
1373
|
directory: PathInput = INFRA_SRC_PATH,
|
|
1363
1374
|
nodes_directory: PathInput = INFRA_NODES_PATH,
|
|
1364
|
-
) -> dict[str, ValidationResult |
|
|
1375
|
+
) -> dict[str, ValidationResult | ModelImportValidationResult]:
|
|
1365
1376
|
"""
|
|
1366
1377
|
Run all validations on infrastructure code.
|
|
1367
1378
|
|
|
@@ -1379,7 +1390,7 @@ def validate_infra_all(
|
|
|
1379
1390
|
Returns:
|
|
1380
1391
|
Dictionary mapping validator name to result.
|
|
1381
1392
|
"""
|
|
1382
|
-
results: dict[str, ValidationResult |
|
|
1393
|
+
results: dict[str, ValidationResult | ModelImportValidationResult] = {}
|
|
1383
1394
|
|
|
1384
1395
|
# HIGH priority validators
|
|
1385
1396
|
results["architecture"] = validate_infra_architecture(directory)
|
|
@@ -1394,7 +1405,7 @@ def validate_infra_all(
|
|
|
1394
1405
|
|
|
1395
1406
|
|
|
1396
1407
|
def get_validation_summary(
|
|
1397
|
-
results: dict[str, ValidationResult |
|
|
1408
|
+
results: dict[str, ValidationResult | ModelImportValidationResult],
|
|
1398
1409
|
) -> dict[str, int | list[str]]:
|
|
1399
1410
|
"""
|
|
1400
1411
|
Generate a summary of validation results.
|
|
@@ -486,6 +486,47 @@ pattern_exemptions:
|
|
|
486
486
|
- CLAUDE.md (Registry Naming Conventions)
|
|
487
487
|
ticket: OMN-953
|
|
488
488
|
# ==========================================================================
|
|
489
|
+
# TransitionNotificationPublisher publisher_id Exemption (OMN-1139)
|
|
490
|
+
# ==========================================================================
|
|
491
|
+
# publisher_id is a human-readable semantic identifier similar to scheduler_id.
|
|
492
|
+
# It identifies the publisher instance and may be auto-generated or user-specified.
|
|
493
|
+
- file_pattern: 'model_transition_notification_publisher_metrics\.py'
|
|
494
|
+
violation_pattern: "Field 'publisher_id' should use UUID"
|
|
495
|
+
reason: >
|
|
496
|
+
publisher_id is a human-readable semantic identifier (e.g., "transition-publisher-<uuid>") that identifies the publisher instance. Follows the same pattern as scheduler_id.
|
|
497
|
+
|
|
498
|
+
documentation:
|
|
499
|
+
- CLAUDE.md (Registry Naming Conventions)
|
|
500
|
+
ticket: OMN-1139
|
|
501
|
+
# ==========================================================================
|
|
502
|
+
# ModelTransitionNotificationOutboxMetrics table_name Exemption (OMN-1139)
|
|
503
|
+
# ==========================================================================
|
|
504
|
+
# table_name is the database table name string, not an entity reference.
|
|
505
|
+
- file_pattern: 'model_transition_notification_outbox_metrics\.py'
|
|
506
|
+
violation_pattern: "Field 'table_name' might reference an entity"
|
|
507
|
+
reason: >
|
|
508
|
+
table_name is the database table name string (e.g., "transition_notification_outbox"), not an entity reference. It identifies the outbox table for metrics reporting and does not require ID + display_name pattern.
|
|
509
|
+
|
|
510
|
+
documentation:
|
|
511
|
+
- CLAUDE.md (Registry Naming Conventions)
|
|
512
|
+
ticket: OMN-1139
|
|
513
|
+
# ==========================================================================
|
|
514
|
+
# TransitionNotificationOutbox Method Count Exemption (OMN-1139)
|
|
515
|
+
# ==========================================================================
|
|
516
|
+
# Outbox pattern requires lifecycle (start/stop), storage (store/cleanup),
|
|
517
|
+
# processing (process_pending), and multiple config properties for observability.
|
|
518
|
+
# NOTE: Pattern anchored with src/omnibase_infra/runtime/ prefix to match only
|
|
519
|
+
# the production file, not test files.
|
|
520
|
+
- file_pattern: 'src/omnibase_infra/runtime/transition_notification_outbox\.py'
|
|
521
|
+
class_pattern: "Class 'TransitionNotificationOutbox'"
|
|
522
|
+
violation_pattern: 'has \d+ methods'
|
|
523
|
+
reason: >
|
|
524
|
+
Transactional outbox pattern inherently requires: lifecycle methods (start/stop), storage operations (store/cleanup_processed), processing (process_pending), background loop (_processor_loop), metrics (get_metrics), and configuration properties (table_name, batch_size, poll_interval, is_running, shutdown_timeout, notifications_stored/processed/failed, strict_transaction_mode). Method count is driven by pattern requirements, not poor design.
|
|
525
|
+
|
|
526
|
+
documentation:
|
|
527
|
+
- src/omnibase_infra/schemas/schema_transition_notification_outbox.sql
|
|
528
|
+
ticket: OMN-1139
|
|
529
|
+
# ==========================================================================
|
|
489
530
|
# ServiceTimeoutEmitter/Scanner Naming Exemptions (OMN-1055)
|
|
490
531
|
# ==========================================================================
|
|
491
532
|
# These service classes follow the CLAUDE.md Service<Name> naming convention.
|
|
@@ -1032,6 +1073,27 @@ pattern_exemptions:
|
|
|
1032
1073
|
- CLAUDE.md (ONEX Architecture - Handler Types)
|
|
1033
1074
|
ticket: OMN-1097
|
|
1034
1075
|
# ==========================================================================
|
|
1076
|
+
# Handler Bootstrap Source Exemptions (OMN-1087)
|
|
1077
|
+
# ==========================================================================
|
|
1078
|
+
# HandlerBootstrapSource provides hardcoded handler descriptors for core
|
|
1079
|
+
# infrastructure handlers. The "Handler" in the name refers to ONEX handler
|
|
1080
|
+
# concepts, consistent with HandlerContractSource and HandlerPluginLoader.
|
|
1081
|
+
#
|
|
1082
|
+
# Pattern specificity note: Uses separate class_pattern + violation_pattern
|
|
1083
|
+
# (not combined "Class name .* contains...") for precise targeting. All three
|
|
1084
|
+
# patterns must match: exact filename, exact class name, and violation type.
|
|
1085
|
+
# This is consistent with HandlerContractSource/HandlerPluginLoader exemptions.
|
|
1086
|
+
- file_pattern: 'handler_bootstrap_source\.py'
|
|
1087
|
+
class_pattern: "Class name 'HandlerBootstrapSource'"
|
|
1088
|
+
violation_pattern: "contains anti-pattern 'Handler'"
|
|
1089
|
+
reason: >
|
|
1090
|
+
HandlerBootstrapSource centralizes hardcoded handler registration for core infrastructure handlers (Consul, DB, HTTP, Vault). The "Handler" refers to ONEX handler concepts, consistent with HandlerContractSource. This is legitimate handler infrastructure code per OMN-1087.
|
|
1091
|
+
|
|
1092
|
+
documentation:
|
|
1093
|
+
- docs/architecture/HANDLER_PROTOCOL_DRIVEN_ARCHITECTURE.md
|
|
1094
|
+
- CLAUDE.md (ONEX Architecture - Handler Types)
|
|
1095
|
+
ticket: OMN-1087
|
|
1096
|
+
# ==========================================================================
|
|
1035
1097
|
# Handler Plugin Loader Exemptions (OMN-1132)
|
|
1036
1098
|
# ==========================================================================
|
|
1037
1099
|
# HandlerPluginLoader discovers and loads ONEX handlers from contract YAML files.
|
|
@@ -1456,16 +1518,17 @@ pattern_exemptions:
|
|
|
1456
1518
|
# ProjectorShell Exemptions (OMN-1169)
|
|
1457
1519
|
# ==========================================================================
|
|
1458
1520
|
# ProjectorShell implements ProtocolEventProjector protocol which requires:
|
|
1459
|
-
# - Protocol properties (projector_id, aggregate_type, consumed_events, is_placeholder)
|
|
1460
|
-
# - Core methods (project, get_state)
|
|
1461
|
-
# - SQL execution modes
|
|
1462
|
-
# - Value extraction (_extract_values, _resolve_path, _get_event_type)
|
|
1463
|
-
# -
|
|
1464
|
-
# Total: 11 methods, all cohesive to the projector
|
|
1465
|
-
#
|
|
1466
|
-
#
|
|
1521
|
+
# - Protocol properties (projector_id, aggregate_type, consumed_events, contract, is_placeholder)
|
|
1522
|
+
# - Core methods (project, get_state, get_states, partial_update, upsert_partial)
|
|
1523
|
+
# - SQL execution modes handled by MixinProjectorSqlOperations
|
|
1524
|
+
# - Value extraction (_extract_values, _resolve_path, _get_event_type, _execute_projection)
|
|
1525
|
+
# - Notification integration (via MixinProjectorNotificationPublishing)
|
|
1526
|
+
# Total: 11 methods, all cohesive to the contract-driven projector pattern.
|
|
1527
|
+
# OMN-1139: Added notification publishing support via mixin composition.
|
|
1528
|
+
# NOTE: Pattern anchored with src/omnibase_infra/runtime/ prefix to match only
|
|
1529
|
+
# the production file at src/omnibase_infra/runtime/projector_shell.py.
|
|
1467
1530
|
# This prevents matching test files in tests/unit/runtime/ or tests/integration/runtime/.
|
|
1468
|
-
- file_pattern: 'omnibase_infra/runtime/projector_shell\.py
|
|
1531
|
+
- file_pattern: 'src/omnibase_infra/runtime/projector_shell\.py'
|
|
1469
1532
|
class_pattern: "Class 'ProjectorShell'"
|
|
1470
1533
|
violation_pattern: 'has \d+ methods'
|
|
1471
1534
|
reason: >
|
|
@@ -1631,6 +1694,47 @@ pattern_exemptions:
|
|
|
1631
1694
|
documentation:
|
|
1632
1695
|
- docs/patterns/binding_config_resolver.md
|
|
1633
1696
|
ticket: OMN-765
|
|
1697
|
+
# ==========================================================================
|
|
1698
|
+
# HandlerMCP Method Count Exemption (OMN-1282)
|
|
1699
|
+
# ==========================================================================
|
|
1700
|
+
# MCP handler is a complex infrastructure component requiring many methods:
|
|
1701
|
+
# - 4 ProtocolHandler methods (initialize, shutdown, execute, health_check)
|
|
1702
|
+
# - 2 factory methods for route handlers (_create_health_endpoint, _create_tools_list_endpoint)
|
|
1703
|
+
# - 2 server lifecycle methods (_start_http_server, _stop_http_server)
|
|
1704
|
+
# - 3 execution/operation methods (_run_server, _execute_tool_operation, _execute_describe)
|
|
1705
|
+
# Complexity is inherent to MCP protocol requirements and uvicorn server management.
|
|
1706
|
+
- file_pattern: 'handler_mcp\.py'
|
|
1707
|
+
class_pattern: "Class 'HandlerMCP'"
|
|
1708
|
+
violation_pattern: 'has \d+ methods'
|
|
1709
|
+
reason: >
|
|
1710
|
+
HandlerMCP is a complex infrastructure handler implementing MCP protocol with internal uvicorn server lifecycle. The 11 methods are cohesive: 4 ProtocolHandler interface methods, 2 factory methods for Starlette route handlers (explicit closure capture), 2 server lifecycle methods (start/stop), and 3 operation methods. Splitting would fragment the unified MCP server abstraction.
|
|
1711
|
+
|
|
1712
|
+
documentation:
|
|
1713
|
+
- CLAUDE.md (Handler Plugin Loader Patterns)
|
|
1714
|
+
ticket: OMN-1282
|
|
1715
|
+
# ==========================================================================
|
|
1716
|
+
# Registry API Models - service_name Exemptions (OMN-1278)
|
|
1717
|
+
# ==========================================================================
|
|
1718
|
+
# service_name in registry API models is the Consul service name for discovery,
|
|
1719
|
+
# NOT an entity reference. It's an external Consul identifier.
|
|
1720
|
+
- file_pattern: 'services/registry_api/models/model_registry_node_view\.py'
|
|
1721
|
+
violation_pattern: "Field 'service_name' might reference an entity"
|
|
1722
|
+
reason: >
|
|
1723
|
+
service_name is the Consul service name for service discovery (e.g., "onex-effect-abc123"). This is an external Consul identifier, NOT an ONEX entity reference. The node_id field provides the UUID identifier; service_name is how the node appears in Consul's catalog.
|
|
1724
|
+
|
|
1725
|
+
documentation:
|
|
1726
|
+
- CLAUDE.md (Type Annotation Conventions)
|
|
1727
|
+
- Consul service discovery documentation
|
|
1728
|
+
ticket: OMN-1278
|
|
1729
|
+
- file_pattern: 'services/registry_api/models/model_registry_instance_view\.py'
|
|
1730
|
+
violation_pattern: "Field 'service_name' might reference an entity"
|
|
1731
|
+
reason: >
|
|
1732
|
+
service_name is the Consul service name for live instance discovery (e.g., "my-service"). This is an external Consul identifier, NOT an ONEX entity reference. The node_id and service_id fields provide UUID identifiers; service_name is the Consul catalog name.
|
|
1733
|
+
|
|
1734
|
+
documentation:
|
|
1735
|
+
- CLAUDE.md (Type Annotation Conventions)
|
|
1736
|
+
- Consul service discovery documentation
|
|
1737
|
+
ticket: OMN-1278
|
|
1634
1738
|
# Architecture validator exemptions
|
|
1635
1739
|
# These handle one-model-per-file violations for domain-grouped protocols
|
|
1636
1740
|
architecture_exemptions:
|
|
@@ -183,7 +183,7 @@ def get_message_id(envelope: ModelEventEnvelope[object]) -> UUID:
|
|
|
183
183
|
"""
|
|
184
184
|
# envelope_id is typed as UUID in ModelEventEnvelope, but mypy sees it as Any
|
|
185
185
|
# due to the generic type parameter. Cast is required for type safety.
|
|
186
|
-
return cast(UUID, envelope.envelope_id)
|
|
186
|
+
return cast("UUID", envelope.envelope_id)
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
def get_correlation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
|
|
@@ -200,7 +200,7 @@ def get_correlation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
|
|
|
200
200
|
correlation_id = envelope.correlation_id
|
|
201
201
|
if correlation_id is None:
|
|
202
202
|
return None
|
|
203
|
-
return cast(UUID, correlation_id)
|
|
203
|
+
return cast("UUID", correlation_id)
|
|
204
204
|
|
|
205
205
|
|
|
206
206
|
def get_causation_id(envelope: ModelEventEnvelope[object]) -> UUID | None:
|
|
@@ -893,7 +893,7 @@ def enforce_execution_shape(node_archetype: EnumNodeArchetype) -> Callable[[F],
|
|
|
893
893
|
|
|
894
894
|
# Cast wrapper to F - functools.wraps preserves the signature at runtime,
|
|
895
895
|
# and mypy cannot prove the equivalence, so we use an explicit cast.
|
|
896
|
-
return cast(F, wrapper)
|
|
896
|
+
return cast("F", wrapper)
|
|
897
897
|
|
|
898
898
|
return decorator
|
|
899
899
|
|