
    NQj-                    T   d Z ddlmZ ddlZddlZddlZddlmZmZ ddl	m
Z
mZ ddlmZ ddlmZ ddlmZmZmZmZmZ d	Zd
ZdZ G d dee          Ze
 G d d                      Z G d de          Z ej        d          Z ej        d          Zd&dZ d'dZ!ddedd(d%Z"dS ))um  Secret-source contract: the ABC every secret backend implements.

A *secret source* resolves credentials from an external secret manager
(Bitwarden Secrets Manager, 1Password, an OS keystore, a user script, ...)
into environment-variable-shaped values at process startup, AFTER
``~/.hermes/.env`` has loaded and BEFORE the rest of Hermes reads
``os.environ``.

Scope of the contract (deliberate, please do not widen):

* **Read-only.**  Sources resolve refs → values.  There is no write-back
  ("save this key to your vault"), no arbitrary secret objects, and no
  mid-session secret API.  If a future need for rotation/refresh appears
  it will arrive as a versioned optional hook — do not bolt it on.
* **Startup-time, synchronous.**  ``fetch()`` is called once per process
  (per HERMES_HOME) by the orchestrator in
  :mod:`agent.secret_sources.registry`, which enforces a wall-clock
  timeout around it.  Sources must not spawn background refreshers.
* **Never raises, never prompts.**  ``fetch()`` returns a
  :class:`FetchResult` — errors go in ``result.error`` with a
  machine-readable :class:`ErrorKind`.  Interactive auth belongs in the
  source's CLI ``setup`` flow, never on the startup path (non-TTY
  gateway/cron startup must never block on stdin).
* **Sources fetch; the orchestrator applies.**  A source returns the
  name→value mapping it *would* contribute.  Precedence (mapped-beats-bulk,
  first-wins, ``override_existing``, protected vars), conflict warnings,
  provenance tracking, and the actual ``os.environ`` writes are owned by
  the orchestrator so no backend can get them wrong.

Versioning: ``SECRET_SOURCE_API_VERSION`` gates plugin compatibility.
New *optional* hooks with default implementations do not bump it;
required-signature changes do, and the registry skips (with a warning)
sources built against a different major version instead of crashing
startup.
    )annotationsN)ABCabstractmethod)	dataclassfield)Enum)Path)Dict	FrozenSetListOptionalSequence   g      ^@g      >@c                  6    e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd
ZdS )	ErrorKinda[  Machine-readable failure taxonomy for :class:`FetchResult.error`.

    A fixed vocabulary keeps startup warnings and ``hermes secrets status``
    uniform across backends, and lets the orchestrator implement
    kind-dependent policy (e.g. a future stale-cache fallback on
    ``NETWORK``/``TIMEOUT`` but not on ``AUTH_FAILED``) exactly once.
    not_configuredbinary_missingauth_failedauth_expiredref_invalidnetworkempty_valuetimeoutinternalN)__name__
__module____qualname____doc__NOT_CONFIGUREDBINARY_MISSINGAUTH_FAILEDAUTH_EXPIREDREF_INVALIDNETWORKEMPTY_VALUETIMEOUTINTERNAL     =/home/alina/.hermes/hermes-agent/agent/secret_sources/base.pyr   r   >   sG          &N%NK!LKGKGHHHr)   r   c                      e Zd ZU dZ ee          Zded<    ee          Z	ded<    ee          Z
ded<    ee          Zded<   d	Zd
ed<   d	Zded<   d	Zded<   edd            Zd	S )FetchResultag  Outcome of one source's fetch.

    ``secrets`` holds what the source *would* contribute; whether each
    var is actually applied is the orchestrator's decision.  ``applied``
    and ``skipped`` exist for backward compatibility with the original
    Bitwarden fetch-and-apply entry point and are left empty by
    conforming ``fetch()`` implementations.
    )default_factoryzDict[str, str]secretsz	List[str]appliedskippedwarningsNOptional[str]errorzOptional[ErrorKind]
