Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,67 @@ if is_open:
- Never suppress InfraUnavailableError from circuit breaker
- Never use circuit breaker for non-transient errors

### Node Introspection Security Considerations

The `MixinNodeIntrospection` mixin uses Python reflection (via the `inspect` module) to automatically discover node capabilities. This provides powerful service discovery but has security implications that developers should understand.

**What Gets Exposed via Introspection**:
- Public method names (potential operations a node can perform)
- Method signatures (parameter names and type annotations)
- Protocol and mixin implementations (discovered capabilities)
- FSM state information (if `MixinFSM` is present)
- Endpoint URLs (health, API, metrics paths)
- Node metadata (name, version, type from contract)

**Built-in Protections**:
The mixin includes several filtering mechanisms to limit exposure:
- **Private method exclusion**: Methods prefixed with `_` are excluded from capability discovery
- **Utility method filtering**: Common utility prefixes (`get_*`, `set_*`, `initialize*`, `start_*`, `stop_*`) are filtered out
- **Operation keyword matching**: Only methods matching operation keywords (`execute`, `process`, `handle`, `run`, `perform`, `compute`, `validate`, `transform`, `aggregate`, `orchestrate`) are reported as capabilities
- **Configurable exclusions**: The `exclude_prefixes` parameter allows additional filtering

**Best Practices for Node Developers**:
- Prefix internal/sensitive methods with `_` to exclude them from introspection
- Avoid exposing sensitive business logic in public method names
- Use generic operation names that don't reveal implementation details (e.g., `process_request` instead of `decrypt_and_forward_to_payment_gateway`)
- Review exposed capabilities before deploying to production environments
- Consider network segmentation for introspection event topics in multi-tenant environments
- Use the `exclude_prefixes` parameter to filter additional method patterns if needed

**Example - Reviewing Exposed Capabilities**:
```python
from omnibase_infra.mixins import MixinNodeIntrospection

class MyNode(MixinNodeIntrospection):
def execute_operation(self, data: dict) -> dict:
"""Public operation - WILL be exposed."""
return self._internal_process(data)

def _internal_process(self, data: dict) -> dict:
"""Private method - will NOT be exposed."""
return {"processed": True}

def get_status(self) -> str:
"""Utility method - will NOT be exposed (get_* prefix filtered)."""
return "healthy"

# Review what gets exposed
node = MyNode()
capabilities = node.get_capabilities()
# capabilities will only include "execute_operation"
```

**Network Security Considerations**:
- Introspection data is published to Kafka topics (`*.introspection.*`)
- In multi-tenant environments, ensure proper topic ACLs
- Consider whether introspection topics should be accessible outside the cluster
- Monitor introspection topic consumers for unauthorized access

**Related**:
- Implementation: `src/omnibase_infra/mixins/mixin_node_introspection.py`
- Ticket: OMN-893
- See `MixinNodeIntrospection.get_capabilities()` for filtering logic details

### Service Integration Architecture
- **Adapter Pattern** - External services wrapped in ONEX adapters (Consul, Kafka, Vault)
- **Connection Pooling** - Database connections managed through dedicated pool managers
Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,10 @@ line-ending = "auto"
# Matches omnibase_core settings for consistency across ONEX ecosystem
select = ["E", "F", "W", "C90", "I", "N", "UP", "YTT", "S", "BLE", "FBT", "B", "A", "COM", "C4", "DTZ", "T10", "EM", "EXE", "ISC", "ICN", "G", "INP", "PIE", "T20", "PT", "Q", "RSE", "RET", "SLF", "SIM", "TID", "TCH", "ARG", "PTH", "ERA", "PD", "PGH", "PL", "TRY", "NPY", "RUF"]
ignore = [
# Type annotation style rules (both needed - UP007 handles Union, UP045 handles Optional)
# Note: ONEX prefers X | None syntax (PEP 604). These ignores allow legacy Optional[X]/Union[X,Y]
# Type annotation style rules
# Note: ONEX prefers X | None syntax (PEP 604). This ignore allows legacy Union[X,Y]
# if introduced, but codebase is already compliant. Can be removed to enforce strict PEP 604.
"UP007", # Union[X, Y] -> X | Y (allow legacy Union syntax if present)
"UP045", # Optional[X] -> X | None (allow legacy Optional syntax if present)
"S101", # Allow assert statements in tests
"E501", # Line too long (technical debt - will fix incrementally)
"BLE001", # Blind exception catching (technical debt)
Expand Down
2 changes: 1 addition & 1 deletion src/omnibase_infra/handlers/handler_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async def initialize(self, config: dict[str, object]) -> None:
)

timeout_raw = config.get("timeout", _DEFAULT_TIMEOUT_SECONDS)
if isinstance(timeout_raw, (int, float)):
if isinstance(timeout_raw, int | float):
self._timeout = float(timeout_raw)

try:
Expand Down
20 changes: 14 additions & 6 deletions src/omnibase_infra/mixins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 OmniNode Team
"""Infrastructure mixins for common cross-cutting concerns.
"""ONEX Infrastructure Mixins.

This module provides reusable mixins for infrastructure components to implement
common patterns such as circuit breakers, retry logic, health checks, and more.

Mixins follow ONEX patterns:
Reusable mixin classes providing:
- Thread-safe async operations
- Infrastructure error integration
- Correlation ID propagation
Expand All @@ -16,5 +13,16 @@
CircuitState,
MixinAsyncCircuitBreaker,
)
from omnibase_infra.mixins.mixin_node_introspection import (
CapabilitiesDict,
IntrospectionCacheDict,
MixinNodeIntrospection,
)

__all__ = ["MixinAsyncCircuitBreaker", "CircuitState"]
__all__ = [
"CapabilitiesDict",
"CircuitState",
"IntrospectionCacheDict",
"MixinAsyncCircuitBreaker",
"MixinNodeIntrospection",
]
Loading
Loading