Ë
    ÛJêjÄL  ã                  ó  — U d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
mZmZmZ ddlmZm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mZ ddlmZ ddlm Z m!Z!m"Z" dZ#de$d<   dZ%de$d<   dd„Z& G d„ de"«      Z' G d„ d«      Z(g d¢Z)y)z7Authorized entry point for invoking execution backends.é    )ÚannotationsN)ÚAny)ÚExecutionProvider)Ú!DEFAULT_EXECUTION_TIMEOUT_SECONDSÚExecutionAuthorizationÚcurrent_execution_authorizationÚexecution_payload_digest)ÚApprovalManagerÚApprovalStatus)ÚAuditEventTypeÚAuditLog)ÚDataClassificationÚ
EgressGateÚEgressPolicyÚEgressRequest)ÚEgressPermissionGateÚLocalClassificationGateÚRemoteClassificationGate)ÚAgentIdentity)ÚPermissionDecisionÚPermissionGatewayÚSecurityErrorÚengagement_profileÚstrÚENGAGEMENT_PROFILE_KEYÚnetwork_allowedÚNETWORK_ALLOWED_KEYc                ó¸   — t        | dd«      }t        |t        «      sy|j                  t        «      }t        |t        «      sy|j                  t
        «      du S )a*  Report whether this identity's engagement profile authorised egress.

    The grant has to be *explicit*, so the check is a strict identity test
    against the singleton ``True``: the string ``"true"``, the integer ``1``, a
    truthy value of any other type, and a missing profile all resolve to
    ``False``. An identity that carries no engagement profile therefore behaves
    exactly as it did before the profile existed - the network namespace stays
    unshared - and no other role changes behaviour by accident.

    This is the only place the sandbox is allowed to be told that sharing the
    host's network namespace is authorised, and it says nothing about whether
    the code itself is trusted; see
    :class:`~cyberbrain26.execution_plane.bubblewrap_provider.BubblewrapExecutionProvider`.
    ÚmetadataNFT)ÚgetattrÚ
isinstanceÚdictÚgetr   r   )Úidentityr   Úprofiles      úQ/home/oem/CyberBrain26-unified/src/cyberbrain26/execution_plane/secure_gateway.pyÚ!engagement_profile_allows_networkr'   +   sP   € ô �x ¨TÓ2€HÜ�h¤Ô%ØØ�l‰lÔ1Ó2€GÜ�gœtÔ$ØØ�;‰;Ô*Ó+¨tÐ3Ð3ó    c                  ó   — e Zd ZdZy)ÚExecutionRefuseda   Raised when a request is refused before any code reached a provider.

    This type is the structural marker for "refused, nothing ran". Only the
    three gates standing in front of ``provider.execute`` raise it: identity
    validation, permission denial, and a missing/denied/expired approval. Every
    failure at or after the provider call raises a plain ``SecurityError`` (or
    propagates the provider's own exception), because there the sandbox may
    already have executed the code and produced side effects.

    Consumers must tell the two cases apart structurally, by type, never by
    matching the error message: only a refusal is safe to re-dispatch.
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r(   r&   r*   r*   C   s   „ òr(   r*   c                  óø   — e Zd ZdZdddddœ	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zeddœ	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd	„Z	 	 	 	 	 	 	 	 	 	 dd
„Z	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	ddœ	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z
y)ÚAuthorizedExecutionServicea�  Enforce identity, permission, approval, and audit before execution.

    The underlying execution provider is a sandbox backend, not an
    authorization boundary. Application and agent code should invoke this
    service so unauthenticated calls cannot reach the backend.

    This is the inner of the two gates in front of the provider, and it is not
    a formality: scope, policy, approval and audit all run again here, on the
    values this call actually carries. What it no longer does is raise a *second*
    independent approval request for a decision a human already made. When the
    dispatcher's chain has already obtained an approval for the same agent, the
    same canonical action and a byte-identical execution payload, the grant it
    minted is re-verified here (identity, action, digest, and that the approval
    record is still ``approved``) and recorded as a reuse instead of a new
    request. Anything else - no grant, a different action, a changed payload, a
    different identity, an approval that is no longer approved - leaves this
    service on its own full gate, and a stale grant is refused outright rather
    than executed.
    Ng      >@gš™™™™™©?)Úapproval_managerÚ	audit_logÚapproval_timeout_secondsÚapproval_poll_intervalc               ó  — |dk  s|dk  rt        d«      ‚|| _        || _        || _        |xs |j                  xs
 t        «       | _        t        |dd«      }t        t        |g«      ¬«      }t        || j                  d¬«      | _
        | j                  | j                  _        | j                  | j                  j                  _        || _        || _        t        «       | _        t!        «       | _        t%        «       | _        y )Nr   z3approval timeout and poll interval must be positiveÚprovider_nameÚunknown)Úlocal_provider_idsT)Úpolicyr3   Úbase_decision)Ú
