Ë
    áß²jr ã                   óD  — U d Z ddlZddlZddlZddlZddlZddlmZ ddlm	Z
  ej                  e«      ZdZi Zeed<    ej$                  «       Zdefd„Zd­d	„Zd­d
„Zdedefd„Z eh d£«      Z ej6                  dd«      j9                  «       dv Zi Zeed<    ej$                  «       Zde fd„Z!g d¢Z"dZ# ejH                  de#› d�«      Z% ejH                  dejL                  «      Z'dZ(dZ)dZ* ejH                  e(ejL                  «      Z+ ejH                  d«      Z, ejH                  de(› de(› de*› �ejL                  «      Z- ejH                  de)› d e(› d!e*› �ejL                  ej\                  z  «      Z/d"Z0 ejH                  d#e)› d$e0› d%�ejL                  ej\                  z  «      Z1 ejH                  d&ejL                  «      Z2 ejH                  d'ejL                  «      Z3 ejH                  d(ejL                  «      Z4d)Z5 ejH                  d*e5› d+e5› d,�«      Z6 ejH                  d-«      Z7d.ed/e8de fd0„Z9d1d2œd.ed3e8d4e de fd5„Z:d6ed7d8de fd9„Z;d6ede fd:„Z<d;ede fd<„Z=d6ed;ed=e de fd>„Z>d?Z? ejH                  d@e?› dA�ejL                  «      Z@ eh dB£«      ZAdCZBdDZC ejH                  dE«      ZD ejH                  dF«      ZE ejH                  dG«      ZF ejH                  dHejL                  «      ZGdIZH ejH                  dJeH› dK�ejL                  «      ZI ejH                  dL«      ZJ ejH                  dM«      ZK ejH                  dNejL                  «      ZL ejH                  dOejL                  «      ZM ejH                  dP«      ZN ejH                  dQ«      ZO ejH                  dR«      ZP ejH                  dS«      ZQ ejH                  dT«      ZR ejH                  dU«      ZS ejH                  dV«      ZT ejH                  dW«      ZU edX«      ZVdYeWdd8fdZ„ZX eXe"«      aY ejH                  d[«      ZZdedefd\„Z[ ejH                  d]«      Z\d^d^d_d`dadbœd;edce8dde8dee8dfedgedefdh„Z]diedefdj„Z^d6ede fdk„Z_dedefdl„Z`dedefdm„Zadnedefdo„Zbdpedefdq„Zcdedefdr„Zdd;eedefds„Zfdedefdt„Zgdiedefdu„Zhd=e fdv„Zidwdxœdedye defdz„Zjded{e defd|„Zkd}„ Zldwdwdwdwdwd~œdede d{e d€e d�e d‚e defdƒ„Zm eh d„£«      Zn eh d…£«      Zo eh d†£«      Zp eh d‡£«      ZqdˆZrd‰ZsdŠedeWe   fd‹„ZtdŒede fd�„ZudŽede fd�„ZvdŠedz  de fd�„ZwdŠedz  de fd‘„Zxd’Zy ejH                  d“ejL                  «      Zzdedefd”„Z{d®dwd•œd–edŠedz  de defd—„Z|d˜edefd™„Z}d˜ed/e8de8fdš„Z~d˜ed3e8de fd›„Zd˜ede€e e f   fdœ„Z�d˜ede fd�„Z‚d˜ede fdž„Zƒ e€dŸ„ e"D «       «      a„dede fd „Z…i Z†eed¡<    ej$                  «       Z‡deWfd¢„Zˆd­d£„Z‰e‚d¤feƒd¥fd¦„ d§ffZŠd¯d¨ede8fd©„Z‹d­dª„ZŒ G d«„ d¬e�j                  «      ZŽy)°zªRegex-based secret redaction for logs and tool output.

