+
    „WÝjÀ  ã                  óÆ   € R t ^ RIHt ^ RIt^ RIt^ RIHtHt ^ RIH	t	 ^ RI
Ht ^ RIHt ^ RIHtHt RtR R	 ltR
 R l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# )zERequest-level helpers shared by the auth routes and both middlewares.)ÚannotationsN)ÚCallableÚOptional)ÚRequest©ÚJSONResponse)Úlist_session_providers)ÚDashboardAuthProviderÚProviderErrorc               ó    € V ^8„  d   QhRRRR/# ©é   Úrequestr   ÚreturnÚstr© )Úformats   "Ú[C:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\dashboard_auth\request_utils.pyÚ__annotate__r      s   € ÷ 9ñ 9�wð 9 3ñ 9ó    c                óV   € V P                   '       d   V P                   P                  # R# )a&  ASGI peer address for rate limits, native pending caps, and auth audit.

Never parse client-supplied ``X-Forwarded-For`` here: direct clients can
spoof it. Trusted proxy normalization belongs upstream, where the server
may rewrite ``request.client`` only for operator-configured trusted peers.
Ú )ÚclientÚhost)r   s   &r   Ú	client_ipr      s!   € ð #*§.§. .ˆ7�>‰>×ÑÐ8°bÐ8r   c               ó    € V ^8„  d   QhRRRR/# r   r   )r   s   "r   r   r      s   € ÷ ñ ˜Gð ¨ñ r   c                ó   € V P                   P                  RR4      P                  R^4      p\        V4      ^8X  dB   V^ ,          P	                  4       P                  4       R8X  d   V^,          P	                  4       # R# )zM``Authorization: Bearer <token>`` value (scheme case-insensitive), or ``""``.Úauthorizationr   Ú Úbearer)ÚheadersÚgetÚsplitÚlenÚstripÚlower)r   Úpartss   & r   Úextract_bearerr'      s_   € à�O‰O×Ñ °Ó4×:Ñ:¸3ÀÓB€EÜ
ˆ5ƒz�Q„˜5 �8Ÿ>™>Ó+×1Ñ1Ó3°xÔ?Ø�Q�x�~‰~ÓÐÙr   c               ó    € V ^8„  d   QhRRRR/# )r   Úpathr   r   Úboolr   )r   s   "r   r   r   %   s   € ÷ <ñ <˜Cð < Dñ <r   c                ó>  a € S P                  R4      '       d   S P                  R4      '       d   R# \        ;QJ d#    V 3R l\         4       F  '       g   K   RM	  RM! V 3R l\         4       4      '       d   R# S R8H  ;'       g    S P                  R4      '       * # )z“Same-origin post-login target: rejects non-relative and protocol-relative (``//evil``)
values, the auth routes themselves, and every ``/api`` path.Ú/z//Fc              3  ó`   <"  € T F#  pSV8H  ;'       g    SP                  V4      x € K%  	  R # 5i©N)Ú
startswith)Ú.0Úpr)   s   & €r   Ú	<genexpr>Ú$is_safe_next_path.<locals>.<genexpr>*   s+   øé € Ð
HÑ4G¨qˆ4�1‰9×*Ð*˜Ÿ™¨Ó*Ô*Ó4Gùs   ƒ.”.Tz/apiz/api/)r/   ÚanyÚ_NEXT_DENY_PREFIXES)r)   s   fr   Úis_safe_next_pathr6   %   si   ø€ ð �?‰?˜3×Ò 4§?¡?°4×#8Ò#8Ùß
ƒsÔ
HÕ4GÓ
H‡s‡s‚sÔ
HÕ4GÓ
H×HÒHÙØ˜‘×:Ð: $§/¡/°'Ó":Ô;Ð;r   c               ó   € V ^8„  d   QhRR/# )r   r   Úintr   )r   s   "r   r   r   /   s   € ÷ ?ñ ? Sñ ?r   c                ó†   € \        ^<\        V P                  4      \        \        P                  ! 4       4      ,
          4      # )zGCookie Max-Age for the access token: seconds to ``exp``, floored at 60.)Úmaxr8   Ú