ValueErrorÚproviderÚpermission_gatewayr2   r3   r   r    r   Ú	frozensetr   Úegress_gateÚpolicy_enginer4   r5   r   Úremote_classification_gater   Úlocal_classification_gater   Úegress_permission_gate)	Úselfr=   r>   r2   r3   r4   r5   r7   Úegress_policys	            r&   Ú__init__z#AuthorizedExecutionService.__init__g   sæ   € ð $ qÒ(Ð,BÀaÒ,GÜÐRÓSÐSØ ˆŒØ"4ˆÔØ 0ˆÔØ"ÒPÐ&8×&BÑ&BÒPÄhÃjˆŒô
   ¨/¸9ÓEˆÜ$¼	À=À/Ó8RÔSˆÜ%¨]ÀdÇnÁnÐdhÔiˆÔØ,0¯N©Nˆ×ÑÔ)Ø:>¿.¹.ˆ×Ñ×-Ñ-Ô7Ø(@ˆÔ%Ø&<ˆÔ#ô +CÓ*DˆÔ'Ü)@Ó)BˆÔ&Ü&:Ó&<ˆÕ#r(   )Útimeout_secondsÚ	workspacec             ƒ  óL  K  — t        |t        «      st        d«      ‚|j                  «       j	                  «       }|dv rd}n|dv rd}nt        d|› �«      ‚| j                  j                  |||«      }	|	j                  t        j                  k(  rC| j                  t        j                  |||d|	j                  «       t        |	j                  «      ‚|	j                  t        j                  k(  r>| j!                  |||||||«      s'| j#                  |||||	j                  «      ƒ d{  –—†  t%        |«      }
| j&                  j(                  r| j&                  j(                  nd	}d
}t+        j,                  |j/                  d«      «      j1                  «       }t3        |r|j4                  nd	||t7        t8        j:                  h«      |¬«      }	 | j<                  j?                  |«       | j                  t        j                  |||d| j&                  j(                  |
¬«       	 | j&                  jC                  |||||
¬«      ƒ d{  –—† }|jM                  d«      dk(  xr |jM                  dd«       }| j                  t        jF                  ||||rdnd| j&                  j(                  «       |S 7 �ŒŽ# t@        $ r}t        d«      |‚d}~ww xY w7 Œ‹# tD        $ r=}| j                  t        jF                  |||dtI        |«      jJ                  «       ‚ d}~ww xY w­w)a  Authorize and run a Python or shell task through the sandbox.

        The approval gate below reuses the dispatcher's grant when - and only
        when - that grant provably covers this exact call; see
        :meth:`_grant_covers_this_execution`.
        z0a valid agent identity is required for execution>   ÚpyÚpythonÚexecute_python>   ÚshÚshellÚexecute_shellz unsupported execution language: ÚdeniedNr8   zhttp://localhostzutf-8)Úagent_idÚprovider_idÚpayload_sha256ÚclassificationsÚdestinationzegress denied by policyÚstarted©Únetwork)rH   rI   Úallow_networkÚfailedÚreturn_coder   Ú	timed_outFÚ	succeeded)'r!   r   r*   ÚstripÚlowerr<   r>   ÚevaluateÚdecisionr   ÚDENYÚ_auditr   ÚTOOL_CALLEDÚreasonÚREQUIRE_APPROVALÚ_grant_covers_this_executionÚ_wait_for_approvalr'   r=   r7   ÚhashlibÚsha256ÚencodeÚ	hexdigestr   rR   r?   r   ÚPUBLICr@   Ú	authorizer   ÚexecuteÚ	ExceptionÚTOOL_RESULTÚtyper+   r#   )rE   r$   ÚcodeÚlanguageÚtask_idrH   rI   ÚlangÚactionrb   rZ   r7   ÚdestrT   ÚrequestÚerrÚresultÚexcÚ
successfuls                      r&   rp   z"AuthorizedExecutionService.executeˆ   s  è ø€ ô  ˜(¤MÔ2ä"Ð#UÓVÐVØ�~‰~Ó×%Ñ%Ó'ˆØÐ#Ñ#Ø%‰FØ�_Ñ$Ø$‰Fô Ð?À¸zÐJÓKÐKà×*Ñ*×3Ñ3°H¸fÀiÓPˆØ×ÑÔ 2× 7Ñ 7Ò7Ø�K‰KÜ×*Ñ*ØØØØØ—‘ôô # 8§?¡?Ó3Ð3Ø×ÑÔ 2× CÑ CÒCØ×4Ñ4Ø˜& $¨¨i¸È'ôð ×-Ñ-Ø˜f i°¸(¿/¹/ó÷ ð ô :¸(ÓCˆð
 8<·}±}×7RÒ7R˜Ÿ™×3Ò3ÐXaˆØ!ˆÜ Ÿ™¨¯©°GÓ(<Ó=×GÑGÓIˆÜÙ*2�X×&Ò&¸	Ø%Ø)ô
 &Ô'9×'@Ñ'@Ð&AÓBØô

