Ë
    :Õži¿  ã                  ó‚   — U d Z ddlmZ ddlZddlZddlmZ  ej                  e«      Z	 G d„ d«      Z
daded<   d
dd	„Zy)u?  
core/secrets/client.py
Secrets client with Infisical SDK â†’ environment variable â†’ default fallback chain.

Resolution order per get() call:
  1. In-memory cache       (fast path, avoids repeated lookups)
  2. Infisical SDK         (if token + project_id both available and SDK importable)
  3. os.environ            (always available)
  4. caller-supplied default
  5. KeyError              (if no default supplied)

# VERIFICATION_STAMP
# Story: M1.02 â€” core/secrets/client.py
# Verified By: parallel-builder
# Verified At: 2026-02-25
# Tests: 16/16
# Coverage: 100%
é    )ÚannotationsN)ÚOptionalc                  óX   — e Zd ZdZ	 	 	 d		 	 	 	 	 	 	 d
d„Zdd„Zdd„Zddd„Zdd„Zdd„Z	y)ÚGenesisSecretsaV  
    Unified secret access for Genesis.

    Parameters
    ----------
    infisical_token : str, optional
        Infisical Universal Auth *client secret*.
        Falls back to ``INFISICAL_TOKEN`` env var when not supplied.
        When neither is present Infisical is skipped silently.
    environment : str
        Infisical environment slug (``"dev"``, ``"staging"``, ``"prod"``).
        Defaults to ``"prod"``.
    project_id : str, optional
        Infisical project ID (UUID).
        Falls back to ``INFISICAL_PROJECT_ID`` env var.
        Required together with *infisical_token* to enable Infisical mode.

    Notes
    -----
    Infisical SDK uses Universal Auth: ``client_id`` == project_id,
    ``client_secret`` == token.  When the SDK is not installed the module
    degrades gracefully to env-var mode with a single debug log line.
    Nc                ó"  — |xs t         j                  j                  d«      | _        || _        |xs t         j                  j                  d«      | _        d | _        i | _        | j                  r| j
                  r| j                  «        y y y )NÚINFISICAL_TOKENÚINFISICAL_PROJECT_ID)	ÚosÚenvironÚgetÚ_tokenÚ_environmentÚ_project_idÚ_infisical_clientÚ_cacheÚ_init_infisical)ÚselfÚinfisical_tokenÚenvironmentÚ