Short tokens (< 18 chars) are fully masked; longer ones keep the first 6 and
last 4 characters for debuggability.
é    N)Úunquote_plus)Ú_BLOCKED_PROJECT_ENV_BASENAMESé@   Ú_VAULT_REDACTION_VALUESÚreturnc                  ó.   — ddl m}  t         | «       «      S )Nr   ©Úget_hermes_home)Úhermes_constantsr
   Ústrr	   s    ú1/home/ubuntu/.hermes/hermes-agent/agent/redact.pyÚ_vault_scoper   #   s   € Ý0Ü‰Ó Ó!Ð!ó    c                 óš  — t        | t        «      r| sy| j                  dd«      j                  dd«      }t        5  t        j                  t        «       i «      }| |fD ]  }|sŒ|j                  |d«       d||<   Œ t        |«      t        kD  r(|t        t        |«      «      = t        |«      t        kD  rŒ(ddd«       y# 1 sw Y   yxY w)aE  Register an exact vault secret value for model-facing redaction.

    Called by the vault fill path BEFORE the injection happens, so no later browser tool result
    can echo the value back into model context. Also registers the form a text input normalizes
    it to (CR/LF stripped), since that is what the page holds.
    NúÚ ú
)Ú
isinstancer   ÚreplaceÚ_VAULT_REDACTION_LOCKr   Ú
setdefaultr   ÚpopÚlenÚ _VAULT_REDACTION_MAX_PER_PROFILEÚnextÚiter)ÚvalueÚ
normalizedÚbucketÚvs       r   Úregister_vault_redaction_valuer!   (   s¹   € ô �eœSÔ!©ØØ—‘˜t RÓ(×0Ñ0°°rÓ:€JÜ	ñ +Ü(×3Ñ3´L³NÀBÓGˆØ˜Ð$ò 	!ˆAÚØ—
‘
˜1˜dÔ#Ø ��q’	ð	!ô �&‹kÔ<Ò<Ø”tœD ›LÓ)Ð*ô �&‹kÔ<Ó<÷+÷ +ñ +ús   ¼(CÁ%ACÃC
c                  óv   — t         5  t        j                  t        «       d«       ddd«       y# 1 sw Y   yxY w)zPDrop the current profile's registered values (profile teardown / explicit lock).N)r   r   r   r   © r   r   Úclear_vault_redaction_valuesr$   <   s,   € ä	ñ :Ü×#Ñ#¤L£N°DÔ9÷:÷ :ñ :úó   ‡/¯8Útextc                 ó  — t        | t        «      r| s| S t        5  t        j	                  t        «       «      }|rt        |t        d¬«      nd}ddd«       D ]  }|| v sŒ| j                  |d«      } Œ | S # 1 sw Y   Œ)xY w)zUExact-substring scrub of every vault secret value registered for the current profile.T)ÚkeyÚreverser#   Nu   Â«redacted-vault-secretÂ»)	r   r   r   r   Úgetr   Úsortedr   r   )r&   r   Úvaluesr   s       r   Úredact_registered_vault_valuesr-   B   s…   € ä�dœCÔ ©ØˆÜ	ñ IÜ(×,Ñ,¬\«^Ó<ˆÙ:@”˜¤C°Õ6Àbˆ÷Ið ò DˆØ�DŠ=Ø—<‘< Ð'BÓC‰DðDð €K÷Ið Iús   ›4A7Á7B >   úx-amz-signatureÚjwtr(   ÚauthÚcodeÚtokenÚapikeyÚsecretÚapi_keyÚsessionÚid_tokenÚpasswordÚ	signatureÚaccess_tokenÚclient_secretÚrefresh_tokenÚHERMES_REDACT_SECRETSÚtrue>   Ú1ÚonÚyesr>   Ú_REDACT_ENABLED_BY_HOMEc                  óü  — ddl m} m}  | «       €t        S  |«       }t        j                  |«      }|�|S d}	 ddlm}  |«       }|r|j                  d«      nd}|€>ddlm	}  |«       j                  d«      xs i j                  d	«      }	|	€dn
t        |	«      }|�)t        |«      j                  «       j                  «       d
v }t        5  |t        |<   ddd«       |S # t        $ r d}Y Œ'w xY w# 1 sw Y   |S xY w)zUEffective redaction switch for the active profile (launch snapshot when no override).r   )Úget_hermes_home_overrideÚhermes_home_keyNT)Úcurrent_secret_scoper=   )Úload_config_readonlyÚsecurityÚredact_secrets>   r?   r@   rA   r>   )r   rD   rE   Ú_REDACT_ENABLEDrB   r*   Úagent.secret_scoperF   Úhermes_cli.configrG   r   ÚstripÚlowerÚ	ExceptionÚ_REDACT_ENABLED_LOCK)
rD   rE   Úhome_keyÚcachedÚenabledrF   ÚscopeÚrawrG   Úcfg_vals
             r   Ú_redact_enabledrW   j   sþ   € çJÙÓ!Ð)ÜÐÙÓ €HÜ$×(Ñ(¨Ó2€FØÐØˆØ€GðÝ;Ù$Ó&ˆÙ49ˆe�i‰iÐ/Ô0¸tˆØˆ;Ý>Ù+Ó-×1Ñ1°*Ó=ÒCÀ×HÑHÐIYÓZˆGØ!˜/‘$¬s°7«|ˆCØˆ?Ü˜#“h—n‘nÓ&×,Ñ,Ó.Ð2LÐLˆGô 
ñ 4Ø,3Ô Ñ)÷4à€Nøô	 ò ØŠðú÷4à€Nús   ¹BC  Ã
C1Ã C.Ã-C.Ã1C;)8z(sk-[A-Za-z0-9_-](?:\.?[A-Za-z0-9_-]){9,}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_(?:org_)?[A-Za-z0-9]{20,}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,}zglpat-[A-Za-z0-9_\-]{10,}zgloas-[A-Za-z0-9_\-]{10,}zgldt-[A-Za-z0-9_\-]{10,}zglrt-[A-Za-z0-9_.\-]{10,}zglrtr-[A-Za-z0-9_.\-]{10,}zglcbt-[A-Za-z0-9_\-]{10,}zglptt-[A-Za-z0-9_\-]{10,}zglft-[A-Za-z0-9_\-]{10,}zglimt-[A-Za-z0-9_\-]{10,}zglagent-[A-Za-z0-9_\-]{10,}zglsoat-[A-Za-z0-9_\-]{10,}zglffct-[A-Za-z0-9_\-]{10,}zglwt-[A-Za-z0-9_\-]{10,}zGR1348941[A-Za-z0-9_\-]{10,}zpk-lf-[A-Za-z0-9\-]{8,}zE(?:API_?KEY|KEY|TOKEN|SECRET|PASSWORD|PASSWD|PASS|PW|CREDENTIAL|AUTH)z([A-Z0-9_]{0,50}z&[A-Z0-9_]{0,50})\s*=\s*(['\"]?)(\S+)\2zƒ(?<![a-z0-9_])([a-z0-9_]+(?:_|^)(?:key|pass|pw|token|secret|password|passwd|credential|auth)(?=[^a-z0-9_]|$))\s*=\s*(['\"]?)(\S+)\2z?(?:api[ _.\-]?key|token|secret|passwd|password|credential|auth)z(?:[0-9]+(?:[|:\-]|\t)[ \t]*)?z(['\"]?)([^\s&]+?)\2(?=[\s&]|$)z0^(?:os\.(?:getenv|environ)|process\.env|\$ENV\{)z7(?<![A-Za-z0-9_.\-])([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]*z (?:export[ \t]+)?[A-Za-z0-9_\-]*z[A-Za-z0-9_\-]*)=z:(?:api[ _.\-]?key|token|secret|passwd|password|credential)z	(^[ \t]*+z[A-Za-z0-9_.\-]*z/[A-Za-z0-9_.\-]*+)(:[ \t]*+)(?!['\"])([^\s&]++)zy(?:api|auth|access|refresh|session|secret)[ _.\\-]?(?:key|token)|token|secret|passwd|password|pass|pw|credential|auth|keyzŽ(?:api|auth|access|refresh|session|id|bearer)[ _.\\-]?(?:key|token)|key[ _.\\-]?material|secret|passwd|password|pass|pw|credential|auth|bearerzpasswd|password|pass|pwz(\$(?:\{[A-Za-z_]\w*[^}]*\}|[A-Za-z_]\w*)z^(?:z|\$\(|~|/)(?:[\w./:-]|z)*$z3(?=[^.]*[a-z])(?=[^.]*[A-Z])(?=[^.]*[0-9])[^.]{16,}ÚsÚic                 ó$  — |dk(  ry| |dz
     | |   }}|j                  «       r |j                  «       r|j                  «       ry|j                  «       xr; |j                  «       xr) |dz   t        | «      k  xr | |dz      j                  «       S )zdTrue if position ``i`` in ``s`` begins a word (edge, non-letter before, camelCase/acronym boundary).r   Té   )ÚisalphaÚisupperÚislowerr   )rX   rY   ÚprevÚcurs       r   Ú_is_word_startra   T  s{   € àˆA‚vØØ�!�a‘%‘˜!˜A™$ˆ#€DØ�<‰<Œ>˜cŸk™kœm°·±´ØØ�;‰;‹=ÒU˜TŸ\™\›^ÒU°°A±¼¸A»±ÒUÀ1ÀQÈÁUÁ8×CSÑCSÓCUÐUr   T©Úallow_pluralÚjrc   c                óÎ   — |t        | «      k\  ry| |   }|j                  «       r&|j                  «       r| |dz
     j                  «       ry|xr |dv xr t	        | |dz   d¬«      S )z\True if position ``j`` (exclusive end) in ``s`` ends a word; one trailing ``s`` is absorbed.Tr[   ÚsSFrb   )r   r\   r]   r^   Ú_is_word_end)rX   rd   rc   r`   s       r   rg   rg   ^  sb   € àŒC�‹F‚{ØØ
ˆA‰$€CØ�;‰;Œ=˜SŸ[™[œ]¨q°°Q±©x×/?Ñ/?Ô/AØØÒV˜C 4˜KÒV¬L¸¸AÀ¹EÐPUÔ,VÐVr   r(   Ú
keyword_rezre.Pattern[str]c                 óJ   ‡ — t        ˆ fd„|j                  ‰ «      D «       «      S )zPTrue if ``keyword_re`` matches ``key`` at a word boundary (see _KEY_KEYWORD_RE).c              3   óŠ   •K  — | ]:  }t        ‰|j                  «       «      xr t        ‰|j                  «       «      –— Œ< y ­w©N)ra   Ústartrg   Úend)Ú.0Úmr(   s     €r   ú	<genexpr>z,_has_word_bounded_keyword.<locals>.<genexpr>j  s4   øè ø€ ÒoÐQRŒ~˜c 1§7¡7£9Ó-ÒL´,¸sÀAÇEÁEÃGÓ2LÓLÑoùs   ƒA A)ÚanyÚfinditer)r(   rh   s   ` r   Ú_has_word_bounded_keywordrs   h  s!   ø€ äÓoÐV`×ViÑViÐjmÓVnÔoÓoÐor   c                 ó"   — t        | t        «      S )zYPost-match key validator: ``API_KEY``/``DB_PW`` count, ``KEYBOARD``/``secretary`` do not.)rs   Ú_KEY_KEYWORD_RE)r(   s    r   Ú_key_has_secret_keywordrv   m  s   € ä$ S¬/Ó:Ð:r   r   c                 ó  ‡ — ‰ dk(  s‰ j                  d«      ryt        ‰ «      dk\  rt        j                  d‰ «      ryt        ‰ «      dk\  rt        j                  d‰ «      ryt        ‰ «      dk  ry	t	        ˆ fd
„dD «       «      dk\  S )z Credential-like shape test for ambiguous ``token``/``key`` values, so short
    technical scalars (``CPU``, ``local``) are not masked merely for their key name.ú***õ   Â«redacted:Té   z[A-Fa-f0-9]+é   z[A-Za-z0-9_./+=-]+é   Fc              3   ó\   •K  — | ]#  }t        t        j                  |‰«      «      –— Œ% y ­wrk   )ÚboolÚreÚsearch)rn   Úpr   s     €r   rp   z0_looks_like_opaque_credential.<locals>.<genexpr>}  s!   øè ø€ ÒQ¨QŒt”B—I‘I˜a Ó'×(ÑQùs   ƒ),)z[a-z]z[A-Z]z[0-9]é   )Ú
startswithr   r   Ú	fullmatchÚsum)r   s   `r   Ú_looks_like_opaque_credentialr†   r  s{   ø€ ð �‚~˜×)Ñ)¨-Ô8ØÜ
ˆ5ƒz�RÒœBŸL™L¨¸%Ô@ØÜ
ˆ5ƒz�RÒœBŸL™LÐ)>ÀÔFØÜ
ˆ5ƒz�B‚ØÜÓQÐ2PÔQÓQÐUVÑVÐVr   Úcheck_keywordc                óP  — t         j                  |«      ry|dk(  s|j                  d«      ry|rt        | «      syt        j                  |«      r:t        | t        «      s*|d   dk(  s!t        d„ |j                  d«      D «       «      syt        | t        «      xs t        |«      S )züShared gate for the ENV / JSON / YAML assignment passes: skip programmatic env
    lookups used as values, optionally require a word-bounded keyword in the key,
    then redact when the key is unambiguously credential-bearing or the value looks opaque.Frx   u
   Â«redactedr   ú$c              3   óF   K  — | ]  }t         j                  |«      –— Œ y ­wrk   )Ú_OPAQUE_PATH_SEGMENT_REr„   )rn   Úsegs     r   rp   z,_should_redact_assignment.<locals>.<genexpr>š  s   è ø€ Ò%iÐQTÔ&=×&GÑ&GÈ×&LÑ%iùs   ‚!ú/)Ú_ENV_LOOKUP_VALUE_REÚmatchrƒ   rv   Ú_PATH_OR_VAR_VALUE_RErs   Ú_PASSWORD_KEY_RErq   ÚsplitÚ_STRONG_KEY_KEYWORD_REr†   )r(   r   r‡   s      r   Ú_should_redact_assignmentr”   €  sž   € ô ×!Ñ! %Ô(Øð �‚~˜×)Ñ)¨,Ô7ØÙÔ4°SÔ9Øô ×"Ñ" 5Ô)Ô2KÈCÔQaÔ2bð
 �‰8�sŠ?¤#Ñ%iÐX]×XcÑXcÐdgÓXhÔ%iÔ"iØÜ% cÔ+AÓBò 4Ü,¨UÓ3ð5r   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*"([^"]+)">   r2   r3   ÚbearerÚpasswdr4   r5   r7   r8   Ú