ˆð	GØ×Ñ×&Ñ& wÔ/ð 	�‰Ü×&Ñ&ØØØØØ�M‰M×'Ñ'Ø!ð 	ô 	
ð	ØŸ=™=×0Ñ0ØØØ /Ø#Ø+ð 1ó ÷ ˆFð$ —Z‘Z Ó.°!Ñ3ÒZ¸F¿J¹JÀ{ÐTYÓ<ZÐ8Zˆ
Ø�‰Ü×&Ñ&ØØØÙ%‰K¨8Ø�M‰M×'Ñ'ô	
ð ˆðIúô8 ò 	Gä"Ð#<Ó=À3ÐFûð	Gúðùô ò 		Ø�K‰KÜ×*Ñ*ØØØØÜ�S“	×"Ñ"ôð ûð		üsn   ‚D)L$Ä+J9Ä,B'L$ÇJ< Ç/:L$È*#K ÉKÉK ÉA(L$Ê<	KËKËKËL$ËK Ë	L!Ë$8LÌL!Ì!L$c                ó  — t        «       }|�|j                  €y|j                  |k7  ryt        ||||¬«      }	|j	                  |j
                  ||	¬«      sXd|j                  dd › d|	dd › d�}
| j                  t        j                  |||d	|
«       t        d
|j                  › d|
› �«      ‚| j                  ||||«      sy| j                  t        j                  |||dd|j                  › d|j                  › d|	dd › d�«       y)aA  Report whether a human already approved this exact execution.

        The caller has *not* skipped any gate: it has already re-run the scope
        check and the policy engine for this identity, action and workspace, and
        it arrives here only because those gates still say "a human has to
        approve". This method answers one question - did one - by re-verifying
        the dispatcher's grant against what is about to be executed.

        The grant is honoured only when all of the following hold:

        * it names the same identity, so one agent's approval is not spendable by
          another;
        * it was minted for the same canonical action, so an approval for action A
          can never authorize action B - a grant minted for a different action is
          ignored here, and the caller then raises its own full approval request;
        * it was minted for a payload whose digest equals the digest of the code,
          language, workspace and timeout in this call, so content that changed
          after the operator approved it is refused instead of run;
        * the approval record it names still reads ``approved``, checked live
          rather than trusted from the grant.

        When the action matches but the payload does not, the caller approved
        code that is no longer the code about to run. That is a tampering signal
        inside a single dispatch rather than a normal condition, so it is
        refused here and audited, instead of quietly raising a fresh request
        that would make the change invisible in the audit trail.
        NF)rt   ru   rI   rH   )rR   rx   Úpayload_digestz[the approval covers a different payload than the one about to be executed (approved digest é   z, executed digest ú)Úpayload_changed_after_approvalú	Approval z  does not cover this execution: Úreusedú	approval z
 for task z# covers this exact payload (digest T)r   Úapproval_request_idrx   r	   ÚcoversrR   r€   rd   r   ÚAPPROVAL_DENIEDr*   Ú_grant_approval_still_approvedÚAPPROVAL_GRANTEDrv   )rE   r$   rx   rt   ru   rI   rH   rv   ÚgrantÚdigestrf   s              r&   rh   z7AuthorizedExecutionService._grant_covers_this_executionú   sU  € ôJ 0Ó1ˆØˆ=˜E×5Ñ5Ð=ð Ø�<‰<˜6Ò!ØÜ)ØØØØ+ô	
ˆð �|‰| X×%6Ñ%6¸vÐV\ˆ|Ô]ð-Ø-2×-AÑ-AÀ#À2Ð-FÐ,Gð H#Ø#)¨#¨2 ; -¨qð2ð ð
 �K‰KÜ×.Ñ.ØØØØ0Øôô #Ø˜E×5Ñ5Ð6Ð6VÐW]ÐV^Ð_óð ð ×2Ñ2°5¸'À8ÈVÔTØØ�‰Ü×+Ñ+ØØØØØ˜×1Ñ1Ð2°*¸U¿]¹]¸Oð L*Ø*0°°"¨+¨°að9ô	
