Ë
    ÛJêj;R  ã                  ó.  — d Z ddlmZ ddl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
 ddlmZmZ ddlZddlmZmZ ddlmZmZmZmZ dd	lmZmZ d
gZ ej6                  ddd¬«      ZdZdZdZd'd„Z d(d„Z!d)d„Z"d*d„Z#	 	 	 d+	 	 	 	 	 	 	 d,d„Z$dddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d-d„Z%d.d„Z&d/d„Z'ejQ                  d«      	 	 	 	 d0	 	 	 	 	 	 	 	 	 d1d„«       Z)ejQ                  d«      	 	 	 	 d0	 	 	 	 	 	 	 	 	 	 	 d2d„«       Z*	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d3d „Z+ejQ                  d!«      	 	 	 	 	 d4	 	 	 	 	 	 	 	 	 	 	 	 	 d5d"„«       Z,ejQ                  d#«      	 	 	 	 	 d4	 	 	 	 	 	 	 	 	 	 	 	 	 d6d$„«       Z-ejQ                  d%«      	 	 	 	 	 d7	 	 	 	 	 	 	 	 	 	 	 d8d&„«       Z.y)9u³  Approvals CLI â€” human-in-the-loop review of pending approval requests.

This module exposes the ``approvals`` Typer sub-application, which lets a local
operator inspect, approve, deny and audit the approval requests produced by the
security plane (``PermissionGateway`` returning ``REQUIRE_APPROVAL``). It only
reads and writes approval state through :class:`ApprovalManager`; it never
constructs a ``PolicyEngine``, never changes the policy mode (SAFE remains the
default everywhere) and never relaxes the sandbox.

Semantics this CLI deliberately surfaces instead of hiding
---------------------------------------------------------
* ``approve`` / ``deny`` return ``None`` both when the request does not exist
  and when it is no longer ``PENDING`` (already decided, expired or cancelled).
  The commands therefore map that ``None`` to an explicit non-zero exit code
  plus a diagnostic; they never report a silent success.
* ``check_expired()`` is lazy: nothing expires until it is called. The
  ``pending`` command calls it first so the printed listing is truthful.
* A ``pending`` request is a blocking gate.
  ``AuthorizedExecutionService._wait_for_approval`` polls ``get_request`` in a
  loop, proceeds when the status resolves to ``APPROVED`` and raises
  ``SecurityError`` on any other terminal status (denied, expired, cancelled,
  missing). Approving is therefore the only way to unblock a waiting execution.
* Approvals are bound to a ``request_id`` and to the recorded ``action``,
  ``resource`` and ``context``. There is **no cryptographic binding** between
  the approval and the code that will eventually run: nothing hashes or signs
  the execution payload, so this record alone cannot prove which concrete code
  an approval was spent on. That is a documented limitation of the current
  prototype, not a security guarantee, and the commands say so.

Display of request payloads
---------------------------
``context`` and ``metadata`` are agent-supplied and may contain arbitrary data.
They are rendered as JSON **unredacted** because this is a local operator's
audit view; the CLI never interprets or executes them and never prints
credentials it generated itself. Treat the terminal output as sensitive.
é    )ÚannotationsN)ÚUTCÚdatetime)ÚPath)Ú	AnnotatedÚAny)Úopen_databaseÚresolve_db_path)ÚApprovalManagerÚApprovalRecordÚApprovalRequestÚApprovalStatus)ÚAuditEventTypeÚAuditLogÚapprovals_appÚ	approvalszDReview, approve, deny and audit human-in-the-loop approval requests.T)ÚnameÚhelpÚno_args_is_helpz7Explicit path to the CyberBrain26 SQLite database file.z2Explicit data directory holding the database file.zCOperate on an in-process manager only (nothing is written to disk).c                 óÞ   — 	 t        j                  «       S # t        t        f$ rG t        j
                  j                  d«      xs# t        j
                  j                  d«      xs dcY S w xY w)zDReturn the local OS user name used as the default reviewer identity.ÚUSERÚUSERNAMEz
