+
    „WÝjjo  ã                  ó¤  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIHtH	t	 ^ RI
HtHtHt ^ RIHtHtHtHtHt ^ RIHtHtHt ^ RIHtHtHt ^ RIHtHt ^ R	IH t  ^ R
I!H"t"H#t#H$t$H%t% ^ RI!H&t' ^ RI(H)t)H*t* ^ RI+H,t,H-t-H.t.H/t/ ^ RI0H1t1H2t2H3t3H4t4H5t5H6t6H7t7H8t8H9t9 ^ RI:H;t;H<t< ^ RI=H>t> ^ RI?H@t@HAtBHCtC ]Pˆ                  ! ]E4      tF]! 4       tGRR/tHRtIR R ltJR R ltKR R ltLR R ltMR R ltNR R  ltOR! R" ltPR# R$ ltQR% R& ltRR' R( ltSR) R* ltTR+ R, ltUR- R. ltVR/ R0 ltWR1 R2 ltX]GP³                  R3R4R57      R6 R7 l4       tZ]GP³                  R8R9R57      R: R; l4       t[]GP³                  R<R=R57      RyR> R? ll4       t\R@R@RARB/t]RC RD lt^RE RF lt_]GP³                  RGRHR57      RzRI RJ ll4       t`]GP³                  RKRLR57      R{RM RN ll4       ta^
tbROtcRPtd]! 4       teRQ]fRR&   ]PÎ                  ! 4       thRS RT ltiRU RV ltjRW RX ltk ! RY RZ]4      tl]GPÛ                  R[R\R57      R] R^ l4       tn]GPÛ                  R_R`R57      Ra Rb l4       toRc Rd ltp]GP³                  ReRfR57      Rg Rh l4       tq]GPÛ                  RiRjR57      Rk Rl l4       tr ! Rm Rn]4      ts]GPÛ                  RoRpR57      Rq Rr l4       tt ! Rs Rt]4      tu]GPÛ                  RuRvR57      Rw Rx l4       tvR# )|aÛ  HTTP routes for the dashboard-auth OAuth round trip.

Mounted at root (no prefix) by ``web_server.py``; ``gated_auth_middleware``
allowlists the public ones.

  GET  /login                  server-rendered login page
  GET  /auth/login?provider=N  302 to IDP, sets PKCE cookie
  GET  /auth/native/authorize  RFC 8252 native-app (desktop) login start
  GET  /auth/callback          completes login, sets session cookies
  POST /auth/password-login    username/password login (JSON)
  POST /auth/logout            clears cookies, best-effort revoke
  POST /auth/native/token      loopback code -> bearer tokens
  POST /auth/native/refresh    desktop-held refresh token rotation
  GET  /api/auth/providers     list registered providers (login bootstrap)
  GET  /api/auth/me            Session as JSON (gated: verified session; loopback:
                                token-validated synthetic loopback identity)
  POST /api/auth/ws-ticket     single-use WS upgrade ticket (auth-required)
)ÚannotationsN)ÚOrderedDictÚdeque)ÚAnyÚDequeÚDict)ÚquoteÚunquoteÚ	urlencodeÚurlparseÚ
urlunparse)Ú	APIRouterÚHTTPExceptionÚRequest)ÚHTMLResponseÚJSONResponseÚRedirectResponse)Ú	BaseModelÚField)Úrun_in_threadpool)Úget_providerÚlist_providersÚlist_session_providersÚnative_flow©Úprefix)Ú
AuditEventÚ	audit_log)ÚInvalidCodeErrorÚInvalidCredentialsErrorÚProviderErrorÚSession)	Úclear_pkce_cookieÚclear_session_cookiesÚclear_sso_attempt_cookieÚdetect_httpsÚparse_pkce_payloadÚread_pkce_cookieÚread_session_cookiesÚset_pkce_cookieÚset_session_cookies)Úrender_login_htmlÚ"render_native_provider_choice_html)Úrefresh_session_coalesced)Úaccess_token_max_ageÚ	client_ipÚis_safe_next_pathzCache-Controlz#no-store, no-cache, must-revalidatez1Native login expired or unknown; restart sign-in.c               ó$   € V ^8„  d   QhRRRRRR/# )é   Ústatus_codeÚintÚdetailÚstrÚreturnr   © )Úformats   "ÚTC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\dashboard_auth\routes.pyÚ__annotate__r;   9   s&   € ÷ Añ A�sð A Cð A¨Mñ Aó    c                ó   € \        WR 7      # )©r3   r5   )r   r>   s   &&r:   Ú_httpr?   9   s   € Ü [Ô@Ð@r<   c               ó    € V ^8„  d   QhRRRR/# ©r2   Úrequestr   r7   r6   r8   )r9   s   "r:   r;   r;   =   s   € ÷ 4ñ 4�Wð 4 ñ 4r<   c                ó.   € \         P                  ! V 4      # )zENormalised ``X-Forwarded-Prefix`` (cookie name/Path + redirect URLs).)Ú_prefix_modÚprefix_from_request)rB   s   &r:   Ú_prefixrF   =   s   € ä×*Ò*¨7Ó3Ð3r<   c               ó$   € V ^8„  d   QhRRRRRR/# )r2   rB   r   Úeventr   r7   ÚNoner8   )r9   s   "r:   r;   r;   B   s!   € ÷ 7ñ 7�Gð 7 Jð 7¸Tñ 7r<   c                ó8   € \        V3/ VBR \        V 4      /B  R# )ÚipN)r   Ú
_client_ip)rB   rH   Úfieldss   &&,r:   Ú_auditrN   B   s   € ÜˆeÑ6�vÑ6¤*¨WÓ"5Õ6r<   c               ó    € V ^8„  d   QhRRRR/# rA   r8   )r9   s   "r:   r;   r;   F   s   € ÷ Fñ F˜7ð F sñ Fr<   c                ó  € \         P                  ! 4       pV'       d   V R2# \        V P                  R4      4      p\	        V 4      pV'       g   V# \        V4      p\        VP                  V VP                   2R7      4      # )aE  Absolute ``/auth/callback`` URL handed to the IDP. An operator-declared public URL is the
complete authority (``X-Forwarded-Prefix`` ignored so a baked-in prefix is not doubled);
otherwise ``url_for`` (honours ``X-Forwarded-Host/Proto`` under uvicorn ``proxy_headers``)
with the prefix prepended, which Starlette does not do.ú/auth/callbackÚauth_callback©Úpath)	rD   Úresolve_public_urlr6   Úurl_forrF   r   r   Ú_replacerT   )rB   Ú
public_urlÚbaser   Úparseds   &    r:   Ú_redirect_urir[   F   ss   € ô
 ×/Ò/Ó1€JßØ�˜^Ð,Ð,Üˆw�‰˜Ó/Ó0€DÜ�WÓ€FßØˆÜ�d‹^€FÜ�f—o‘o¨f¨X°f·k±k°]Ð+C�oÓDÓEÐEr<   c               ó    € V ^8„  d   QhRRRR/# )r2   Úcookie_payloadúdict[str, str]r7   r8   )r9   s   "r:   r;   r;   V   s   € ÷ Lñ L¨Nð L¸~ñ Lr<   c                óh   € V P                  RR4      p\        R VP                  R4       4       4      # )uŸ   Parse a provider's flat ``state=â€¦;verifier=â€¦`` PKCE string into a dict â€” the ONE place
the flat form is parsed; :func:`set_pkce_cookie` encodes the dict.Úhermes_session_pkceÚ c              3  óX   "  € T F   pR V9   g   K  VP                  R ^4      x € K"  	  R# 5i)Ú=N)Úsplit)Ú.0Úsegs   & r:   Ú	<genexpr>Ú*_provider_pkce_segments.<locals>.<genexpr>Z   s'   é € ÐK©_ cÀÀsÁ
Ô!�—	‘	˜#˜q×!Ð!«_ùs   ‚	*�*Ú;)ÚgetÚdictrd   )r]   Úflats   & r:   Ú_provider_pkce_segmentsrm   V   s0   € ð ×ÑÐ3°RÓ8€DÜÑK¨T¯Z©Z¸¬_ÓKÓKÐKr<   c               ó    € V ^8„  d   QhRRRR/# ©r2   Úrawr6   r7   r8   )r9   s   "r:   r;   r;   ]   s   € ÷ Eñ E Sð E¨Sñ Er<   c                óf   € V '       d   \        V 4      MRpV'       d   \        V4      '       d   V# R# )z˜``raw`` (URL-decoded) if it is a safe same-origin path, else ``""``. Re-validated
at every hop because a ``next=`` value can re-enter via a crafted URL.ra   )r	   r0   )rp   Údecodeds   & r:   Ú_validate_post_login_targetrs   ]   s)   € ÷ "Œg�cŒl r€GßÔ"3°G×"<Ò"<ˆ7ÐDÀ"ÐDr<   c               ó$   € V ^8„  d   QhRRRRRR/# )r2   rB   r   Úpayloadr^   r7   rI   r8   )r9   s   "r:   r;   r;   d   s&   € ÷ eñ e˜Wð e¨~ð eÀ$ñ er<   c                óF   € \        W\        V4      \        V4      R 7       R# ))ru   Ú	use_httpsr   N)r)   r%   rF   )ÚresprB   ru   s   &&&r:   Ú	_set_pkcery   d   s   € Ü�D´\À'Ó5JÔSZÐ[bÓSc×dr<   c               ó$   € V ^8„  d   QhRRRRRR/# )r2   rB   r   Úsessionr!   r7   rI   r8   )r9   s   "r:   r;   r;   h   s!   € ÷ <ñ < ð <°'ð <¸dñ <r<   c           
     óš   € \        WP                  VP                  \        V4      \	        V4      \        V4      VP                  R 7       R# ))Úaccess_tokenÚrefresh_tokenÚaccess_token_expires_inrw   r   ÚproviderN)r*   r}   r~   r.   r%   rF   r€   )rx   rB   r{   s   &&&r:   Ú_set_sessionr�   h   s;   € ÜØ×/Ñ/¸w×?TÑ?TÜ 4°WÓ =ÌÐV]ÓI^Ü�wÓ¨'×*:Ñ*:÷<r<   c               ó    € V ^8„  d   QhRRRR/# )r2   r{   r!   r7   zdict[str, Any]r8   )r9   s   "r:   r;   r;   o   s   € ÷ Bñ B˜Wð B¨ñ Br<   c                ó‚   € RV P                   RV P                  RRRV P                  RV P                  RV P                  /# )zMJSON body for the native token/refresh endpoints (tokens in body, no cookie).r}   r~   Ú
token_typeÚBearerÚ
expires_atr€   Úuser_id)r}   r~   r†   r€   r‡   ©r{   s   &r:   Ú_bearer_payloadr‰   o   sG   € ð 	˜×,Ñ,¨o¸w×?TÑ?TØ�h ¨g×.@Ñ.@Ø�G×$Ñ$ i°·±ðBð Br<   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r2   rB   r   Úbroker_stater6   r{   r!   r€   r7   r8   )r9   s   "r:   r;   r;   w   s4   € ÷ 1ñ 1Øð1Ø'*ð1Ø5<ð1ØHKð1ØPSñ1r<   c               ó¶  €  \         P                  ! V4      p\         P                  ! WR7      pRTP                  9   d   RMRp\        RTRTP                  /4      p\	        T \
        P                  Y2P                  R	7       TP                   T T 2#   \         P                   d/    \	        T \
        P                  TRR7       \        R\        4      hi ; i)
u¶   Mint the one-time loopback code and return the desktop's ``redirect_uri?code=â€¦&state=â€¦``.
No session cookies on the native path â€” the desktop redeems at ``/auth/native/token``.rˆ   Úpending_not_found©r€   Úreasoné�  Ú?Ú&ÚcodeÚstate©r€   r‡   )r   Úget_pendingÚcomplete_pendingÚNativeFlowErrorrN   r   ÚNATIVE_TOKEN_FAILUREr?   Ú_NATIVE_EXPIRED_DETAILÚredirect_urir
   Úclient_stateÚNATIVE_CODE_ISSUEDr‡   )rB   r‹   r{   r€   ÚpendingÚgw_codeÚsepÚquerys   &$$$    r:   Ú_finish_native_loginr¢   w   sÂ   € ð1Ü×)Ò)¨,Ó7ˆÜ×.Ò.¨|ÔMˆð
 ˜×,Ñ,Ô,‰#°#€CÜ�v˜w¨°×1EÑ1EÐFÓG€EÜ
ˆ7”J×1Ñ1¸HÏoÉoÕ^Ø×"Ñ"Ð# C 5¨¨Ð0Ð0øô ×&Ñ&ô 1Üˆwœ
×7Ñ7À(Ø)õ	+ä�CÔ/Ó0Ð0ð1ús   ‚-B ÂACc               ó(   € V ^8„  d   QhRRRRRRRR/# )r2   rB   r   r€   r6   r�   r7   rI   r8   )r9   s   "r:   r;   r;   ˆ   s.   € ÷ Yñ Y˜Gð Y¨sð Y¸Cð YÈTñ Yr<   c                óD   € \        V \        P                  3R VRV/VB  R# )r€   r�   N)rN   r   ÚLOGIN_FAILURE)rB   r€   r�   Úextras   &&&,r:   Ú_login_failurer§   ˆ   s"   € Ü
ˆ7”J×,Ñ,ÑX°xÐXÈÐXÐRWÔXr<   c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r2   rB   r   r{   r!   r€   r6   r7   rI   r8   )r9   s   "r:   r;   r;   Œ   s(   € ÷ 7ñ 7˜Gð 7¨gð 7Àð 7Èñ 7r<   c           	     ó~   € \        V \        P                  W!P                  VP                  VP
                  R 7       R# ))r€   r‡   ÚemailÚorg_idN)rN   r   ÚLOGIN_SUCCESSr‡   rª   r«   )rB   r{   r€   s   &&&r:   Ú_login_successr­   Œ   s'   € Ü
ˆ7”J×,Ñ,°xÏÉØ—‘ w§~¡~÷7r<   c               ó$   € V ^8„  d   QhRRRRRR/# )r2   Útargetr6   r   r7   r8   )r9   s   "r:   r;   r;   ‘   s!   € ÷ ñ ¨3ð ¸ð Àñ r<   c                ó˜   € VP                  R4      pV '       d	   V'       g   V # W8X  g   V P                  V R24      '       d   V # V V  2# )aŽ  Prepend *prefix* to *target* when behind a reverse proxy.

When the dashboard is mounted at a sub-path (e.g. ``/hermes``) via
``X-Forwarded-Prefix``, a bare ``/`` landing must become ``/hermes/``
so the browser stays inside the mount. Paths that already carry the
prefix are returned unchanged; the native loopback redirect (an
absolute ``http://127.0.0.1...`` URL) never matches and is untouched.
Ú/)ÚrstripÚ
startswith)r¯   r   s   &&r:   Ú_externalize_post_login_targetr´   ‘   sL   € ð �]‰]˜3Ó€FßŸØˆØÔ˜6×,Ñ,°¨x°q¨\×:Ò:ØˆØˆX�f�XÐÐr<   c               ó0   € V ^8„  d   QhRRRRRRRRRRR	R
/# )r2   rB   r   r€   r6   r{   r!   r‹   Únext_rawr7   Útupler8   )r9   s   "r:   r;   r;   ¢   sA   € ÷ 
Lñ 
L˜Wð 
L°ð 
L¸gð 
LÐX[ð 
LØ!ð
LØ&+ñ
Lr<   c               ó    € \        WV4       V'       d   \        WW!R7      R3# \        V4      ;'       g    Rp\        V\	        V 4      4      R3# )zÅShared tail of the callback + password routes after credentials verified: audit success,
then either the native loopback redirect (no cookies) or the landing path. Returns
``(target_url, native)``.)r‹   r{   r€   Tr±   F)r­   r¢   rs   r´   rF   )rB   r€   r{   r‹   r¶   Úlandings   &&&$$ r:   Ú_complete_loginrº   ¢   sW   € ô
 �7 XÔ.ßÜ#Ø¸ôTØUYðZð 	Zä)¨(Ó3×:Ð:°s€GÜ)¨'´7¸7Ó3CÓDÀeÐKÐKr<   c               ó$   € V ^8„  d   QhRRRRRR/# )r2   rB   r   Úaudit_failureÚboolÚ
extra_pkcer^   r8   )r9   s   "r:   r;   r;   ¯   s"   € ÷ ñ  7ð Àð ÐSañ r<   c               óˆ  €  VP                  \        V 4      R7      p\        TP                  RR7      p\        TP                  4      pTP                  RTP                  4       TP                  T4       \        Y`T4       T#   \         d3   pT'       d   \        YP                  R4       \        RRT 24      hRp?ii ; i)	zâRun ``start_login`` and 302 to the IDP with the PKCE cookie set. That cookie is the only
server-controlled channel surviving the round trip (IDPs echo back only code+state), so it
carries the provider name plus ``extra_pkce``.)r›   Úprovider_unreachableé÷  úProvider unreachable: Né.  ©Úurlr3   r€   )Ústart_loginr[   r    r§   Únamer?   r   Úredirect_urlrm   r]   Ú
setdefaultÚupdatery   )rB   Úpr¼   r¾   ÚlsÚerx   Úpkces   &&$$    r:   Ú_start_upstream_loginrÏ   ¯   s¤   € ð7Ø�]‰]¬°gÓ(>ˆ]Ó?ˆô
  §¡¸SÔA€DÜ" 2×#4Ñ#4Ó5€DØ‡O�O�J §¡Ô'Ø‡K�K�
ÔÜˆd˜TÔ"Ø€Køô ô 7ßÜ˜7§F¡FÐ,BÔCÜ�CÐ1°!°Ð5Ó6Ð6ûð7ús   ‚B ÂCÂ-B<Â<Cú/loginÚ
login_page)rÇ   c               ó    € V ^8„  d   QhRRRR/# )r2   rB   r   r7   r   r8   )r9   s   "r:   r;   r;   Ä   s   € ÷ \ñ \˜gð \¨,ñ \r<   c              ƒ  óž   "  € \        V P                  P                  R R4      4      p\        \	        V\        V 4      R7      \        R7      # 5i)Únextra   )Ú	next_pathr   ©Úheaders)rs   Úquery_paramsrj   r   r+   rF   Ú	_NO_STORE)rB   rÕ   s   & r:   rÑ   rÑ   Ã   sE   é € ô ,¨G×,@Ñ,@×,DÑ,DÀVÈRÓ,PÓQ€IÜÜ I´g¸gÓ6FÔGÔQZô\ð \ùs   ‚AAz/api/auth/providersÚauth_providersc               ó   € V ^8„  d   QhRR/# )r2   r7   r   r8   )r9   s   "r:   r;   r;   Ì   s   € ÷ ñ  #ñ r<   c               ƒ  óÚ   "  € \        4       p V '       g   \        R R/RR7      # RV  Uu. uF3  pRVP                  RVP                  R\	        \        VRR4      4      /NK5  	  up/# u upi 5i)	r5   zno auth providers registeredrÁ   ©r3   Ú	providersrÇ   Údisplay_nameÚsupports_passwordF)r   r   rÇ   rß   r½   Úgetattr)rÞ   rË   s     r:   Úapi_auth_providersrâ   Ë   s   é € ô 'Ó(€IßÜ˜XÐ'EÐFÐTWÔXÐXØñ óñ ˆAð 
�—‘˜¨¯©Ø	œd¤7¨1Ð.AÀ5Ó#IÓJó	Láñð ð ùò ùs   ‚'A+©9A&Á"	A+z/auth/loginÚ
auth_loginc               ó$   € V ^8„  d   QhRRRRRR/# )r2   rB   r   r€   r6   rÔ   r8   )r9   s   "r:   r;   r;   Ú   s!   € ÷ ñ ˜gð °ð ¸Cñ r<   c              ƒ  ó¤  "  € \        V4      pVf   \        RRV: 24      h\        VRR4      '       g   \        RRV: 24      h\        V4      p\        VRR4      '       d6   \	        V 4       R2pV'       d   V R	\        VR
R7       2p\        VRR7      # \        YRV'       d   RV/M/ R7      p\        V \        P                  VR7       V# 5i)Né”  úUnknown provider: Úsupports_sessionTz-Provider does not support interactive login: rà   FrÐ   z?next=ra   )ÚsaferÃ   rÄ   rÔ   ©r¼   r¾   ©r€   )r   r?   rá   rs   rF   r   r   rÏ   rN   r   ÚLOGIN_START)rB   r€   rÔ   rË   Ú	safe_nextÚ	login_urlrx   s   &&&    r:   rã   rã   Ù   sÕ   é € ä�XÓ€AØ‚yÜ�CÐ-¨h©\Ð:Ó;Ð;Ü�1Ð(¨$×/Ò/Ü�CÐHÈÉÐUÓVÐVÜ+¨DÓ1€IÜˆqÐ% u×-Ò-Ü˜wÓ'Ð(¨Ð/ˆ	ßØ$˜+ V¬E°)À"Ô,EÐ+FÐGˆIÜ I¸3Ô?Ð?Ü Ø $Ï)°F¸IÑ3FÐY[ô]€Dä
ˆ7”J×*Ñ*°XÕ>Ø€Kùs   ‚CCz	127.0.0.1z::1z[::1]c               ó    € V ^8„  d   QhRRRR/# ro   r8   )r9   s   "r:   r;   r;   ò   s   € ÷ "@ñ "@¨ð "@°ñ "@r<   c                ó"  € V '       g   \        RR4      hV P                  4       '       dB   RV 9   g;   \        ;QJ d    R V  4       F  '       g   K   RM	  RM! R V  4       4      '       d   \        RR4      h \        V 4      pVP                  pVP
                  pTP                  R8w  d   \        RR	4      hR