auth_tokenÚ
credentialÚ
raw_secretÚcredentialsÚprivate_keyr:   Úkey_materialÚsecret_inputÚsecret_valueÚauthorizationr;   r<   )Ú_API_KEYÚ_TOKENÚ_SECRETÚ	_PASSWORDÚ_PASSWDÚ_CREDENTIALÚ_CREDENTIALS)r3   r5   r2   r4   r8   r–   r˜   rš   z¯'(?P<key>[A-Za-z_][A-Za-z0-9_]*)'(?P<sep>\s*:\s*)(?:(?P<single_prefix>[bB]?)'(?P<single_value>(?:\\.|[^'\\])+)'|(?P<double_prefix>[bB]?)\"(?P<double_value>(?:\\.|[^\"\\])+)\")z*^(?P<prefix>[ \t]*E[ \t]{2,})(?P<body>.*)$z[^(?P<prefix>(?:[A-Za-z_]\w*\.)*[A-Za-z_]\w*(?:Error|Exception|Warning):[ \t]*)(?P<body>.*)$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.([?#&;])([A-Za-z0-9_.~+%\-]+)=([^#&;\s\"'<>]*)z(//)([^/\s?#@]+)@zH^[A-Za-z_][A-Za-z0-9_.-]*=[^&\s]*(?:&[A-Za-z_][A-Za-z0-9_.-]*=[^&\s]*)+$z5[\x00-\x1f\x7f\u200b-\u200f\u2028-\u202f\u2060\ufeff]zAABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.Úpatternsc                 óV   — t        j                  ddj                  | «      z   dz   «      S )Nz(?<![A-Za-z0-9_-])(ú|z)(?![A-Za-z0-9_-]))r   ÚcompileÚjoin)r¨   s    r   Ú_compile_prefix_matcherr­   8  s&   € Ü�:‰:Ð,¨s¯x©x¸Ó/AÑAÐDYÑYÓZÐZr   zE(?<![A-Za-z0-9_.-])([0-9a-f]{32}\.[A-Za-z0-9]{16,})(?![A-Za-z0-9_.-])c           
      óª  — t         j                  d| «      }|| k(  r| S t        | «      D ��cg c]  \  }}t         j                  |«      rŒ|‘Œ }}}t	        | «      g }}t
        j                  |«      D ]¦  }||j                  d«         }	||j                  d«      dz
     dz   }
| |	|
 }d|v sd|v rt
        j                  |«      rŒTt        d„ |D «       «      sŒg|
t        | «      k\  s	| |
   dk7  sŒ~|j                  |	|
 ||j                  d«      «      f«       Œ¨ t        |«      D ]  \  }	}
}t	        |«      ||	|
 Œ dj                  |«      S c c}}w )u  Mask tokens whose body is split by control/zero-width characters.

    Match on a control-stripped copy, then mask the corresponding span in the
    ORIGINAL â€” only when that span holds solely token-body and control chars, so
    a match can never cross into another line's unrelated text.

    A credential like ``sk-abc\x1bdef456â€¦`` or ``ghp_abc\n123defâ€¦`` has its token body interrupted, so the
    contiguous _PREFIX_RE cannot match it and the secret leaks verbatim (issue #77484). ``EXA_API_KEY=*** is
    rejected).
    r   r[   r   r   c              3   óZ   K  — | ]#  }|t         v xs t        j                  |«      –— Œ% y ­wrk   )Ú_TOKEN_BODY_CHARSÚ_CONTROL_CHARS_REr�   )rn   Úcs     r   rp   z-_mask_control_split_tokens.<locals>.<genexpr>d  s*   è ø€ ÒSÈ�Ô&Ð&ÒDÔ*;×*AÑ*AÀ!Ó*DÓDÑSùs   ‚)+ú=)r±   ÚsubÚ	enumerater�   ÚlistÚ
_PREFIX_RErr   rl   rm   r€   Úallr   ÚappendÚgroupÚreversedr¬   )r&   Úmask_fnÚstrippedrY   r²   Úorig_idxÚoutÚmatchesro   Ú
start_origÚend_origÚspanÚreplacements                r   Ú_mask_control_split_tokensrÅ   H  sV  € ô !×$Ñ$ R¨Ó.€HØ�4ÒØˆÜ'¨›o×P‘d�a˜Ô5F×5LÑ5LÈQÕ5O’ÐP€HÑPÜ˜“:˜rˆ€CÜ× Ñ  Ó*ò HˆØ˜aŸg™g a›jÑ)ˆ
Ø˜AŸE™E !›H q™LÑ)¨AÑ-ˆØ�J˜xÐ(ˆð
 �D‰L˜D D™L¬j×.?Ñ.?ÀÔ.EØô ÑSÈdÔSÕSØ¤ T£Ò*¨d°8©nÀÓ.CØ�N‰N˜J¨±'¸!¿'¹'À!»*Ó2EÐFÕGðHô .6°gÓ->ò 5Ñ)ˆ
�H˜kÜ#'¨Ó#4ˆˆJ�xÑ ð5à�7‰7�3‹<Ðùó' Qs   ¬EÁ
Ez?[\x00-\x1f\x7f\x80-\x9f\u200b-\u200f\u202a-\u202e\u2060-\u2064]é   r|   rx   r   )ÚheadÚtailÚfloorÚplaceholderÚemptyrÇ   rÈ   rÉ   rÊ   rË   c                óz   — | rt         j                  d| «      n| } | s|S t        | «      |k  r|S | d| › d| | d › �S )u¿   Mask a secret for display (``hermes config`` / ``status`` / ``dump``):
    ``sk-p...7890``; shorter than ``floor`` (after control-byte stripping) â†’
    ``placeholder``; falsy â†’ ``empty``.r   Nz...)Ú_DISPLAY_CONTROL_REr´   r   )r   rÇ   rÈ   rÉ   rÊ   rË   s         r   Úmask_secretrÎ   q  sR   € ñ
 38Ô×#Ñ# B¨Ô.¸U€EÙØˆÜ˜e›* uÒ,ˆ;ÐU°U¸5¸D°\°NÀ#ÀeÈTÈEÈFÀmÀ_Ð2UÐUr   r2   c                 ó&   — | syt        | ddd¬«      S )uU   Mask a log token â€” 18-char floor, preserves 6 prefix / 4 suffix; empty â†’ ``***``.rx   é   rÆ   é   )rÇ   rÈ   rÉ   )rÎ   )r2   s    r   Ú_mask_tokenrÒ   |  s   € áØÜ�u 1¨1°BÔ7Ð7r   c                 óª   — | j                  «       }|t        v ry| j                  «       r| j                  t        «      ry|j                  t
        «      S )zCReturn True for exact secret keys or credential-suffixed key names.T)ÚcasefoldÚ_PYTHON_REPR_SECRET_KEYSr]   ÚendswithÚ_PYTHON_REPR_ENV_SUFFIXESÚ _PYTHON_REPR_CREDENTIAL_SUFFIXES)r(   Úfoldeds     r   Ú_is_python_repr_secret_keyrÚ   ƒ  sC   € à�\‰\‹^€FØÔ)Ñ)ØØ
‡{�{„}˜Ÿ™Ô&?Ô@Øð �?‰?Ô;Ó<Ð<r   c                 ób   — dt         j                  dt        fd„}t        j	                  || «      S )z?Fully mask credential fields in Python mapping ``repr`` output.r�   r   c                 óÚ  — | j                  d«      }t        |«      s| j                  d«      S | j                  d«      }|�| j                  d«      xs d}d}|}n(| j                  d«      xs d}d}| j                  d	«      }t        j                  |«      r| j                  d«      S d
|v s|j	                  d«      r| j                  d«      S d|› d| j                  d«      › |› |› d
|› �S )Nr(   r   Úsingle_valueÚsingle_prefixr   ú'Údouble_prefixú"Údouble_valuerx   ry   Úsep)rº   rÚ   rŽ   r�   rƒ   )r�   r(   rÝ   ÚprefixÚquoter   s         r   Ú_subz(_redact_python_repr_fields.<locals>._sub•  sì   € Ø�k‰k˜%Ó ˆÜ)¨#Ô.Ø—;‘;˜q“>Ð!à—{‘{ >Ó2ˆØÐ#Ø—[‘[ Ó1Ò7°RˆFØˆEØ ‰Eà—[‘[ Ó1Ò7°RˆFØˆEØ—K‘K Ó/ˆEô  ×%Ñ% eÔ,Ø—;‘;˜q“>Ð!ð �E‰>˜U×-Ñ-¨mÔ<Ø—;‘;˜q“>Ð!ð �3�%�q˜Ÿ™ UÓ+Ð,¨V¨H°U°G¸3¸u¸gÐFÐFr   )r   ÚMatchr   Ú_PYTHON_REPR_FIELD_REr´   )r&   ræ   s     r   Ú_redact_python_repr_fieldsré   “  s1   € ðG”B—H‘Hð G¤ó Gô: !×$Ñ$ T¨4Ó0Ð0r   c                 óÂ  — | j                  d¬«      }t        |«      D ]¯  \  }}d}|}|j                  d«      r|dd d}}n,|j                  d«      s|j                  d«      r
|dd	 |d	d }}t        j	                  |«      }|€t
        j	                  |«      }|€Œ~|j                  d
