Ë
    âß²j.  ã                  ó>  — d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	  ed¬«       G d„ d	«      «       Z
 ed¬«       G d
„ d«      «       Z ed¬«       G d„ d«      «       Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Zdd„Z G d„ de«      Zdd„Zy)zFAbstract base + dataclasses + exceptions for dashboard auth providers.é    )Úannotations)ÚABCÚabstractmethod)Ú	dataclass)ÚOptionalT)Úfrozenc                  ób   — e Zd ZU dZded<   ded<   ded<   ded<   ded<   ded	<   ded
<   ded<   y)ÚSessionz´A verified interactive identity (from ``complete_login`` / ``verify_session``). All fields
    mandatory; providers without orgs set ``org_id=""``. The tokens are opaque to Hermes.ÚstrÚuser_idÚemailÚdisplay_nameÚorg_idÚproviderÚintÚ
expires_atÚaccess_tokenÚrefresh_tokenN©Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__© ó    úC/home/ubuntu/.hermes/hermes-agent/hermes_cli/dashboard_auth/base.pyr
   r
   	   s3   … ñ]àƒLØƒJØÓØƒKØƒMØƒOØÓØÔr   r
   c                  ó4   — e Zd ZU dZded<   ded<   dZded<   y)	ÚTokenPrincipalu  A verified non-interactive (service-to-service) caller â€” the token analog of
    :class:`Session`: one bearer token on one request, no login/cookie/refresh. ``principal`` is
    an opaque stable caller id; ``scopes`` empty means "unscoped" (a route MAY enforce one).r   Ú	principalr   r   ztuple[str, ...]ÚscopesN)r   r   r   r   r   r!   r   r   r   r   r      s   … ñ`ð ƒNØƒMØ €FˆOÔ r   r   c                  ó&   — e Zd ZU dZded<   ded<   y)Ú
LoginStarta  First leg of the OAuth round trip: ``redirect_url`` is the IDP's authorize endpoint;
    ``cookie_payload`` maps cookie name -> serialised PKCE/CSRF state that the auth route sets
    (HttpOnly, Secure + ``SameSite=None`` over HTTPS, TTL <= 10 min; see ``set_pkce_cookie``).r   Úredirect_urlzdict[str, str]Úcookie_payloadNr   r   r   r   r#   r#   !   s   … ñbð ÓØ"Ô"r   r#   c                  ó   — e Zd ZdZy)ÚProviderErrorz<IDP unreachable / transient failure. Middleware -> HTTP 503.N©r   r   r   r   r   r   r   r'   r'   *   s   „ ÚFr   r'   c                  ó   — e Zd ZdZy)ÚInvalidCodeErrorzLOAuth callback ``code``/``state`` failed validation. Middleware -> HTTP 400.Nr(   r   r   r   r*   r*   .   s   „ ÚVr   r*   c                  ó   — e Zd ZdZy)ÚInvalidCredentialsErrorzQUsername/password rejected. The route answers a generic 401 (no username oracle).Nr(   r   r   r   r,   r,   2   s   „ Ú[r   r,   c                  ó   — e Zd ZdZy)ÚRefreshExpiredErrorzÀThis provider rejects the refresh token. Not proof of ownership in a multi-provider
    deployment: middleware tries the rest and forces re-login only after every reachable one
    rejects it.Nr(   r   r   r   r.   r.   6   s   „ òr   r.   c                óš  — 	 ddl }t        | |j                  «      rt        d| › �«      S t        | |j
                  |j                  f«      rt        d| › �«      S t        | |j                  «      rt        d| › �«      S t        | |j                  «      rt        d| › �«      S t        d| ›�«      S # t        $ r t        d| ›�«      cY S w xY w)uý  Map a ``PyJWKClient.get_signing_key_from_jwt`` failure to the protocol. Only a genuine
    transport failure (``PyJWKClientConnectionError``, or an unexpected JWKS shape) is a
    :class:`ProviderError` (503, never forces logout). A non-JWT bearer (``DecodeError``), a JWKS
    with no key for this ``kid`` (``PyJWKSetError``) or any other invalid token is simply not
    verifiable by this provider -> :class:`InvalidCodeError` (``verify_session`` returns ``None``).
    Folding "cannot parse" into "cannot reach" once made every opaque bearer a fast 503.

    * ``jwt.DecodeError`` â€” the bearer is not a JWT at all (an opaque peer key, a legacy session token,
    garbage). #94558: hosted agents answered every non-JWT bearer with a fast 503 ``Auth provider 'nous'
    unreachable`` even though Portal was healthy, because "cannot parse" and "cannot reach" were folded into
    one branch. * ``jwt.PyJWKSetError`` â€” the JWKS was fetched fine but holds no key for this token's
    ``kid`` (rotated/foreign key).
    r   NzJWKS lookup failed: z'token not verifiable by this provider: )
ÚjwtÚ	Exceptionr'   Ú
isinstanceÚPyJWKClientConnectionErrorÚDecodeErrorÚPyJWKSetErrorr*   ÚPyJWKClientErrorÚInvalidTokenError)Úexcr0   s     r   Úclassify_jwks_lookup_errorr9   <   sØ   € ð=Ûô
 �#�s×5Ñ5Ô6ÜÐ3°C°5Ð9Ó:Ð:Ü�#˜Ÿ™¨×):Ñ):Ð;Ô<ÜÐ"IÈ#ÈÐ OÓPÐPÜ�#�s×+Ñ+Ô,ÜÐ3°C°5Ð9Ó:Ð:Ü�#�s×,Ñ,Ô-ÜÐ"IÈ#ÈÐ OÓPÐPÜÐ/°¨wÐ7Ó8Ð8øô ò =ÜÐ3°C°7Ð;Ó<Ò<ð=ús   ‚B0 Â0C
Ã	C
c                  óÖ   — e Zd ZU dZdZded<   dZded<   dZded<   dZded	<   d
Z	ded<   e
dd„«       Ze
	 	 	 	 	 	 	 	 	 	 dd„«       Ze
dd„«       Ze
dd„«       Ze
dd„«       Zdd„Zdd„Zy)ÚDashboardAuthProvideraó  Protocol every dashboard-auth provider plugin implements.

    Lifecycle: ``start_login`` (redirect URL + PKCE state) -> IDP -> ``complete_login`` (code +
    verifier -> Session) -> ``verify_session`` per request -> ``refresh_session`` near expiry ->
    ``revoke_session`` on logout (best-effort, must not raise). Failure semantics: ``start_login``
    / ``complete_login`` raise ``ProviderError`` when the IDP is unreachable, ``complete_login``
    ``InvalidCodeError`` on a bad code/state; ``verify_session`` returns ``None`` for
    expired/unknown tokens (middleware refreshes) and raises ``ProviderError`` when unreachable
    (503); ``refresh_session`` raises ``RefreshExpiredError`` when the token is invalid for that
    provider (a foreign opaque token looks expired, so middleware tries the rest) and
    ``ProviderError`` on network failure (503, cookies kept).

    Subclasses MUST set ``name`` (stable lowercase id) and ``display_name``. Capability flags:
    ``supports_password`` (credential form + ``complete_password_login``; OAuth methods may be
    ``NotImplementedError`` stubs), ``supports_token`` (``verify_token`` for the token-auth seam),
    ``supports_session`` (False for token-only credentials such as drain, never offered a login).
    Ú r   Únamer   FÚboolÚsupports_passwordÚsupports_tokenTÚsupports_sessionc                ó   — y ©Nr   )ÚselfÚredirect_uris     r   Ústart_loginz!DashboardAuthProvider.start_logins   s   € Ø?Br   c                ó   — y rC   r   )rD   ÚcodeÚstateÚcode_verifierrE   s        r   Úcomplete_loginz$DashboardAuthProvider.complete_loginv   s   € à[^r   c                ó   — y rC   r   )rD   r   s     r   Úverify_sessionz$DashboardAuthProvider.verify_sessionz   s   € ØILr   c                ó   — y rC   r   ©rD   r   s     r   Úrefresh_sessionz%DashboardAuthProvider.refresh_session}   s   € ØADr   c                ó   — y rC   r   rO   s     r   Úrevoke_sessionz$DashboardAuthProvider.revoke_session€   s   € Ø=@r   c               óD   — t        t        | «      j                  › d�«      ‚)u]  Verify a username/password pair and mint a :class:`Session` (only called when
        ``supports_password``). Raise ``InvalidCredentialsError`` on rejection (SHOULD be constant
        time for unknown users â€” no timing oracle) and ``ProviderError`` when the store is
        unreachable. The default raises so a mis-flagged provider fails loudly.zd does not support password login (set supports_password = True and override complete_password_login)©ÚNotImplementedErrorÚtyper   )rD   ÚusernameÚpasswords      r   Úcomplete_password_loginz-DashboardAuthProvider.complete_password_loginƒ   s/   € ô
 "Ü�D‹z×"Ñ"Ð#ð $Rð RóSð 	Sr   c               óD   — t        t        | «      j                  › d�«      ‚)a}  Verify a non-interactive bearer token; return its principal. Mirrors ``verify_session``:
        return ``None`` (never raise) for an unrecognised token so the seam falls through; raise
        ``ProviderError`` ONLY for a genuine backing-store outage. Shared secrets MUST be compared
        with ``hmac.compare_digest``. The default raises so a mis-flagged provider fails loudly.zR does not support token auth (set supports_token = True and override verify_token)rT   )rD   Útokens     r   Úverify_tokenz"DashboardAuthProvider.verify_tokenŒ   s/   € ô
 "Ü�D‹z×"Ñ"Ð#ð $Dð DóEð 	Er   N)rE   r   Úreturnr#   )
rH   r   rI   r   rJ   r   rE   r   r]   r
   )r   r   r]   zOptional[Session])r   r   r]   r
   )r   r   r]   ÚNone)rW   r   rX   r   r]   z	'Session')r[   r   r]   z'Optional[TokenPrincipal]')r   r   r   r   r=   r   r   r?   r@   rA   r   rF   rK   rM   rP   rR   rY   r\   r   r   r   r;   r;   [   sÃ   … ñð" €Dˆ#ƒNØ€L�#ÓØ#Ð�tÓ#Ø €N�DÓ Ø!Ð�dÓ!àÚBó ØBàð_Øð_Ø#&ð_Ø7:ð_ØJMð_ØRYò_ó ð_ð ÚLó ØLàÚDó ØDàÚ@ó Ø@óSôEr   r;   c                óB  — dD ])  }t        | |d«      rŒt        | j                  › d|›�«      ‚ dD ]2  }t        t        | |d«      «      rŒt        | j                  › d|› �«      ‚ t        | dd«      r-t        | j                  › dt	        | j
                  «      › �«      ‚y)	zzRaise ``TypeError`` if ``cls`` doesn't fully implement the protocol (call it from every
    provider plugin's unit tests).)r=   r   r<   z missing or empty attribute: )rF   rK   rM   rP   rR   Nz missing method: Ú__abstractmethods__z% has unimplemented abstract methods: )ÚgetattrÚ	TypeErrorr   ÚcallableÚsortedr`   )ÚclsÚattrÚmethods      r   Úassert_protocol_compliancerh   –   s½   € ð )ò TˆÜ�s˜D "Õ%Ü˜sŸ|™|˜nÐ,IÈ$ÈÐRÓSÐSðTð%ò Hˆäœ  V¨TÓ2Õ3Ü˜sŸ|™|˜nÐ,=¸f¸XÐFÓGÐGðHô ˆsÐ)¨4Ô0ÜØ�|‰|ˆnÐAÄ&È×I`ÑI`ÓBaÐAbÐcóeð 	eð 1r   N)r8   ÚBaseExceptionr]   r1   )re   rV   r]   r^   )r   Ú
__future__r   Úabcr   r   Údataclassesr   Útypingr   r
   r   r#   r1   r'   r*   r,   r.   r9   r;   rh   r   r   r   ú<module>rn      s¾   ðÙ LÝ "ç #Ý !Ý ñ �$Ô÷
ð 
ó ð
ñ �$Ô÷!ð !ó ð!ñ �$Ô÷#ð #ó ð#ôG�Iô GôW�yô Wô\˜iô \ô˜)ô ó9ô>8E˜Cô 8Eôver   