T 9   d   \        RR4      hTP                  f   TP                  e   \        RR4      h\        P                  T4      pTf   \        RR4      hYCe   RT 2MR,           pTP                  T8w  d   \        RR4      h\        TP                  TP                  ;'       g    RR7      4      #   \         d    \        RR4      hi ; i)uH  Return a canonical RFC 8252 loopback URI or reject it.

Both the server parser and the system browser must see the same authority: URL userinfo,
backslashes, fragments, controls, and non-canonical host/port spellings are rejected before
the URI is persisted. ``localhost`` is rejected in favour of IP literals (RFC 8252 Â§8.3).
r�   zredirect_uri requiredÚ\c              3  ój   "  € T F)  p\        V4      ^ 8*  ;'       g    \        V4      ^8H  x € K+  	  R# 5i)é    N)Úord)re   Úchs   & r:   rg   Ú2_validate_loopback_redirect_uri.<locals>.<genexpr>þ   s+   é € Ð@¹C°bŒs�2‹w˜$‰×1Ð1¤# b£'¨T¡/Ô1»Cùs   ‚3œ3TFz5native redirect_uri must use a canonical loopback URLÚhttpz=native redirect_uri must be http:// on the loopback interfaceÚ#z/native redirect_uri must not contain a fragmentz-native redirect_uri must not contain userinfozHnative redirect_uri host must be a loopback IP literal (127.0.0.1 / ::1)Ú:ra   z;native redirect_uri must use a canonical loopback authorityr±   rS   )r?   ÚisasciiÚanyr   ÚhostnameÚportÚ
ValueErrorÚschemeÚusernameÚpasswordÚ_LOOPBACK_NETLOC_HOSTSrj   Únetlocr   rW   rT   )rp   rZ   rü   rý   Úcanonical_hostÚcanonical_netlocs   &     r:   Ú_validate_loopback_redirect_urir  ò   sa  € ÷ Ü�CÐ0Ó1Ð1à�K‰K�MŠMØ�3Œ;ß‹3Ñ@¹CÓ@�3�3Š3Ñ@¹CÓ@×@Ò@ä�CÐPÓQÐQðRÜ˜#“ˆØ—?‘?ˆØ�{‰{ˆð ‡}�}˜ÔÜ�CÐXÓYÐYØ
ˆc„zÜ�CÐJÓKÐKØ‡�Ò" f§o¡oÒ&AÜ�CÐHÓIÐIÜ+×/Ñ/°Ó9€NØÒÜ�CÐcÓdÐdØ%Ò7G¨1¨T¨F©ÈRÕPÐØ‡}�}Ð(Ô(Ü�CÐVÓWÐWä�f—o‘o¨6¯;©;×+=Ð+=¸#�oÓ>Ó?Ð?øô ô RÜ�CÐPÓQÐQðRús   Á9#E6 Å6Fc               ó   € V ^8„  d   QhRR/# )r2   r€   r6   r8   )r9   s   "r:   r;   r;     s   € ÷ ;ñ ; cñ ;r<   c                ór   € V '       d   \        V 4      # \        4       p\        V4      ^8X  d
   V^ ,          # R# )u
  Resolve the provider for a native authorize request. An empty ``provider`` auto-selects
