Feature: Explicit exception handling and error classification As a security-conscious developer I want structured error types with redaction and classification So that errors are safe for users and diagnostics are preserved Background: Given a security exceptions test environment # -- Error code mapping --------------------------------------------------- Scenario: Classify a ValidationError as 422 Given a ValidationError with message "field is invalid" When I classify the security exception Then the error code should be 422 And the error code name should be "VALIDATION_FAILED" And the error handling category should be "CLIENT" Scenario: Classify a ResourceNotFoundError as 404 Given a ResourceNotFoundError for resource "plan" with id "01PLAN001" When I classify the security exception Then the error code should be 404 And the error code name should be "NOT_FOUND" Scenario: Classify an AuthenticationError as 401 Given an AuthenticationError with message "invalid token" When I classify the security exception Then the error code should be 401 And the error code name should be "UNAUTHORIZED" Scenario: Classify an AuthorizationError as 403 Given an AuthorizationError with message "access denied" When I classify the security exception Then the error code should be 403 And the error code name should be "FORBIDDEN" Scenario: Classify a RateLimitError as 429 Given a RateLimitError with message "slow down" When I classify the security exception Then the error code should be 429 And the error code name should be "RATE_LIMITED" Scenario: Classify a DatabaseError as 522 Given a DatabaseError with message "connection lost" When I classify the security exception Then the error code should be 522 And the error handling category should be "SERVER" Scenario: Classify a ConfigurationError as 525 Given a ConfigurationError with message "missing key" When I classify the security exception Then the error code should be 525 Scenario: Classify a NetworkError as 524 Given a NetworkError with message "timeout" When I classify the security exception Then the error code should be 524 Scenario: Classify a FileSystemError as 523 Given a FileSystemError with message "permission denied" When I classify the security exception Then the error code should be 523 Scenario: Classify a ProviderError as 520 Given a ProviderError with message "model failed" When I classify the security exception Then the error code should be 520 Scenario: Classify a TokenLimitExceededError as 526 Given a TokenLimitExceededError with message "context too long" When I classify the security exception Then the error code should be 526 Scenario: Classify a BusinessRuleViolation as 400 Given a BusinessRuleViolation with message "invalid transition" When I classify the security exception Then the error code should be 400 Scenario: Classify a PlanError as 400 Given a PlanError with message "plan stuck" When I classify the security exception Then the error code should be 400 Scenario: Classify an unknown Exception as 500 Given a bare Exception with message "something broke" When I classify the security exception Then the error code should be 500 And the error handling category should be "SERVER" Scenario: Classify an ExecutionError as 521 Given an ExecutionError with message "agent failed" When I classify the security exception Then the error code should be 521 Scenario: Classify a StreamRoutingError as 528 Given a StreamRoutingError with message "routing failed" When I classify the security exception Then the error code should be 528 Scenario: Classify a ModelNotAvailableError as 527 Given a ModelNotAvailableError with message "deprecated" When I classify the security exception Then the error code should be 527 Scenario: Classify a ResourceConflictError as 409 Given a ResourceConflictError with message "already exists" When I classify the security exception Then the error code should be 409 Scenario: Classify a MissingConfigurationError as 525 Given a MissingConfigurationError with message "key not set" When I classify the security exception Then the error code should be 525 Scenario: Classify an ExternalServiceError as 503 Given an ExternalServiceError with message "service down" When I classify the security exception Then the error code should be 503 # -- Secret redaction ----------------------------------------------------- Scenario: Redact API key from error details Given redaction test details with key "api_key" and value "sk-abc123secret" When I redact the error details Then the redacted detail "api_key" should be "***REDACTED***" Scenario: Redact password from error details Given redaction test details with key "password" and value "my-secret-pass" When I redact the error details Then the redacted detail "password" should be "***REDACTED***" Scenario: Redact OpenAI key pattern from string value Given redaction test details with key "message" and value "Failed with key sk-abcdefghijklmnopqrstuvwxyz" When I redact the error details Then the redacted detail "message" should contain "***REDACTED***" And the redacted detail "message" should not contain "sk-abcdefghijklmnopqrstuvwxyz" Scenario: Redact JWT token pattern from string value Given redaction test details with key "log" and value "auth eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 failed" When I redact the error details Then the redacted detail "log" should contain "***REDACTED***" Scenario: Redact nested dict values Given redaction test details with nested key "config" containing secret_key "abc123" When I redact the error details Then the redacted nested detail "config" key "secret_key" should be "***REDACTED***" Scenario: Non-sensitive values pass through unchanged Given redaction test details with key "plan_id" and value "01PLAN001" When I redact the error details Then the redacted detail "plan_id" should be "01PLAN001" Scenario: Redact GitHub PAT pattern from string value Given redaction test details with key "msg" and value "token ghp_abcdefghijklmnopqrstuvwxyz0123456 expired" When I redact the error details Then the redacted detail "msg" should contain "***REDACTED***" Scenario: Redact value with redact_value function Given a redaction test string value "key=sk-abcdefghijklmnopqrstuvwxyz" When I redact the string value Then the redacted string should contain "***REDACTED***" # -- Wrapping unexpected exceptions ---------------------------------------- Scenario: Wrap a bare Exception into CleverAgentsError Given a bare Exception with message "internal crash" When I wrap the unexpected exception Then the wrapped error should be a CleverAgentsError And the wrapped error message should be "An unexpected error occurred" And the wrapped error details should have key "exception_type" Scenario: Wrap preserves CleverAgentsError as-is Given a CleverAgentsError with message "known issue" When I wrap the unexpected exception Then the wrapped error message should be "known issue" Scenario: Wrap merges context into CleverAgentsError details Given a CleverAgentsError with message "known issue" And a wrapping context with key "plan_id" and value "01PLAN001" When I wrap the unexpected exception Then the wrapped error details should have key "plan_id" Scenario: Wrap with custom safe message Given a bare Exception with message "segfault" When I wrap the unexpected exception with message "Operation failed" Then the wrapped error message should be "Operation failed" Scenario: Wrap redacts secrets in context Given a bare Exception with message "oops" And a wrapping context with key "api_key" and value "sk-secret123456789012345" When I wrap the unexpected exception Then the wrapped error details key "api_key" should be "***REDACTED***" # -- CLI formatting ------------------------------------------------------- Scenario: Format error for CLI output Given a ValidationError with message "name is required" When I classify the security exception And I format the error for CLI Then the error CLI output should contain "422" And the error CLI output should contain "VALIDATION_FAILED" And the error CLI output should contain "name is required" Scenario: Format error with details for CLI output Given a detailed CleverAgentsError "db fail" with detail "table" as "plans" When I classify the security exception And I format the error for CLI Then the error CLI output should contain "table: plans"