+
    jHàjÓ,  ã                  ó  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIHt ^ RIt^ RI	t	^ RI
t
^ RIt^ RIHt ^ RIt ! R R]4      tR R ltR	 R
 ltRR/R R lltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR# )z´Bounded local-control discovery without diagnostic fallback or mutation (the one exception: an
upgraded same-owner ``gateway.lock`` is narrowed to 0600, see :func:`_private_lock`).)ÚannotationsN)ÚPath)ÚLiteralc                  ó>   a € ] tR t^tRR V 3R llltR R ltRtV ;t# )ÚDiscoveryErrorc               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚreasonÚstrÚdetailú
str | NoneÚfix© )Úformats   "ÚI/home/ubuntu/.hermes/hermes-agent/hermes_cli/gateway_runtime_discovery.pyÚ__annotate__ÚDiscoveryError.__annotate__   s&   € ÷ Pñ P˜sð P¨Jð PÀJñ Pó    c                	óÞ   <€ WVuV n         V n        V n        V'       d   V'       d   V R V 2MTV n        \        ST `  V P                  '       d   V RV P                   24       R# T4       R# )z; z: N)r	   Úcauser   r   ÚsuperÚ__init__)Úselfr	   r   r   Ú	__class__s   &&&&€r   r   ÚDiscoveryError.__init__   sZ   ø€ ð -3¸CÐ)ˆŒ�T”Z ¤ß,2·s˜˜  3 %Ñ(ÀˆŒÜ‰Ñ°t·{·{°{˜F˜8 2 d§k¡k ]Ð3ÖOÈÖOr   c               ó    € V ^8„  d   QhRRRR/# )r   ÚlimitÚintÚreturnr   r   )r   s   "r   r   r      s   € ÷ ñ  Cð ¨Jñ r   c                óT  € V P                   e   \        V P                   4      V8:  d   V P                   # V P                  '       d   RMRpV\        V4      ,
          RV P                  ;'       g    RrTp\        V4      V8:  d   TMVRV\        V4      ,
           V,           pWR,           # )z®``detail`` within ``limit`` characters, never with a cut-off command: a repair command
that does not fit is dropped with a notice, and an overlong description is cut visibly.Nz1; repair command omitted (path too long to print)Ú u   â€¦ [truncated])r   Úlenr   r   )r   r   ÚnoticeÚroomÚmarkerr   s   &&    r   Úbounded_detailÚDiscoveryError.bounded_detail   s‹   € ð �;‰;Ò¤# d§k¡kÓ"2°eÔ";Ø—;‘;ÐØHLÏÏÈÑDÐVXˆØ#¤c¨&£kÕ1Ð3DÀdÇjÁj×FVÐFVÐTV�eˆÜ˜U› tÔ+‘°Ð7J¸¼sÀ6»{Õ8JÐ1KÈfÕ1TˆØ�~Ðr   )r   r   r   r	   )NN)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   r%   Ú__static_attributes__Ú__classcell__)r   s   @r   r   r      s   ø† ÷Pò P÷ó r   r   c               ó    € V ^8„  d   QhRRRR/# )r   Úpathr   r   Úboolr   )r   s   "r   r   r   %   s   € ÷ 
ñ 
˜tð 
¨ñ 
r   c                ó  € \        \        R4      '       g   R#  R\        P                  ! V RR7      9   #   \         dA   pTP                  \        P
                  \        P                  09   d    Rp?R#  Rp?R# Rp?ii ; i)z³A Linux POSIX access ACL is present, or its absence cannot be established. Python has no