the ONLY interactive session provider (password providers included â€” native sign-in brokers
them via ``/login``); with several the caller renders a chooser instead of guessing.N)r   r   Úlen)r€   Ú
candidatess   & r:   Ú_select_native_providerr    s4   € ÷ Ü˜HÓ%Ð%Ü'Ó)€JÜ 
›O¨qÔ0ˆ:�a�=Ð:°dÐ:r<   ú/auth/native/authorizeÚauth_native_authorizec               ó0   € V ^8„  d   QhRRRRRRRRRRRR/# )	r2   rB   r   r€   r6   Úcode_challengeÚcode_challenge_methodr›   r”   r8   )r9   s   "r:   r;   r;   "  s<   € ÷ -ñ -Øð-Ø #ð-Ø:=ð-àð-à36ð-àDGñ-r<   c              ƒ  óÎ  "  € VP                  4       R8w  d   \        RR4      hV'       g   \        RR4      h\        V4      p\        V4      pVfX   V'       gP   \	        4       p\        V4      ^8”  d6   \        \        V\        V 4       R2VVWE\        V 4      R7      \        R7      # Vf   \        R	R
V: 24      h\        VRR4      '       g   \        RRVP                  : 24      h \        P                  ! W$V\        V 4      R7      p\        TRR4      '       d\   \#        T \$        P&                  TP                  R7       \)        \        T 4       R2RR7      p
\+        Y RTP                  RT/4       T
# \-        YRRT/R7      p
\#        T \$        P&                  TP                  R7       T
#   \        P                   d   p	\        R\!        T	4      4      hRp	?	ii ; i5i)a#  Begin an RFC 8252 native-app login: stash a pending broker authorization keyed by an
opaque ``broker_state`` riding in the gateway's own PKCE cookie (the desktop's
challenge/state never touch it), then run the normal upstream round trip. Password providers
go to the ``/login`` form instead.ÚS256r�   z"code_challenge_method must be S256zcode_challenge requiredNr  )rÞ   Úauthorize_pathr  r  r›   r”   r   rÖ   ræ   rç   rè   Tz(Provider does not support native login: )r  r›   rœ   r/   rÁ   rà   Frë   rÐ   rÃ   rÄ   r€   Úbrokerrê   )Úupperr?   r  r  r   r	  r   r,   rF   rÙ   rá   rÇ   r   Úregister_pendingrL   r˜   r6   rN   r   ÚNATIVE_AUTHORIZE_STARTr   ry   rÏ   )rB   r€   r  r  r›   r”   rË   r
  r‹   rÍ   rx   s   &&&&&&     r:   r  r  !  sÆ  é € ð ×"Ñ"Ó$¨Ô.Ü�CÐ=Ó>Ð>ßÜ�CÐ2Ó3Ð3Ü2°<Ó@€LÜ Ó)€AØ‚yŸÜ+Ó-ˆ
