
    `gjt              	       r   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ZddlZddl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  ej"                  e      ZdZde dZdZded	ed
efdZded	ed
efdZd
efdZdaedz  ez  ed<   dZ da!eed<   dZ"da#eed<   da$eed<   dCdZ% ejL                         Z'da(ejR                  dz  ed<    e*       Z+e*e   ed<    ejL                         Z,deded
dfdZ-dCdZ.dZ/d
efdZ0d
efdZ1d
edz  fdZ2d
efdZ3dDd efd!Z4d" Z5d
efd#Z6d
edz  fd$Z7d
efd%Z8dEd&ed'ed(efd)Z9d*ed+ed,ed
edz  fd-Z:d.ed*ed/ed
efd0Z;d1e	jx                  d2ed
e=edz  ef   fd3Z>d4d5d6ed
e=edz  ef   fd7Z?d8ed
efd9Z@d8ed
efd:ZAd4d5d6efd;ZBd4d5d6efd<ZCd=ZDd>ZEd?ed
efd@ZFdAed
efdBZGy)Fu  Tirith pre-exec security scanning wrapper.

Runs the tirith binary as a subprocess to scan commands for content-level
threats (homograph URLs, pipe-to-interpreter, terminal injection, etc.).

Exit code is the verdict source of truth:
  0 = allow, 1 = block, 2 = warn

JSON stdout enriches findings/summary but never overrides the verdict.
Operational failures (spawn error, timeout, unknown exit code) respect
the fail_open config setting. Programming errors propagate.

Auto-install: if tirith is not found on PATH or at the configured path,
it is automatically downloaded from GitHub releases to $HERMES_HOME/bin/tirith.
The download always verifies SHA-256 checksums.  When cosign is available on
PATH, provenance verification (GitHub Actions workflow signature) is also
performed.  If cosign is not installed, the download proceeds with SHA-256
verification only — still secure via HTTPS + checksum, just without supply
chain provenance proof.  Installation runs in a background thread so startup
never blocks.
    N)get_hermes_homezsheeki03/tirithz^https://github.com/z,/\.github/workflows/release\.yml@refs/tags/vz+https://token.actions.githubusercontent.comkeydefaultreturnc                 X    t        j                  |       }||S |j                         dv S )N>   1yestrue)osgetenvlowerr   r   vals      H/root/.hermes/venv/lib/python3.12/site-packages/tools/tirith_security.py	_env_boolr   3   s+    
))C.C
{99;...    c                 n    t        j                  |       }||S 	 t        |      S # t        $ r |cY S w xY w)N)r   r   int
ValueErrorr   s      r   _env_intr   :   s;    
))C.C
{3x s   
& 44c                     ddddd} 	 ddl m}  |       j                  di       xs i }t	        d|j                  d	| d	               t        j                  d
|j                  d| d               t        d|j                  d| d               t	        d|j                  d| d               dS # t        $ r i }Y w xY w)z@Load security settings from config.yaml, with env var overrides.Ttirith   )tirith_enabledtirith_pathtirith_timeouttirith_fail_openr   )load_configsecurityTIRITH_ENABLEDr   
TIRITH_BINr   TIRITH_TIMEOUTr   TIRITH_FAIL_OPENr   )hermes_cli.configr   get	Exceptionr   r   r   r   )defaultsr   cfgs      r   _load_security_configr)   D   s      	H1m
B/52
 $$4cgg>NPXYiPj6klyysww}h}F]/^_"#3SWW=MxXhOi5jk%&8#''BTV^_qVr:st	   s   !B/ /B=<B=_resolved_pathF _install_failure_reason   _crash_count_circuit_openc                  j    t         dz  a t         t        k\  rdat        j	                  dt                yy)zCIncrement the crash counter and open the circuit breaker if needed.   Tzbtirith circuit breaker opened after %d consecutive failures; disabling for the rest of the processN)r.   _CRASH_LIMITr/   loggerwarning r   r   _record_tirith_crashr6   u   s4     AL|#4	
 $r   _install_thread_warned_messagesmessagec                     t         5  | t        v r
	 ddd       yt        j                  |        ddd       t        j                  |g|  y# 1 sw Y    xY w)z``logger.warning`` but at-most-once per ``key`` for the process
    lifetime. Used to avoid drowning the log when a fail-open tirith
    misconfiguration fires on every command.N)_warned_lockr8   addr3   r4   )r   r9   argss      r   
_warn_oncer>      sU     
 """" " 	S!" NN7"T"	" "s   
AAAc                  b    t         5  t        j                          ddd       y# 1 sw Y   yxY w)u   Clear the warn-once dedupe set. Called when tirith is freshly
    (re)installed so a subsequent failure surfaces again — e.g. user
    deletes the binary mid-session.
    N)r;   r8   clearr5   r   r   _reset_spawn_warning_staterA      s(    
 
 ! ! ! !s   %.iQ c                  (    t        t                     S )zAReturn the Hermes home directory, respecting HERMES_HOME env var.)strr   r5   r   r   _get_hermes_homerD      s     !!r   c                  R    t         j                  j                  t               d      S )z3Return the path to the install-failure marker file.z.tirith-install-failed)r   pathjoinrD   r5   r   r   _failure_marker_pathrH      s    77<<(*,DEEr   c                  6   	 t               } t        j                  j                  |       }t	        j                         |z
  t
        k\  ryt        | dd      5 }|j                         j                         cddd       S # 1 sw Y   yxY w# t        $ r Y yw xY w)zRead the failure reason from the disk marker.

    Returns the reason string, or None if the marker doesn't exist or is
    older than _MARKER_TTL.
    Nrutf-8encoding)
rH   r   rF   getmtimetime_MARKER_TTLopenreadstripOSError)pmtimefs      r   _read_failure_reasonrX      s}     "  #IIK%K/!S7+ 	$q668>>#	$ 	$ 	$ s6   AB 
B B 6	B  B	B 	B 	BBc                  h    t               } | y| dk(  r t        j                  d      rt                yy)zCheck if a recent install failure was persisted to disk.

    Returns False (allowing retry) when:
    - No marker exists
    - Marker is older than _MARKER_TTL (24h)
    - Marker reason is 'cosign_missing' and cosign is now on PATH
    Fcosign_missingcosignT)rX   shutilwhich_clear_install_failed)reasons    r   _is_install_failed_on_diskr`      s4     "#F~!!fll8&<r   r_   c                    	 t               }t        j                  t        j                  j	                  |      d       t        |dd      5 }|j                  |        ddd       y# 1 sw Y   yxY w# t        $ r Y yw xY w)a  Persist install failure to disk to avoid retry on next process.

    Args:
        reason: Short tag identifying the failure cause. Use "cosign_missing"
                when cosign is not on PATH so the marker can be auto-cleared
                once cosign becomes available.
    Texist_okwrK   rL   N)rH   r   makedirsrF   dirnamerQ   writerT   )r_   rU   rW   s      r   _mark_install_failedrh      si     "
