
    Jj                        d Z ddlZddlZddlZddlZ ej        e          Z eh d          Z	 eh d          Z
 ej        dd                                          dv Zg dZd	Z ej        d
e d          ZdZdZ ej        d          Z ej        de de de ej                  Z ej        de de ej        ej        z            ZdZ ej        de dej        ej        z            ZdZ ej        de dej                  Z ej        dej                  ZdZ ej        de dej                  Z ej        d          Z  ej        d          Z! ej        d ej                  Z" ej        d!ej                  Z# ej        d"          Z$ ej        d#          Z% ej        d$          Z& ej        d%          Z' ej        d&ej                  Z( ej        d'          Z) ej        d(d)*                    e          z   d*z             Z+d+d+d,d-d.d/d0e,d1e-d2e-d3e-d4e,d5e,d6e,fd7Z.d8e,d6e,fd9Z/d:e,d6e,fd;Z0d<e,d6e,fd=Z1d<e,d6e,fd>Z2d0e3d6e,fd?Z4d<e,d6e,fd@Z5d<e,d6e,fdAZ6d8e,d6e,fdBZ7dCdCdCdDd<e,dEe8dFe8dGe8d6e,f
dHZ9 eh dI          Z:dJe,dz  d6e8fdKZ;	 dWdCdLdMe,dJe,dz  dEe8d6e,fdNZ<dOe,d6e,fdPZ= e>dQ eD                       Z?d<e,d6e8fdRZ@dSZAd<e,d6e8fdTZB G dU dVejC                  ZDdS )Xa2  Regex-based secret redaction for logs and tool output.

Applies pattern matching to mask API keys, tokens, and credentials
before they reach log files, verbose output, or gateway logs.