Üˆz‹?˜QÔô  Ü2Ø(Ü&-¨gÓ&6Ð%7Ð7MÐ#NØ#1Ø*?Ø!-Ü" 7Ó+ô-ô "ô#ð #ð 	‚yÜ�CÐ-¨h©\Ð:Ó;Ð;Ü�1Ð(¨$×/Ò/Ü�CÐCÀAÇFÁFÁ:ÐNÓOÐOð!Ü"×3Ò3Ø)ÐSXÜ  Ó)ô+ˆô
 ˆqÐ% u×-Ò-Üˆwœ
×9Ñ9ÀAÇFÁFÕKÜ¤w¨wÓ'7Ð&8¸Ð$?ÈSÔQˆÜ�$ *¨a¯f©f°hÀÐ!MÔNØˆÜ Ø %°X¸|Ð4LôN€Dä
ˆ7”J×5Ñ5ÀÇÁÕGØ€Køô ×&Ñ&ô !Ü�Cœ˜Q›Ó Ð ûð!üs6   ‚)G%¬-G%ÁBG%Ã+"F3 ÄB&G%Æ3G"ÇGÇG"Ç"G%rQ   rR   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )r2   rB   r   r“   r6   r”   ÚerrorÚerror_descriptionr8   )r9   s   "r:   r;   r;   S  s4   € ÷ (ñ (Øð(Øð(Ø-0ð(Ø>Að(àñ(r<   c           
   ƒ  óÂ  "  € \        V 4      pV'       g)   \        V \        P                  R R7       \	        RR4      h\        V4      pVP                  RR4      p\        V4      pVf   \	        RRV: 24      hV'       d"   \        WRVR	7       \	        RR
V RV R24      hV'       d   W&P                  RR4      8w  d   \        WR4       \	        RR4      h VP                  WVP                  RR4      \        V 4      R7      p	\        YY–P                  RR4      TP                  RR4      R7      w  r¼\        TRR7      pT'       g   \        YÐT	4       \!        T 4      p\#        T\%        T 4      TR7       \'        YÞR7       T#   \         d!   p
\        YR4       \	        RRT
 24      hRp
?
i\         d!   p
\        YR4       \	        RRT
 24      hRp