project_ids       ú,/mnt/e/genesis-system/core/secrets/client.pyÚ__init__zGenesisSecrets.__init__5   st   € ð &5Ò%Y¼¿
¹
¿¹ÐGXÓ8YˆŒØ!,ˆÔØ*4Ò*^¼¿
¹
¿¹ÐG]Ó8^ˆÔØ!%ˆÔØ&(ˆŒð ;Š;˜4×+Ò+Ø× Ñ Õ"ð ,ˆ;ó    c                ó~  — 	 ddl m}  |d¬«      }|j                  j                  j	                  | j
                  | j                  ¬«       || _        t        j                  d| j
                  «       y	# t        $ r t        j                  d«       Y y	t        $ r }t        j                  d|«       Y d	}~y	d	}~ww xY w)
z1Try to import and authenticate the Infisical SDK.r   )ÚInfisicalSDKClientzhttps://app.infisical.com)Úhost)Ú	client_idÚclient_secretz9GenesisSecrets: Infisical client initialised (project=%s)uH   GenesisSecrets: infisical_sdk not installed â€” falling back to env varsuG   GenesisSecrets: Infisical auth failed (%s) â€” falling back to env varsN)Úinfisical_sdkr   ÚauthÚuniversal_authÚloginr   r   r   ÚloggerÚinfoÚImportErrorÚdebugÚ	ExceptionÚwarning)r   r   ÚclientÚexcs       r   r   zGenesisSecrets._init_infisicalI   s¢   € ð	Ý8á'Ð-HÔIˆFØK‰K×&Ñ&×,Ñ,Ø×*Ñ*Ø"Ÿk™kð -ô ð &,ˆDÔ"ÜK‰KÐSÐUY×UeÑUeÕføÜò 	ÜL‰LØZöô ò 	ÜN‰NØYÐ[^÷ñ ûð	ús   ‚A1A4 Á4B<ÂB<ÂB7Â7B<c                ó  — | j                   €y	 | j                   j                  j                  || j                  | j                  ¬«      }|j
                  S # t        $ r!}t        j                  d||«       Y d}~yd}~ww xY w)z=Return the secret value from Infisical, or None on any error.N)Úsecret_namer   Úenvironment_slugz2GenesisSecrets: Infisical lookup failed for %r: %s)	r   ÚsecretsÚget_secret_by_namer   r   Úsecret_valuer'   r#   r&   )r   ÚkeyÚsecretr*   s       r   Ú_fetch_from_infisicalz$GenesisSecrets._fetch_from_infisical^   s€   € à×!Ñ!Ð)Øð		Ø×+Ñ+×3Ñ3×FÑFØØ×+Ñ+Ø!%×!2Ñ!2ð Gó ˆFð
 ×&Ñ&Ð&øÜò 	ÜL‰LÐMÈsÐTWÔXÜûð	ús   AA Á	BÁ A<Á<Bc                ó  — || j                   v r| j                   |   S | j                  |«      }||| j                   |<   |S t        j                  j	                  |«      }||| j                   |<   |S ||S t        d|›d«      ‚)u  
        Fetch a secret by *key*.

        Resolution order: **cache â†’ Infisical â†’ env var â†’ default â†’ KeyError**

        Parameters
        ----------
        key : str
            Secret name (case-sensitive).
        default : str, optional
            Value to return when the secret is not found anywhere.

        Returns
        -------
        str
            The resolved secret value.

        Raises
        ------
        KeyError
            When *key* is absent from all sources and no *default* is given.
        zSecret z; not found in Infisical, environment variables, or defaults)r   r3   r
   r   r   ÚKeyError)r   r1   ÚdefaultÚvalueÚ	env_values        r   r   zGenesisSecrets.getq   s¡   € ð0 $—+‘+ÑØ—;‘;˜sÑ#Ð#ð ×*Ñ*¨3Ó/ˆØÐØ$ˆDK‰K˜ÑØˆLô —J‘J—N‘N 3Ó'ˆ	ØÐ Ø(ˆDK‰K˜ÑØÐð ÐØˆNô ØcWÐWÐXó
ð 	
r   c                ó,   — t        | j                  «      S )zÆ
        Return a copy of all *cached* secrets.

        This does **not** pull the full secret list from Infisical.
        Only secrets that have been fetched via :meth:`get` appear here.
        )Údictr   ©r   s    r   Úget_allzGenesisSecrets.get_all¡   s   € ô D—K‘KÓ Ð r   c                ó8   — | j                   j                  «        y)zGDiscard all cached secret values, forcing fresh lookups on next access.N)r   Úclearr;   s    r   Úclear_cachezGenesisSecrets.clear_cacheª   s   € à‰×ÑÕr   )NÚprodN)r   úOptional[str]r   Ústrr   rA   ÚreturnÚNone)rC   rD   )r1   rB   rC   rA   ©N©r1   rB   r6   rA   rC   rB   )rC   zdict[str, str])
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r3   r   r<   r?   © r   r   r   r      sW   „ ñð4 *.Ø!Ø$(ð	#à&ð#ð ð#ð "ð	#ð
 
ó#ó(ó*ô&.
ó`!ôr   r   zOptional[GenesisSecrets]Ú	_instancec                óN   — t         €
t        «       a t         j                  | |«      S )a5  
    Fetch a single secret using the module-level :class:`GenesisSecrets` singleton.

    The singleton is created lazily on first call.  It reads
    ``INFISICAL_TOKEN`` and ``INFISICAL_PROJECT_ID`` from the environment
    automatically.

    Parameters
    ----------
    key : str
        Secret name.
    default : str, optional
        Fallback when the secret is absent from all sources.

    Returns
    -------
    str
        The resolved secret value.

    Raises
    ------
    KeyError
        When *key* is not found and no *default* is provided.
    )rL   r   r   )r1   r6   s     r   Ú
get_secretrN   ¶   s#   € ô4 ÐÜ"Ó$ˆ	Ü=‰=˜˜gÓ&Ð&r   rE   rF   )rJ   Ú
__future__r   Úloggingr
   Útypingr   Ú	getLoggerrG   r#   r   rL   Ú__annotations__rN   rK   r   r   ú<module>rT      sI   ðòõ$ #ã Û 	Ý à	ˆ×	Ñ	˜8Ó	$€÷Pñ Pðn '+€	Ð#Ó *õ'r   