«      t        |j                  d«      «      z   |z   ||<   Œ± dj                  |«      S )zHMask repr fields only on pytest/error lines in source-preserving output.T)Úkeependsr   z
Néþÿÿÿr   r   éÿÿÿÿrä   Úbody)	Ú
splitlinesrµ   rÖ   Ú_PYTEST_DIAGNOSTIC_LINE_REr�   Ú_PYTHON_EXCEPTION_LINE_RErº   ré   r¬   )r&   ÚlinesÚindexÚlineÚendingÚ	body_liner�   s          r   Ú%_redact_python_diagnostic_repr_fieldsr÷   µ  sê   € à�O‰O TˆOÓ*€EÜ  Ó'ò ‰ˆˆtØˆØˆ	Ø�=‰=˜Ô Ø $ S b 	¨6�v‰IØ�]‰]˜4Ô  D§M¡M°$Ô$7Ø $ S b 	¨4°°¨9�vˆIä*×0Ñ0°Ó;ˆØˆ=Ü-×3Ñ3°IÓ>ˆEØÑà—‘˜HÓ%Ü,¨U¯[©[¸Ó-@ÓAñBàñð �%ŠLðð" �7‰7�5‹>Ðr   Úqueryc                 óX   — | s| S dj                  d„ | j                  d«      D «       «      S )zQReplace values of sensitive ``k=v&k=v`` params with ``***``; others pass through.ú&c              3   ó„   K  — | ]8  }|j                  d «      \  }}}|r|j                  «       t        v r|› d�n|–— Œ: y­w)r³   ú=***N)Ú	partitionrN   Ú_SENSITIVE_QUERY_PARAMS)rn   Úpairr(   rã   Ú_s        r   rp   z'_redact_query_string.<locals>.<genexpr>Ð  sF   è ø€ ò à¸¿¹ÈÓ9L©¨¨c°1ñ  §	¡	£Ô/FÑ Fˆ3ˆ%ˆt‰ÈDÓPñùs   ‚>A )r¬   r’   )rø   s    r   Ú_redact_query_stringr  Ì  s1   € áØˆØ�8‰8ñ à—K‘K Ó$ôó ð r   Únamec                 óŽ   — | }t        d«      D ]  }t        |«      }||k(  r n|}Œ |j                  «       j                  dd«      S )zSDecode a URL parameter name (up to 3 unquote rounds) for case-insensitive matching.é   ú-r   )Úranger   rÔ   r   )r  Údecodedr   Ú
next_values       r   Ú_canonical_url_param_namer	  Ö  sR   € à€GÜ�1‹Xò ˆÜ! 'Ó*ˆ
Ø˜Ò ÙØ‰ð	ð
 ×ÑÓ×%Ñ% c¨3Ó/Ð/r   c                 ó^   — t         j                  d„ | «      } t        j                  d„ | «      S )z�Strict egress-boundary redaction of URL credentials (absolute, relative and
    network references); preserves keys, separators, public params, hosts, paths.c                 ó®   — t        | j                  d«      «      t        v r%| j                  d«      › | j                  d«      › d�S | j                  d«      S )Nr‚   r[   rü   r   )r	  rº   rþ   ©ro   s    r   ú<lambda>z0_redact_strict_url_credentials.<locals>.<lambda>å  sN   € Ü$ Q§W¡W¨Q£ZÓ0Ô4KÑKð —W‘W˜Q“Z�L §¡¨£ ¨DÐ1€ ØQR×QXÑQXÐYZÓQ[ð r   c                 ó¾   — d| j                  d«      v r7| j                  d«      › | j                  d«      j                  d«      d   › d�S | j                  d«      › d�S )Nú:r‚   r[   r   ú:***@z***@)rº   rý   r  s    r   r  z0_redact_strict_url_credentials.<locals>.<lambda>è  s\   € ÈÈqÏwÉwÐWXËzÑHY�Q—W‘W˜Q“Z�L §¡¨£×!5Ñ!5°cÓ!:¸1Ñ!=Ð >¸eÐD€ Ðbc×biÑbiÐjkÓblÐamÐmqÐ_r€ r   )Ú_STRICT_URL_PARAM_REr´   Ú_STRICT_URL_USERINFO_RE©r&   s    r   Ú_redact_strict_url_credentialsr  á  s9   € ô  ×#Ñ#ñ	\Ø]aóc€Dô #×&Ñ&ÙrØóð r   c                 ó–   — t        | €dn
t        | «      «      }|s|S t        j                  d„ |«      }t        j                  d„ |«      S )a%  Mask secrets in a CDP/browser endpoint URL before it is logged.

    Unlike ``redact_sensitive_text`` (which passes web-URL query params and
    ``user:pass@`` through for OAuth callbacks / magic links), CDP discovery
    tokens are pure credentials, so this opts INTO both URL redactors.
    r   c           
      óÎ   — | j                  d«      › d| j                  d«      › | j                  d«      › dt        | j                  d«      «      › | j                  d«      xs d› �S )	Nr[   ú://r‚   r  ú?rÆ   é   r   )rº   r  r  s    r   r  z redact_cdp_url.<locals>.<lambda>÷  s_   € �Q—W‘W˜Q“Z�L  A§G¡G¨A£J <°·±¸³
¨|¸1Ô=QÐRS×RYÑRYÐZ[ÓR\Ó=]Ð<^Ð_`×_fÑ_fÐghÓ_iÒ_oÐmoÐ^pÐq€ r   c                 óN   — | j                  d«      › d| j                  d«      › d�S )Nr[   r  r‚   r  ©rº   r  s    r   r  z redact_cdp_url.<locals>.<lambda>ú  s#   € ¨Q¯W©W°Q«Z¨L¸¸A¿G¹GÀA»J¸<ÀuÐ*M€ r   )Úredact_sensitive_textr   Ú_URL_WITH_QUERY_REr´   Ú_URL_USERINFO_RE)r   r&   s     r   Úredact_cdp_urlr  ì  sL   € ô ! u }¡¼#¸e»*ÓE€DÙØˆÜ×!Ñ!ÙqØó€Dô ×ÑÑ MÈtÓTÐTr   c                 ó’   — | r+d| v s'd| vs#t         j                  | j                  «       «      s| S t        | j                  «       «      S )zIRedact sensitive values when the ENTIRE text is a clean ``k=v&k=v`` body.r   rú   )Ú_FORM_BODY_REr�   rM   r  r  s    r   Ú_redact_form_bodyr"  ý  s:   € á�4˜4‘< 3¨d¡?¼-×:MÑ:MÈdÏjÉjËlÔ:[ØˆÜ §
¡
£Ó-Ð-r   c                 óR   ‡ — ‰ rt        ˆ fd„t        D «       d«      nd}|rd|› d�S dS )a  Redact a prefix-matched credential to a NON-REUSABLE sentinel: no head/tail
    chars (an agent once wrote a truncated-looking mask back into a config file),
    only the vendor prefix label so the credential KIND stays visible.

    * 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).
    c              3   óF   •K  — | ]  }‰j                  |«      sŒ|–— Œ y ­wrk   )rƒ   )rn   r´   r2   s     €r   rp   z*_mask_token_nonreusable.<locals>.<genexpr>  s   øè ø€ ÒM˜#°u×7GÑ7GÈÕ7L”#ÑMùs   ƒ!š!r   ry   u   â€¦Â»u   Â«redacted-secretÂ»)r   Ú_PREFIX_SUBSTRINGS)r2   Úlabels   ` r   Ú_mask_token_nonreusabler'    s6   ø€ ñ W\ŒDÓMÔ!3ÔMÈrÔRÐac€EÙ).ˆ[˜˜˜uÐ%ÐIÐ4IÐIr   c                ó   ‡ ‡— ˆˆ fd„}|S )zbre.sub callback: keep the match unless the key/value pair (groups[0], groups[-1]) needs redaction.c                 ó~   •— | j                  «       }t        |d   |d   ‰¬«      s| j                  d«      S  ‰|«      S )Nr   rí   ©r‡   )Úgroupsr”   rº   )ro   r+  r‡   Úrenders     €€r   ræ   z_assignment_sub.<locals>._sub  s:   ø€ Ø—‘“ˆÜ(¨°©°F¸2±JÈmÕ\Ø—7‘7˜1“:ÐÙ�f‹~Ðr   r#   )r,  r‡   ræ   s   `` r   Ú_assignment_subr-    s   ù€ õð
 €Kr   F©Úmask_nonreusabler/  c                ó  ‡— |rt         nt        Šd| v r…t        ˆfd„d¬«      }t        j	                  || «      } d| vrt
        j	                  || «      } d| vrAt        j                  | «      r,t        j	                  || «      } t        j	                  || «      } d| v r(d| v r$t        j	                  t        ˆfd„d	¬«      | «      } d| v rd