expires_atÚtime)Úsessions   &r   Úaccess_token_max_ager>   /   s*   € äˆr”3�w×)Ñ)Ó*¬S´·²³Ó-=Õ=Ó>Ð>r   c               ó    € V ^8„  d   QhRRRR/# )r   Úprovider_namer   r   r   r   )r   s   "r   r   r   4   s   € ÷ eñ e¨ð e°ñ er   c                ó*   € \        RRV : R2/RR7      # )zG503 for a transient IDP/backing-store outage (never a forced re-login).ÚdetailzAuth provider z unreachablei÷  )Ústatus_coder   )r@   s   &r   Úunreachable_responserD   4   s   € ä˜ ^°MÑ3DÀLÐ#QÐRÐ`cÔdÐdr   ÚswallowÚ
on_swallowÚon_unreachablec               ó4   € V ^8„  d   QhRRRRRRRRR	R
RRRR/# )r   Úprovider_hintzOptional[str]Úcallz)Callable[[DashboardAuthProvider], object]Úphaser   Úlogzlogging.LoggerrE   ztuple[type[BaseException], ...]rF   z1Optional[Callable[[DashboardAuthProvider], None]]rG   r   )r   s   "r   r   r   9   sJ   € ÷ $ñ $Ø ð$Ø(Qð$Ø]`ð$à	ð$à"Að$ð Bð$ð Fñ	$r   c               ó|  a € \        4       pS '       d   VP                  V 3R lR7       RpV F  p	 V! V	4      p
T
f   K  T
u # 	  Ve   \        V4      hR#   T d    Te	   T! T	4        K?  \         dE   pTP                  RT	P                  Y+4       Te	   T! T	4       Tf   T	P                  p Rp?Kˆ  Rp?ii ; i)u  Run ``call`` across the session providers; first non-``None`` result or ``None``.

The hinted provider goes first (stable sort; a stale/unknown hint leaves registration order
intact). ``swallow`` exceptions reject that candidate only. A ``ProviderError`` (IDP/JWKS
unreachable) must NOT abort the chain â€” the credential may belong to a different, reachable
provider; it is logged under ``phase`` and, if nothing else succeeds, re-raised as
``ProviderError(name)`` so the caller answers 503 instead of forcing a re-login.
c                ó"   <€ V P                   S8g  # r.   )Úname)ÚproviderrI   s   &€r   Ú<lambda>Ú(scan_session_providers.<locals>.<lambda>H   s   ø€ ¨H¯M©M¸]Ò,Jr   )ÚkeyNz5dashboard-auth: provider %r unreachable during %s: %s)r   Úsortr
   ÚwarningrO   )rI   rJ   rK   rL   rE   rF   rG   Ú	providersÚunreachablerP   ÚresultÚes   f&$$$$$     r   Úscan_session_providersrZ   9   sÂ   ø€ ô 'Ó(€IßØ�‰ÔJˆÔKØ!%€KÛˆð	Ù˜(“^ˆFð ÔØŠMñ! ð" ÒÜ˜KÓ(Ð(Ùøð! ô 	ØÒ%Ù˜8Ô$ÚÜô 	Ø�K‰KÐOØ Ÿ™ uô1àÒ)Ù˜xÔ(ØÒ"Ø&Ÿm™m�Ýûð	ús#   ²AÁB;Á-B;Á6B;Á79B6Â6B;)z/loginz/auth/z
/api/auth/r   )Ú__doc__Ú
__future__r   Úloggingr<   Útypingr   r   Úfastapir   Úfastapi.responsesr   Úhermes_cli.dashboard_authr   Úhermes_cli.dashboard_auth.baser	   r
   r5   r   r'   r6   r>   rD   rZ   r   r   r   Ú<module>rc      sl   ðÙ KÝ "ã Û ß %å Ý *å <ß Oð 9Ð õ9õõ<õ?õ
eð
$àDFð$ð EIð$ð IM÷	$ñ $r   