BGGOOA&6!S7+ 	qGGFO	 	 	 s0   AA5 A) A5 )A2.A5 2A5 5	B Bc                  r    t                	 t        j                  t                      y# t        $ r Y yw xY w)z3Remove the failure marker after successful install.N)rA   r   unlinkrH   rT   r5   r   r   r^   r^      s1    
  
		&() s   * 	66c                      t         j                  j                  t               d      } t        j                  | d       | S )z/Return $HERMES_HOME/bin, creating it if needed.binTrb   )r   rF   rG   rD   re   )ds    r   _hermes_bin_dirrn      s-    
%'/AKKD!Hr   c                      t        j                         } t        j                         j                         }| dk(  rd}n| dv rd}ny|dv rd}n|dv rd	}ny| d
| S )u  Return the Rust target triple for the current platform, or None.

    Windows is intentionally unsupported — tirith does not ship a Windows
    build. Callers should treat `None` as "this platform will never have
    tirith" and silently fall back to pattern-matching guards.
    Darwinzapple-darwin>   LinuxAndroidzunknown-linux-gnuN>   amd64x86_64rt   >   arm64aarch64rv   -)platformsystemmachiner   )ry   rz   platarchs       r   _detect_targetr}      sw     __F &&(G 	'	'"%%	(	(V1TFr   c                      t               duS )u  True when tirith ships a prebuilt binary for this OS+arch.

    Used by callers (CLI banner, etc.) to distinguish "tirith failed to
    install" from "tirith was never going to install here" — the latter
    is silent because there is nothing the user can do about it.
    N)r}   r5   r   r   is_platform_supportedr     s     4''r   urldesttimeoutc                 t   t         j                  j                  |       }t        j                  d      }|r|j                  dd|        t         j                  j                  ||      5 }t        |d      5 }t        j                  ||       ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)zDownload a URL to a local file.GITHUB_TOKENAuthorizationztoken )r   wbN)