| v rt        | «      } d| v r(d| vr$t        j	                  t        ˆfd„d¬«      | «      } | S )u?  ENV / config / JSON / YAML assignment passes (skipped for code files). Passes
    that would match ``token=``/``key=`` URL params skip ``://`` text (web-URL query
    params are intentionally passed through, see redact_sensitive_text).

    ``mask_nonreusable`` masks the assignments with the ``Â«redacted:â€¦Â»`` sentinel that
    ``file_read=True`` already uses for prefix-matched credentials. Without it an agent
    that read a secret-bearing file would hold a head/tail mask shaped like a real but
    truncated key and could write it back as a dead credential (#35519).r³   c                 ó>   •— | d   › d| d   ›  ‰| d   «      › | d   › �S )Nr   r³   r[   r‚   r#   ©ÚgÚmasks    €r   r  z%_redact_assignments.<locals>.<lambda>&  s.   ø€ °1°Q±4°&¸¸!¸A¹$¸ÁÀQÀqÁTÃ
¸|ÈAÈaÉDÈ6Ð0R€ r   Tr*  r  r  rá   c                 ó,   •— | d   › d ‰| d   «      › d�S )Nr   z: "r[   rá   r#   r2  s    €r   r  z%_redact_assignments.<locals>.<lambda>=  s    ø€ ¨¨1©¨¨c±$°q¸±t³*°¸QÐ&?€ r   Frß   c                 ó2   •— | d   › | d   ›  ‰| d   «      › �S )Nr   r[   r‚   r#   r2  s    €r   r  z%_redact_assignments.<locals>.<lambda>G  s$   ø€ ¨¨1©¨¨q°©t¨f±T¸!¸A¹$³Z°LÐ&A€ r   )r'  rÒ   r-  Ú_ENV_ASSIGN_REr´   Ú_ENV_ASSIGN_LOWER_REÚ_CFG_SECRET_WORD_REr€   Ú_CFG_DOTTED_REÚ_CFG_ANCHORED_REÚ_JSON_FIELD_REré   Ú_YAML_ASSIGN_RE)r&   r/  Ú_redact_envr4  s      @r   Ú_redact_assignmentsr?    s  ø€ ñ '7Õ"¼K€DØ
ˆd�{Ü%Ó&RÐbfÔgˆÜ×!Ñ! +¨tÓ4ˆØ˜Ñô
 (×+Ñ+¨K¸Ó>ˆDð ˜ÑÔ!4×!;Ñ!;¸DÔ!AÜ!×%Ñ% k°4Ó8ˆDÜ#×'Ñ'¨°TÓ:ˆDà
ˆd�{�s˜d‘{Ü×!Ñ!ÜÓ?ÈuÔUÐW[ó]ˆð
 ˆd�{�s˜d‘{Ü)¨$Ó/ˆð ˆd�{�u DÑ(Ü×"Ñ"ÜÓAÐQUÔVÐX\ó^ˆà€Kr   Ú	code_filec                 óh   ‡— ˆfd„}t         j                  || «      } t        j                  d„ | «      S )zODB connection-string passwords and bare-token URL userinfo (``://`` text only).c                 óÚ   •— | j                  d«      }‰r3|j                  d«      r"|j                  d«      r| j                  d«      S | j                  d«      › d| j                  d«      › �S )Nr‚   ú{ú}r   r[   rx   r  )rº   rƒ   rÖ   )ro   Úpwr@  s     €r   Ú
_redact_dbz+_redact_url_credentials.<locals>._redact_dbM  sZ   ø€ ð �W‰W�Q‹ZˆÙ˜Ÿ™ sÔ+°·±¸CÔ0@Ø—7‘7˜1“:ÐØ—'‘'˜!“*�˜S §¡¨£ Ð-Ð-r   c                 ó~   — | j                  d«      › t        | j                  d«      «      › | j                  d«      › �S )Nr[   r‚   r  ©rº   rÒ   r  s    r   r  z)_redact_url_credentials.<locals>.<lambda>U  s7   € ¨q¯w©w°q«z¨l¼;ÀqÇwÁwÈqÃzÓ;RÐ:SÐTU×T[ÑT[Ð\]ÓT^ÐS_Ð,`€ r   )Ú_DB_CONNSTR_REr´   Ú_URL_BARE_TOKEN_RE)r&   r@  rF  s    ` r   Ú_redact_url_credentialsrK  K  s1   ø€ ô.ô ×Ñ˜j¨$Ó/€DÜ×!Ñ!Ñ"`ÐbfÓgÐgr   c                 óf   — | j                  d«      }t        |«      dk  rdnd}|d | dz   || d  z   S )Nr[   é   r‚   rÆ   z****)rº   r   )ro   ÚphoneÚkeeps      r   Ú_redact_phonerP  X  s>   € Ø�G‰G�A‹J€EÜ�E“
˜a’‰1 Q€DØ��$ˆ<˜&Ñ  5¨$¨¨ =Ñ0Ð0r   )Úforcer@  Ú	file_readÚsecret_fileÚredact_url_credentialsrQ  rR  rS  rT  c                ó:  ‡‡— | €yt        | t        «      r| n
t        | «      } | s| S t        | «      } |st        «       s| S |xs |xr | }t	        | «      r3|rt
        nt        Št        | ‰«      } t        j                  ˆfd„| «      } d| v r'|rt
        nt        Št        j                  ˆfd„| «      } |st        | |¬«      } d| v sd| v rt        j                  d„ | «      } d	| v r.t        j                  d
„ | «      } t        j                  d„ | «      } d| v rd| v rt        j                  d| «      } d| v rt!        | |«      } d| v rt"        j                  d„ | «      } |rt%        | «      } d| v rd| v rt'        | «      } d| v rt(        j                  t*        | «      } | S )uÍ	  Apply all redaction patterns to a block of text.

    Safe on any string. Enabled by default (``security.redact_secrets: false``
    disables); ``force=True`` is for safety boundaries that must never return
    raw secrets regardless.

    ``redact_url_credentials=True``: also redact credential-named query params
    and ``user:pass@`` userinfo â€” off by default because OAuth-callback /
    magic-link / pre-signed URLs must survive ordinary tool flows unchanged.
    ``code_file=True``: skip the ENV/JSON assignment passes for known source
    code (``MAX_TOKENS=***``, ``"apiKey": "test"`` fixtures). ``file_read=True``
    (implies code_file unless ``secret_file``): prefix-matched credentials become a
    non-reusable sentinel (``Â«redacted:ghp_â€¦Â»``) instead of a head/tail mask an agent
    could write back into config.yaml as a dead credential.
    Every regex sits behind a cheap substring gate that its pattern requires,
    so the gates are never false-negative.

    Set code_file=True to also skip the Python-repr mapping pass (``{'API_KEY': 'â€¦'}``
    fixtures in source); pytest/exception diagnostic lines get a narrow pass in
    redact_terminal_output instead.

    Set file_read=True for file *content* returned to the agent (read_file / search_files / cat). 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.

    Set ``secret_file=True`` when the caller has already classified the SOURCE as secret-bearing
    (``_is_secret_file_arg``: command reads on the terminal side, resolved tool paths on the
    file side). It re-enables the ENV/JSON/YAML assignment passes that ``file_read`` would
    otherwise skip, so an opaque prefix-less credential assigned to a credential-shaped key is
    masked instead of passed through in cleartext (issue #110567). With ``file_read=True`` those
    assignments are masked with the non-reusable sentinel, so the #35519 write-back hazard stays
    closed. ``secret_file`` is authoritative: it wins over ``code_file``, so a caller cannot be
    fail-open by setting both. Files that are not secret-bearing (any source file, a project's own
    ``config.yaml``) keep the code_file behaviour: ``MAX_TOKENS: 100`` and ``"apiKey": "test"``
    fixtures are untouched.
    Nc                 ó2   •—  ‰| j                  d«      «      S ©Nr[   r  )ro   Ú_prefix_subs    €r   r  z'redact_sensitive_text.<locals>.<lambda>›  s   ø€ ©°A·G±G¸A³JÓ(?€ r   ú.c                 ó2   •—  ‰| j                  d«      «      S rW  r  )ro   Ú
_zhipu_subs    €r   r  z'redact_sensitive_text.<locals>.<lambda>Ÿ  s   ø€ ©z¸!¿'¹'À!»*Ó/E€ r   r.  ÚuthorizationÚUTHORIZATIONc                 ó†   — | j                  d«      | j                  d«      xs dz   t        | j                  d«      «      z   S )Nr[   r‚   r   r  rH  r  s    r   r  z'redact_sensitive_text.<locals>.<lambda>¥  s7   € ¨Q¯W©W°Q«Z¸1¿7¹7À1»:Ò;KÈÑ-LÌ{Ð[\×[bÑ[bÐcdÓ[eÓOfÑ-f€ r   r  c                 óZ   — | j                  d«      t        | j                  d«      «      z   S )Nr[   r‚   rH  r  s    r   r  z'redact_sensitive_text.<locals>.<lambda>¨  s!   € ¨q¯w©w°q«z¼KÈÏÉÐPQË
Ó<SÑ/S€ r   c                 óT   — | j                  d«      xs d› | j                  d«      › d�S )Nr[   r   r‚   z:***r  r  s    r   r  z'redact_sensitive_text.<locals>.<lambda>©  s'   € ¨Q¯W©W°Q«ZÒ-=¸2Ð,>¸q¿w¹wÀq»z¸lÈ$Ð*O€ r   ÚBEGINz-----z[REDACTED PRIVATE KEY]r  ÚeyJc                 ó6   — t        | j                  d«      «      S ©Nr   )rÒ   rº   r  s    r   r  z'redact_sensitive_text.<locals>.<lambda>·  s   € ¤[°·±¸³Ó%<€ r   rú   r³   ú+)r   r   r-   rW   Ú_has_known_prefix_substringr'  rÒ   rÅ   r·   r´   Ú_ZHIPU_API_KEY_REr?  Ú_AUTH_HEADER_REÚ_SECRET_HEADER_REÚ_TELEGRAM_REÚ_PRIVATE_KEY_RErK  Ú_JWT_REr  r"  Ú_SIGNAL_PHONE_RErP  )r&   rQ  r@  rR  rS  rT  rX  r[  s         @@r   r  r  ^  s�  ù€ ðP €|ØÜ˜d¤CÔ(‰4¬c°$«i€DÙØˆä)¨$Ó/€DÙ”_Ô&Øˆð Ò'˜iÒ<°¨_€Iô # 4Ô(Ù1:Õ-Äˆô
 *¨$°Ó<ˆÜ�~‰~Ó?ÀÓFˆà
ˆd�{Ù09Õ,¼{ˆ
Ü ×$Ñ$Ó%EÀtÓLˆáÜ" 4¸)ÔDˆà˜Ñ °4Ñ!7Ü×"Ñ"Ñ#fÐhlÓmˆà
ˆd�{Ü ×$Ñ$Ñ%SÐUYÓZˆÜ×ÑÑ OÐQUÓVˆà�$�˜7 d™?Ü×"Ñ"Ð#;¸TÓBˆð ��}Ü& t¨YÓ7ˆà��}Ü�{‰{Ñ<¸dÓCˆáô .¨dÓ3ˆà
ˆd�{�s˜d‘{Ü  Ó&ˆà
ˆd�{Ü×#Ñ#¤M°4Ó8ˆà€Kr   >   ÚenvÚsetÚexportÚdeclareÚprintenv>   ÚnlÚawkÚbatÚcatÚsedÚtacÚgreprÇ   ÚlessÚmorerÈ   ÚtypeÚviewÚzcatÚbatcat>   ú.zshrcú.bashrcú.zloginú.zshenvú.profileú	.zprofileú.bash_loginú.bash_profile>   rt  rw  ry  )z$HERMES_HOME/z${HERMES_HOME}/)z$HOME/z${HOME}/Úcommandc                 ó~  — g }g }d}| D ]  }|r|j                  |«       ||k(  rd}Œ|dv r|}|j                  |«       Œ6|dv r5dj                  |«      j                  «       }|r|j                  |«       g }Œo|j                  |«       Œ� dj                  |«      j                  «       }|r|j                  |«       |S )zÙPipeline/sequence segments, split only on unquoted ``| ; &`` so an
    ``awk '{print $1; print $2}'`` program or ``grep 'foo|bar'`` pattern stays one
    segment. Backslash is not an escape (Windows ``C:\Users\...``).Nz'"z|;&r   )r¹   r¬   rM   )rˆ  ÚsegmentsÚbufrå   ÚchrŒ   s         r   Ú_command_segmentsr�  í  sÄ   € ð €HØ€CØ€EØò ˆÙØ�J‰J�rŒNØ�UŠ{Ø�ØØ�‰;ØˆEØ�J‰J�rŒNØØ�‰;Ø—'‘'˜#“,×$Ñ$Ó&ˆCÙØ—‘ Ô$ØˆCØØ�
‰
�2�ð!ð" �'‰'�#‹,×
Ñ
Ó
€CÙ
Ø�‰˜ÔØ€Or   Úpathc                 ó  — ddl m} 	 t        j                  j	                  t        j                  j                  t        j                  j                  | «      «      «      } |«       D ]q  }	 t        j                  j	                  t        j                  j                  t        |«      «      «      }||k(  s#|j                  |t        j                  z   «      sŒq y y# t        t        f$ r Y yw xY w# t        t        f$ r Y Œ›w xY w)u  True when an absolute ``config.yaml`` path sits under the active Hermes home or root.

    The default home's basename is an installation detail â€” ``.hermes`` on POSIX, ``hermes``
    under ``AppData/Local`` on Windows â€” and a resolved path never spells ``$HERMES_HOME``,
    so the literal-segment test in ``_is_secret_file_arg`` cannot see a native Windows path.
    Compare against the resolved homes instead. Only reached for a ``config.yaml`` basename,
    so the resolve cost stays off the per-token command scan.
    r   )Ú_hermes_dirsFT)Úagent.file_safetyr�  ÚosrŽ  ÚnormcaseÚrealpathÚ
expanduserÚOSErrorÚ
ValueErrorr   rƒ   rã   )rŽ  r�  ÚtargetÚhomeÚbases        r   Ú_is_under_hermes_homer›    sÔ   € õ /ðÜ—‘×!Ñ!¤"§'¡'×"2Ñ"2´2·7±7×3EÑ3EÀdÓ3KÓ"LÓMˆñ “ò ˆð	Ü—7‘7×#Ñ#¤B§G¡G×$4Ñ$4´S¸³YÓ$?Ó@ˆDð �TŠ>˜V×.Ñ.¨t´b·f±f©}Õ=Ùðð øô ”ZÐ ò Ùðûô
 œÐ$ò 	Ùð	ús%   ˆAC Á,AC2ÃC/Ã.C/Ã2DÄDÚargc                 ó  — | j                  d«      j                  dd«      }d}t        D ]%  }|j                  |«      sŒ|t	        |«      d }d} n t
        D ]#  }|j                  |«      sŒ|t	        |«      d } n d|v ry|j                  d«      D �cg c]  }|sŒ|j                  «       ‘Œ }}|sy|d   t        v s|d   t        v ry|d   d	k7  r|d   j                  d
