+
    lHàjU)  ã                  ó”  € R t ^ RIHt ^ RIt^ RIt^ RIHtHt	 ^RI
HtHt ]P                  ! ]4      t]! 4       t]P"                  tRtRtRtRtR	tR
 R ltR R ltR R ltR]RRR]RR/R R lltR R lt]! RRR]R7      R R l4       t]! R4      R  R! l4       t]! R"4      R# R$ l4       t]! R%]R&7      R' R( l4       tR) R* ltR# )+aŽ  Browser controller registration and result routing for the dashboard.

The controller extension registers over the authenticated ``/api/ws`` gateway. Everything
binds to the SERVER-MINTED identity (``WSTransport.auth_identity``, stamped from the single-use
ticket); a client-supplied ``principal_id`` is ignored and replaced by a digest of it. Broker
frames are re-enveloped as Gateway ``event`` frames; ``result`` resolves a command only when the
request arrives on a transport ATTACHED to the session and that transport is the broker-recorded
owner of the exact attached scope (the broker's exact-scope ``complete`` is the backstop).
Capabilities come from the broker's explicit allowlist (no raw CDP/eval/uploads). Bodies are
rebound onto server.py's globals (bind_module publishes this module's helpers too), which is how
the session gate reaches ``_session_transport_contains`` with no import of its own.
)ÚannotationsN)ÚINTERNAL_PROVIDERÚINTERNAL_USER_ID)ÚHandlerRegistryÚbind_modulezcloud-ticket-wsi3  z*authenticated controller identity requiredz)controller is not owned by this transportz)no controller registered for this sessionc               ó    € V ^8„  d   QhRRRR/# )é   ÚidentityÚobjectÚreturnÚbool© )Úformats   "ÚH/home/ubuntu/.hermes/hermes-agent/tui_gateway/methods_browser_control.pyÚ__annotate__r   &   s   € ÷ 	Qñ 	Q¨ð 	Q°Dñ 	Qó    c                ój  € \        V \        4      '       g   R# V P                  R4      V P                  R4      r!\        V\        4      '       d   VP	                  4       '       g   R# \        V\        4      '       d   VP	                  4       '       g   R# V\
        8H  ;'       d
    V\        8H  '       * # )zHTrue for a server-minted, non-internal ``{user_id, provider}`` identity.FÚuser_idÚprovider)Ú
isinstanceÚdictÚgetÚstrÚstripÚ_INTERNAL_USER_IDÚ_INTERNAL_PROVIDER)r	   r   r   s   &  r   Ú_is_authenticated_identityr   &   s~   € ä�h¤×%Ò%ÙØ Ÿ™ YÓ/°·±¸jÓ1IˆXÜ�gœs×#Ò#¨7¯=©=¯?ª?ÙÜ�h¤×$Ò$¨H¯N©N×,<Ò,<ÙØÔ,Ñ,×OÐO°Ô=OÑ1OÔPÐPr   c               ó    € V ^8„  d   QhRRRR/# )r   r	   r   r   r   r   )r   s   "r   r   r   2   s   € ÷ Yñ Y ð Y¨ñ Yr   c                ó˜   € ^ RI Hp V! V 4      pR\        P                  ! VP	                  R4      4      P                  4       R,           2# )zVServer-derived principal id: stable per user, unspoofable without the minted identity.)Úauthenticated_subjectzprincipal:dashboard:zutf-8:Né    N)Úgateway.session_identityr   ÚhashlibÚsha256ÚencodeÚ	hexdigest)r	   r   Úraws   &  r   Ú_principal_digestr'   2   s>   € å>Ù
 Ó
)€CØ!¤'§.¢.°·±¸GÓ1DÓ"E×"OÑ"OÓ"QÐRUÕ"VÐ!WÐXÐXr   c               ó    € V ^8„  d   QhRRRR/# )r   Ú	transportr
   Ú
