f281fa3b24
CI / lint (pull_request) Successful in 35s
CI / typecheck (pull_request) Successful in 50s
CI / security (pull_request) Successful in 50s
CI / quality (pull_request) Successful in 32s
CI / unit_tests (pull_request) Successful in 3m32s
CI / integration_tests (pull_request) Successful in 59s
CI / build (pull_request) Successful in 34s
CI / lint (push) Successful in 33s
CI / build (push) Successful in 37s
CI / quality (push) Successful in 48s
CI / typecheck (push) Successful in 48s
CI / security (push) Successful in 1m4s
CI / integration_tests (push) Successful in 1m18s
CI / coverage (pull_request) Successful in 3m34s
CI / status-check (pull_request) Successful in 3s
CI / unit_tests (push) Successful in 3m45s
CI / coverage (push) Successful in 3m34s
CI / status-check (push) Successful in 3s
Implements Wave 3 of the cleveractors-core integration (ADR-2026, ADR-2028). ## AgentFactory - Added optional credentials: dict[str, dict[str, str]] | None parameter to __init__. Stored as self.credentials. - When creating LLMAgent instances, the full credentials dict is forwarded via a new credentials constructor kwarg, threading per-request API keys without touching the stored actor config_dict. - Added explicit type annotation ReactiveAgentFactory: type[AgentFactory]. - _create_agent_instance raises ConfigurationError when credentials is not None but does not contain an entry for the requested provider (AC4 compliance). ## LLMAgent - Added optional credentials: dict[str, str] | None parameter to __init__. Stored as self._credentials; config_dict is never modified. - LangChain client construction deferred to first access (lazy init) via a chat_model property backed by _ensure_chat_model(). The property setter allows test-injection of mock models without going through the lazy-init path. - _create_chat_model() dispatches to credential-injection / standalone paths. - Extracted to llm_client.py and llm_providers.py for modularity. - Defined shared module-level constants DEFAULT_MODEL, DEFAULT_TEMPERATURE, DEFAULT_MAX_TOKENS to eliminate duplicated magic numbers across llm.py, runtime.py, and factory.py. - Added public credentials property exposing self._credentials. - Added type narrowing guard in chat_model property to satisfy static analysis. - Added temperature_override type validation in process_message. - Guarded cleanup() null-assignment with _chat_model_lock (TOCTOU fix). ## SSRF Prevention (ADR-2028) - _validate_base_url(): https-only, userinfo rejection, localhost rejection, raw IP literal rejection, numeric-hostname (dotted-hex/octal/compact) rejection, percent-decode loop with iteration cap (10), trailing-dot FQDN strip. - DNS resolution intentionally omitted (blocking call in async path). - Canonical URL reconstruction uses lowercased scheme. ## Credential Leak Prevention - All logger.exception(...) replaced with logger.debug(..., exc_info=True). - Error messages use type(e).__name__ instead of str(e). - process_message exception chains broken with from None to prevent LangChain authentication errors from leaking via __cause__. ## Runtime fixes - Executor._execute_llm: shallow copy for setdefault mutations. - Executor._execute_graph: restructured try/finally for resource cleanup. - Uses DEFAULT_MODEL, DEFAULT_TEMPERATURE, DEFAULT_MAX_TOKENS from llm.py. - Defensive copy of credentials dict in Executor.__init__ to prevent caller mutation after construction. ## Test improvements - Added BDD scenarios for llm_imports.py ImportError fallback branches using sys.modules manipulation with a custom import hook, exercised via subprocess. - Added BDD scenario for AgentFactory.create_agents_from_config() credential threading to all created agents. - Removed tautological dataclass test scenarios (NodeUsage, ActorResult) from runtime_coverage.feature. - Fixed misleading scenario title in runtime_coverage.feature (exception chain suppressed, not chained) and updated step to assert __cause__ is None. - Added CHANGELOG entry for ReactiveAgentFactory backward-compatibility alias. - Removed duplicate log emission in _check_known_provider_domain. ISSUES CLOSED: #12
25 lines
1.2 KiB
Gherkin
25 lines
1.2 KiB
Gherkin
Feature: Executor Constructor Argument Validation
|
|
As a router developer
|
|
I want Executor.__init__ to reject invalid argument types immediately
|
|
So that misconfigurations fail fast with a clear error message
|
|
|
|
# These scenarios exercise the argument-type validation guards in
|
|
# Executor.__init__ (src/cleveractors/runtime.py:79-95). Each guard
|
|
# raises ConfigurationError when the argument is not a dict.
|
|
|
|
Scenario: Executor rejects non-dict config_dict
|
|
Given I construct an Executor with config_dict set to "not a dict"
|
|
Then a ConfigurationError should be raised containing "config_dict must be a dict"
|
|
|
|
Scenario: Executor rejects non-dict credentials
|
|
Given I construct an Executor with credentials set to "not a dict"
|
|
Then a ConfigurationError should be raised containing "credentials must be a dict"
|
|
|
|
Scenario: Executor rejects non-dict limits
|
|
Given I construct an Executor with limits set to "not a dict"
|
|
Then a ConfigurationError should be raised containing "limits must be a dict"
|
|
|
|
Scenario: Executor rejects non-dict pricing
|
|
Given I construct an Executor with pricing set to "not a dict"
|
|
Then a ConfigurationError should be raised containing "pricing must be a dict"
|