«      sy|xs d|dd v xs t        |«      S c c}w )aB  ``.env``-style or shell rc basename anywhere; ``config.yaml`` only under a
    ``.hermes`` directory, ``$HERMES_HOME``, or the resolved Hermes home (never arbitrary
    YAML). The resolved-home arm is what covers native Windows, where the home directory
    is ``%LOCALAPPDATA%\hermes`` and carries no ``.hermes`` segment.z"'ú\r�   FNTr‰   rí   zconfig.yaml)zconfig.yaml.good.zconfig.yaml.corrupt.z.hermes)rM   r   Ú_HERMES_HOME_PREFIXESrƒ   r   Ú_HOME_PREFIXESr’   rN   Ú_ENV_FILE_BASENAMESÚ_SHELL_RC_BASENAMESr›  )rœ  rŽ  Úhermes_homerä   ÚpartÚpartss         r   Ú_is_secret_file_argr¦  $  s!  € ð
 �9‰9�UÓ×#Ñ# D¨#Ó.€DØ€KÜ'ò ˆØ�?‰?˜6Õ"Øœ˜F›˜Ð%ˆDØˆKÙð	ô
 !ò ˆØ�?‰?˜6Õ"Øœ˜F›˜Ð%ˆDÙðð ˆd�{ØØ&*§j¡j°£oÖ>˜dºˆT�Z‰Z�\Ð>€EÐ>ÙØØˆR�yÔ'Ñ'¨5°©9Ô8KÑ+KØð ˆR�y�MÒ!¨%°©)×*>Ñ*>Ð?lÔ*mØØÒP˜) u¨S¨b zÐ1ÒPÔ5JÈ4Ó5PÐPùò ?s   ÂDÂDc                 ób  — | rt        | t        «      syt        | «      D ]‰  }|j                  «       }|sŒ|d   j	                  dd«      d   j                  «       }|t        vrŒE|dd D �cg c]  }|j                  d«      rŒ|‘Œ }}|t        v r|dd }t        d„ |D «       «      sŒ‰ y	 yc c}w )
a  True if ``command`` reads a secret-bearing file (see ``_is_secret_file_arg``) to
    stdout. Defense-in-depth, not a boundary: indirect reads (``sudo cat .env``, ``$(cat
    .env)``, unresolved variable paths) are not detected, matching ``is_env_dump_command``.Fr   r�   r[   rí   Nr  c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wrk   )r¦  )rn   rœ  s     r   rp   z-_command_reads_secret_file.<locals>.<genexpr>R  s   è ø€ Ò>¨CÔ" 3×'Ñ>ùó   ‚T)
r   r   r�  r’   ÚrsplitrN   Ú_FILE_READ_COMMANDSrƒ   Ú_PATTERN_FIRST_COMMANDSrq   )rˆ  rŒ   ÚtokensÚreaderrœ  Ú
positionals         r   Ú_command_reads_secret_filer°  B  s¼   € ñ œ* W¬cÔ2ØÜ  Ó)ò ˆØ—‘“ˆÙØØ˜‘×!Ñ! # qÓ)¨"Ñ-×3Ñ3Ó5ˆØÔ,Ñ,ØØ%+¨A¨B ZÖK˜c°s·~±~ÀcÕ7J’cÐKˆ
ÐKØÔ,Ñ,Ø# A B˜ˆJÜÑ>°:Ô>Õ>Ùðð ùò Ls   Á+B,ÂB,c                 óÔ   — | rt        | t        «      syt        | «      D ](  }	 t        j                  |«      }|sŒ|d   t        v sŒ( y y# t
        $ r |j	                  «       }Y Œ.w xY w)už   True if any pipeline/sequence segment starts with an _ENV_DUMP_COMMANDS
    token. Conservative: unrecognized â†’ False (callers fall back to code_file=True).Fr   T)r   r   r�  Úshlexr’   r—  Ú_ENV_DUMP_COMMANDS)rˆ  rŒ   r­  s      r   Úis_env_dump_commandr´  W  so   € ñ œ* W¬cÔ2ØÜ  Ó)ò ˆð	!Ü—[‘[ Ó%ˆFò �f˜Q‘iÔ#5Ò5Ùðð øô	 ò 	!Ø—Y‘Y“[ŠFð	!ús   £AÁA'Á&A'z[redaction-unavailable]z2\bBearer\s+(?:\[[^\]]+\]|[A-Za-z0-9._~+/-]{20,}=*)c                 óž   — t        | xs d«      } 	 t        | d¬«      } d| v rt        j                  d| «      } | S # t        $ r	 t        cY S w xY w)u‚  The one scrub for text leaving the process for a remote reader (chat platforms, A2A peers,
    telemetry). ``redact_sensitive_text(force=True)`` â€” the only secret-pattern list â€” plus a bearer
    sweep, because a ``Bearer <opaque>`` value with no vendor prefix carries no shape the prefix
    matcher can key on. Fails CLOSED: if the redactor raises, the raw text is never returned.r   T©rQ  ÚearerzBearer [redacted])r   r  rO   ÚREDACTION_UNAVAILABLEÚ_BEARER_RESIDUE_REr´   r  s    r   Úredact_for_egressrº  m  sZ   € ô
 ˆtŠz�r‹?€Dð%Ü$ T°Ô6ˆð �$�Ü!×%Ñ%Ð&9¸4Ó@ˆØ€Køô	 ò %Ü$Ò$ð%ús   ‘: ºAÁAr¶  Úoutputc                óž   — | s| S t        |«      xs t        |«       }t        | ||¬«      }|r|s