Short tokens (< 18 chars) are fully masked. Longer tokens preserve
the first 6 and last 4 characters for debuggability.
    N>   x-amz-signaturejwtkeyauthcodetokenapikeysecretapi_keysessionid_tokenpassword	signatureaccess_tokenclient_secretrefresh_token>   r   r   r   r   r	   r
   r   r   r   private_keyr   authorizationr   r   HERMES_REDACT_SECRETStrue>   1onyesr   ))zsk-[A-Za-z0-9_-]{10,}zghp_[A-Za-z0-9]{10,}zgithub_pat_[A-Za-z0-9_]{10,}zgho_[A-Za-z0-9]{10,}zghu_[A-Za-z0-9]{10,}zghs_[A-Za-z0-9]{10,}zghr_[A-Za-z0-9]{10,}zxapp-\d+-[A-Za-z0-9-]{10,}zxox[baprs]-[A-Za-z0-9-]{10,}zAIza[A-Za-z0-9_-]{30,}zpplx-[A-Za-z0-9]{10,}zfal_[A-Za-z0-9_-]{10,}zfc-[A-Za-z0-9]{10,}zbb_live_[A-Za-z0-9_-]{10,}zgAAAA[A-Za-z0-9_=-]{20,}zAKIA[A-Z0-9]{16}zsk_live_[A-Za-z0-9]{10,}zsk_test_[A-Za-z0-9]{10,}zrk_live_[A-Za-z0-9]{10,}zSG\.[A-Za-z0-9_-]{10,}zhf_[A-Za-z0-9]{10,}zr8_[A-Za-z0-9]{10,}znpm_[A-Za-z0-9]{10,}zpypi-[A-Za-z0-9_-]{10,}zdop_v1_[A-Za-z0-9]{10,}zdoo_v1_[A-Za-z0-9]{10,}zam_[A-Za-z0-9_-]{10,}zsk_[A-Za-z0-9_]{10,}ztvly-[A-Za-z0-9]{10,}zexa_[A-Za-z0-9]{10,}zgsk_[A-Za-z0-9]{10,}zsyt_[A-Za-z0-9]{10,}zretaindb_[A-Za-z0-9]{10,}zhsk-[A-Za-z0-9]{10,}zmem0_[A-Za-z0-9]{10,}zbrv_[A-Za-z0-9]{10,}zxai-[A-Za-z0-9]{30,}zntn_[A-Za-z0-9]{10,}zfw-[A-Za-z0-9]{30,}zfw_[A-Za-z0-9]{30,}zfpk_[A-Za-z0-9]{30,}z9(?:API_?KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)z([A-Z0-9_]{0,50}z&[A-Z0-9_]{0,50})\s*=\s*(['\"]?)(\S+)\2z?(?:api[ _.\-]?key|token|secret|passwd|password|credential|auth)z(['\"]?)([^\s&]+?)\2(?=[\s&]|$)z0^(?:os\.(?:getenv|environ)|process\.env|\$ENV\{)z'((?:[A-Za-z0-9_\-]+\.)+[A-Za-z0-9_.\-]*z![A-Za-z0-9_.\-]*|[A-Za-z0-9_.\-]*z$[A-Za-z0-9_.\-]*\.[A-Za-z0-9_.\-]+)=z((^[ \t]*(?:export[ \t]+)?[A-Za-z0-9_\-]*z[A-Za-z0-9_\-]*)=z:(?:api[ _.\-]?key|token|secret|passwd|password|credential)z(^[ \t]*[A-Za-z0-9_.\-]*z,[A-Za-z0-9_.\-]*)(:[ \t]*)(?!['\"])([^\s&]+)z(?:api_?[Kk]ey|token|secret|password|access_token|refresh_token|auth_token|bearer|secret_value|raw_secret|secret_input|key_material)z("z")\s*:\s*"([^"]+)"z?((?:Proxy-)?Authorization:\s*)([A-Za-z][\w.+-]*\s+)?([^\s\"']+)zS(?:x-api-key|x-goog-api-key|api-key|apikey|x-api-token|x-auth-token|x-access-token)(z\s*:\s*)(\S+)z#(bot)?(\d{8,}):([-A-Za-z0-9_]{30,})zH-----BEGIN[A-Z ]*PRIVATE KEY-----[\s\S]*?-----END[A-Z ]*PRIVATE KEY-----zO((?:postgres(?:ql)?|mysql|mongodb(?:\+srv)?|redis|amqp)://[^:\s]+:)([^@\s]+)(@)zA((?:https?|wss?|git|ssh|ftp|ftps|sftp)://)([^\s:@/]{8,})(@[^\s]+)z2eyJ[A-Za-z0-9_-]{10,}(?:\.[A-Za-z0-9_=-]{4,}){0,2}z (\+[1-9]\d{6,14})(?![A-Za-z0-9])z;(https?|wss?|ftp)://([^\s/?#]+)([^\s?#]*)\?([^\s#]+)(#\S*)?z+(https?|wss?|ftp)://([^/\s:@]+):([^/\s@]+)@z`\b((?:GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE|CONNECT)\s+[^ \t\r\n\"']*?)\?([^ \t\r\n\"']+)zH^[A-Za-z_][A-Za-z0-9_.-]*=[^&\s]*(?:&[A-Za-z_][A-Za-z0-9_.-]*=[^&\s]*)+$z(?<![A-Za-z0-9_-])(|z)(?![A-Za-z0-9_-])      *** )headtailfloorplaceholderemptyvaluer    r!   r"   r#   r$   returnc                d    | s|S t          |           |k     r|S | d|          d| | d          S )u  Mask a secret for display, preserving ``head`` and ``tail`` characters.

    Canonical helper for display-time redaction across Hermes — used by
    ``hermes config``, ``hermes status``, ``hermes dump``, and anywhere
    a secret needs to be shown truncated for debuggability while still
    keeping the bulk hidden.

    Args:
        value:       The secret to mask. ``None``/empty returns ``empty``.
        head:        Leading characters to preserve. Default 4.
        tail:        Trailing characters to preserve. Default 4.
        floor:       Values shorter than ``head + tail + floor_margin`` are
                     fully masked (returns ``placeholder``). Default 12 —
                     matches the existing config/status/dump convention.
        placeholder: Value returned for too-short inputs. Default ``"***"``.
        empty:       Value returned when ``value`` is falsy (None, ""). The
                     caller can override this to e.g. ``color("(not set)",
                     Colors.DIM)`` for user-facing display.

    Examples:
        >>> mask_secret("sk-proj-abcdef1234567890")
        'sk-p...7890'
        >>> mask_secret("short")                         # fully masked
        '***'
        >>> mask_secret("")                              # empty default
        ''
        >>> mask_secret("", empty="(not set)")           # empty override
        '(not set)'
        >>> mask_secret("long-token", head=6, tail=4, floor=18)
        '***'
    Nz...)len)r%   r    r!   r"   r#   r$   s         2/home/rurouni/.hermes/hermes-agent/agent/redact.pymask_secretr*   5  sO    P  
5zzEETEl..udUVV}...    r   c                 0    | sdS t          | ddd          S )uO   Mask a log token — conservative 18-char floor, preserves 6 prefix / 4 suffix.r      r      )r    r!   r"   )r*   )r   s    r)   _mask_tokenr/   d  s(      uu11B7777r+   queryc                 `   | s| S g }|                      d          D ]~}d|vr|                    |           |                    d          \  }}}|                                t          v r|                    | d           i|                    |           d                    |          S )a   Redact sensitive parameter values in a URL query string.

    Handles `k=v&k=v` format. Sensitive keys (case-insensitive) have values
    replaced with `***`. Non-sensitive keys pass through unchanged.
    Empty or malformed pairs are preserved as-is.
    &=z=***)splitappend	partitionlower_SENSITIVE_QUERY_PARAMSjoin)r0   partspairr   _r%   s         r)   _redact_query_stringr=   l  s      EC    d??LLs++Q99;;111LLC&&&&LL88E??r+   textc                 f    dt           j        dt          fd}t                              ||           S )u   Scan text for URLs with query strings and redact sensitive params.

    Catches opaque tokens that don't match vendor prefix regexes, e.g.
    `https://example.com/cb?code=ABC123&state=xyz` → `...?code=***&state=xyz`.
    mr&   c                    |                      d          }|                      d          }|                      d          }t          |                      d                    }|                      d          pd}| d| | d| | S )	N         r      r   ://?groupr=   )r@   scheme	authoritypathr0   fragments         r)   _subz&_redact_url_query_params.<locals>._sub  s    GGAJJ	wwqzz$QWWQZZ00771::#@@Y@@@u@h@@@r+   )reMatchstr_URL_WITH_QUERY_REsubr>   rN   s     r)   _redact_url_query_paramsrU     sD    A AS A A A A !!$---r+   c                 :    t                               d |           S )zStrip `user:password@` from HTTP/WS/FTP URLs.

    DB protocols (postgres, mysql, mongodb, redis, amqp) are handled
    separately by `_DB_CONNSTR_RE`.
    c                 ^    |                      d           d|                      d           dS )NrB   rF   rC   z:***@rI   r@   s    r)   <lambda>z&_redact_url_userinfo.<locals>.<lambda>  s+    QWWQZZ55AGGAJJ555 r+   )_URL_USERINFO_RErS   r>   s    r)   _redact_url_userinfor]     s%     55  r+   c                     t          | dnt          |                     }|s|S t          |          }t          |          }|S )a  Mask secrets in a CDP/browser endpoint URL before it is logged.

    The global ``redact_sensitive_text`` deliberately passes web-URL query
    params and ``user:pass@`` userinfo through unmasked (OAuth callbacks,
    magic-link / pre-signed URLs the agent is meant to follow -- see the
    web-URL note above). CDP discovery endpoints are NOT such a workflow:
    their query-string tokens and userinfo passwords are pure credentials
    that must never reach the logs. So for CDP URLs we opt INTO the two URL
    redactors that the global pass leaves off.

    This is the single source of truth for redacting a CDP URL that is passed
    *directly* to a log or error message. Callers that instead need to redact an
    exception whose text embeds the URL (e.g. a ``websockets`` connect error)
    should route that through their own error-text helper, which delegates here
    -- see ``tools.browser_supervisor._redact_cdp_error_text``.
    Nr   )redact_sensitive_textrQ   rU   r]   )r%   r>   s     r)   redact_cdp_urlr`     sK    " !u}#e**EED #D))D%%DKr+   c                 f    dt           j        dt          fd}t                              ||           S )zARedact sensitive query params in HTTP access-log request targets.r@   r&   c                 ~    |                      d          }t          |                      d                    }| d| S )NrB   rC   rG   rH   )r@   prefixr0   s      r)   rN   z6_redact_http_request_target_query_params.<locals>._sub  s<    $QWWQZZ00""5"""r+   )rO   rP   rQ   _HTTP_REQUEST_TARGET_QUERY_RErS   rT   s     r)   (_redact_http_request_target_query_paramsre     s>    # #S # # # # ),,T4888r+   c                     | rd| v sd| vr| S t                               |                                           s| S t          |                                           S )uN  Redact sensitive values in a form-urlencoded body.

    Only applies when the entire input looks like a pure form body
    (k=v&k=v with no newlines, no other text). Single-line non-form
    text passes through unchanged. This is a conservative pass — the
    `_redact_url_query_params` function handles embedded query strings.
    
r2   )_FORM_BODY_REmatchstripr=   r\   s    r)   _redact_form_bodyrk     sZ      44<<3d??tzz||,, 

---r+   c                 h    | sdS d}t           D ]}|                     |          r|} n|rd| dndS )u  Redact a prefix-matched credential to a NON-REUSABLE sentinel.

    Unlike :func:`_mask_token` (which keeps head/tail chars — fine for logs
    that are never fed back into a config), this emits a marker that:

    * cannot be mistaken for a usable-but-truncated key, so an agent that
      reads it from a config file and writes it back does NOT corrupt the
      stored credential into a dead 13-char string (issue #35519); and
    * still does not leak the secret material (no head/tail chars).

    The vendor prefix label is preserved for debuggability so the agent can
    still tell *which* credential is present (e.g. a GitHub PAT vs an OpenAI
    key) without seeing any of its bytes.
    u   «redacted-secret»r   u   «redacted:u   …»)_PREFIX_SUBSTRINGS
startswith)r   labelrS   s      r)   _mask_token_nonreusablerp     sl      %$$ E!  C   	EE	 */I%%%%%4IIr+   F)force	code_file	file_readrq   rr   rs   c                  
 | dS t          | t                    st          |           } | s| S |s	t          s| S |rd}t          |           r.|rt          nt
          
t                              
fd|           } |sd| v rXd }t                              ||           } d| vr6t                              ||           } t                              ||           } d| v r"d| v rd	 }t                              ||           } d| v r"d| vrd
 }t                              ||           } d| v sd| v rt                              d |           } d| v rt                              d |           } d| v rd }t                              ||           } d| v rd| v rt                               d|           } d| v rY|rd }t"                              ||           } nt"                              d |           } t$                              d |           } d| v rt&                              d |           } d| v rd| v rt)          |           } d| v rd }	t*                              |	|           } | S )u  Apply all redaction patterns to a block of text.

    Safe to call on any string -- non-matching text passes through unchanged.
    Enabled by default. Disable via security.redact_secrets: false in config.yaml.
    Set force=True for safety boundaries that must never return raw secrets
    regardless of the user's global logging redaction preference.

    Set code_file=True to skip the ENV-assignment and JSON-field regex
    patterns when the text is known to be source code (e.g. MAX_TOKENS=***
    constants, "apiKey": "test" fixtures). Prefix patterns, auth headers,
    private keys, DB connstrings, JWTs, and URL secrets are still redacted.

    Set file_read=True for file *content* returned to the agent (read_file /
    search_files / cat). Secrets are STILL redacted — they are never exposed —
    but prefix-matched credentials are replaced with a non-reusable sentinel
    (``«redacted:ghp_…»``) instead of a head/tail-preserving mask
    (``ghp_S1...Pn2T``). The old mask looked like a real-but-truncated key, so
    an agent reading it from config.yaml and writing it back silently corrupted
    the stored credential into a dead 13-char value → 401 (issue #35519). The
    sentinel is syntactically invalid as a token, so it can't be mistaken for a
    usable key or written back as one. Implies code_file=True (config/data
    files shouldn't trigger the source-code ENV/JSON false-positive paths).

    Performance: each regex pattern is gated behind a cheap substring
    pre-check (e.g. ``"=" in text`` for ENV assignments, ``"://" in text``
    for URLs, ``"eyJ" in text`` for JWTs). On a typical hermes log line
    (no secrets) this drops the 13-pattern scan from ~5.6us to ~1.8us per
    record (-68%). The pre-checks are conservative — false positives
    still run the full regex, which then doesn't match. False negatives
    are impossible because every regex requires the gated substring to
    match.
    NTc                 @     |                      d                    S )NrB   rX   )r@   _prefix_subs    r)   rZ   z'redact_sensitive_text.<locals>.<lambda>#  s    AGGAJJ(?(? r+   r3   c                    |                      d          |                      d          |                      d          }}}t                              |          r|                      d          S | d| t          |           | S )NrB   rC   rD   r   r3   rI   _ENV_LOOKUP_VALUE_REri   r/   )r@   namequoter%   s       r)   _redact_envz*redact_sensitive_text.<locals>._redact_env(  s{    %&WWQZZQWWQZZUe (--e44 &771::%CCCE(:(:CECCCr+   rF   :"c                     |                      d          |                      d          }}t                              |          r|                      d          S | dt          |           dS )NrB   rC   r   z: "r~   rx   )r@   r   r%   s      r)   _redact_jsonz+redact_sensitive_text.<locals>._redact_json;  sf    WWQZZU (--e44 &771::%77+e"4"47777r+   c                    |                      d          |                      d          |                      d          }}}t                              |          r|                      d          S | | t          |           S )NrB   rC   rD   r   rx   )r@   r   sepr%   s       r)   _redact_yamlz+redact_sensitive_text.<locals>._redact_yamlI  ss    "#''!**aggajj!''!**%S (--e44 &771::%8s8K$6$6888r+   uthorizationUTHORIZATIONc                     |                      d          |                      d          pdz   t          |                      d                    z   S )NrB   rC   r   rD   rI   r/   rY   s    r)   rZ   z'redact_sensitive_text.<locals>.<lambda>X  s;    aggajjAGGAJJ$4"5AGGAJJ8O8OO r+   c                 r    |                      d          t          |                      d                    z   S )NrB   rC   r   rY   s    r)   rZ   z'redact_sensitive_text.<locals>.<lambda>`  s'    aggajj;qwwqzz#:#:: r+   c                 h    |                      d          pd}|                      d          }| | dS )NrB   r   rC   z:***rX   )r@   rc   digitss      r)   _redact_telegramz/redact_sensitive_text.<locals>._redact_telegramf  s9    WWQZZ%2FWWQZZF*f****r+   BEGINz-----z[REDACTED PRIVATE KEY]c                    |                      d          }|                    d          r*|                    d          r|                      d          S |                      d           d|                      d           S )NrC   {}r   rB   r   rD   )rI   rn   endswith)r@   pws     r)   