local-user)ÚgetpassÚgetuserÚOSErrorÚKeyErrorÚosÚenvironÚget© ó    úD/home/oem/CyberBrain26-unified/src/cyberbrain26/product/approvals.pyÚ_default_reviewerr#   H   sU   € ðTÜ�‰Ó Ð øÜ”XÐò TÜ�z‰z�~‰~˜fÓ%ÒS¬¯©¯©¸
Ó)CÒSÀ|ÒSðTús   ‚ –AA,Á+A,c                ó~   — | €yt        j                  | t        ¬«      j                  d¬«      j	                  dd«      S )zEFormat a POSIX timestamp as ISO-8601 UTC, or ``-`` when it is absent.ú-)ÚtzÚseconds)Útimespecz+00:00ÚZ)r   Úfromtimestampr   Ú	isoformatÚreplace)Úvalues    r"   Ú	_fmt_timer.   P   s:   € à€}ØÜ×!Ñ! %¬CÔ0×:Ñ:ÀIÐ:ÓN×VÑVÐW_ÐadÓeÐer!   c                ó<   — t        j                  | ddt        ¬«      S )z×Render a JSON-compatible mapping as pretty JSON.

    The mapping is local approval/audit data owned by the agent that raised the
    request. It is printed unredacted and is never interpreted or executed here.
    é   T)ÚindentÚ	sort_keysÚdefault)ÚjsonÚdumpsÚstr)Úpayloads    r"   Ú	_fmt_jsonr8   W   s   € ô �:‰:�g a°4ÄÔEÐEr!   c           	     ó(  ‡— | D �cg c]  }t        |«      ‘Œ c}Š|D ]0  }t        |«      D ]   \  }}t        ‰|   t        |«      «      ‰|<   Œ" Œ2 dj                  ˆfd„t        | «      D «       «      j	                  «       g}|j                  dj                  d„ ‰D «       «      j	                  «       «       |D ]B  }|j                  dj                  ˆfd„t        |«      D «       «      j	                  «       «       ŒD dj                  |«      S c c}w )z<Render a fixed-width plain-text table with a separator line.z  c              3  óL   •K  — | ]  \  }}|j                  ‰|   «      –— Œ y ­w©N©Úljust)Ú.0ÚiÚhÚwidthss      €r"   ú	<genexpr>z _render_table.<locals>.<genexpr>f   s"   øè ø€ ÒI©d¨a°�q—w‘w˜v a™y×)ÑIùó   ƒ!$c              3  ó&   K  — | ]	  }d |z  –— Œ y­w)r%   Nr    )r>   Úwidths     r"   rB   z _render_table.<locals>.<genexpr>g   s   è ø€ Ò;¨5˜3 �;Ñ;ùs   ‚c              3  óL   •K  — | ]  \  }}|j                  ‰|   «      –— Œ y ­wr;   r<   )r>   r?   ÚcellrA   s      €r"   rB   z _render_table.<locals>.<genexpr>i   s"   øè ø€ ÒS¹¸¸D˜tŸz™z¨&°©)×4ÑSùrC   ú
)ÚlenÚ	enumerateÚmaxÚjoinÚrstripÚappend)ÚheadersÚrowsÚheaderÚrowÚindexrG   ÚlinesrA   s          @r"   Ú_render_tablerU   `   sí   ø€ à(/Ö0˜fŒc�&�kÒ0€FØò :ˆÜ$ S›>ò 	:‰KˆE�4Ü  u¡¬s°4«yÓ9ˆF�5ŠMñ	:ð:ð �Y‰YÓI´iÀÓ6HÔIÓI×PÑPÓRÐS€EØ	‡L�L�—‘Ñ;°FÔ;Ó;×BÑBÓDÔEØò ^ˆØ�‰�T—Y‘YÓSÄIÈcÃNÔSÓS×ZÑZÓ\Õ]ð^à�9‰9�UÓÐùò 1s   †Dc                ó  — |skt        | |¬«      }|j                  «       sd|› d�}t        j                  |«      ‚t        j                  d|› d�d¬«       t        t        | |d¬	«      ¬
«      S t        t        | |d¬	«      ¬
«      S )a~  Open an :class:`ApprovalManager` on the local store.

    Args:
        db: Optional explicit database file path.
        data_dir: Optional data directory used to derive the default database path.
        persist: When ``False``, no database file is opened or written.

    Returns:
        A manager bound to the opened database, or an in-memory manager when
        ``persist`` is ``False``.

    Raises:
        typer.BadParameter: If ``persist`` is ``False`` and the resolved database
            file does not exist. Nothing could be read or decided in that case,
            and pretending otherwise would hide a real failure.
    )Údata_dirz,--no-persist was requested but the database a   does not exist. Without persistence no approval can be read or written, and a decision taken with --no-persist cannot affect another process (such as the execution blocked on this request). Run without --no-persist, or point --db/--data-dir at the existing store.z>WARNING: --no-persist is active; decisions are not written to z; and cannot unblock a waiting execution in another process.T©ÚerrF)Údb_pathrW   Úpersist)Údatabase)r
   ÚexistsÚtyperÚBadParameterÚechor   r	   )ÚdbrW   r[   ÚpathÚmessages        r"   Ú_open_managerrd   m   s•   € ñ* Ü˜r¨HÔ5ˆØ�{‰{Œ}à>¸t¸fð E9ð 9ð ô ×$Ñ$ WÓ-Ð-Ü�
‰
ØLÈTÈFð SEð Eàõ	
ô
 ¬¸bÈ8Ð]bÔ(cÔdÐdÜ¤M¸"ÀxÐY]Ô$^Ô_Ð_r!   Ú )Úagent_idÚresourceÚerrorÚmetadatac       	        ó�   — t        | j                  «      }d|i}|
r|j                  |
«       |j                  ||||||||	|¬«	       y)ar  Write an audit event for a mutating approvals command.

    Read-only commands (``pending``, ``show``, ``history``) are deliberately not
    audited; only state changes are.

    Args:
        manager: Manager whose database receives the audit record.
        event_type: Audit event type for this command.
        actor: Identity of the operator running the command.
        action: Action recorded on the approval request.
        approval_id: The approval request id.
        result: Outcome label, e.g. ``approved``, ``denied`` or ``not_applied``.
        command: The CLI command name, stored in metadata.
        agent_id: Optional agent id that raised the request.
        resource: Optional resource the request targets.
        error: Optional error description when the command did not apply.
        metadata: Optional extra metadata; must never contain credentials.
    Úcommand)Úactorrf   Úactionrg   Úapproval_idÚresultrh   ri   N)r   r\   ÚupdateÚrecord)ÚmanagerÚ
