Files
cleveragents-core/docs/api/shared.md
T

4.1 KiB

cleveragents.shared — Secret Redaction Utilities

The cleveragents.shared package exposes cross-cutting helpers that can be used from any layer without violating architecture boundaries. At the moment its public surface focuses on a single responsibility: deterministic masking of secrets before they reach logs, error payloads, or tool output.

All exports live in cleveragents.shared.redaction and are re-exported from the package root for convenience.


Quick start

from cleveragents.shared import redact_dict, register_pattern

# redact nested structures before logging
payload = {
    "provider_api_key": "sk-ant-api03-secret-1234567890",
    "token_usage": 1280,
    "upstream": {
        "authorization": "Bearer 0123456789ABCDEFGHIJKLMNOPQRSTUV",
    },
}
print(redact_dict(payload))
# {'provider_api_key': '***REDACTED***', 'token_usage': 1280,
#  'upstream': {'authorization': '***REDACTED***'}}

# extend detection with an internal pattern
register_pattern(r"my-secret-[0-9a-f]{16}")

Global redaction controls

Symbol Description
REDACTED Constant string (***REDACTED***) used as the replacement token.
get_show_secrets() -> bool Returns the global flag that determines whether redaction is bypassed.
set_show_secrets(value: bool) -> None Toggles the flag. Accepts only boolean values and is thread-safe.

When get_show_secrets() returns True, the redaction helpers shortcut and return the original data unmodified—useful for debugging in trusted environments. The flag is protected by a lock so it can be flipped safely from CLI options or unit tests.


Key helpers

is_sensitive_key(name: str) -> bool

Heuristically classifies dictionary keys as sensitive (e.g. containing "token", "secret", "password"). False positives such as token_count are explicitly whitelisted in the implementation.

redact_value(value: str) -> str

Scans a string for known secret patterns (OpenAI, Anthropic, Google keys, tok_ IDs, bearer tokens, long hex strings) and replaces each match with REDACTED. Additional patterns can be registered at runtime via register_pattern().

redact_dict(data: Mapping[str, Any], *, show_secrets: bool | None = None) -> dict

Recursively traverses nested dictionaries and lists, redacting sensitive keys with REDACTED and scrubbing string values via redact_value. By default it honours the global get_show_secrets() flag; override it per call with show_secrets=True when you explicitly need the original values.

mask_database_url(url: str) -> str

Masks the password segment of SQL connection URLs. SQLite URLs are returned unchanged; any scheme://user:password@host pattern is rewritten as scheme://user:***@host.

register_pattern(pattern: str) -> None

Allows projects or extensions to add custom regular expressions to the redaction list. Patterns are compiled under a lock so multiple workers can register safely. Passing an empty pattern raises ValueError.


Structlog integration

secrets_masking_processor(logger, method_name, event_dict) implements the structlog processor contract. It walks every value in the event dictionary, redacting keys detected by is_sensitive_key and values using redact_value and redact_dict. The processor is designed to be inserted near the top of the structlog pipeline so that downstream formatters never observe raw secrets.

import structlog
from cleveragents.shared import secrets_masking_processor

structlog.configure(
    processors=[
        secrets_masking_processor,
        structlog.processors.JSONRenderer(),
    ],
)

Thread-safety notes

The module guards both the global show_secrets flag and the list of compiled patterns with locks. You can safely call set_show_secrets() or register_pattern() from concurrent tasks without corrupting shared state.

Because all helpers return new dictionaries (never mutating inputs), you may confidently hand the redacted payloads to logging subsystems or telemetry pipelines without affecting the original objects used by business logic.