urllibrequestRequestr   r   
add_headerurlopenrQ   r\   copyfileobj)r   r   r   reqtokenresprW   s          r   _download_filer     s    
..
 
 
%CIIn%E&(89			W		5 $tD$?O $ST4#$ $ $ $ $ $s$   -B.:B"B."B+	'B..B7checksums_pathsig_path	cert_pathc                 
   t        j                  d      }|st        j                  d       y	 t	        j
                  |dd|d|dt        dt        | gd	d	d
t        j                        }|j                  dk(  rt        j                  d       y	t        j                  d|j                  |j                  j                                y# t        t        j                  f$ r }t        j                  d|       Y d}~yd}~ww xY w)uk  Verify cosign provenance signature on checksums.txt.

    Returns:
        True  — cosign verified successfully
        False — cosign found but verification failed
        None  — cosign not available (not on PATH, or execution failed)

    The caller treats both False and None as "abort auto-install" — only
    True allows the install to proceed.
    r[   zcosign not found on PATHNzverify-blobz--certificatez--signaturez--certificate-identity-regexpz--certificate-oidc-issuerT   capture_outputtextr   stdinr   z%cosign provenance verification passedz(cosign verification failed (exit %d): %sFzcosign execution failed: %s)r\   r]   r3   info
subprocessrun_COSIGN_IDENTITY_REGEXP_COSIGN_ISSUERDEVNULL
returncoder4   stderrrS   rT   TimeoutExpired)r   r   r   r[   resultexcs         r   _verify_cosignr   %  s     \\(#F./]iH,.E(.  $$
 !KK?@NNE ++V]]-@-@-BDZ../ 4c:s   AC	 9C	 	D"C==Darchive_patharchive_namec                   	 d}t        |d      5 		D ]@  }|j                         j                  dd      }t        |      dk(  s2|d   |k(  s;|d   } n ddd       |st        j                  d|       y	t        j                         }t        | d
      5 	t        	fdd      D ]  }|j                  |        	 ddd       |j                         }||k7  rt        j                  d||       y	y# 1 sw Y   xY w# 1 sw Y   CxY w)z4Verify SHA-256 of the archive against checksums.txt.NrK   rL   z  r1      r   zNo checksum entry for %sFrbc                  &     j                  d      S )Ni    )rR   )rW   s   r   <lambda>z"_verify_checksum.<locals>.<lambda>^  s    !&&, r   r   z&Checksum mismatch: expected %s, got %sT)rQ   rS   splitlenr3   r4   hashlibsha256iterupdate	hexdigest)
r   r   r   expectedlinepartsshachunkactualrW   s
            @r   _verify_checksumr   N  s   H	nw	/ 1 	DJJL&&tQ/E5zQ58|#; 8	 1<@
..
C	lD	! Q.4 	EJJu	 ]]_F?6R'  s#   4C5C5C5&D5C>D
tardest_dirc                 :   | j                         D ]  }|j                  dk(  s|j                  j                  d      s.d|j                  v r=|j                         s |d|j                          y| j	                  |      }|
 |d        yt
        j                  j                  |d      }	 t        |d	      5 }t        j                  ||       ddd       |j                          |d
fc S   |d       y# 1 sw Y   )xY w# |j                          w xY w)z?Extract the tirith binary from a release archive into dest_dir.r   z/tirithz..z/tirith archive member is not a regular file: %s)Nbinary_not_regular_fileNz,tirith binary could not be read from archive)Nbinary_extract_failedr   r+   z"tirith binary not found in archive)Nbinary_not_in_archive)
getmembersnameendswithisfileextractfiler   rF   rG   rQ   r\   r   close)r   r   logmembersrc_file	dest_pathouts          r   _extract_tirith_binaryr   g  s    .." !;;("fkk&:&:9&Ev{{"==?Ev{{S6v.HBC4Xx8I!)T* 6c&&x56  b= %!( ,-(6 6  s$   1D=C<D<D	DDTlog_failuresr   c                    | rt         j                  nt         j                  }t               }|s<t         j	                  dt        j                         t        j                                yd| d}dt         d}	 t        j                  d      }	 t        j                  j                  ||      }t        j                  j                  |d      }t        j                  j                  |d      }	t        j                  j                  |d      }
t         j	                  d|       	 t        | d| |       t        | d|       d}t#        j&                  d      rn	 t        | d|	       t        | d|
       t)        ||	|
      }|du rd}nP|du r! |d       	 t#        j$                  |d       yt         j	                  d       nt         j	                  d       t+        |||      s	 t#        j$                  |d       yt-        j.                  |d       5 }t1        |||      \  }}|$d