?
ii ; i5i)Úmissing_pkce_cookie©r�   r�   zMissing PKCE state cookier€   ra   NzUnknown provider in cookie: Ú	idp_error)r  zOAuth error from provider: z (Ú)r”   Ústate_mismatchz(OAuth state mismatch (CSRF check failed)Úverifier)r“   r”   Úcode_verifierr›   Úinvalid_codezInvalid code: rÀ   rÁ   rÂ   r  rÔ   ©r‹   r¶   rÃ   rÄ   ©rw   r   r   )r'   rN   r   r¥   r?   r&   rj   r   r§   Úcomplete_loginr[   r   r    rº   r   r�   rF   r"   r%   r$   )rB   r“   r”   r  r  Úpkce_rawÚpartsÚprovider_namerË   r{   rÍ   r¯   Únativerx   r   s   &&&&&          r:   rR   rR   R  sÊ  é € ô   Ó(€HßÜˆwœ
×0Ñ0Ð9NÕOÜ�CÐ4Ó5Ð5ô ˜xÓ(€EØ—I‘I˜j¨"Ó-€MÜ�]Ó#€AØ‚yÜ�CÐ7¸Ñ7HÐIÓJÐJßÜ�w¨{À%ÕHÜ�CÐ6°u°g¸RÐ@QÐ?RÐRSÐTÓUÐUß�EŸY™Y w°Ó3Ô3Ü�wÐ/?Ô@Ü�CÐCÓDÐDð	7Ø×"Ñ"Ø°%·)±)¸JÈÓ2KÜ& wÓ/ð #ó 1ˆô %Ø ·i±iÀÈ"Ó6MØ—‘˜6 2Ó&ô(�N€Fô  °CÔ8€DßÜ�T GÔ,Ü�WÓ€FÜ�d¤l°7Ó&;ÀFÕKä˜TÕ1Ø€Køô! ô /Ü�w¨~Ô>Ü�C˜>¨!¨Ð-Ó.Ð.ûÜô 7Ü�wÐ/EÔFÜ�CÐ1°!°Ð5Ó6Ð6ûð7üsI   ‚A?GÂ(GÂ+.GÃ-F ÄBGÆGÆF.Æ.GÆ;GÆ<GÇGÇGg      N@i   zOrderedDict[str, deque[float]]Ú_pw_attemptsc               ó    € V ^8„  d   QhRRRR/# )r2   ÚcutoffÚfloatr7   rI   r8   )r9   s   "r:   r;   r;   ‰  s   € ÷ 
/ñ 
/°ð 
/¸$ñ 
/r<   c                óø   € \        \        P                  4       4       FX  p\        V,          pV'       d!   V^ ,          V 8  d   VP                  4        K(  V'       d   KB  \        P	                  VR4       KZ  	  R# )zdDrop expired/empty password-login limiter buckets.

Must be called with ``_pw_attempts_lock`` held.
N)Úlistr+  ÚkeysÚpopleftÚpop)r-  Ú
bucket_keyÚbuckets   &  r:   Ú#_prune_password_rate_buckets_lockedr6  ‰  sS   € ô
 œ<×,Ñ,Ó.Ö/ˆ
Ü˜jÕ)ˆß˜ � VÔ+Ø�N‰NÖß‰vÜ×Ñ˜Z¨Ö.ó 0r<   c               ó    € V ^8„  d   QhRRRR/# )r2   rK   r6   r7   r½   r8   )r9   s   "r:   r;   r;   –  s   € ÷ ñ ˜sð  tñ r<   c                óâ  € \         P                  ! 4       pV\        ,
          p\        ;_uu_ 4        T ;'       g    Rp\	        ^\        \        4      4      pV\        9  d    \        \        4      V8¼  d   \        V4       V\        9  d-   \        \        4      V8¼  d   \        P                  RR7       K7  \        P                  V4      pVf   \        4       pV\        V&   M\        P                  V4       V'       d!   V^ ,          V8  d   VP                  4        K(  \        V4      \        8¼  d    RRR4       R# VP!                  V4        RRR4       R#   + '       g   i     R# ; i)u„   True if ``ip`` exceeded the budget; records the attempt when allowed. An empty IP shares
one bucket â€” fail-safe toward throttling.Ú	_unknown_F)ÚlastNT)ÚtimeÚ	monotonicÚ_PW_RATE_WINDOW_SECÚ_pw_attempts_lockÚmaxr4   Ú_PW_RATE_MAX_BUCKETSr+  r	  r6  Úpopitemrj   r   Úmove_to_endr2  Ú_PW_RATE_MAX_ATTEMPTSÚappend)rK   Únowr-  ÚkeyÚmax_bucketsr5  s   &     r:   Ú_password_rate_limitedrH  –  s  € ô �.Š.Ó
€CØÔ&Õ&€Fß	Ö	Ø×Ð�KˆÜ˜!œSÔ!5Ó6Ó7ˆØ”lÔ"¤s¬<Ó'8¸KÔ'GÜ/°Ô7ØœÔ%¬#¬lÓ*;¸{Ô*JÜ× Ñ  eÐ Ö,ä×!Ñ! #Ó&ˆØŠ>Ü“WˆFØ &ŒL˜Òä×$Ñ$ SÔ)ß˜ � VÔ+Ø�N‰NÖÜˆv‹;Ô/Ô/Ø÷# 
Ñ	ð$ 	�‰�cÔØ÷' 
×	×	Ò	ús   ±CEÄ5EÅEÅE.	c               ó   € V ^8„  d   QhRR/# )r2   r7   rI   r8   )r9   s   "r:   r;   r;   ±  s   € ÷ ñ  Dñ r<   c                 ó„   € \         ;_uu_ 4        \        P                  4        RRR4       R#   + '       g   i     R# ; i)z(Test-only: clear all rate-limit buckets.N)r>  r+  Úclearr8   r<   r:   Ú_reset_password_rate_limitrL  ±  s#   € ç	Ö	Ü×ÑÔ÷ 
×	×	Ò	ús   �.®?	c                  óV   € ] tR tRt$ ]! ^€R7      tR]R&   R]R&   R]R&   RtR]R&   R	tR
# )Ú_PasswordLoginBodyi·  )Ú
max_lengthr6   r€   r   r  ra   rÔ   r8   N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   r€   Ú__annotations__rÔ   Ú__static_attributes__r8   r<   r:   rN  rN  ·  s$   ‡ á SÔ)€HˆcÓ)ØƒMØƒMØ€Dˆ#‡Nr<   rN  z/auth/password-loginÚauth_password_loginc               ó    € V ^8„  d   QhRRRR/# )r2   rB   r   ÚbodyrN  r8   )r9   s   "r:   r;   r;   À  s   € ÷ -ñ - wð -Ð6Hñ -r<   c              ƒ  óT  "  € \        \        V 4      4      '       d#   \        WP                  R4       \	        RR4      h\        VP                  4      pVe   \        VRR4      '       g#   \        WP                  R4       \	        RR	4      h\        V 4      pV'       d   \        V4      M/ pVP                  R
R4      pV'       dU   VP                  RR4      VP                  8w  d4   \        V \        P                  VP                  RR7       \	        RR4      h VP                  VP                  VP                  R7      p\'        YP                  YeTP(                  R7      w  r‰\+        RRRT/4      p
T	'       d#   \-        T
\/        T 4      \1        T 4      R7       T
# \3        Y T4       T
#   \          d$    \        YP                  R4       \	        RR4      h\"         d    \	        RR4      h\$         d+   p\        YP                  R4       \	        RRT 24      hRp?ii ; i5i)aÙ  Authenticate a username/password against a password provider.