event_typerl   rm   rn   ro   rk   rf   rg   rh   ri   Úauditr7   s                r"   Ú_record_auditru   –   sZ   € ô@ �W×%Ñ%Ó&€EØ(¨'Ð2€GÙØ�‰�xÔ Ø	‡L�LØØØØØØØØØð õ 
r!   c           	     óì  — i d| j                   “d| j                  j                  “d| j                  j                  “dt	        | j                  j
                  d| j                  j
                  «      “d| j                  “d| j                  “d| j                  “d	| j                  “d
| j                  j                  “d| j                  r| j                  j                  nd“d| j                  “dt        | j                  «      “d| j                  “dt        | j                  «      “d| j                   “d| j"                  “d| j$                  “dt'        t)        d|| j                  z
  «      d«      i¥S )z8Build the JSON-serialisable view of an approval request.Ú
request_idrf   Ú
agent_roleÚagent_trust_levelr-   rm   rg   ÚcontextÚ
risk_scoreÚstatusÚdecisionNÚ
created_atÚcreated_at_isoÚreviewed_atÚreviewed_at_isoÚreviewerÚreasonri   Úage_secondsç        é   )rw   Úagentrf   ÚroleÚgetattrÚtrust_levelrm   rg   rz   r{   r|   r-   r}   r~   r.   r€   r‚   rƒ   ri   ÚroundrK   )ÚrequestÚnows     r"   Ú_request_payloadrŽ   Ç   s–  € ðØ�g×(Ñ(ðà�G—M‘M×*Ñ*ðð 	�g—m‘m×(Ñ(ðð 	œW W§]¡]×%>Ñ%>ÀÈÏÉ×IbÑIbÓcð	ð
 	�'—.‘.ðð 	�G×$Ñ$ðð 	�7—?‘?ðð 	�g×(Ñ(ðð 	�'—.‘.×&Ñ&ðð 	¨g×.>Ò.>�G×$Ñ$×*Ò*ÀDðð 	�g×(Ñ(ðð 	œ) G×$6Ñ$6Ó7ðð 	�w×*Ñ*ðð 	œ9 W×%8Ñ%8Ó9ðð 	�G×$Ñ$ðð  	�'—.‘.ð!ð" 	�G×$Ñ$ð#ð$ 	”uœS  c¨G×,>Ñ,>Ñ&>Ó?ÀÓCñ%ð r!   c           
     óô   — | j                   | j                  | j                  | j                  | j                  j
                  | j                  | j                  t        | j                  «      | j                  dœ	S )z7Build the JSON-serialisable view of an approval record.)	rw   rf   rm   rg   r}   r‚   Ú	timestampÚtimestamp_isorƒ   )