_redact_dbz)redact_sensitive_text.<locals>._redact_dbx  sp    WWQZZ==%% &"++c*:*: &771::%''!**55555r+   c                 \    |                      d           d|                      d           S )NrB   r   rD   rX   rY   s    r)   rZ   z'redact_sensitive_text.<locals>.<lambda>  s(    1771::0N0N!''!**0N0N r+   c                     |                      d           t          |                      d                     |                      d           S )NrB   rC   rD   r   rY   s    r)   rZ   z'redact_sensitive_text.<locals>.<lambda>  s<    J[%<%<JaggajjJJ r+   eyJc                 F    t          |                     d                    S )Nr   )r/   rI   rY   s    r)   rZ   z'redact_sensitive_text.<locals>.<lambda>  s    [%<%< r+   r2   +c                     |                      d          }t          |          dk    r|d d         dz   |dd          z   S |d d         dz   |dd          z   S )NrB      rC   z****r   )rI   r(   )r@   phones     r)   _redact_phonez,redact_sensitive_text.<locals>._redact_phone  s`    GGAJJE5zzQRaRy6)E"##J66!9v%bcc
22r+   )
isinstancerQ   _REDACT_ENABLED_has_known_prefix_substringrp   r/   
_PREFIX_RErS   _ENV_ASSIGN_RE_CFG_DOTTED_RE_CFG_ANCHORED_RE_JSON_FIELD_RE_YAML_ASSIGN_RE_AUTH_HEADER_RE_SECRET_HEADER_RE_TELEGRAM_RE_PRIVATE_KEY_RE_DB_CONNSTR_RE_URL_BARE_TOKEN_RE_JWT_RErk   _SIGNAL_PHONE_RE)r>   rq   rr   rs   r|   r   r   r   r   r   rv   s             @r)   r_   r_     s+   N |tdC   4yy  _   	 #4(( G1:K--~~????FF  +;$;;D D D "%%k488D
 D  %))+t<<'++K>> $;;3$;;8 8 8 "%%lD99D
 $;;5,,9 9 9 #&&|T::D
 4!7!7""OO
 
 d{{ $$::
 
 d{{	+ 	+ 	+  0$77 $7d??""#;TBB }} 	V6 6 6
 "%%j$77DD!%%&N&NPTUUD "%%JJ
 
 }}{{<<dCC" d{{sd{{ && d{{	3 	3 	3
  ##M488Kr+   >   envsetexportdeclareprintenvcommandc                 6   | rt          | t                    sdS t          j        d|           }|D ]g}|                                }|s	 t          j        |          }n$# t          $ r |                                }Y nw xY w|r|d         t          v r dS hdS )a  Return True if ``command`` dumps environment variables to stdout.

    Detects ``env`` / ``printenv`` / ``set`` / ``export`` / ``declare`` as the
    first token of any segment in a pipeline or sequence (``;`` / ``&&`` /
    ``||`` / ``|``). Conservative: a parse failure or anything unrecognized
    returns False (callers then fall back to the safer code_file=True path,
    which still masks prefix-shaped keys).
    Fz[|;&]+r   T)r   rQ   rO   r4   rj   shlex
ValueError_ENV_DUMP_COMMANDS)r   segmentssegtokenss       r)   is_env_dump_commandr     s      *Wc22 ux	7++H 	 	iikk 		![%%FF 	! 	! 	!YY[[FFF	! 	fQi#555445s   A  B B)rq   outputc                R    | s| S t          |pd           }t          | ||          S )u  Redact secrets from terminal/process stdout.

    Single redaction policy for ALL terminal-output surfaces — foreground
    ``terminal`` results AND background ``process(action=poll/log/wait)``
    output — so they can't diverge. Picks ``code_file`` based on whether
    ``command`` is an environment dump:

    - env-dump command (``env``/``printenv``/``set``/``export``/``declare``)
      → ``code_file=False`` so the ENV-assignment pass masks opaque tokens.
    - anything else (or unknown command) → ``code_file=True`` to avoid
      false positives on source/config dumps.

    ``force=True`` bypasses the global ``security.redact_secrets`` preference
    for safety boundaries that must never emit raw credentials.
    r   )rq   rr   )r   r_   )r   r   rq   rr   s       r)   redact_terminal_outputr     s:    $  '2666I u	JJJJr+   patternc                 T    d}t          |           D ]\  }}||v r| d|         c S | S )aG  Return the leading literal characters of a regex pattern.

    Stops at the first regex metacharacter (``[``, ``(``, ``\``, ``.``,
    ``?``, ``*``, ``+``, ``|``, ``{``, ``^``, ``$``).  Returns the literal
    that any match of the pattern MUST contain as a substring, so the
    pre-screen never produces false negatives.
    z[(\.?*+|{^$N)	enumerate)r   metaichs       r)   _extract_literal_prefixr     sK     D7##  2::2A2; Nr+   c              #   4   K   | ]}t          |          V  d S N)r   ).0ps     r)   	<genexpr>r     s<        #$A     r+   c                 D     t           fdt          D                       S )zReturn True if ``text`` contains any known credential prefix substring.

    Used as a cheap pre-check before invoking the expensive ``_PREFIX_RE``.
    c              3       K   | ]}|v V  	d S r    )r   r   r>   s     r)   r   z._has_known_prefix_substring.<locals>.<genexpr>  s'      55QqDy555555r+   )anyrm   r\   s   `r)   r   r     s)    
 5555"4555555r+   )	zGET zPOST zPUT zPATCH zDELETE zHEAD zOPTIONS zTRACE zCONNECT c                 l    |                                  t          fdt          D                       S )z?Cheap pre-check before scanning for access-log request targets.c              3       K   | ]}|v V  	d S r   r   )r   methoduppers     r)   r   z-_has_http_method_substring.<locals>.<genexpr>   s'      EE6vEEEEEEr+   )r   r   _HTTP_METHOD_SUBSTRINGS)r>   r   s    @r)   _has_http_method_substringr     s4    JJLLEEEEE-DEEEEEEr+   c                   B     e Zd ZdZd fd	Zdej        def fdZ xZ	S )	RedactingFormatterz9Log formatter that redacts secrets from all log messages.N%c                 @     t                      j        |||fi | d S r   )super__init__)selffmtdatefmtstylekwargs	__class__s        r)   r   zRedactingFormatter.__init__&  s,    gu7777777r+   recordr&   c                 d    t                                          |          }t          |          S r   )r   formatr_   )r   r   originalr   s      r)   r   zRedactingFormatter.format)  s&    77>>&))$X...r+   )NNr   )