ð r(   c                ó8  — | j                   }|€y|j                  |j                  xs d«      }|�|j                  t        j
                  k(  ry| j                  t        j                  |||dd|j                  › d|�|j                  j                  nd› �«       y)aÑ  Re-read the approval record a grant names, and report whether it holds.

        The grant is a statement made at dispatch time; this is the check made
        now. A request that has since been denied, cancelled, expired or removed
        is not honoured, and when the approval cannot be read at all the grant is
        not honoured either - the caller then raises its own request, which is
        strictly stronger than trusting an unverifiable claim.
        FÚ TÚgrant_not_approvedr†   z is Ú
unreadable)
r2   Úget_requestr‡   Ústatusr   ÚAPPROVEDrd   r   r‰   Úvalue)rE   rŒ   rv   r$   rx   ÚmanagerÚcurrents          r&   rŠ   z9AuthorizedExecutionService._grant_approval_still_approvedJ  sŸ   € ð ×'Ñ'ˆØˆ?ØØ×%Ñ% e×&?Ñ&?Ò&EÀ2ÓFˆØÐ 7§>¡>´^×5LÑ5LÒ#LØØ�‰Ü×*Ñ*ØØØØ Ø˜×1Ñ1Ð2°$Ø'.Ð':ˆw�~‰~×#Ò#ÀÐMðOô	
ð r(   c           	   ƒ  óø  K  — | j                   }|€3| j                  t        j                  |||dd«       t	        d|› d�«      ‚|j                  |||d|i|¬«      }| j                  t        j                  |||d|j                  «       t        | j                  |j                  «      }t        j                  «       j                  «       |z   }		 t        j                  «       j                  «       |	k  rã|j                  |j                  «      }
|
€nÅ|
j                  t         j"                  k(  r3| j                  t        j$                  |||d|
j&                  xs d	«       y |
j                  t         j(                  k7  rnWt        j*                  t        | j,                  |«      «      ƒ d {  –—†  t        j                  «       j                  «       |	k  rŒã|j3                  «        |j                  |j                  «      }
|
�8|
j                  t         j(                  k(  r|j1                  |j                  «       |
�|
j                  j4                  nd}| j                  t        j                  |||||j                  «       t	        d|› d|› d�«      ‚7 Œé# t        j.                  $ rK |j1                  |j                  «       | j                  t        j                  |||d
|j                  «       ‚ w xY w­w)NÚunavailablez"approval manager is not configuredz!Approval unavailable for action 'ú'rv   )Úcontextrf   ÚpendingÚapprovedzapproval grantedÚ	cancelledÚmissingr„   z for action ')r2   rd   r   r‰   r*   Úcreate_requestÚAPPROVAL_REQUIREDÚ
request_idÚminr4   rH   ÚasyncioÚget_running_loopÚtimer’   r“   r   r”   r‹   ÚreviewerÚPENDINGÚsleepr5   ÚCancelledErrorÚcancelÚcheck_expiredr•   )rE   r$   rx   Úresourcerv   rf   r–   rz   Úwait_secondsÚdeadliner—   r“   s               r&   ri   z-AuthorizedExecutionService._wait_for_approvalj  s¶  è ø€ ð ×'Ñ'ˆØˆ?Ø�K‰KÜ×.Ñ.ØØØØØ4ôô #Ð%FÀvÀhÈaÐ#PÓQÐQà×(Ñ(ØØØØ Ð(Øð )ó 
ˆð 	�‰Ü×,Ñ,ØØØØØ×Ñô	
ô ˜4×8Ñ8¸'×:QÑ:QÓRˆÜ×+Ñ+Ó-×2Ñ2Ó4°|ÑCˆð	Ü×*Ñ*Ó,×1Ñ1Ó3°hÒ>Ø!×-Ñ-¨g×.@Ñ.@ÓA�Ø�?ØØ—>‘>¤^×%<Ñ%<Ò<Ø—K‘KÜ&×7Ñ7ØØ ØØ"Ø×(Ñ(Ò>Ð,>ôð Ø—>‘>¤^×%;Ñ%;Ò;ØÜ—m‘m¤C¨×(CÑ(CÀ\Ó$RÓS×SÐSô! ×*Ñ*Ó,×1Ñ1Ó3°hÓ>ð: 	×ÑÔØ×%Ñ% g×&8Ñ&8Ó9ˆØÐ 7§>¡>´^×5KÑ5KÒ#KØ�N‰N˜7×-Ñ-Ô.Ø)0Ð)<�—‘×%Ò%À)ˆØ�‰Ü×*Ñ*ØØØØØ×Ñô	
ô  ¨6¨(°-À¸xÀqÐIÓJÐJð5 TùÜ×%Ñ%ò 
	Ø�N‰N˜7×-Ñ-Ô.Ø�K‰KÜ×.Ñ.ØØØØØ×"Ñ"ôð ð
	üs@   ‚CK:ÃBJ Å"K:Å#A
J Æ-JÆ.)J ÇB?K:ÊJ ÊAK7Ë7K:rX   c          	     óÊ   — | j                   �W|| j                  j                  dœ}|�||d<   | j                   j                  ||j                  |j                  ||||¬«       y y )N)Údetailr=   rY   )ÚactorrR   rv   rx   r|   r   )r3   r=   r7   ÚrecordrR   )	rE   Ú
event_typerv   r$   rx   r|   r±   rY   r   s	            r&   rd   z!AuthorizedExecutionService._audit¼  st   € ð �>‰>Ð%à Ø ŸM™M×7Ñ7ñ(ˆHð Ð"Ø&-�˜Ñ#Ø�N‰N×!Ñ!ØØ×'Ñ'Ø!×*Ñ*ØØØØ!ð "õ ð &r(   )r=   r   r>   r   r2   zApprovalManager | Noner3   zAuditLog | Noner4   Úfloatr5   rµ   ÚreturnÚNone)r$   r   rt   r   ru   r   rv   r   rH   ÚintrI   ú
str | Noner¶   zdict[str, Any])r$   r   rx   r   rt   r   ru   r   rI   r¹   rH   r¸   rv   r   r¶   Úbool)
rŒ   r   rv   r   r$   r   rx   r   r¶   rº   )r$   r   rx   r   r­   r¹   rv   r   rf   r   r¶   r·   )r´   r   rv   r   r$   r   rx   r   r|   r   r±   r   rY   zbool | Noner¶   r·   )r+   r,   r-   r.   rG   r   rp   rh   rŠ   ri   rd   r/   r(   r&   r1   r1   R   só  „ ñð2 48Ø%)Ø*.Ø(,ñ=à#ð=ð .ð=ð
 1ð=ð #ð=ð #(ð=ð !&ð=ð 
ó=ðP  AØ $ñpàðpð ðpð ð	pð ðpð ðpð ðpð 
ópðdNàðNð ðNð ð	Nð
 ðNð ðNð ðNð ðNð 
óNð`à%ðð ðð  ð	ð
 ðð 
óð@PKàðPKð ðPKð ð	PKð
 ðPKð ðPKð 
óPKðv  $ñà"ðð ðð  ð	ð
 ðð ðð ðð ðð 
ôr(   r1   )r   r   r1   r*   r'   )r$   r   r¶   rº   )*r.   Ú
__future__r   r¤   rj   Útypingr   Ú/cyberbrain26.extension_layer.execution_providerr   Ú#cyberbrain26.security_plane.actionsr   r   r   r	   Ú$cyberbrain26.security_plane.approvalr
   r   Ú!cyberbrain26.security_plane.auditr   r   Ú"cyberbrain26.security_plane.egressr   r   r   r   Ú,cyberbrain26.security_plane.extension_pointsr   r   r   Ú$cyberbrain26.security_plane.identityr   Ú&cyberbrain26.security_plane.permissionr   r   r   r   Ú__annotations__r   r'   r*   r1   Ú__all__r/   r(   r&   ú<module>rÇ      sŠ   ðÚ =å "ã Û Ý å M÷ó ÷ Qß F÷ó ÷ñ õ
 ?÷ñ ð 3Ð ˜Ó 2Ø,Ð �SÓ ,ó4ô0�}ô ÷Gñ GòT�r(   