rw   rf   rm   rg   r}   r-   r‚   r�   r.   rƒ   )rq   s    r"   Ú_record_payloadr’   ß   s^   € ð ×'Ñ'Ø—O‘OØ—-‘-Ø—O‘OØ—O‘O×)Ñ)Ø—O‘OØ×%Ñ%Ü" 6×#3Ñ#3Ó4Ø—-‘-ñ
ð 
r!   Úpendingc                óX  — t        || | ¬«      }|j                  «       }|j                  «       }t        j                  «       }|rHt	        j
                  t        j                  |D �cg c]  }t        ||«      ‘Œ c}dt        ¬«      «       y|D ]2  }	t	        j
                  d|	j                  › d|	j                  › d�«       Œ4 |st	        j
                  d«       yg d	¢}
|D �	cg c]t  }	|	j                  |	j                  j                  |	j                  |	j                  xs d
|	j                  d›t!        d||	j"                  z
  «      d›|	j$                  xs d
g‘Œv }}	t	        j
                  t'        |
|«      «       t	        j
                  dt)        |«      › d�«       yc c}w c c}	w )zÂList pending approval requests, oldest first.

    ``check_expired()`` runs before the listing because expiry is lazy: without
    it, timed-out requests would still be shown as actionable.
    ©ra   rW   r[   r0   ©r1   r3   Nzexpired during this call: z	 (action=ú)zNo pending approvals.)rw   r‡   rm   rg   r{   r„   rƒ   r%   ú.2fr…   z.1frH   z= pending request(s). Decide with: approvals approve|deny <id>)rd   Úcheck_expiredÚlist_pendingÚtimer^   r`   r4   r5   rŽ   r6   rw   rm   r‡   rf   rg   r{   rK   r~   rƒ   rU   rI   )rW   ra   Ú
no_persistÚas_jsonrr   ÚexpiredÚrequestsr�   ÚrrŒ   rO   rP   s               r"   r“   r“   î   s  € ô ˜r¨HÀ*¸nÔM€GØ×#Ñ#Ó%€GØ×#Ñ#Ó%€HÜ
�)‰)‹+€CÙÜ�
‰
”4—:‘:ÀÖJ¸AÔ/°°3Õ7ÒJÐSTÔ^aÔbÔcØØò `ˆÜ�
‰
Ð/°×0BÑ0BÐ/CÀ9ÈWÏ^É^ÐL\Ð\]Ð^Õ_ð`áÜ�
‰
Ð*Ô+Øò€Gð&  öð ð ×ÑØ�M‰M×"Ñ"Ø�N‰NØ×ÑÒ# Ø×!Ñ! #Ð&Ü�3˜˜g×0Ñ0Ñ0Ó1°#Ð6Ø�N‰NÒ!˜cò	
ð€Dð ô 
‡J�JŒ}˜W dÓ+Ô,Ü	‡J�J�”C˜“M�?Ð"_Ð`Õaùò; Kùò s   Á(F"Ã%A9F'Úshowc                óÊ  — t        ||| ¬«      }|j                  | «      }|€0t        j                  d| ›d�d¬«       t        j                  d«      ‚|j                  | «      }|r`t        |t        j                  «       «      }|rt        |«      nd|d<   t        j                  t        j                  |d	t        ¬
«      «       yt        j                  d|j                  › �«       t        j                  d|j                  j                  › �«       t        j                  d|j                  r|j                  j                  nd› �«       t        j                  d|j                   j"                  › d|j                   j$                  › d�«       t        j                  dt'        |j                   j(                  dd«      › �«       t        j                  d|j*                  › �«       t        j                  d|j,                  xs d› �«       t        j                  d|j.                  d›�«       t        j                  dt1        |j2                  «      › �«       t        j                  dt1        |j4                  «      › �«       t        j                  d|j6                  xs d› �«       t        j                  d|j8                  xs d› �«       t        j                  d«       t        j                  t;        |j<                  «      «       t        j                  d«       t        j                  t;        |j>                  «      «       t        j                  d«       |€t        j                  d«       nŸt        j                  d |j                  j                  › �«       t        j                  d!|j6                  › �«       t        j                  d"t1        |j@                  «      › �«       t        j                  d#|j8                  xs d› �«       t        j                  d$«       |j                  tB        jD                  k(  rt        j                  d%«       yy)&zEShow the full detail of one approval request and its decision record.r•   NúApproval request zP was not found in the local store. Check the id and the --db/--data-dir options.TrX   é   rq   r0   r–   zrequest_id    : zstatus        : zdecision      : r%   zagent         : z (role=r—   ztrust_level   : r-   zaction        : zresource      : zrisk_score    : r˜   zcreated_at    : zreviewed_at   : zreviewer      : zreason        : zcontext       :zmetadata      :zrecord        :z7  none (no decision has been recorded for this request)z  decision     : z  reviewer     : z  timestamp    : z  reason       : z›
Note: this approval is bound to the request id and the recorded action/resource/context only. It is not cryptographically bound to the code that will run.z‡Status PENDING blocks execution: the waiting execution proceeds only on APPROVED and raises SecurityError on any other terminal status.)#rd   Úget_requestr^   r`   ÚExitÚ
get_recordrŽ   r›   r’   r4   r5   r6   rw   r|   r-   r}   r‡   rf   rˆ   r‰   rŠ   rm   rg   r{   r.   r~   r€   r‚   rƒ   r8   rz   ri   r�   r   ÚPENDING)	rw   rW   ra   rœ   r�   rr   rŒ   rq   r7   s	            r"   r¡   r¡     sY  € ô ˜r¨HÀ*¸nÔM€GØ×!Ñ! *Ó-€GØ€Ü�
‰
Ø 
˜~ð .<ð <àõ	
ô
 �j‰j˜‹mÐØ×Ñ 