Returns ``{"ok": true, "next": <path>}`` (the form POSTs via fetch, which follows a 302
opaquely) and sets the session cookies; with a native ``broker`` handle in the PKCE cookie,
``next`` is the desktop's loopback redirect and NO cookies are set. Failures are deliberately
generic (no username/provider oracle): unknown/non-password provider 404, bad credentials
401, store unreachable 503, rate limited 429.
Úrate_limitedi­  z+Too many login attempts. Try again shortly.Nrà   FÚunknown_password_providerræ   zUnknown providerr  ra   r€   Úprovider_mismatchrŽ   r�   zfThis native sign-in was started for a different provider; use that provider's form or restart sign-in.)r   r  Úinvalid_credentialsé‘  zInvalid credentialsiô  zProvider misconfiguredrÀ   rÁ   rÂ   r$  ÚokTrÔ   r%  )rH  rL   r§   r€   r?   r   rá   r'   r&   rj   rN   r   r™   Úcomplete_password_loginr   r  r   ÚNotImplementedErrorr    rº   rÔ   r   r"   r%   rF   r�   )rB   rX  rË   r'  Ú
pkce_partsr‹   r{   rÍ   r¯   r*  rx   s   &&         r:   rV  rV  ¿  sÝ  é € ô œj¨Ó1×2Ò2Ü�w§¡¨~Ô>Ü�CÐFÓGÐGÜ�T—]‘]Ó#€AØ‚yœ Ð#6¸×>Ò>Ü�w§¡Ð/JÔKÜ�CÐ+Ó,Ð,ô   Ó(€Hß19Ô# HÔ-¸r€JØ—>‘> (¨BÓ/€Lß˜
Ÿ™ z°2Ó6¸$¿-¹-ÔGÜˆwœ
×7Ñ7À$Ç-Á-Ø)õ	+ä�Cð Hó Ið 	Ið
7Ø×+Ñ+°T·]±]ÈTÏ]É]Ð+Ó[ˆô %Ø—‘ ÈTÏYÉYôX�N€Fä˜˜t V¨VÐ4Ó5€DßÜ˜$¬,°wÓ*?ÌÐPWÓHXÕYð €Kô 	�T GÔ,Ø€Køô! #ô 0Ü�w§¡Ð/DÔEÜ�CÐ.Ó/Ð/Üô 3ä�CÐ1Ó2Ð2Üô 7Ü�w§¡Ð/EÔFÜ�CÐ1°!°Ð5Ó6Ð6ûð7üs>   ‚CH(ÃAH(Ä'F. ÅA+H(Æ.5H%Ç$H%Ç:H%Ç;%H È H%È%H(z/auth/logoutÚauth_logoutc               ó   € V ^8„  d   QhRR/# ©r2   rB   r   r8   )r9   s   "r:   r;   r;   ñ  s   € ÷ ñ ˜wñ r<   c              ƒ  ó,  "  € \        V 4      w  rV'       d   \        4       MR F  p VP                  VR 7       K  	  \        V P                  RR4      p\        T \        P                  V'       d   VP                  MRV'       d   VP                  MRR7       \        V 4      p\        V R2RR	7      p\!        WvR
7       \#        V\%        V 4      VR7       V#   \         d-   p\        P                  RTP                  T4        Rp?Kè  Rp?ii ; i5i))r~   z'dashboard-auth: revoke on %r failed: %sNr{   Úunknownra   r•   rÐ   rÃ   rÄ   r   r%  r8   )r(   r   Úrevoke_sessionÚ	ExceptionÚ_logÚwarningrÇ   rá   r”   rN   r   ÚLOGOUTr€   r‡   rF   r   r#   r"   r%   )rB   Ú_atÚrtr€   rÍ   Úsessr   rx   s   &       r:   rc  rc  ð  sÞ   é € ä" 7Ó+�G€Cç(*”NÔ$°Ò2ˆð	VØ×#Ñ#°"Ð#Ö5ñ 3ô
 �7—=‘= )¨TÓ2€DÜ
ˆ7”J×%Ñ%Ç$°·²ÈIß$(�D—L’L¨bõ3ä�WÓ€FÜ 6 (¨&Ð 1¸sÔC€DÜ˜$Õ.Ü�d¤l°7Ó&;ÀFÕKØ€Køô ô 	VÜ�L‰LÐBÀHÇMÁMÐST×UÒUûð	Vüs5   ‚%D¨CºADÂADÃDÃ%!DÄDÄDÄDc               ó   € V ^8„  d   QhRR/# re  r8   )r9   s   "r:   r;   r;     s   € ÷ ñ ˜gñ r<   c                óT   € \        V P                  R R4      pVf   \        RR4      hV# )r{   Nr^  ÚUnauthorized)rá   r”   r?   )rB   ro  s   & r:   Ú_require_sessionrs    s+   € Ü�7—=‘= )¨TÓ2€DØ‚|Ü�C˜Ó(Ð(Ø€Kr<   z/api/auth/meÚauth_mec               ó   € V ^8„  d   QhRR/# re  r8   )r9   s   "r:   r;   r;     s   € ÷ Yñ Y˜wñ Yr<   c              ƒ  ó–  "  € \        V P                  RR4      pVfb   \        V P                  P                  RR4      '       d   \        RR4      h^ RIHp V! V 4      '       g   \        RR4      hRR	R
RRRRRRRR^ /# RVP                  R
VP                  RVP                  RVP                  RVP                  RVP                  /# 5i)uÙ  Return the verified session as JSON.

Gated mode: the auth middleware attached a verified Session â€” return it.
Loopback mode (``auth_required`` False): there is no OAuth Session, but the
legacy ``_SESSION_TOKEN`` middleware has already validated the bearer
token for non-public ``/api/`` routes. Report the loopback identity
honestly instead of 401-ing (GH #66223). Belt-and-braces: re-verify the
token so the handler stays safe even if this route were ever allowlisted.
r{   NÚauth_requiredFr^  rr  )Ú_has_valid_session_tokenr‡   Úlocalrª   ra   rß   ÚLocalr«   r€   Úloopbackr†   )rá   r”   Úappr?   Úhermes_cli.web_serverrx  r‡   rª   rß   r«   r€   r†   )rB   ro  rx  s   &  r:   Úapi_auth_mer~    sÉ   é € ô �7—=‘= )¨TÓ2€DØ‚|Ü�7—;‘;×$Ñ$ o°u×=Ò=Ü˜˜^Ó,Ð,ÝBá'¨×0Ò0Ü˜˜^Ó,Ð,à�wØ�RØ˜GØ�bØ˜
Ø˜!ð
ð 	
ð 	�4—<‘< ¨$¯*©*°nÀd×FWÑFWØ�$—+‘+˜z¨4¯=©=¸,ÈÏÉðYð Yùs   ‚A"C	Á%A$C	z/api/auth/ws-ticketÚauth_ws_ticketc               ó   € V ^8„  d   QhRR/# re  r8   )r9   s   "r:   r;   r;   -  s   € ÷ :ñ : gñ :r<   c              ƒ  óð   "  € \        V 4      p^ RIHpHp V! VP                  VP
                  VP                  R7      p\        V \        P                  VP
                  VP                  R7       RVRV/# 5i)zxMint a 30s single-use ticket for a WS upgrade (browsers cannot set