session_idr   r   )r   s   "r   r   r   9   s   € ÷ ñ  Fð ¸ñ r   c                ó   a a€ R VV 3R llpV# )zžBroker send callback: re-envelope ``{method, params}`` as a Gateway ``event`` frame
(``type`` = method, ``payload`` = params, plus the owning ``session_id``).c               ó    € V ^8„  d   QhRRRR/# )r   Úframer   r   ÚNoner   )r   s   "r   r   Ú*_broker_event_writer.<locals>.__annotate__=   s   € ÷ Kñ K�Dð K˜Tñ Kr   c                ó  <€  SP                  R RRRRRV P                  R4      RSRV P                  R4      //4      pTR	J d   \        R
4      hR#   \         d)    \        P	                  RST P                  R4      4       h i ; i)Újsonrpcz2.0ÚmethodÚeventÚparamsÚtyper*   Úpayloadz9browser controller event write failed session=%s frame=%sFz%browser controller event write failedN)Úwriter   Ú	ExceptionÚloggerÚ	exceptionÚConnectionError)r-   Úacceptedr*   r)   s   & €€r   ÚsendÚ"_broker_event_writer.<locals>.send=   sœ   ø€ ð	Ø —‘Ø˜5 (¨GØØ˜EŸI™I hÓ/°¸zØ˜uŸy™y¨Ó2ðð(ó ˆHð �uÓÜ!Ð"IÓJÐJñ øô ô 	Ü×ÑØKØ˜EŸI™I hÓ/ôð ð	ús   ƒ;A Á3Br   )r)   r*   r=   s   ff r   Ú_broker_event_writerr?   9   s   ù€ ÷Kñ Kð" €Kr   Úidentity_messageÚlookup_scopeTÚmissing_scope_messageÚprecheckc               ó(   € V ^8„  d   QhRRRRRRRR/# )r   Únamer   r@   rA   r   rB   r   )r   s   "r   r   r   Q   s,   € ÷ 3ñ 3Ø
ð3Ø$'ð3ØLPð3àñ3r   c               ó$   a aaaa€ VVVV V3R lpV# )u  Register a handler behind the shared fail-closed (4403) controller gates.

Order: ``precheck(rid, params)`` (may return an error envelope) â†’ caller holds a
server-authenticated, non-internal identity â†’ the named session exists and the caller is
ATTACHED to it, directly or through the ``FanoutTransport`` a mirrored session holds in its
slot â†’ when ``lookup_scope``, a scope is attached for this session/principal/family and the
caller owns it. Then
``fn(rid, params, transport, identity, session_id, broker, scope, session)`` runs.
c                ód   <a € R  V VVVV3R llpS P                   Vn         \        S4      ! V4      # )c               ó    € V ^8„  d   QhRRRR/# ©r   r4   r   r   r   )r   s   "r   r   Ú5_controller_method.<locals>.dec.<locals>.__annotate___   s   € ÷  	\ñ  	\ ð  	\¨$ñ  	\r   c           
     óÖ  <€ ^ RI Hp Se   S! W4      pVe   V# \        4       p\        VRR4      p\	        V4      '       g   \        V \        S4      # \        VP                  R4      ;'       g    R4      p\        ;_uu_ 4        \        P                  V4      p\        Wt4      '       g   \        V \        R4      uuRRR4       #  RRR4       VP                  4       pRp	S'       dc   VP                  V\        V4      \        R7      p	V	f   \        V \        S4      # VP!                  W”4      '       g   \        V \        \"        4      # S