|fcd
d
d
       t#        j$                  |d       S 	 d
d
d
       t        j                  j                  t3               d!      }	 t#        j4                  |       t        j:                  |t        j<                  |      j>                  t<        j@                  z  t<        jB                  z  t<        jD                  z         |rd#nd$}t         j	                  d%||       |d&ft#        j$                  |d       S # t        $ r} |d	|       Y d
}~yd
}~ww xY w# t         $ r*} |d|       Y d
}~t#        j$                  |d       yd
}~ww xY w# t         $ r!}t         j	                  d|       Y d
}~d
}~ww xY w# 1 sw Y   ixY w# t        $ ri 	 t#        j6                  |       nM# t        $ rA 	 t        j8                  |       n# t        $ r Y nw xY wY Y t#        j$                  |d       y"w xY wY w xY w# t#        j$                  |d       w xY w)'a^  Download and install tirith to $HERMES_HOME/bin/tirith.

    Verifies provenance via cosign and SHA-256 checksum.
    Returns (installed_path, failure_reason).  On success failure_reason is "".
    failure_reason is a short tag used by the disk marker to decide if the
    failure is retryable (e.g. "cosign_missing" clears when cosign appears).
    z/tirith auto-install: unsupported platform %s/%s)Nunsupported_platformztirith-z.tar.gzzhttps://github.com/z/releases/latest/downloadztirith-install-)prefixz1tirith install failed: cannot create temp dir: %sN)Nno_spacezchecksums.txtzchecksums.txt.sigzchecksums.txt.pemu9   tirith not found — downloading latest release for %s.../z/checksums.txtztirith download failed: %sT)ignore_errors)Ndownload_failedFr[   z/checksums.txt.sigz/checksums.txt.pemz=tirith install aborted: cosign provenance verification failed)Ncosign_verification_failedz5cosign execution failed, proceeding with SHA-256 onlyz?cosign artifacts unavailable (%s), proceeding with SHA-256 onlyu{   cosign not on PATH — installing tirith with SHA-256 verification only (install cosign for full supply chain verification))Nchecksum_failedzr:gzr   )Ncross_device_copy_failedzcosign + SHA-256zSHA-256 onlyztirith installed to %s (%s)r+   )#r3   r4   debugr}   r   rx   ry   rz   _REPOtempfilemkdtemprT   r   rF   rG   r   r&   r\   rmtreer]   r   r   tarfilerQ   r   rn   movecopyrj   chmodstatst_modeS_IXUSRS_IXGRPS_IXOTH)r   r   targetr   base_urltmpdirr   r   r   r   r   cosign_verifiedcosign_resultr   srcr_   r   verifications                     r   _install_tirithr     s    )&..fllCFE__&(8(8(:	<+VHG,L$UG+DEH !!):;K2ww||FL9fo>77<<(;<GGLL)<=	OQWX	+hZq7FhZ~6G  <<!Y(+=>I(+=>	J !/~x S D(&*O"e+ WX=P 	fD1I KK WXKK N O  nlK*< 	fD19 \\,/ 	$30fcBKC{V|	$ 	$8 	fD15 	$
 ww||O-x8	8KKT" 	rwwt},,t||;dllJT\\YZ-<).14FRx 	fD1]   ?E   	+,c2*| 	fD1A	+  d]_bccd,	$ 	$  	88C& 8IIdO 7 	fD18 '	8( 	fD1s  <L= BQ * M 
Q "N   Q 98Q 
Q  N?6	Q 0Q 	O BQ =	M	MM	N%	N
.Q 
NQ 	N<N71Q 7N<<Q ?O	Q 	P>O-,P>-	P77PP7	PP7PP7P>Q 6P77P>:Q =P>>Q Qconfigured_pathc                     | dk7  S )zHReturn True if the user explicitly configured a non-default tirith path.r   r5   )r   s    r   _is_explicit_pathr     s    h&&r   c                 \   t         t         t        urt         S t        j                  j	                  |       }t        |       }t         t        u }|st               s
t        a da|S |rt        j                  j                  |      r(t        j                  |t        j                        r|a |S t        j                  |      }|r|a |S t        j                  d|        t        a da|S t        j                  d      }|r|a dat                |S t        j                  j!                  t#               d      }t        j                  j                  |      r4t        j                  |t        j                        r|a dat                |S |r1t        dk(  r&t        j                  d      rda dat                d	}n|S t$        t$        j'                         r|S t)               }|t+               r
t        a |a|S t-               \  }}|r|a dat                |S t        a |at/        |       |S )
u@  Resolve the tirith binary path, auto-installing if necessary.

    If the user explicitly set a path (anything other than the bare "tirith"
    default), that path is authoritative — we never fall through to
    auto-download a different binary.

    For the default "tirith":
    1. PATH lookup via shutil.which
    2. $HERMES_HOME/bin/tirith (previously auto-installed)
    3. Auto-install from GitHub releases → $HERMES_HOME/bin/tirith

    Failed installs are cached for the process lifetime (and persisted to
    disk for 24h) to avoid repeated network attempts.
    Nr   z6Configured tirith path %r not found; scanning disabledexplicit_path_missingr   r+   rZ   r[   F)r*   _INSTALL_FAILEDr   rF   