t        «       rd|v rd|v rt	        |«      }|S )a!  Single redaction policy for ALL terminal-output surfaces: the ENV/YAML-assignment
    pass runs only when ``command`` is an env dump or reads a secret-bearing file (``.env``,
    shell rc, Hermes ``config.yaml``); otherwise code_file=True avoids false positives on
    source/config dumps.)rQ  r@  r  rß   )r´  r°  r  rW   r÷   )r»  rˆ  rQ  r@  Úredacteds        r   Úredact_terminal_outputr¾  |  s[   € ñ
 ØˆÜ(¨Ó1ÒXÔ5OÐPWÓ5XÐY€IÜ$ V°5ÀIÔN€Hñ ‘eœÔ0°c¸X±oÈ#ÐQYÉ/Ü8¸ÓBˆØ€Or   Úpatternc                 óF   — d}t        | «      D ]  \  }}||v sŒ| d| c S  | S )zALeading literal chars of a regex (up to the first metacharacter).z[(\.?*+|{^$N)rµ   )r¿  ÚmetarY   rŒ  s       r   Ú_extract_literal_prefixrÂ  �  s9   € à€DÜ˜7Ó#ò ‰ˆˆ2Ø�Š:Ø˜2˜A�;Òðð €Nr   c                 ó¨   — || |dz   |dz    dk(  rdndz  }|t        | «      k  r.| |   dk7  r&|| |   dk(  rdndz  }|t        | «      k  r	| |   dk7  rŒ&|S )zJGiven ``pattern[i] == "["``, return the index just past the closing ``]``.r[   r‚   ú]rž  )r   )r¿  rY   s     r   Ú_skip_char_classrÅ  ™  sp   € àˆg�a˜!‘e˜A ™EÐ" cÒ)‰¨qÑ0€AØ
Œc�'‹lÒ
˜w q™z¨SÒ0Ø	�'˜!‘* Ò$‰Q¨!Ñ+ˆð Œc�'‹lÒ
˜w q™z¨SÓ0à€Hr   c                 óÐ   — |t        | «      k\  ry| |   dv ry| |   dk(  rG| j                  d|«      }|dk7  r| |dz   | nd}|d	d j                  «       xr |j                  d
«      S y)zSTrue if an open-ended quantifier (``*``, ``+``, ``{m,}``) starts at ``pattern[j]``.Fz*+TrC  rD  rí   r[   r   Nú,)r   ÚfindÚisdigitrÖ   )r¿  rd   Úkrî   s       r   Ú_unbounded_quantifier_followsrË  ¡  sz   € àŒC�‹LÒØØˆq�z�TÑØØˆq�z�SÒØ�L‰L˜˜aÓ ˆØ#$¨¢7ˆw�q˜1‘u˜QÑ°ˆØ�C�Rˆy× Ñ Ó"Ò9 t§}¡}°SÓ'9Ð9Ør   c                 óØ  — dx}}dg}d}|t        | «      k  rÐ| |   }|dk(  r|dz  }Œ|dk(  rt        | |«      }nš|dk(  r|j                  d«       nƒ|dk(  r@t        |«      dkD  r|j                  «       nd}|rt	        | |dz   «      rd	}|d
   xs ||d
<   n>|dk(  rt        |«      dk(  rd	}n(t	        | |«      rd	|d
<   |dk(  r| j                  d|«      }|dz  }|t        | «      k  rŒÐ||fS )u“  One scan â†’ ``(has_top_level_alternation, has_nested_unbounded_repeat)``.

    Top-level ``|`` defeats the literal-prefix guarantee (in ``ab|.*`` the prefix
    binds only the first branch; ``ab(?:x|y)`` is fine). An unbounded quantifier
    on a group containing one (``(a+)+``, ``(a{2,})+``) is the canonical ReDoS
    shape. Structural only; overlapping branches (``(a|aa)+``) are not detected.
    Fr   rž  r‚   ú[r§   ú)r[   Trí   rª   rC  rD  )r   rÅ  r¹   r   rË  rÈ  )r¿  Útop_level_altÚnestedÚcontains_unboundedrY   rŒ  Úinners          r   Ú_pattern_structurerÓ  ®  s%  € ð #Ð"€M�FØ˜ÐØ	€AØ
Œc�'‹lÒ
Ø�Q‰ZˆØ�Š:Ø�‰FˆAØØ�Š9Ü  ¨!Ó,‰AØ�3ŠYØ×%Ñ% eÕ,Ø�3ŠYÜ03Ð4FÓ0GÈ!Ò0KÐ&×*Ñ*Ô,ÐQVˆEÙÔ6°wÀÀAÁÔFØ�Ø%7¸Ñ%;Ò%D¸uÐ˜rÒ"Ø�3ŠYœ3Ð1Ó2°aÒ7Ø ‰MÜ*¨7°AÔ6Ø%)Ð˜rÑ"Ø�SŠyØ—L‘L  aÓ(�Ø	ˆQ‰ˆð) Œc�'‹lÓ
ð* ˜&Ð Ð r   c                 ó   — t        | «      d   S rd  ©rÓ  ©r¿  s    r   Ú_has_top_level_alternationr×  Ñ  ó   € Ü˜gÓ& qÑ)Ð)r   c                 ó   — t        | «      d   S rW  rÕ  rÖ  s    r   Ú_has_nested_unbounded_repeatrÚ  Õ  rØ  r   c              #   ó2   K  — | ]  }t        |«      –— Œ y ­wrk   ©rÂ  ©rn   r�   s     r   rp   rp   Ù  s   è ø€ ÒP¸!Ô2°1×5ÑPùr©  c                 ó4   ‡ — t        ˆ fd„t        D «       «      S )z4Cheap pre-check before the expensive ``_PREFIX_RE``.c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wrk   r#   )rn   r�   r&   s     €r   rp   z._has_known_prefix_substring.<locals>.<genexpr>Þ  s   øè ø€ Ò5˜Qˆq�DŒyÑ5ùs   ƒ)rq   r%  r  s   `r   rf  rf  Ü  s   ø€ äÓ5Ô"4Ô5Ó5Ð5r   Ú_PLUGIN_PREFIX_PATTERNSc                  ód   — t         j                  «       D � �cg c]  } | D ]  }|‘Œ Œ c}} S c c}} w )z5All plugin-registered patterns in registration order.)rà  r,   )r¨   r�   s     r   Ú_plugin_patternsrâ  ë  s+   € ä5×<Ñ<Ó>×Q�(ÈÒQÀ1ŠAÐQˆAÓQÐQùÓQs   ˜,c                  ó`   — t         t        «       z   } t        | «      at	        d„ | D «       «      ay)z‘Recompile the prefix alternation and pre-screen substrings; callers read the
    module globals at call time, so the swap propagates immediately.c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wrk   rÜ  rÝ  s     r   rp   z*_rebuild_prefix_matcher.<locals>.<genexpr>ö  s   è ø€ ÒL¸aÔ6°q×9ÑLùr©  N)Ú_PREFIX_PATTERNSrâ  r­   r·   Útupler%  )Úcombineds    r   Ú_rebuild_prefix_matcherrè  ð  s-   € ô  Ô"2Ó"4Ñ4€HÜ(¨Ó2€JÜÑLÀ8ÔLÓLÑr   uÔ   %s: skipping redaction pattern %r â€” top-level alternation escapes the literal-prefix guarantee (in 'ab|.*' the prefix binds only the first branch); wrap alternation in a group after the prefix, e.g. 'ab(?:x|y)'u¯   %s: skipping redaction pattern %r â€” nested unbounded quantifiers (e.g. '(a+)+') can backtrack catastrophically, and registered patterns run on every log line and tool outputc                 ó0   — t        t        | «      «      dk  S )Nr‚   )r   rÂ  rÖ  s    r   r  r    s   € ”SÔ0°Ó9Ó:¸QÑ>€ r   u~   %s: skipping redaction pattern %r â€” must start with at least 2 literal characters (needed for the pre-screen substring gate)Úsourcec                 ó   ‡— g }| xs g D ]Ó  Št        ‰t        «      r‰j                  «       st        j	                  d|«       Œ:‰j                  «       Š	 t        j                  ‰«       t        ˆfd„t        D «       d«      }|rt        j	                  ||‰«       Œ“‰t        v s‰t        «       v s‰|v rt        j                  d|‰«       ŒÃ|j                  ‰«       ŒÕ |r^t        5  t        j!                  |g «      j#                  |«       t%        «        ddd«       t        j'                  d|t)        |«      «       t)        |«      S # t
        j                  $ r#}t        j	                  d|‰|«       Y d}~�Œrd}~ww xY w# 1 sw Y   ŒmxY w)u&  Additively register credential-token regexes; returns the count accepted.

    Invalid entries (non-compiling, top-level alternation, nested unbounded
    quantifiers, < 2 literal prefix chars) and duplicates are warned/skipped,
    never raised â€” a broken plugin must not break startup.
    z/%s: skipping empty/non-string redaction patternz.%s: skipping invalid redaction pattern %r (%s)Nc              3   ó:   •K  — | ]  \  }} |‰«      sŒ|–— Œ y ­wrk   r#   )rn   ÚrejectÚmessager¿  s      €r   rp   z.register_redaction_patterns.<locals>.<genexpr>  s   øè ø€ Òa¡_ V¨WÑQWÐX_ÕQ`œÑaùs   ƒ”z+%s: redaction pattern %r already registeredz&%s: registered %d redaction pattern(s))r   r   rM   ÚloggerÚwarningr   r«   Úerrorr   Ú_PATTERN_REJECT_RULESrå  râ  Údebugr¹   Ú_registry_lockrà  r   Úextendrè  Úinfor   )r¨   rê  ÚacceptedÚexcÚrejectedr¿  s        @r   Úregister_redaction_patternsrú  	  sS  ø€ ð €HØ’>˜rò !ˆÜ˜'¤3Ô'¨w¯}©}¬Ü�N‰NÐLÈfÔUØØ—-‘-“/ˆð	Ü�J‰J�wÔô ÓaÔ8MÔaÐcgÓhˆÙÜ�N‰N˜8 V¨WÔ5ØØÔ&Ñ&¨'Ô5EÓ5GÑ*GÈ7ÐV^ÑK^Ü�L‰LÐFÈÐPWÔXØØ�‰˜Õ ð#!ñ& Üñ 	&Ü#×.Ñ.¨v°rÓ:×AÑAÀ(ÔKÜ#Ô%÷	&ô 	�‰Ð<¸fÄcÈ(ÃmÔTÜˆx‹=Ðøô# �x‰xò 	Ü�N‰NÐKÈVÐU\Ð^aÔbÝûð	ú÷	&ð 	&ús$   ÁEÃ(0FÅFÅE<Å<FÆFc                  óv   — t         5  t        j                  «        t        «        ddd«       y# 1 sw Y   yxY w)z:Drop all plugin-registered patterns (tests/teardown only).N)rô  rà  Úclearrè  r#   r   r   Ú _reset_plugin_redaction_patternsrý  ,  s,   € ä	ñ "Ü×%Ñ%Ô'ÜÔ!÷"÷ "ñ "úr%   c                   ó@   ‡ — e Zd ZdZdej
                  defˆ fd„Zˆ xZS )ÚRedactingFormatterz9Log formatter that redacts secrets from all log messages.Úrecordr   c                 ó4   •— t        t        ‰| �	  |«      «      S rk   )r  ÚsuperÚformat)Úselfr   Ú	__class__s     €r   r  zRedactingFormatter.format6  s   ø€ Ü$¤U¡W¡^°FÓ%;Ó<Ð<r   )	Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚloggingÚ	LogRecordr   r  Ú__classcell__)r  s   @r   rÿ  rÿ  3  s$   ø„ ÙCð=˜W×.Ñ.ð =°3÷ =ñ =r   rÿ  )r   Nrk   )Úplugin)�r	  r
  r’  r   r²  Ú	threadingÚurllib.parser   r‘  r   r¡  Ú	getLoggerr  rï  r   r   ÚdictÚ__annotations__ÚLockr   r   r   r!   r$   r-   Ú	frozensetrþ   ÚgetenvrN   rJ   rB   rP   r~   rW   rå  Ú_SECRET_ENV_NAMESr«   r7  Ú