! WWEWhV	X4      #   + '       g   i     L˜; i)é    ©Úbrowser_control_brokerNÚauth_identityr*   Ú z&session is not owned by this transport)r*   Úprincipal_idÚtransport_family)ÚgatewayrN   Úcurrent_transportÚgetattrr   Ú_errÚ_ERR_FORBIDDENr   r   Ú_sessions_lockÚ	_sessionsÚ_session_transport_containsÚget_browser_control_brokerÚscope_for_sessionr'   Ú_CLOUD_TRANSPORT_FAMILYÚis_ownerÚ
_NOT_OWNED)Úridr4   rN   Údeniedr)   r	   r*   ÚsessionÚbrokerÚscopeÚfnr@   rA   rB   rC   s   &&        €€€€€r   ÚhandlerÚ0_controller_method.<locals>.dec.<locals>.handler_   s:  ø€ Ý6àÒ#Ù! #Ó.�ØÒ%Ø!�MÜ)Ó+ˆIÜ˜y¨/¸4Ó@ˆHÜ-¨h×7Ò7Ü˜C¤Ð1AÓBÐBÜ˜VŸZ™Z¨Ó5×;Ð;¸Ó<ˆJß–Ü#Ÿ-™-¨
Ó3�ô
 3°7×FÒFÜ ¤^Ð5]Ó^÷  ’ð G÷  ð ,×FÑFÓHˆFØˆEßØ×0Ñ0Ø)Ô8IÈ(Ó8SÜ%<ð 1ó >�ð ’=Ü ¤^Ð5JÓKÐKð —‘ u×8Ò8Ü ¤^´ZÓ@Ð@Ù�c 9¸
ÈEÐSZÓ[Ð[÷)  —ús   Â7EÅE(	)Ú__doc__r2   )re   rf   r@   rA   rB   rE   rC   s   f €€€€€r   ÚdecÚ_controller_method.<locals>.dec^   s,   ù€ ÷ 	\ô  	\ðD Ÿ*™*ˆŒÜ�dŒ|˜GÓ$Ð$r   r   )rE   r@   rA   rB   rC   ri   s   fdddd r   Ú_controller_methodrk   Q   s   ü€ ÷$%ñ $%ðL €Jr   c               ó   € V ^8„  d   QhRR/# )r   r4   r   r   )r   s   "r   r   r   ‡   s   € ÷ ñ  Dñ r   c                óð   € ^ RI Hp VP                  4       '       g   \        V \        R4      # TpVP                  VP                  R4      4      '       g!   VP                  p\        V \        RV 24      # R# )rL   rM   z,browser.extension_control.enabled is not setÚprotocol_versionz7unsupported browser-control protocol version; expected N)rS   rN   Úbrowser_control_enabledrV   rW   Ú"browser_control_protocol_supportedr   Ú BROWSER_CONTROL_PROTOCOL_VERSION)r`   r4   rN   Ú
broker_modÚexpecteds   &&   r   Ú_register_precheckrt   ‡   sp   € Ý.à!×9Ñ9×;Ò;Ü�CœÐ)WÓXÐXØ'€JØ×8Ñ8¸¿¹ÐDVÓ9W×XÒXØ×>Ñ>ˆÜØ”ØEÀhÀZÐPó
ð 	
ñ r   zbrowser.controller.registerzKbrowser.controller.register requires an authenticated non-internal identityF)r@   rA   rC   c               ó    € V ^8„  d   QhRRRR/# rI   r   )r   s   "r   r   r   š   s   € ÷ :ñ :�4ð :ÐVZñ :r   c                óT  € ^ RI Hp \        VP                  R4      ;'       g    R4      P	                  4       p	\        VP                  R4      ;'       g    R4      P	                  4       p
\        VP                  R4      ;'       g    R4      P	                  4       pV	'       d   V
'       d	   V'       g   \        V \        R4      # VP                  VP                  R4      4      pV'       g   \        V \        R4      # VP                  \        V4      W´Wš\        VR	7      pVP                  V\        W$4      VR
7       \        V RRVP                  RVP                  RVP                   RVP"                  RVP$                  RVP&                  R\)        VP*                  4      //4      # )z¹Attach this connection as the browser controller for one session; fails closed (4403) unless
the flag is on, the protocol version is supported, the gates pass and a capability survives.rM   Úcontroller_idrP   Úbrowser_profile_idÚprofilezJcontroller_id, browser_profile_id, and server session profile are requiredÚcapabilitiesz.no permitted controller capabilities requested)rQ   Ú
profile_idr*   rw   rx   rR   rz   )Úownerrd   rQ   r{   r*   rR   )rS   rN   r   r   r   rV   rW   Ú#filter_browser_control_capabilitiesÚControllerScoper'   r]   Úattachr?   Ú_okrQ   r{   r*   rw   rx   rR   Úsortedrz   )r`   r4   r)   r	   r*   rc   Ú_scoperb   rN   rw   rx   r{   rz   rd   s   &&&&&&&&      r   Ú_rƒ   –   ss  € õ /ä˜Ÿ
™
 ?Ó3×9Ð9°rÓ:×@Ñ@ÓB€MÜ˜VŸZ™ZÐ(<Ó=×CÐCÀÓD×JÑJÓLÐÜ�W—[‘[ Ó+×1Ð1¨rÓ2×8Ñ8Ó:€Jß× 2¿*ÜØ”ØXó
ð 	
ð *×MÑMØ�
‰
�>Ó"ó€L÷ Ü�CœÐ)YÓZÐZØ"×2Ñ2Ü& xÓ0¸ZØ#Ü0¸|ð 3ó M€Eð ‡M�M�%Ô-¨iÓDÈI€MÔVÜˆsØØ˜E×.Ñ.°¸e×>NÑ>NØ˜%×*Ñ*¨O¸U×=PÑ=PØ  %×":Ñ":Ø × 6Ñ 6ØœF 5×#5Ñ#5Ó6ð8ð9ó :ð :r   zbrowser.controller.resultc               ó    € V ^8„  d   QhRRRR/# rI   r   )r   s   "r   r   r   »   s   € ÷ 	,ñ 	,�4ð 	,ÐY]ñ 	,r   c                ó4  € \        VP                  R4      ;'       g    R4      pV'       g   \        V \        R4      # VP                  R4      RJ p	TP	                  Y†Y™'       d   VP                  R4      MVP                  R4      R7      p
\        V R	V
/4      # )
z£Deliver one command result to the broker; ``accepted`` is False for unknown / resolved /
cancelled command ids (the broker's idempotent answer, surfaced verbatim).Ú
command_idrP   zcommand_id requiredÚokTÚresultÚerror)rd   r‡   rˆ   r<   )r   r   rV   rW   Úcompleter€   )r`   r4   Ú
_transportÚ	_identityÚ_session_idrc   rd   Ú_sessionr†   r‡   r<   s   &&&&&&&&   r   rƒ   rƒ   º   s‰   € ô �V—Z‘Z Ó-×3Ð3°Ó4€JßÜ�CœÐ)>Ó?Ð?Ø	�‰�DÓ	˜TÐ	!€BØ�‰Ø BÆr¨v¯z©z¸(Ô/CÈvÏzÉzÐZaÓObð ó d€Häˆs�Z Ð*Ó+Ð+r   zbrowser.controller.heartbeatc               ó    € V ^8„  d   QhRRRR/# rI   r   )r   s   "r   r   r   È   s   € ÷ "ñ "�4ð " Dñ "r   c                ó   € \        V RR/4      # )a  Acknowledge a heartbeat only for this transport's own attached controller.

The session gate admits any client attached to the session, including a fan-out peer; the
broker's ``is_owner`` check then narrows the answer to the transport that actually registered
the controller.r‡   T)r€   )r`   r4   Ú_gates   &&*r   rƒ   rƒ   Ç   s   € ô ˆs�T˜4�LÓ!Ð!r   zbrowser.controller.detach)rB   c               ó    € V ^8„  d   QhRRRR/# rI   r   )r   s   "r   r   r   Ò   s   € ÷ (ñ (�4ð (ÐX\ñ (r   c                óD   € VP                  WbRR7       \        V RR/4      # )zFHard-detach only the controller owned by this authenticated transport.F)r|   Únotify_controllerÚdetachedT)Údetachr€   )r`   r4   r)   rŒ   r�   rc   rd   rŽ   s   &&&&&&&&r   rƒ   rƒ   Ñ   s&   € ð ‡M�M�%¸E€MÔBÜˆs�Z Ð&Ó'Ð'r   c               ó   € V ^8„  d   QhRR/# )r   r   r.   r   )r   s   "r   r   r   Ø   s   € ÷ 0ñ 0˜ñ 0r   c                ó2   € \        \        4       V RR7       R# )zXPublish helpers/constants onto ``server`` and install handlers (rebound to its globals).)ÚskipN)rƒ   )r   Úglobals)Úservers   &r   Úregisterrœ   Ø   s   € ä”“	˜6¨×/r   )rh   Ú
__future__r   r"   ÚloggingÚ$hermes_cli.dashboard_auth.ws_ticketsr   r   r   r   Ú
method_ctxr   r   Ú	getLoggerÚ__name__r9   Ú	_registryr2   r]   rW   Ú_IDENTITY_REQUIREDr_   Ú_NO_CONTROLLERr   r'   r?   rk   rt   rƒ   rœ   r   r   r   Ú<module>r¦      s  ðñõ #ã Û ÷T÷ 5à	×	Ò	˜8Ó	$€áÓ€	Ø	×	Ñ	€ð ,Ð Ø€ØAÐ Ø8€
Ø<€õ	QõYõð03Ø*<ð3ØSWð3à!/ð3à:>÷3õlñ Ø!ØbØÐ!3ô5ô:ó	5ð:ñ@ Ð/Ó0ô	,ó 1ð	,ñ Ð2Ó3ô"ó 4ð"ñ Ð/ÀzÔRô(ó Sð(÷0r   