os.listxattr on macOS (whose chmod +a ACLs are separate); mode bits stay the policy there.Ú	listxattrFzsystem.posix_acl_access)Úfollow_symlinksNT)ÚhasattrÚosr1   ÚOSErrorÚerrnoÚENOTSUPÚ
EOPNOTSUPP)r.   Úexcs   & r   Ú_may_have_access_aclr:   %   s`   € ô ”2�{×#Ò#ÙðØ(¬B¯LªL¸ÈuÔ,UÑUÐUøÜô Ø�9‰9œŸ™¬×(8Ñ(8Ð9Ô9ÝÝûðús   š5 µB Á /A;Á;B c               ó$   € V ^8„  d   QhRRRRRR/# )r   Únodeúos.stat_resultr.   r   r   r/   r   )r   s   "r   r   r   2   s&   € ÷ ^ñ ^˜>ð ^°ð ^¸$ñ ^r   c                óø  € \         P                  ! V P                  4      pV^,          '       d   R# V^,          '       g   R# \        V4      '       d   R#  ^ RIp^ RIpVP                  V P                  4      VP                  V P                  4      reVP                  4        Uu0 uF+  qwP                  VP                  8X  g   K  VP                  kK-  	  ppTP                  TP                  8H  ;'       d\    TP"                  TP$                  8H  ;'       d;    \'        TP(                  4      TP$                  08*  ;'       d    Y€P                  08*  '       * # u upi   \        \        \         3 d     R# i ; i)aj  The profile home keeps the operator's mode (main's home policy: symlinked homes,
HERMES_HOME_MODE 0701/0750). Only write by another user lets them swap the socket; read/search
bits grant nothing against our 0600 socket, and group-write is harmless when the group is the
owner's private group (the umask-002 user-private-group default). What we create stays 0700.TFN)ÚstatÚS_IMODEÚst_moder:   ÚgrpÚpwdÚgetpwuidÚst_uidÚgetgrgidÚst_gidÚgetpwallÚpw_gidÚgr_gidÚpw_uidÚImportErrorÚKeyErrorr5   Úgr_nameÚpw_nameÚsetÚgr_mem)	r<   r.   ÚmoderB   rC   ÚuserÚgroupÚpÚprimary_memberss	   &&       r   Úhome_mode_unsaferW   2   s,  € ô
 �<Š<˜Ÿ™Ó%€DØˆe‡|„|ÙØ�%�<Œ<Ùô ˜D×!Ò!ÙðÛÛØ—l‘l 4§;¡;Ó/°·±¸d¿k¹kÓ1JˆeØ-0¯\©\¬^ÓX©^¨¿x¹xÈ5Ï<É<Ñ?Wœ8˜1Ÿ8œ8©^ˆÐXð —‘ §¡Ñ+÷ ]ð ]°·±ÀÇÁÑ0M÷ ]ð ]Ü˜Ÿ™Ó%¨$¯,©,¨Ñ7÷]ð ]Ø<K×P[ÑP[È}Ñ<\ô^ð ^ùò YøÜœ¤7Ð+ô Úðús+   ÁAE Â&EÃEÃE ÅE ÅE9Å8E9ÚhomeFc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   r.   r   Úkindr
   rX   r/   r   r=   r   )r   s   "r   r   r   M   s(   € ÷ ñ ˜ð  sð °$ð À>ñ r   c          
     óî  € V P                  4       pR \        P                  R\        P                  R\        P                  /pWA,          ! VP
                  4      '       g3   \        RV  R\        P                  ! VP
                  4       RV 24      h\        P                  ! 4       pVP                  V8w  d    \        RV  RVP                   RV R24      h\        P                  ! VP
                  4      pV'       dF   \        W04      '       d5   \        R	V  R
VR R2R\        P                  ! \        V 4      4       24      hV'       g)   V^?,          '       d   \!        YVR8X  d   R4      hR4      hV# )ÚsocketÚfileÚ	directoryÚunsafe_control_pathz is ú, expected z is owned by uid z, expected uid z- (gateway user); chown it to the gateway userÚunsafe_control_permissionsú
 has mode Ú04oz, writable by another userzchmod go-w iÀ  i€  )Úlstatr?   ÚS_ISSOCKÚS_ISREGÚS_ISDIRrA   r   Úfilemoder4   ÚgetuidrE   r@   rW   ÚshlexÚquoter
   Ú
_open_mode)r.   rZ   rX   r<   Ú
predicatesÚexpected_uidrR   s   &$$    r   Ú_private_nodero   M   sD  € Ø�:‰:‹<€DØœDŸM™M¨6´4·<±<ÀÌdÏlÉlÐ[€JØÖ˜DŸL™L×)Ò)ÜØ!Øˆf�DœŸš t§|¡|Ó4Ð5°[ÀÀÐGó
ð 	
ô —9’9“;€LØ‡{�{�lÔ"ÜØ!ØˆfÐ% d§k¡k ]°/À,Àð P+ð +ó
ð 	
ô
 �<Š<˜Ÿ™Ó%€DßÔ  ×,Ò,ÜÐ9¸d¸VÀ:ÈdÐSVÈZÐWqÐ;rØ*¬5¯;ª;´s¸4³yÓ+AÐ*BÐCóEð 	Eç�D˜5—L”LÜ˜¨d°kÔ.A UÓMÐMÀuÓMÐMØ€Kr   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r.   r   rR   r   Úexpectedr   r   r   )r   s   "r   r   r   e   s.   € ÷ Jñ J�Tð J ð J°ð J¸ñ Jr   c                óx   € \        R V  RVR RVR 2RVR R\        P                  ! \        V 4      4       24      # )ra   rb   rc   r`   zchmod ÚoÚ )r   rj   rk   r
   )r.   rR   rq   s   &&&r   rl   rl   e   sP   € ÜÐ6¸4¸&À