error_kindzOptional[Path]binary_pathreturnboolc                    | j         d u S )N)r3   selfs    r*   okzFetchResult.okg   s    zT!!r)   )r6   r7   )r   r   r   r   r   dictr.   __annotations__listr/   r0   r1   r3   r4   r5   propertyr;   r(   r)   r*   r,   r,   R   s           $eD999G9999t444G4444t444G4444%555H5555E&*J**** #'K&&&&" " " X" " "r)   r,   c                      e Zd ZU dZe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ddZddZddZddZd dZd
S )!SecretSourceu[  One external secret backend.

    Subclasses set the class attributes and implement :meth:`fetch`.
    Everything else has a sensible default.

    Attributes:
        name: Config-section key under ``secrets:`` in config.yaml.
            Lowercase ``[a-z0-9_]+``.  Also the provenance label stored
            for every var this source supplies.
        label: Human-readable name used in startup messages and
            ``hermes secrets status`` (e.g. ``"Bitwarden Secrets Manager"``).
        shape: ``"mapped"`` when the user explicitly binds env-var names
            to refs (1Password ``env:`` map, command source) or
            ``"bulk"`` when the backend injects whole projects/folders
            of secrets implicitly (Bitwarden BSM).  The orchestrator
            gives mapped sources precedence over bulk sources: an
            explicit binding is stronger intent than a project dump.
        scheme: Optional URI scheme this source owns for secret
            references (``"op"`` for ``op://...``).  Must be unique
            across registered sources — refs may eventually appear
            outside the ``secrets:`` block (e.g. credential-pool
            ``api_key`` fields), so scheme collisions are rejected at
            registration time to keep that future possible.
        api_version: Contract version this source was built against.
    intapi_version strnamelabelmappedshapeNr2   schemecfgr<   	home_pathr	   r6   r,   c                    dS )u  Resolve this source's secrets. MUST NOT raise or prompt.

        ``cfg`` is the source's raw config section (``secrets.<name>``)
        from config.yaml — treat every field defensively, the section
        may be malformed.  ``home_path`` is the resolved HERMES_HOME.
        Nr(   )r:   rK   rL   s      r*   fetchzSecretSource.fetch   s      r)   r7   c                p    t          t          |t                    o|                    d                    S )z'Whether the user turned this source on.enabledr7   
isinstancer<   getr:   rK   s     r*   
is_enabledzSecretSource.is_enabled   s+    JsD))@cggi.@.@AAAr)   c                r    t          t          |t                    o|                    dd                    S )u  May this source overwrite vars that .env / the shell already set?

        This NEVER extends to vars claimed by another secret source in the
        same startup pass — cross-source overrides are a config error the
        orchestrator warns about, not a knob.
        override_existingFrQ   rT   s     r*   rW   zSecretSource.override_existing   s0     JsD))Qcgg6I5.Q.QRRRr)   FrozenSet[str]c                    t                      S )a  Env vars the orchestrator must never let ANY source overwrite.

        Typically the source's own bootstrap-auth var (e.g.
        ``BWS_ACCESS_TOKEN``) so a vault that contains its own access
        token can't clobber the credential used to reach it.
        )	frozensetrT   s     r*   protected_env_varszSecretSource.protected_env_vars   s     {{r)   floatc                    	 t          |pi                     dt                              }n# t          t          f$ r
 t          cY S w xY w|dk    r|nt          S )z;Wall-clock budget the orchestrator enforces around fetch().timeout_secondsr   )r\   rS   DEFAULT_FETCH_TIMEOUT_SECONDS	TypeError