expanduserr   r   r,   r   accessX_OKr\   r]   r3   r4   r^   rG   rn   r7   is_aliverX   r`   r   rh   )	r   expandedexplicitinstall_failedfound
hermes_bindisk_reason	installedr_   s	            r   _resolve_tirith_pathr     s   $ !nO&Kww!!/2H 1H#6N 13("8 77>>(#		(BGG(D%NOX&"NLOQ`a("9
 LL"E"$o/:J	ww~~j!bii
BGG&D#"$
 "&666<<;Q!N&(#!#"NO
 "'?'?'A
 '(K#=#?("-')Iv""$ %N$ Or   c                    t         5  t        
	 ddd       yt        j                  d      }|r|ada	 ddd       yt
        j                  j                  t               d      }t
        j                  j                  |      r2t        j                  |t
        j                        r|ada	 ddd       yt        |       \  }}|r|adat                nt        a|at        |       ddd       y# 1 sw Y   yxY w)z6Background thread target: download and install tirith.Nr   r+   r   )_install_lockr*   r\   r]   r,   r   rF   rG   rn   r   r   r   r   r^   r   rh   )r   r   r   r   r_   s        r   _background_installr  X  s     
 )%) ) X&"N&(#) ) WW\\/"3X>
77>>*%"))J*H'N&(#!) )$ ,F	6&N&(#!#,N&,# (5) ) )s   C2C2A0C263C22C;c                    t               }|d   syt        Xt        t        urLt        }t        j                  j                  |      r&t        j                  |t        j                        r|S yt               s	t        ada	y|d   }t        |      }t        j                  j                  |      }|rkt        j                  j                  |      r(t        j                  |t        j                        r|a|S t        j                  |      }|r|a|S t        ada	yt        j                  d      }|r|ada	t                |S t        j                  j                  t!               d      }t        j                  j                  |      r4t        j                  |t        j                        r|ada	t                |S t        t        u r.t        dk(  r$t        j                  d	      rdada	t                nyt#               }|t%               r	t        a|a	yt&        t&        j)                         s2t+        j,                  t.        d
| id      at&        j1                          y)a  Ensure tirith is available, downloading in background if needed.

    Quick PATH/local checks are synchronous; network download runs in a
    daemon thread so startup never blocks. Safe to call multiple times.
    Returns the resolved path immediately if available, or None.
    r   Nr   r   r   r   r+   rZ   r[   r   T)r   kwargsdaemon)r)   r*   r   r   rF   r   r   r   r   r,   r   r   r\   r]   r^   rG   rn   rX   r`   r7   r   	threadingThreadr  start)	r   r(   rF   r   r   r   r   r   r   s	            r   ensure_installedr
  x  s     
!C  !nO&K77>>$BIIdBGG$<K
 !"("8-(O 1Hww!!/2H 77>>(#		(BGG(D%NOX&"NL("9 LL"E"$o/:J	ww~~j!bii
BGG&D#"$ ("&666<<;Q!N&(#!#
 '(K#=#?("- o&>&>&@#**&"L1

 	r   2   i  commandc           
      $   t               }|d   sdg ddS t        rdg ddS t               sdg ddS t        |d         }|d   }|d   }|t	        d
d       |rdg ddS dg ddS 	 t        j                  |dddddd| gdd|t
        j                        }|j                  }|d"k(  rd}	d"anF|d#k(  rd}	n>|d$k(  rd%}	n6t         j#                  d&|       t                |r
dg d'| d(dS dg d'| d)dS g }
d}	 |j$                  j'                         rt)        j*                  |j$                        ni }|j-                  d*g       }|d	t.         }
|j-                  d+d      xs dd	t0         }|	d%k(  r%|
r#|
D cg c]  }t9        |      r| }}|sd}	g }
d}|	|
|dS # t        $ r`}dt        |      j                   dt        |dd       }t	        |d|       t                |rdg d| dcY d	}~S dg d| dcY d	}~S d	}~wt
        j                  $ r1 t	        d| d|       t                |rdg d| d dcY S dg d!dcY S w xY w# t(        j2                  t4        f$ r( t         j7                  d,       |	dk(  rd-}n|	d%k(  rd.}Y w xY wc c}w )/a@  Run tirith security scan on a command.

    Exit code determines action (0=allow, 1=block, 2=warn). JSON enriches
    findings/summary. Spawn failures and timeouts respect fail_open config.
    Programming errors propagate.

    Returns:
        {"action": "allow"|"warn"|"block", "findings": [...], "summary": str}
    r   allowr+   )actionfindingssummaryz!tirith disabled (circuit breaker)r   r   r   Ntirith_path_nonez/tirith path resolved to None; scanning disabledztirith path unavailableblockz%tirith path unavailable (fail-closed)checkz--jsonz--non-interactivez--shellposixz--Tr   ztirith_spawn_failed::errnoztirith spawn failed: %sztirith unavailable: z#tirith spawn failed (fail-closed): ztirith_timeout:ztirith timed out after %dsztirith timed out (zs)ztirith timed out (fail-closed)r   r1   r   warnz'tirith returned unexpected exit code %dztirith exit code z (fail-open)z (fail-closed)r  r  z.tirith JSON parse failed, using exit code onlyz-security issue detected (details unavailable)z/security warning detected (details unavailable))r)   r/   r   r   r>   r   r   r   rT   type__name__getattrr6   r   r   r.   r3   r4   stdoutrS   jsonloadsr%   _MAX_FINDINGS_MAX_SUMMARY_LENJSONDecodeErrorAttributeErrorr   _is_app_tld_finding)r  r(   r   r   	fail_openr   r   	spawn_key	exit_coder  r  r  dataraw_findingsrW   non_suppressibles                   r   check_command_securityr*    sE     