__name__
__module____qualname____doc__r   logging	LogRecordrQ   r   __classcell__)r   s   @r)   r   r   #  sr        CC8 8 8 8 8 8/W. /3 / / / / / / / / / /r+   r   r   )Er   r   osrO   r   	getLoggerr   logger	frozensetr8   _SENSITIVE_BODY_KEYSgetenvr7   r   _PREFIX_PATTERNS_SECRET_ENV_NAMEScompiler   _SECRET_CFG_NAMES
_CFG_VALUEry   
IGNORECASEr   	MULTILINEr   _YAML_CFG_NAMESr   _JSON_KEY_NAMESr   r   _SECRET_HEADER_NAMESr   r   r   r   r   r   r   rR   r[   rd   rh   r9   r   rQ   intr*   r/   r=   rU   r]   objectr`   re   rk   rp   boolr_   r   r   r   r   tuplerm   r   r   r   	Formatterr   r   r+   r)   <module>r     s     				 				 		8	$	$
 $) % % %   , !y " " "   4 ")3V<<BBDDHbb* * * ^ Q U+UUU * W /
 "rz7   /@  * 	  M	  2:`0A``T^``MBL    P"*]]]]MBL   Z-/---M " "*FM  [  BJ,	,,,M   rz* 
 "*O  VM (  RZ M	   "*%  2:ABB 
  RZ   2:2   !+
M! !  
O 
 RZSXX&6777:OO 
 ,/ ,/ ,/,/ ,/ 	,/
 ,/ ,/ ,/ 	,/ ,/ ,/ ,/^8s 8s 8 8 8 8     ,.3 .3 . . . . 	s 	s 	 	 	 	& S    293 93 9 9 9 9.C .C . . . . J3 J3 J J J J<   
  	
  	   R YNNNOO t     6 (,K>CK K KK*K7;KK K K KFS S     U  (8     
6c 6d 6 6 6 6
 FS FT F F F F/ / / / /* / / / / /r+   