ValueError)r:   rK   vals      r*   fetch_timeout_secondsz"SecretSource.fetch_timeout_seconds   si    	1(9;XYYZZCC:& 	1 	1 	10000	1Aggss#@@s   *- AAc                    i S )zOptional description of this source's config keys.

        Shape: ``{key: {"description": str, "default": Any}}``.  Used by
        setup surfaces to render config without hardcoding per-source
        knowledge.  Purely informational.
        r(   r9   s    r*   config_schemazSecretSource.config_schema   s	     	r)   )rK   r<   rL   r	   r6   r,   )rK   r<   r6   r7   )rK   r<   r6   rX   )rK   r<   r6   r\   )r6   r<   )r   r   r   r   SECRET_SOURCE_API_VERSIONrC   r=   rF   rG   rI   rJ   r   rN   rU   rW   r[   rc   re   r(   r)   r*   rA   rA   l   s          4 1K0000DNNNNEOOOOE F        ^B B B BS S S S   A A A A     r)   rA   z^[A-Za-z_][A-Za-z0-9_]*$z<\x1b(?:\[[0-9;?]*[ -/]*[@-~]|\][^\x07\x1b]*(?:\x07|\x1b\\)?)rF   rE   r6   r7   c                n    t          |           o&t          t                              |                     S )z8True when ``name`` is a legal environment-variable name.)r7   _ENV_NAME_REmatch)rF   s    r*   is_valid_env_namerj      s)    ::8$|11$77888r)   textc                <    t                               d| pd          S )zDStrip ANSI escape sequences (whole CSI/OSC sequences, not just ESC).rD   )_ANSI_REsub)rk   s    r*   
scrub_ansiro      s    <<DJB'''r)   r(   )	allow_env	extra_envr   argvSequence[str]rp   rq   Optional[Dict[str, str]]r   r\   subprocess.CompletedProcessc          
        d}i }g ||R D ](}t           j                            |          }||||<   )|r|                    |           |                    dd           	 t          j        t          |           |dd|t
          j                  }n# t
          j	        $ rA}	t          t          t          | d                             j         d|d	d
          |	d}	~	wt          $ r@}	t          dt          t          | d                             j         d|	           |	d}	~	ww xY w|j        pd|_        t!          |j        pd          |_        |S )u  Run a secret-manager helper CLI with a minimal, allowlisted env.

    Security posture shared by every subprocess-driven backend:

    * argv list only — never ``shell=True``.  Callers pass user-supplied
      reference strings AFTER a ``--`` option terminator in their argv.
    * The child gets ``PATH``/``HOME``/locale basics plus only the env
      vars named in ``allow_env`` (auth/session vars) and ``extra_env``
      — never a copy of the full post-dotenv ``os.environ``, which by
      this point holds every credential Hermes knows about.
    * ``NO_COLOR=1`` is set and stderr/stdout are ANSI-scrubbed so
      helper diagnostics can't smuggle escape sequences into Hermes
      output.
    * stdin is ``/dev/null`` so a helper that decides to prompt fails
      fast instead of hanging startup.

    Raises ``RuntimeError`` on spawn failure or timeout (message safe to
    surface); returns the completed process otherwise — callers own
    returncode interpretation.
    )
PATHHOMEUSERPROFILE
SYSTEMROOTTMPDIRTEMPLANGLC_ALLXDG_CONFIG_HOMEXDG_DATA_HOMENNO_COLOR1T)envcapture_outputrk   r   stdinr   z timed out after z.0fszfailed to invoke z: rD   )osenvironrS   update
setdefault
subprocessrunr>   DEVNULLTimeoutExpiredRuntimeErrorr	   rE   rF   OSErrorstdoutro   stderr)
rr   rp   rq   r   	base_keepr   keyrb   procexcs
             r*   run_secret_clir      s   6GIC''Y''  jnnS!!?CH 

9NN:s###~JJ$
 
 
 $   CQLL!!&GGGGGG
 
	    @Sa\\ 2 2 7@@3@@
 
	
 +#DKT[.B//DKKs$   #1B D-$<C  D--;D((D-)rF   rE   r6   r7   )rk   rE   r6   rE   )
rr   rs   rp   rs   rq   rt   r   r\   r6   ru   )#r   
__future__r   r   rer   abcr   r   dataclassesr   r   enumr   pathlibr	   typingr
   r   r   r   r   rf   r_   DEFAULT_CLI_TIMEOUT_SECONDSrE   r   r,   rA   compilerh   rm   rj   ro   r   r(   r)   r*   <module>r      s  " "H # " " " " " 				 				     # # # # # # # # ( ( ( ( ( ( ( (             < < < < < < < < < < < < < <
  
 !&  #     T   ( " " " " " " " "2S S S S S3 S S Sv rz566 2:UVV9 9 9 9
( ( ( (  "*.0: : : : : : : :r)   