Feature: SEC5 - Secrets masking and validation
  As a security-conscious developer
  I want secrets automatically masked in logs and CLI output
  So that API keys and tokens are never leaked

  # --- Core redaction utility ---

  Scenario: Redact OpenAI API key pattern
    Given a string containing "sk-proj-abc123def456ghi789"
    When I redact the string
    Then the redacted value should be "***REDACTED***"

  Scenario: Redact Anthropic API key pattern
    Given a string containing "sk-ant-api03-xyzzy1234567890abcdef"
    When I redact the string
    Then the redacted value should be "***REDACTED***"

  Scenario: Redact token pattern
    Given a string containing "tok_01HXYZ1234567890ABCDEF"
    When I redact the string
    Then the redacted value should be "***REDACTED***"

  Scenario: Redact generic bearer token
    Given a string containing "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJz"
    When I redact the string
    Then the redacted value should contain "***REDACTED***"

  Scenario: Non-secret strings are not redacted
    Given a string containing "hello world this is normal text"
    When I redact the string
    Then the redacted value should be "hello world this is normal text"

  Scenario: Mixed text with embedded secret is partially redacted
    Given a string containing "My key is sk-proj-abc123def456ghi789 and name is Bob"
    When I redact the string
    Then the redacted value should contain "***REDACTED***"
    And the redacted value should contain "My key is"
    And the redacted value should contain "and name is Bob"

  Scenario: Empty string is returned unchanged
    Given a string containing ""
    When I redact the string
    Then the redacted value should be empty

  # --- Dict redaction ---

  Scenario: Dict with sensitive key names are masked
    Given a dict with key "api_key" and value "sk-proj-abc123"
    When I redact the dict
    Then the key "api_key" should have value "***REDACTED***"

  Scenario: Dict with password key is masked
    Given a dict with key "password" and value "mysecretpass"
    When I redact the dict
    Then the key "password" should have value "***REDACTED***"

  Scenario: Dict with secret key is masked
    Given a dict with key "secret" and value "topsecretvalue"
    When I redact the dict
    Then the key "secret" should have value "***REDACTED***"

  Scenario: Dict with token key is masked
    Given a dict with key "token" and value "sometoken123"
    When I redact the dict
    Then the key "token" should have value "***REDACTED***"

  Scenario: Dict with credential key is masked
    Given a dict with key "credential" and value "cred-value"
    When I redact the dict
    Then the key "credential" should have value "***REDACTED***"

  Scenario: Dict with non-sensitive key is not masked
    Given a dict with key "username" and value "bob"
    When I redact the dict
    Then the key "username" should have value "bob"

  Scenario: Nested dict values are redacted recursively
    Given a nested dict with inner key "api_key" and value "sk-proj-nested"
    When I redact the dict
    Then the nested key "api_key" should have value "***REDACTED***"

  Scenario: Dict with pattern-matched value is masked regardless of key name
    Given a dict with key "config_value" and value "sk-ant-api03-somekey123"
    When I redact the dict
    Then the key "config_value" should have value "***REDACTED***"

  Scenario: Dict redaction respects show_secrets flag
    Given a dict with key "api_key" and value "sk-proj-abc123"
    When I redact the dict with show_secrets enabled
    Then the key "api_key" should have value "sk-proj-abc123"

  # --- Sensitive key detection ---

  Scenario Outline: Sensitive key names are detected
    When I check if "<key>" is a sensitive key
    Then the sensitivity check should be true

    Examples:
      | key             |
      | api_key         |
      | API_KEY         |
      | password        |
      | secret          |
      | token           |
      | credential      |
      | openai_api_key  |
      | ANTHROPIC_API_KEY |
      | access_token    |
      | auth_token      |
      | private_key     |

  Scenario Outline: Non-sensitive key names are not flagged
    When I check if "<key>" is a sensitive key
    Then the sensitivity check should be false

    Examples:
      | key            |
      | username       |
      | email          |
      | name           |
      | description    |
      | project_id     |
      | token_count    |

  # --- Database URL masking ---

  Scenario: SQLite URL is not masked
    Given a database URL "sqlite:///path/to/db.sqlite"
    When I mask the database URL
    Then the masked URL should be "sqlite:///path/to/db.sqlite"

  Scenario: PostgreSQL URL with credentials is masked
    Given a database URL "postgresql://admin:s3cret@localhost:5432/mydb"
    When I mask the database URL
    Then the masked URL should contain "***"
    And the masked URL should contain "localhost"
    And the masked URL should not contain "s3cret"

  # --- Global show_secrets flag ---

  Scenario: Global show_secrets defaults to false
    When I check the global show_secrets flag
    Then the flag should be false

  Scenario: Global show_secrets can be toggled
    When I set the global show_secrets flag to true
    Then the flag should be true
    When I set the global show_secrets flag to false
    Then the flag should be false

  # --- structlog processor ---

  Scenario: Structlog masking processor redacts event dict values
    Given a structlog event dict with key "api_key" and value "sk-proj-secret123"
    When the masking processor is applied
    Then the event dict key "api_key" should be "***REDACTED***"

  Scenario: Structlog masking processor redacts event message
    Given a structlog event dict with event "Failed with key sk-ant-api03-xyz"
    When the masking processor is applied
    Then the event message should contain "***REDACTED***"
    And the event message should not contain "sk-ant-api03-xyz"

  Scenario: Structlog masking processor passes non-secret events
    Given a structlog event dict with event "User logged in successfully"
    When the masking processor is applied
    Then the event message should be "User logged in successfully"

  # --- CLI error detail redaction ---

  Scenario: Error details with secret values are redacted
    Given error details with key "api_key" and value "sk-proj-leaked"
    When I redact the error details for CLI display
    Then the redacted details key "api_key" should be "***REDACTED***"

  Scenario: Error details with non-secret values are preserved
    Given error details with key "plan_id" and value "01HXR123"
    When I redact the error details for CLI display
    Then the redacted details key "plan_id" should be "01HXR123"

  # --- Secret pattern registration ---

  Scenario: Custom secret pattern can be registered
    Given the default secret patterns
    When I register a custom pattern "custom_[a-z0-9]{16}"
    And I redact the string "my custom_abcdef1234567890 key"
    Then the redacted value should contain "***REDACTED***"
    And the redacted value should not contain "custom_abcdef1234567890"