!C !rbAA !r>abb
 !"!rbAA&s='9:K"#G&'I=	
 %2B[\\!r>eff`'8-@w0$$
B !!IA~	a	a 	@)L%2DUV_U``lBmnn!r@QR[Q\\j>kll HGH,2MM,?,?,Atzz&--(rxx
B//88Ir*0b2C3CD H'/N!7J17MANNFHG(wGGO  k +49+=+=*>aWVX@Y?Z[	97=%2DXY\X]B^__!r@cdgch>ijj$$ 	`gY'(	

 	%2DVW^V__aBbcc!r>^__	`L   .1 HEFWEGvGGH OsV   '0F 8A3I	 6JJ	I$AG?+I1G?9I?<I=II	=J
	J
findingc                     t        | t              sy| j                  d      dk7  rydD ]3  }| j                  |      }|dt        |      j	                         v s3 y y)zReturn True if this finding is a lookalike_tld warning for the .app TLD only.

    Checks the rule_id and inspects common value/detail field names that
    Tirith may use to carry the TLD string.
    Frule_idlookalike_tld)valuetlddetaildescriptionr9   z.appT)
isinstancedictr%   rC   r   )r+  fieldr   s      r   r#  r#  Y  sa     gt${{90E kk% ?vS)99 r   )r   N)r+   )
   )H__doc__r   r  loggingr   rx   r\   r   r   r   r   r  rO   urllib.requestr   hermes_constantsr   	getLoggerr  r3   r   r   r   rC   boolr   r   r   r4  r)   r*   __annotations__r   r,   r2   r.   r/   r6   Lockr  r7   r  setr8   r;   r>   rA   rP   rD   rH   rX   r`   rh   r^   rn   r}   r   r   r   r   TarFiletupler   r   r   r   r  r
  r  r   r*  r#  r5   r   r   <module>rB     s  ,    	          ,			8	$ 17ef >/3 / /$ /#   t 8 %)d
T! (!  ! c t 

 	 +/!!D( / !U #c( "y~~#C ## # #! "# "
Fc F
cDj "D " "	 d
 8(t ($ $3 $ $&3 &# &# &$QU+ &R3  3 SW 2) )3 )cTXjZ]oH^ )4 -1 c2T c2U3:s?5K c2L's 't '
i# i# iX 15 ) )@ .2 Wd W|  |HC |HD |H~ $ r   