È4ÐPSÈ*ÐT_Ð`hÐilÐ_mÐ8nØ" 8¨A ,¨a´·²¼CÀ»IÓ0FÐ/GÐHóJð Jr   c               ó    € V ^8„  d   QhRRRR/# )r   Úsockúsocket.socketr   z
int | Noner   )r   s   "r   r   r   j   s   € ÷ ñ ˜-ð ¨Jñ r   c                óà  € \        \        R4      '       dK   ^ RIpVP                  RV P	                  \        P
                  \        P                  ^4      4      ^,          # \        P                  R8w  d   R# ^ RI	pVP                  4       VP                  4       rCVP                  RRR7      P                  pVP                  VP                  VP                  4      VP                  VP                  4      .Vn        VP                  Vn        V! V P#                  4       VP%                  V4      VP%                  V4      4      ^ 8w  d   \'        VP)                  4       R4      hVP*                  # )z™Kernel-reported uid of the process on the other end of a connected AF_UNIX socket
(SO_PEERCRED on Linux, getpeereid on macOS); None where neither exists.ÚSO_PEERCREDNÚ3iÚdarwinT)Ú	use_errnozgetpeereid failed)r3   r\   ÚstructÚunpackÚ
getsockoptÚ
SOL_SOCKETry   ÚsysÚplatformÚctypesÚc_uintÚCDLLÚ
getpeereidÚc_intÚPOINTERÚargtypesÚrestypeÚfilenoÚbyrefr5   Ú	get_errnoÚvalue)rv   r}   rƒ   ÚuidÚgidr†   s   &     r   Úsocket_peer_uidr‘   j   s  € ô Œv�}×%Ò%ÛØ�}‰}˜T 4§?¡?´6×3DÑ3DÄf×FXÑFXÐZ\Ó#]Ó^Ð_`ÕaÐaÜ
‡|�|�xÔÙÛØ�}‰}‹ §¡£ˆØ—‘˜T¨T�Ó2×=Ñ=€JØ!Ÿ<™<¨¯©¸¿¹Ó)FÈÏÉÐW]×WdÑWdÓHeÐf€JÔØŸ™€JÔÙ�$—+‘+“- §¡¨cÓ!2°F·L±LÀÓ4EÓFÈ!ÔKÜ�f×&Ñ&Ó(Ð*=Ó>Ð>Ø�9‰9Ðr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   rX   r   ÚtimeoutÚfloatr   rw   r   )r   s   "r   r   r   |   s!   € ÷ ñ ˜$ð ¨ð °=ñ r   c                ó‚  € \        V 4      p\        P                  ! \        P                  \        P                  4      p VP	                  V4       VP                  \        V4      4       \        V4      pVe&   V\        P                  ! 4       8w  d   \        R4      hV#   \         d    TP                  4        h i ; i)aX  Connected control socket for *home* whose listener runs as this user (caller closes it).
The path is validated by lstat first, but connect() follows a symlink swapped in afterwards,
so the listening process itself is authenticated. Platforms without a peer-credential API
(neither SO_PEERCRED nor getpeereid) fall back to the path checks alone.Úunsafe_control_peer)Ú_socket_pathr\   ÚAF_UNIXÚSOCK_STREAMÚ
settimeoutÚconnectr
   r‘   r4   ri   r   ÚBaseExceptionÚclose)rX   r“   r.   Úpeerr�   s   &&   r   Úconnect_privaterŸ   |   s‘   € ô
 ˜Ó€DÜ�=Š=œŸ™¬×);Ñ);Ó<€Dð	Ø�‰˜Ô Ø�‰”S˜“YÔÜ˜dÓ#ˆØŠ?˜s¤b§i¢i£kÔ1Ü Ð!6Ó7Ð7ØˆøÜô Ø�
‰
ŒØðús   Á A B! Â!B>c               ó    € V ^8„  d   QhRRRR/# )r   rX   r   r   r   )r   s   "r   r   r   �   s   € ÷ ñ �tð  ñ r   c                óÊ  € \        V R RR7       V R,          p\        P                  P                  V4      '       d   \        VRR7       V# V R,          p\        P                  \        P
                  ,          \        P                  ,          p\        P                  ! \        P                  ! W#4      R4      ;_uu_ 4       p\        P                  ! VP                  4       4      p\        P                  ! VP                  4      '       dR   VP                  \        P                  ! 4       8w  g.   \        P                   ! VP                  4      ^?,          '       d   \#        R4      hVP%                  R	4      pR
R
R
4       \'        X4      R8”  d   \#        R4      h\)        VP+                  R4      P-                  4       4      pVP/                  4       '       g   \#        R4      h^ RIHp VP4                  R8w  g%   VP6                  P4                  RV! V 4       28w  d   \#        R4      h\        VP6                  R R7       \        VRR7       V#   + '       g   i     Là; i)r^   T)rZ   rX   zgateway.sockr\   ©rZ   zgateway.sock.pathÚrbÚunsafe_control_pointeri  Ni   Úinvalid_control_pointerzutf-8)Ú
_home_hashzcontrol.sockz
hermes-gw-)ro   r4   r.   ÚlexistsÚO_RDONLYÚ
O_NOFOLLOWÚ
O_NONBLOCKÚfdopenÚopenÚfstatr‹   r?   rf   rA   rE   ri   r@   r   Úreadr!   r   ÚdecodeÚstripÚis_absoluteÚgateway.control_socketr¦   ÚnameÚparent)	rX   ÚdirectÚpointerÚflagsÚstreamÚmetadataÚdataÚtargetr¦   s	   &        r   r—   r—   �   s¢  € Ü�$˜[¨tÕ4Ø�NÕ"€FÜ	‡w�w‡��v×ÒÜ�f 8Õ,ØˆØÐ(Õ(€Gä�K‰Kœ"Ÿ-™-Õ'¬"¯-©-Õ7€EÜ	�Š”2—7’7˜7Ó*¨D×	1Ô	1°VÜ—8’8˜FŸM™M›OÓ,ˆÜ—’˜X×-Ñ-×.Ò.°(·/±/ÄRÇYÂYÃ[Ô2PÜ—<’< × 0Ñ 0Ó1°E×9Ô9Ü Ð!9Ó:Ð:Ø�{‰{˜4Ó ˆ÷ 
2ô ˆ4ƒy�4ÔÜÐ6Ó7Ð7Ü�$—+‘+˜gÓ&×,Ñ,Ó.Ó/€FØ×Ñ×ÒÜÐ6Ó7Ð7Ý1ð ‡{�{�nÔ$¨¯©×(:Ñ(:À
É:ÐVZÓK[ÐJ\Ð>]Ô(]ÜÐ6Ó7Ð7Ü�&—-‘- kÕ2Ü�&˜xÕ(Ø€M÷' 
2×	1ús   ÃBIÅIÉI"	c               ó$   € V ^8„  d   QhRRRRRR/# )r   rX   r   r“   r”   r   Údictr   )r   s   "r   r   r   ®   s!   € ÷ +ñ +˜ð +¨5ð +°Tñ +r   c               ó&  € \         P                  R8X  d   ^ RIHp \	        V! V RV4      4      # \
        P                  ! 4       V,           pRp\        W4      ;_uu_ 4       pV\
        P                  ! 4       ,
          pV^ 8:  d   \        hVP                  V4       VP                  V4       \        4       pRV9  d§   V\
        P                  ! 4       ,
          pV^ 8:  d   \        hVP                  V4       VP                  \        RR\        V4      ,
          4      4      p	V	'       g   \        R4      hVP!                  V	4       \        V4      R8”  g   K¢  \        R	4      h R
R
R
4       \	        \#        X4      4      #   + '       g   i     L$; i)zCUnlike diagnostic queries, retain timeout/access/protocol failures.Únt)Úquery_runtime_controls(   {"protocol":1,"verb":"identify","id":1}
ó   
i   i  Úincomplete_control_responsei   Úoversized_control_responseN)r4   r³   Ú!gateway.runtime_bootstrap_windowsrÀ   Ú_identify_responseÚtimeÚ	monotonicrŸ   ÚTimeoutErrorrš   ÚsendallÚ	bytearrayÚrecvÚminr!   r   ÚextendÚbytes)
rX   r“   rÀ   ÚdeadlineÚrequestÚclientÚbudgetrº   Ú	remainingÚchunks
   &$        r   Úquery_identifyrÕ   ®   s;  € ä	‡w�w�$„ÝKÜ!Ñ"7ØÐ>Àó#Ió Jð 	Jä�~Š~Ó 'Õ)€HØ:€GÜ	˜×	'Ô	'¨6ØœDŸNšNÓ,Õ,ˆØ�QŒ;ÜÐØ×Ñ˜&Ô!Ø�‰�wÔÜ‹{ˆØ˜4ÔØ ¤4§>¢>Ó#3Õ3ˆIØ˜AŒ~Ü"Ð"Ø×Ñ˜iÔ(Ø—K‘K¤ E¨6´C¸³IÕ+=Ó >Ó?ˆEßÜ$Ð%BÓCÐCØ�K‰K˜ÔÜ�4‹y˜6Ö!Ü$Ð%AÓBÐBð  ÷ 
(ô$ œe D›kÓ*Ð*÷% 
(×	'ús   Á C3F ÅF Æ F	c               ó    € V ^8„  d   QhRRRR/# )r   rº   rÎ   r   r½   r   )r   s   "r   r   r   Ë   s   € ÷ ñ ˜Uð  tñ r   c                ó|  € \         P                  ! V P                  R ^4      ^ ,          4      p\        V\        4      '       dg   VP                  R4      RJgR   VP                  R4      ^8w  g<   VP                  R4      ^8w  g&   \        VP                  R4      \        4      '       g   \        R4      hVR,          # )rÁ   ÚokTÚprotocolÚidÚresultÚinvalid_control_response)ÚjsonÚloadsÚsplitÚ
isinstancer½   Úgetr   )rº   Úresponses   & r   rÅ   rÅ   Ë   s‹   € Ü�zŠz˜$Ÿ*™* U¨AÓ.¨qÕ1Ó2€HÜ�x¤×&Ò&¨(¯,©,°tÓ*<ÀDÓ*HØ�|‰|˜JÓ'¨1Ô,°·±¸TÓ0BÀaÔ0GÜ˜hŸl™l¨8Ó4´d×;Ò;ÜÐ7Ó8Ð8Ø�HÕÐr   c               ó    € V ^8„  d   QhRRRR/# )r   Úlockr   r   ÚNoner   )r   s   "r   r   r   Ô   s   € ÷ )ñ )˜ð ) ñ )r   c                ó²  €  \        V RR7       R#   \         d»   pTP                  R8w  d   h ^ RIHp \
        P                  ! T \
        P                  \
        P                  ,          \
        P                  ,          4      p T! T4       \
        P                  ! T4       M  \
        P                  ! T4       i ; i\        T RR7        Rp?R# Rp?ii ; i)a¶  Validate ``gateway.lock``; narrow an upgraded same-owner lock to 0600 first.

Main created the inode with ``open(path, "a+")`` under the umask (0644), and lock inodes are
never replaced, so without this an upgraded home reads ``inaccessible`` forever and nothing
auto-starts its owner. Only the mode is touched, only on a regular single-link inode this user
owns, through a NOFOLLOW descriptor; a foreign or non-regular node still raises.r]   r¢   ra   )Útighten_lock_modeN)ro   r   r	   Úgateway.runtime_ownershiprç   r4   r¬   r¨   r©   rª   r�   )rä   r9   rç   Úfds   &   r   Ú_private_lockrê   Ô   s‹   € ð)Ü�d ×(øÜô 	)Ø�:‰:Ð5Ô5ØÝ?Ü�WŠW�Tœ2Ÿ;™;¬¯©Õ6¼¿¹ÕFÓGˆð	Ù˜bÔ!ä�HŠH�R�LøŒB�HŠH�R�LúÜ�d ×(Ó(ûð	)ús-   ‚ ‘CœA'CÂB#ÂCÂ#B;Â;CÃCc               ó    € V ^8„  d   QhRRRR/# )r   rX   r   r   z-Literal['starting', 'absent', 'inaccessible']r   )r   s   "r   r   r   é   s   € ÷ ñ ˜dð Ð'Tñ r   c                óÚ   € ^ RI Hp V R,          p \        P                  R8w  d   \	        V4       V! V4      '       d   R# R#   \
         d     R# \        \        \        3 d     R# i ; i)zJA reservation before PID/control publication already excludes a new owner.)Ú&_is_gateway_runtime_lock_active_strictzgateway.lockr¿   ÚstartingÚabsentÚinaccessible)	Úgateway.statusrí   r4   r³   rê   ÚFileNotFoundErrorr5   ÚRuntimeErrorr   )rX   rí   rä   s   &  r   Úmissing_owner_staterô   é   s`   € åEØ�.Õ €DðÜ�7‰7�dŒ?Ü˜$ÔÙCÀD×IÒIˆzÐWÈxÐWøÜô ÚÜ”\¤>Ð2ô Úðús(   ‘-A ¿A ÁA ÁA*ÁA*Á%A*Á)A*)Ú__doc__Ú
__future__r   r6   rÝ   r4   Úpathlibr   rj   r\   r?   r�   Útypingr   rÆ   Ú
ValueErrorr   r:   rW   ro   rl   r‘   rŸ   r—   rÕ   rÅ   rê   rô   r   r   r   Ú<module>rú      sz   ðñYõ #ã Û Û 	Ý Û Û Û Û 
Ý Û ô�Zô õ&
õ^ð6¸÷ õ0Jõ
õ$õ&õ>+õ:õ)÷*r   