
    `gj                        U d Z ddlmZ ddlZddlZddlmZmZmZm	Z	  ej                  d      ZdZi Zded<    ej                         Zdd	Zddd
d	 	 	 	 	 	 	 	 	 	 	 ddZddZy)u  Inbound cron-fire token verification for Chronos (Phase 4E.1).

When NAS relays an external scheduler fire to the agent, it POSTs
``/api/cron/fire`` with a short-lived NAS-minted JWT. This module verifies that
JWT before any job runs — the security boundary for remotely-triggered job
execution.

We verify a NAS-minted JWT (the trust path the agent already has) rather than
let an external scheduler call the agent directly: the scheduler signs with
NAS's keys, which the agent doesn't (and shouldn't) hold. See the plan's DQ-4.

The verifier is pluggable (``get_fire_verifier``) so the escape-hatch mode
(direct per-job cron-key) can swap in later with no handler change.

Crypto is delegated to PyJWT (already a declared dependency) — we do NOT
hand-roll JWT verification.
    )annotationsN)AnyCallableDictOptionalzcron.chronos.verify	cron_firezDict[str, Any]_JWK_CLIENTSc                    t         j                  |       }||S t        5  t         j                  |       }|ddlm}  ||       }|t         | <   |cddd       S # 1 sw Y   yxY w)ax  Return a process-cached PyJWKClient for ``jwks_url`` (one per URL).

    PyJWKClient does its own key caching internally (``cache_keys``/``lifespan``);
    the whole point here is to reuse the SAME instance across fires so that cache
    is actually hit instead of discarded. Double-checked-locked so concurrent
    fires resolve to a single shared client without racing.
    Nr   )PyJWKClient)r	   get_JWK_CLIENTS_LOCKjwtr   )jwks_urlclientr   s      X/root/.hermes/venv/lib/python3.12/site-packages/plugins/cron_providers/chronos/verify.py_get_jwk_clientr   1   sf     h'F	 !!(+>' *F%+L"  s   0AA#   )jwks_or_keyissuerleeway_secondsc                   | r|sy|st         j                  d       y	 ddl}d}|j                  d      s|j                  d      r't	        |      }|j                  |       j                  }n|}dddgi}t        g d	|||
      }	|r||	d<    |j                  | |fi |	}
|
j                  d      t        k7  rt         j                  dt               y|
S # t        $ r }t         j                  d|       Y d}~yd}~ww xY w)u  Verify a NAS-minted cron-fire JWT. Return decoded claims, or None.

    Checks (all must pass):
      - signature against the NAS JWKS (``jwks_or_key`` is a JWKS URL) — RS256
        family; symmetric secrets are rejected (NAS signs asymmetrically).
      - ``aud`` == ``expected_audience`` (this agent: ``agent:{instance_id}``).
      - ``exp`` / ``nbf`` within ``leeway_seconds``.
      - ``iss`` == ``issuer`` when an issuer is configured.
      - ``purpose`` == ``"cron_fire"`` — so a general agent JWT can't be
        replayed against the fire endpoint.

    Returns None (never raises) on any failure, so the handler can answer 401
    without leaking which check failed.
    Nz1cron fire: no JWKS/key configured; refusing tokenr   zhttp://zhttps://requireexpaud)RS256RS384RS512ES256ES384)
algorithmsaudienceleewayoptionsr   z(cron fire: token verification failed: %spurposez+cron fire: token missing/!=%s purpose claim)loggerwarningr   
startswithr   get_signing_key_from_jwtkeydictdecode	Exceptionr   _FIRE_PURPOSE)tokenexpected_audiencer   r   r   r   signing_key
jwk_clientr#   decode_kwargsclaimses               r   verify_nas_fire_tokenr5   F   s   , ) 	JK !!),0F0Fz0R
 )5J$==eDHHK &Kuen-(,D&!	)
 &,M(#E;@-@
 zz)-DmTM  A1Es   BC 	D  C;;D c                     t         S )u  Return the active inbound-fire verifier.

    Default = the NAS-JWT verifier. The DQ-4 escape hatch (direct per-job
    cron-key) would return a cron-key verifier here instead, selected by config
    — so the webhook handler never changes when the auth mode is swapped.
    )r5        r   get_fire_verifierr9      s
     ! r8   )r   strreturnr   )r.   r:   r/   r:   r   Optional[str]r   r<   r   intr;   zOptional[Dict[str, Any]])r;   z'Callable[..., Optional[Dict[str, Any]]])__doc__
__future__r   logging	threadingtypingr   r   r   r   	getLoggerr%   r-   r	   __annotations__Lockr   r   r5   r9   r7   r8   r   <module>rF      s   $ #   0 0			0	1    "n !"INN$ 2 "& AA A 	A
 A A AH!r8   