IGNORECASEr8  Ú_SECRET_CFG_NAMESÚ_LINE_NUMBER_GUTTERÚ
_CFG_VALUEr9  rŽ   r:  Ú	MULTILINEr;  Ú_YAML_CFG_NAMESr=  ru   r“   r‘   Ú_SHELL_VAR_REFr�   r‹   Úintra   rg   rs   rv   r†   r”   Ú_JSON_KEY_NAMESr<  rÕ   r×   rØ   rè   rð   rñ   rh  Ú_SECRET_HEADER_NAMESri  rj  rk  rI  rJ  rl  rm  r  r  r  r  r!  r±   r°   r¶   r­   r·   rg  rÅ   rÍ   rÎ   rÒ   rÚ   ré   r÷   r  r	  r  Úobjectr  r"  r'  r-  r?  rK  rP  r  r³  r«  r¢  r¬  rŸ  r   r�  r›  r¦  r°  r´  r¸  r¹  rº  r¾  rÂ  rÅ  rË  ræ  rÓ  r×  rÚ  r%  rf  rà  rô  râ  rè  rò  rú  rý  Ú	Formatterrÿ  r#   r   r   ú<module>r#     sØ	  ðòó Û 	Û 	Û Û Ý %õ Tà	ˆ×	Ñ	˜8Ó	$€ð $&Ð  Ø "Ð ˜Ó "Ø&˜	Ÿ™Ó(Ð ð"�có "ó
+ó(:ð
¨ð 
°ó 
ñ  $ò %ó Ð ð �"—)‘)Ð3°VÓ<×BÑBÓDÐHbÐb€ð !#Ð ˜Ó "Ø%�y—~‘~Ó'Ð ð˜ó ò:EÐ ð^ ]Ð Ø�—‘Ð1Ð2CÐ1DÐDlÐmÓn€ð "�r—z‘zð KØ‡M�MóÐ ð$ WÐ ð
 8Ð Ø/€
à �b—j‘jÐ!2°B·M±MÓBÐ ð "�r—z‘zÐ"UÓVÐ ð �—‘ð+Ø+<Ð*=ð >Ø*Ð+ð ,	Ø	ˆðð ‡M�Mó€ð �2—:‘:ØÐ#Ð$Ð$DÐEVÐDWÐWhÐisÐhtÐuØ‡M�M�B—L‘LÑ óÐ ð P€Ø�"—*‘*ØÐ$Ð%Ð%5°oÐ5FÐFuÐvØ‡M�M�B—L‘LÑ ó€ð* �"—*‘*ðAà‡M�Mó€ð $˜Ÿ™ðSà‡M�MóÐ ð �2—:‘:Ð8¸"¿-¹-ÓHÐ ð =€Ø"˜Ÿ
™
 d¨>Ð*:Ð:PÐQ_ÐP`Ð`cÐ#dÓeÐ ð
 %˜"Ÿ*™*Ð%[Ó\Ð ðV�cð V˜cð V dó Vð :>ò W�Cð W˜Cð W°$ð WÀ$ó Wðp 3ð pÐ4Eð pÈ$ó pð
; ð ;¨ó ;ð
W¨ð W°ó Wð5 3ð 5¨sð 5Àdð 5Ètó 5ðB Z€Ø�—‘˜r /Ð!2Ð2DÐEÀrÇ}Á}ÓU€ñ %ò &ó Ð ð,Ð ð	$Ð  ð #˜Ÿ
™
ð	óÐ ð (˜RŸZ™ZÐ(UÓVÐ Ø&˜BŸJ™Jð8óÐ ð �"—*‘*Ð_Ðac×anÑanÓo€ð nÐ Ø�B—J‘J !Ð$8Ð#9¸ÐGÈÏÉÓWÐ ð ˆr�z‰zÐ@ÓA€à�"—*‘*ÐhÓi€ð �—‘ØVØ‡M�Mó€ð   �R—Z‘Zðð ‡M�Mó	Ð ð ˆ"�*‰*ÐJÓ
K€ð �2—:‘:ÐAÓBÐ ð  �R—Z‘ZÐ ^Ó_Ð Ø�2—:‘:ÐLÓMÐ ð
 "�r—z‘zÐ"SÓTÐ ð %˜"Ÿ*™*Ð%9Ó:Ð ð �—
‘
ÐfÓg€ð �B—J‘JÐWÓXÐ ñ
 ÐaÓbÐ ð[ dð [Ð/@ó [ñ %Ð%5Ó6€
ð �B—J‘JØLóÐ ð
! Sð !°có !ðL !�b—j‘jÐ!cÓdÐ ð ,-¸!È"Ø#(°ròV�sð V Sð V°Cð VÀCð VØ ðVØ14ðVØ>AóVð8�sð 8˜só 8ð= Cð =¨Dó =ð 1 Sð 1¨Só 1ðD°ð ¸ó ð. ð ¨ó ð0 Cð 0¨Có 0ð¨ð °ó ðU˜&ð U Só Uð".˜Cð . Có .ð
J 3ð 
J¨3ó 
Jð¨dó ð @Eò -˜cð -¸ð -Èó -ð`
h #ð 
h°$ð 
h¸3ó 
hò1ð 7<ÈuØ,1ÀuØ9>òm ð m¨tð mÈð mØ%)ðmØ@Dðmà26ðmàCFómñn ÒNÓOÐ ñ  ò !ó Ð ñ  ò !ó Ð ñ $Ò$:Ó;Ð Ø<Ð ð (€ð˜sð  t¨C¡yó ð< ð ¨ó ð2Q˜Sð Q Tó Qð<¨¨d©
ð °tó ð*  t¡ð °ó ð 2Ð ð  �R—Z‘ZÐ UÐWY×WdÑWdÓeÐ ð˜Cð  Có ðÐUZò  3ð °°t±ð Èdð Ð_bó ð( Sð ¨Só ð˜cð  cð ¨có ð
¨3ð 
°3ð 
¸4ó 
ð ! ð  !¨¨d°D¨jÑ(9ó  !ðF*¨ð *°ó *ð*¨#ð *°$ó *ñ ÑPÐ?OÔPÓPÐ ð6 cð 6¨dó 6ð !#Ð ˜Ó "Ø�—‘Ó!€ðR˜$ó Ró
Mð  ð2ð3ð "ðaðbñ ?ð2ð3ðÐ ñ °#ð  ÀSó  óF"ô=˜×*Ò*õ =r   