``Authorization`` on the upgrade); one ticket per WS.)ÚTTL_SECONDSÚmint_ticket)r‡   r€   Úissuerr•   ÚticketÚttl_seconds)
rs  Ú$hermes_cli.dashboard_auth.ws_ticketsr‚  rƒ  r‡   r€   r„  rN   r   ÚWS_TICKET_MINTED)rB   ro  r‚  rƒ  r…  s   &    r:   Úapi_auth_ws_ticketr‰  ,  s\   é € ô ˜GÓ$€DßMÙ §¡¸¿¹ÈdÏkÉkÔZ€FÜ
ˆ7”J×/Ñ/¸$¿-¹-ÐQU×Q]ÑQ]Õ^Ø�f˜m¨[Ð9Ð9ùs   ‚A4A6c                  ó,   € ] tR tRt$ R]R&   R]R&   RtR# )Ú_NativeTokenBodyi9  r6   r“   r"  r8   N)rP  rQ  rR  rS  rT  rU  r8   r<   r:   r‹  r‹  9  s   ‡ Ø
ƒIØ×r<   r‹  z/auth/native/tokenÚauth_native_tokenc               ó    € V ^8„  d   QhRRRR/# )r2   rB   r   rX  r‹  r8   )r9   s   "r:   r;   r;   ?  s   € ÷ $ñ $ Wð $Ð4Dñ $r<   c              ƒ  ó^  "  €  \         P                  ! VP                  VP                  R7      p\        T \        P                  TP                  TP                  R7       \        T4      #   \         P                   d*    \        T \        P                  RR7       \        RR4      hi ; i5i)zÓExchange a loopback gateway code + PKCE verifier for bearer tokens. The code is consumed
on every path (no verifier oracle, no replay); any failure is a generic 400. Tokens go in
the JSON body; no cookie is set.)r“   r"  Úinvalid_code_or_pkcer  r�   z&Invalid or expired authorization code.r•   )r   Úredeem_coder“   r"  ÚCodeInvalidrN   r   r™   r?   ÚNATIVE_TOKEN_SUCCESSr€   r‡   r‰   )rB   rX  r{   s   && r:   rŒ  rŒ  >  sŽ   é € ð
CÜ×)Ò)¨t¯y©yÈ×HZÑHZÔ[ˆô ˆ7”J×3Ñ3¸g×>NÑ>NØ—?‘?õ$ä˜7Ó#Ð#øô ×"Ñ"ô CÜˆwœ
×7Ñ7Ð@VÕWÜ�CÐAÓBÐBðCüs   ‚B-„,A, °<B-Á,>B*Â*B-c                  ó0   € ] tR tRt$ R]R&   RtR]R&   RtR# )Ú_NativeRefreshBodyiM  r6   r~   ra   r€   r8   N)rP  rQ  rR  rS  rT  r€   rU  r8   r<   r:   r”  r”  M  s   ‡ ØÓØ€Hˆc×r<   r”  z/auth/native/refreshÚauth_native_refreshc               ó    € V ^8„  d   QhRRRR/# )r2   rB   r   rX  r”  r8   )r9   s   "r:   r;   r;   S  s   € ÷ _ñ _ wð _Ð6Hñ _r<   c              ƒ  óú  "  € VP                   '       g   \        RR4      h \        \        VP                   VP                  R\
        R7      G Rj  x€L
 pTeF   T^ ,          p\        T \        P                  TP                  TP                  R	7       \        T4      # \        T \        P                  R
R7       \        RRRR/RR7      #  Lz  \         d    p\        RR\        T4      : R24      hRp?ii ; i5i)zÅRotate a desktop-held refresh token (mirrors the gate's ``_attempt_refresh``): every
provider rejecting the RT -> 401 ``session_expired`` (desktop re-logs); none rotated and one
unreachable -> 503.r�   zrefresh_token requiredznative refresh)ÚphaseÚlogNrÁ   zAuth provider z unreachabler•   Úall_providers_rejected_rtr  r  Úsession_expiredr5   z6Refresh token expired or invalid; start a new sign-in.r^  rÝ   )r~   r?   r   r-   r€   rj  r    r6   rN   r   ÚREFRESH_SUCCESSr‡   r‰   ÚREFRESH_FAILUREr   )rB   rX  Ú	refreshedrÍ   r{   s   &&   r:   r•  r•  R  sô   é € ð
 ××ÐÜ�CÐ1Ó2Ð2ðBô ,Ü% t×'9Ñ'9¸4¿=¹=Ø"¬ô.÷ .ˆ	ð
 ÒØ˜A•,ˆÜˆwœ
×2Ñ2¸W×=MÑ=MØ—‘õ	(ä˜wÓ'Ð'Ü
ˆ7”J×.Ñ.Ð7RÕSÜØ	Ð#Ø	ÐKð	MØZ]ô_ð _ñ.øô ô BÜ�C˜>¬#¨a«&©°<Ð@ÓAÐAûðBüs;   ‚C;¢/C ÁCÁC ÁA6C;ÃC ÃC8ÃC3Ã3C8Ã8C;)ra   )ra   ra   ra   ra   ra   )ra   ra   ra   ra   )wÚ__conditional_annotations__Ú__doc__Ú
__future__r   ÚloggingÚ	threadingr;  Úcollectionsr   r   Útypingr   r   r   Úurllib.parser   r	   r
   r   r   Úfastapir   r   r   Úfastapi.responsesr   r   r   Úpydanticr   r   Ústarlette.concurrencyr   Úhermes_cli.dashboard_authr   r   r   r   r   rD   Úhermes_cli.dashboard_auth.auditr   r   Úhermes_cli.dashboard_auth.baser   r   r    r!   Ú!hermes_cli.dashboard_auth.cookiesr"   r#   r$   r%   r&   r'   r(   r)   r*   Ú$hermes_cli.dashboard_auth.login_pager+   r,   Ú.hermes_cli.dashboard_auth.refresh_singleflightr-   Ú'hermes_cli.dashboard_auth.request_utilsr.   r/   rL   r0   Ú	getLoggerrP  rj  ÚrouterrÙ   rš   r?   rF   rN   r[   rm   rs   ry   r�   r‰   r¢   r§   r­   r´   rº   rÏ   rj   rÑ   râ   rã   r  r  r  r  rR   rC  r=  r@  r+  rT  ÚLockr>  r6  rH  rL  rN  ÚpostrV  rc  rs  r~  r‰  r‹  rŒ  r”  r•  )rŸ  s   @r:   Ú<module>r¶     sÿ  øðôõ$ #ã Û Û ß *ß #Ñ #ß HÕ Hç 5Ñ 5ß JÑ Jß %Ý 3÷Gó Gå ;ß A÷Gó G÷÷ õ ÷;å T÷Fñ Fð ×Ò˜Ó"€á	‹€àÐCÐD€	ØLÐ õAõ4õ
7õFõ LõEõeõ<õBõ1õ"Yõ7õ
õ"
Lõð( ‡�ˆH˜<€Ó(ô\ó )ð\ð ‡�Ð!Ð(8€Ó9ôó :ðð ‡�ˆM €Ó-öó .ðð* & {°E¸7ÐCÐ õ"@õJ;ð ‡�Ð$Ð+B€ÓCö-ó Dð-ð` ‡�Ð ?€Ó3ö(ó 4ð(ð^ Ð ØÐ ØÐ Ù/:«}€Ð,Ó <Ø—N’NÓ$Ð õ
/õõ6ô˜ô ð ‡�Ð#Ð*?€Ó@ô-ó Að-ð` ‡�ˆ^ -€Ó0ôó 1ðõ(ð ‡�ˆN €Ó+ôYó ,ðYð> ‡�Ð"Ð)9€Ó:ô:ó ;ð:ô�yô ð
 ‡�Ð!Ð(;€Ó<ô$ó =ð$ô˜ô ð
 ‡�Ð#Ð*?€Ó@ô_ó Aò_r<   