Ó+€FÙÜ"2°7¼D¿I¹I»KÓ"HˆÙ7=œO¨FÔ3À4ˆ�ÑÜ�
‰
”4—:‘:˜g¨a¼Ô=Ô>ØÜ	‡J�JÐ! '×"4Ñ"4Ð!5Ð6Ô7Ü	‡J�JÐ! '§.¡.×"6Ñ"6Ð!7Ð8Ô9Ü	‡J�JÐ!¸G×<LÒ<L '×"2Ñ"2×"8Ò"8ÐRUÐ!VÐWÔXÜ	‡J�JÐ! '§-¡-×"8Ñ"8Ð!9¸ÀÇÁ×ASÑASÐ@TÐTUÐVÔWÜ	‡J�JÐ!¤'¨'¯-©-×*CÑ*CÀWÈcÓ"RÐ!SÐTÔUÜ	‡J�JÐ! '§.¡.Ð!1Ð2Ô3Ü	‡J�JÐ! '×"2Ñ"2Ò"9°cÐ!:Ð;Ô<Ü	‡J�JÐ! '×"4Ñ"4°SÐ!9Ð:Ô;Ü	‡J�JÐ!¤)¨G×,>Ñ,>Ó"?Ð!@ÐAÔBÜ	‡J�JÐ!¤)¨G×,?Ñ,?Ó"@Ð!AÐBÔCÜ	‡J�JÐ! '×"2Ñ"2Ò"9°cÐ!:Ð;Ô<Ü	‡J�JÐ! '§.¡.Ò"7°CÐ!8Ð9Ô:ä	‡J�JÐ Ô!Ü	‡J�JŒy˜Ÿ™Ó)Ô*Ü	‡J�JÐ Ô!Ü	‡J�JŒy˜×)Ñ)Ó*Ô+Ü	‡J�JÐ Ô!Ø€~Ü�
‰
ÐLÕMä�
‰
Ð& v§¡×'<Ñ'<Ð&=Ð>Ô?Ü�
‰
Ð& v§¡Ð&7Ð8Ô9Ü�
‰
Ð&¤y°×1AÑ1AÓ'BÐ&CÐDÔEÜ�
‰
Ð& v§}¡}Ò';¸Ð&<Ð=Ô>Ü	‡J�Jð	ôð
 ‡~�~œ×/Ñ/Ò/Ü�
‰
ðNõ	
ð 0r!   c                óp  — t        ||| ¬«      }|j                  |«      }|€0t        j                  d|›d�d¬«       t        j                  d«      ‚|j
                  t        j                  k7  r³t        j                  d|› d|j
                  j                  › d	| › d
�d¬«       t        |t        j                  ||j                  |dd| › �|j                  j                  |j                  xs dd|j
                  j                  › �¬«
       t        j                  d«      ‚| dk(  r$|j!                  |||«      }	t        j"                  }
n#|j%                  |||«      }	t        j&                  }
|	€…t        j                  d|› d| › d�d¬«       t        |t        j                  ||j                  |dd| › �|j                  j                  |j                  xs dd¬«
       t        j                  d«      ‚t        ||
||	j                  || › d�d| › �|	j                  j                  |	j                  xs d|	j(                  |dœ¬«
       t        j                  d|› d| › d|› dt+        t-        j,                  «       «      › d�	«       | dk(  rt        j                  d«       yt        j                  d«       y)z÷Shared implementation of the ``approve`` and ``deny`` commands.

    Raises:
        typer.Exit: With code 1 when the request is missing and code 2 when it was
            already decided or changed state concurrently. Neither case is silent.
    r•   Nr£   z" was not found in the local store.TrX   r¤   z is z, not pending; z was not applied.Únot_appliedz
approvals re   zrequest is )rl   rm   rn   ro   rk   rf   rg   rh   r0   Úapprovez could not be zRd; its state changed concurrently. Run 'approvals show' to see the current status.zconcurrent state changeÚd)r{   rƒ   )rl   rm   rn   ro   rk   rf   rg   ri   ú zd by z at ú.z„A waiting execution blocked on this request will now proceed. The approval is not cryptographically bound to the code that will run.zEA waiting execution blocked on this request will raise SecurityError.)rd   r¥   r^   r`   r¦   r|   r   r¨   r-   ru   r   ÚUSER_ACTIONrm   r‡   rf   rg   r«   ÚAPPROVAL_GRANTEDÚdenyÚAPPROVAL_DENIEDr{   r.   r›   )r}   rw   rW   ra   rœ   r‚   rƒ   rr   ÚexistingÚupdatedrs   s              r"   Ú_deciderµ   \  s™  € ô ˜r¨HÀ*¸nÔM€GØ×"Ñ" :Ó.€HØÐÜ�
‰
Ð& z nÐ4VÐWÐ]aÕbÜ�j‰j˜‹mÐØ‡�œ.×0Ñ0Ò0Ü�
‰
Ø 
˜|¨4°·±×0EÑ0EÐ/FÀoØˆjÐ)ð+àõ	
ô
 	ØÜ×&Ñ&ØØ—?‘?Ø"Ø Ø   
Ð+Ø—^‘^×,Ñ,Ø×&Ñ&Ò,¨"Ø §¡× 5Ñ 5Ð6Ð7õ	
ô �j‰j˜‹mÐØ�9ÒØ—/‘/ *¨h¸Ó?ˆÜ#×4Ñ4‰
à—,‘,˜z¨8°VÓ<ˆÜ#×3Ñ3ˆ
Ø€ä�
‰
Ø 
˜|¨>¸(¸ð DLð Làõ	
ô
 	ØÜ×&Ñ&ØØ—?‘?Ø"Ø Ø   
Ð+Ø—^‘^×,Ñ,Ø×&Ñ&Ò,¨"Ø+õ	
ô �j‰j˜‹mÐÜØØØØ�~‰~ØØ�˜1ˆ~Ø˜X˜JÐ'Ø—‘×'Ñ'Ø×!Ñ!Ò' RØ '× 2Ñ 2¸fÑEõô 
‡J�JØ
˜J˜< q¨¨
°%¸°zð BÜœŸ	™	›Ó$Ð% Qð	(ôð �9ÒÜ�
‰
ðHõ	
ô
 	�
‰
ÐZÕ[r!   r«   c           	     ó>   — t        d| ||||xs
 t        «       |«       y)zNApprove a pending request; exits non-zero if it is missing or already decided.r«   N©rµ   r#   ©rw   rW   ra   rœ   r‚   rƒ   s         r"   r«   r«   ¶  s*   € ô ØØØØ
ØØÒ'Ô%Ó'Øõr!   r±   c           	     ó>   — t        d| ||||xs
 t        «       |«       y)zKDeny a pending request; exits non-zero if it is missing or already decided.r±   Nr·   r¸   s         r"   r±   r±   Î  s"   € ô ˆF�J ¨"¨j¸(Ò:YÔFWÓFYÐ[aÕbr!   Úhistoryc                óÜ  — t        || | ¬«      }t        |j                  |«      d„ d¬«      }|rGt        j                  t        j                  |D �cg c]  }t        |«      ‘Œ c}dt        ¬«      «       y|s#t        j                  |€d«       yd	|› d
�«       yg d¢}|D �	cg c]w  }	|	j                  |	j                  |	j                  |	j                  xs d|	j                  j                  |	j                  t!        |	j"                  «      |	j$                  xs dg‘Œy }
}	t        j                  t'        ||
«      «       t        j                  dt)        |«      › d�«       yc c}w c c}	w )z/List recorded approval decisions, newest first.r•   c                ó   — | j                   S r;   )r�   )r    s    r"   ú<lambda>zhistory.<locals>.<lambda>è  s
   € À1Ç;Á;€ r!   T)ÚkeyÚreverser0   r–   NzNo approval decisions recorded.z No approval decisions for agent r®   )rw   rf   rm   rg   r}   r‚   r�   rƒ   r%   rH   z decision(s) recorded.)rd   ÚsortedÚlist_recordsr^   r`   r4   r5   r’   r6   rw   rf   rm   rg   r}   r-   r‚   r.   r�   rƒ   rU   rI   )rW   ra   rœ   rf   r�   rr   Úrecordsr    rO   rq   rP   s              r"   rº   rº   Þ  sL  € ô ˜r¨HÀ*¸nÔM€GÜ�W×)Ñ)¨(Ó3Ñ9NÐX\Ô]€GÙÜ�
‰
”4—:‘:¸7ÖC°aœ¨qÕ1ÒCÈAÔWZÔ[Ô\ØÙÜ�
‰
àÐð .ô	
ð
 	ð 4°H°:¸QÐ?ô	
ð
 	ò	€Gð* öð ð ×ÑØ�O‰OØ�M‰MØ�O‰OÒ"˜sØ�O‰O×!Ñ!Ø�O‰OÜ�f×&Ñ&Ó'Ø�M‰MÒ ˜Sò		
ð€Dð ô 
‡J�JŒ}˜W dÓ+Ô,Ü	‡J�J�”C˜“L�>Ð!7Ð8Õ9ùòC Dùò&s   ÁE$Â$A<E))Úreturnr6   )r-   zfloat | NonerÃ   r6   )r7   údict[str, Any]rÃ   r6   )rO   z	list[str]rP   zlist[list[str]]rÃ   r6   )NNT)ra   úPath | NonerW   rÅ   r[   ÚboolrÃ   r   )rr   r   rs   r   rl   r6   rm   r6   rn   r6   ro   r6   rk   r6   rf   r6   rg   r6   rh   r6   ri   zdict[str, Any] | NonerÃ   ÚNone)rŒ   r   r�   ÚfloatrÃ   rÄ   )rq   r   rÃ   rÄ   )NNFF)
rW   úGAnnotated[Path | None, typer.Option('--data-dir', help=_DATA_DIR_HELP)]ra   ú;Annotated[Path | None, typer.Option('--db', help=_DB_HELP)]rœ   úDAnnotated[bool, typer.Option('--no-persist', help=_NO_PERSIST_HELP)]r�   úCAnnotated[bool, typer.Option('--json', help='Print a JSON array.')]rÃ   rÇ   )rw   ú;Annotated[str, typer.Argument(help='Approval request id.')]rW   rÉ   ra   rÊ   rœ   rË   r�   zDAnnotated[bool, typer.Option('--json', help='Print a JSON object.')]rÃ   rÇ   )r}   r6   rw   r6   rW   rÅ   ra   rÅ   rœ   rÆ   r‚   r6   rƒ   r6   rÃ   rÇ   )NNFre   re   )rw   rÍ   rW   rÉ   ra   rÊ   rœ   rË   r‚   úUAnnotated[str, typer.Option('--reviewer', help='Identity recorded as the reviewer.')]rƒ   zMAnnotated[str, typer.Option('--reason', help='Why the request is approved.')]rÃ   rÇ   )rw   rÍ   rW   rÉ   ra   rÊ   rœ   rË   r‚   rÎ   rƒ   zKAnnotated[str, typer.Option('--reason', help='Why the request is denied.')]rÃ   rÇ   )NNFNF)rW   rÉ   ra   rÊ   rœ   rË   rf   zMAnnotated[str | None, typer.Option('--agent-id', help='Filter by agent id.')]r�   rÌ   rÃ   rÇ   )/Ú__doc__Ú
__future__r   r   r4   r   r›   r   r   Úpathlibr   Útypingr   r   r^   Ú cyberbrain26.product.local_storer	   r
   Ú$cyberbrain26.security_plane.approvalr   r   r   r   Ú!cyberbrain26.security_plane.auditr   r   Ú__all__ÚTyperr   Ú_DB_HELPÚ_DATA_DIR_HELPÚ_NO_PERSIST_HELPr#   r.   r8   rU   rd   ru   rŽ   r’   rk   r“   r¡   rµ   r«   r±   rº   r    r!   r"   ú<module>rÛ      sè  ðñ#õJ #ã Û Û 	Û ß "Ý ß !ã ç K÷ó ÷ GàÐ
€à�—‘Ø	Ø	OØô€ð E€ØE€ØXÐ óTófóFó
ð Ø Øð&`Øð&`àð&`ð ð&`ð ó	&`ðd ØØØ&*ñ.Øð.àð.ð ð	.ð
 ð.ð ð.ð ð.ð ð.ð ð.ð ð.ð ð.ð $ð.ð 
ó.óbó0ð ×Ñ�yÓ!àX\ØFJØW\ØSXð	-bØUð-bàCð-bð Uð-bð Qð	-bð
 
ò-bó "ð-bð` ×Ñ�vÓð Y]ØFJØW\ØTYð9
ØKð9
àUð9
ð 	Dð9
ð Uð	9
ð
 Rð9
ð 
ò9
ó ð9
ðxW\ØðW\àðW\ð ðW\ð 	ð	W\ð
 ðW\ð ðW\ð ðW\ð 
óW\ðt ×Ñ�yÓ!ð Y]ØFJØW\ð 	Ø\^ðØKðàUðð 	Dðð Uð	ð
ðð Zðð 
òó "ðð. ×Ñ�vÓð Y]ØFJØW\ð 	ØZ\ðcØKðcàUðcð 	Dðcð Uð	cð
ðcð Xðcð 
òcó ðcð ×Ñ�yÓ!àX\ØFJØW\Ø^bØSXð,:ØUð,:àCð,:ð Uð,:ð \ð	,:ð
 Qð,:ð 
ò,:ó "ñ,:r!   