Ë
    ÛJêj½A  ã                  óø   — 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 ddlmZ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 ddlmZ  ej:                  e«      Z G d„ d«      Z  G d„ d«      Z!ddgZ"y)a  In-memory AgentRegistry and TaskDispatcher implementations.

These are the default concrete implementations for Phase 4 modular
contracts. They are intentionally simple and testable; production
deployments may substitute database-backed or distributed variants.
é    )ÚannotationsN)Údefaultdict)ÚAny)ÚAgentÚAgentRegistry)Ú!DEFAULT_EXECUTION_TIMEOUT_SECONDSÚExecutionAuthorizationÚbound_execution_authorizationÚexecution_payload_digestÚnormalize_action)ÚApprovalManagerÚApprovalStatus)ÚAuditEventTypeÚAuditLog)ÚPermissionGatewayÚSecurityError)ÚPolicyEnginec                  óH   — e Zd ZdZd
d„Zdd„Zdd„Zdd„Zdd„Zdd„Z	dd„Z
y	)ÚInMemoryAgentRegistryz¼Default AgentRegistry backed by an in-memory dict.

    Supports register, unregister, lookup by ID, listing by role,
    and existence checks. Thread-safe via simple dict operations.
    c                ó    — i | _         i | _        y ©N)Ú_agentsÚ_roles©Úselfs    úP/home/oem/CyberBrain26-unified/src/cyberbrain26/extension_layer/registry_impl.pyÚ__init__zInMemoryAgentRegistry.__init__&   s   € Ø)+ˆŒØ,.ˆ�ó    c                ó$  — || j                   v rt        j                  d|«       || j                   |<   t        |dd «      }|rN|| j                  vrg | j                  |<   || j                  |   vr| j                  |   j                  |«       y y y )Nz<Re-registering agent '%s'; overwriting previous registrationÚrole)r   ÚloggerÚwarningÚgetattrr   Úappend)r   Úagent_idÚagentr    s       r   ÚregisterzInMemoryAgentRegistry.register*   s�   € Ø�t—|‘|Ñ#Ü�N‰NØNØôð "'ˆ�‰�XÑÜ�u˜f dÓ+ˆÙØ˜4Ÿ;™;Ñ&Ø$&�—‘˜DÑ!Ø˜tŸ{™{¨4Ñ0Ñ0Ø—‘˜DÑ!×(Ñ(¨Õ2ð 1ð r   c                ó¦   — || j                   vry| j                   |= | j                  j                  «       D ]  }||v sŒ|j                  |«       Œ y)NFT)r   r   ÚvaluesÚremove)r   r%   Ú	role_lists      r   Ú
unregisterz InMemoryAgentRegistry.unregister8   sT   € Ø˜4Ÿ<™<Ñ'ØØ�L‰L˜Ð"ØŸ™×+Ñ+Ó-ò 	+ˆIØ˜9Ò$Ø× Ñ  Õ*ð	+ð r   c                ó8   — | j                   j                  |«      S r   )r   Úget©r   r%   s     r   r.   zInMemoryAgentRegistry.getA   s   € Ø�|‰|×Ñ Ó)Ð)r   c                ó˜   — | j                   j                  |g «      D �cg c]   }|| j                  v sŒ| j                  |   ‘Œ" c}S c c}w r   )r   r.   r   )r   r    Úaids      r   Úlist_by_rolez"InMemoryAgentRegistry.list_by_roleD   s<   € Ø-1¯[©[¯_©_¸TÀ2Ó-FÖ^ cÈ#ÐQU×Q]ÑQ]ÒJ]�—‘˜SÓ!Ò^Ð^ùÒ^s
   ŸA³Ac                óH   — t        | j                  j                  «       «      S r   )Úlistr   Úitemsr   s    r   Úlist_allzInMemoryAgentRegistry.list_allG   s   € Ü�D—L‘L×&Ñ&Ó(Ó)Ð)r   c                ó   — || j                   v S r   )r   r/   s     r   ÚexistszInMemoryAgentRegistry.existsJ   s   € Ø˜4Ÿ<™<Ð'Ð'r   N)ÚreturnÚNone©r%   Ústrr&   r   r9   r:   )r%   r<   r9   Úbool)r%   r<   r9   zAgent | None)r    r<   r9   zlist[Agent])r9   zlist[tuple[str, Agent]])Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r'   r,   r.   r2   r6   r8   © r   r   r   r      s+   „ ñó/ó3óó*ó_ó*ô(r   r   c                  ó>  — e Zd ZdZ	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zdd„Zdd„Zej                  dœ	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z		 d	 	 	 	 	 	 	 	 	 	 	 dd„Z
	 d	 	 	 	 	 	 	 	 	 	 	 dd	„Z	 	 	 	 	 	 	 	 dd
„Zdd„Zdd„Z	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	 d	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zy)ÚInMemoryTaskDispatcheruÞ  Default TaskDispatcher backed by an AgentRegistry.

    Routes tasks to agents by ID or by role. Requires agents to be
    registered in the registry before dispatching.

    All dispatches pass through Identity â†’ Policy â†’ Permission â†’ Audit
    before agent.execute() is called.

    This dispatcher owns the *outer* authorization gate, and an approval it
    obtains is the one human decision for the step. When the authorized action
    is one the agent will really perform, the decision is handed to the agent as
    an ``ExecutionAuthorization`` bound to that single call, so the inner gate
    (the execution gateway standing in front of the sandbox) re-verifies it
    instead of asking the same operator the same question again. The grant is
    minted only when a human actually decided, and it is bound to a digest of the
    execution payload, so a step whose payload changes afterwards is refused at
    the inner gate rather than executed under the earlier approval.
    Nc                ór  — |dk  rt        d«      ‚|dk  rt        d«      ‚|xs
 t        «       | _        |xs
 t        «       | _        || _        | j
                  | j                  _        t        | j                  | j
                  ¬«      | _        || _	        || _
        || _        t        t        «      | _        y )Nr   z)approval_timeout_seconds must be positivez'approval_poll_interval must be positive)Ú	audit_log)Ú
ValueErrorr   Ú	_registryr   Ú_policy_engineÚ_audit_log_instancerF   r   Ú_permission_gatewayÚ_approval_managerÚ_approval_timeout_secondsÚ_approval_poll_intervalr   ÚintÚ_role_indices)r   ÚregistryÚpolicy_enginerF   Úapproval_managerÚapproval_timeout_secondsÚapproval_poll_intervals          r   r   zInMemoryTaskDispatcher.__init__b   s¬   € ð $ qÒ(ÜÐHÓIÐIØ! QÒ&ÜÐFÓGÐGØ!Ò<Ô%:Ó%<ˆŒØ+Ò=¬|«~ˆÔØ#,ˆÔ Ø(,×(@Ñ(@ˆ×ÑÔ%Ü#4Ø×Ñ¨4×+CÑ+Cô$
ˆÔ ð "2ˆÔØ)AˆÔ&Ø'=ˆÔ$Ü-8¼Ó-=ˆÕr   c                ó<   — | j                   j                  ||«       y r   )rH   r'   )r   r%   r&   s      r   Úregister_agentz%InMemoryTaskDispatcher.register_agent{   s   € Ø�‰×Ñ ¨%Õ0r   c                ó¼   — | j                   j                  |«      }|st        d|› �«      ‚| j                  |   }|dz   t	        |«      z  | j                  |<   ||   S )z8Select an agent by role using deterministic round-robin.zno agent with role: é   )rH   r2   ÚKeyErrorrP   Úlen)r   r    ÚagentsÚidxs       r   Ú_select_agent_by_rolez,InMemoryTaskDispatcher._select_agent_by_role~   sc   € à—‘×,Ñ,¨TÓ2ˆÙÜÐ1°$°Ð8Ó9Ð9Ø× Ñ  Ñ&ˆØ$'¨!¡G¬s°6«{Ñ#:ˆ×Ñ˜4Ñ Ø�c‰{Ðr   ©Ú
event_typec               ór   — | j                   �+| j                   j                  ||||||||dk7  r|nd¬«       yy)z=Record a dispatch-level security event with task correlation.NÚallowÚ )Úactorr%   Útask_idÚactionÚpolicy_decisionÚresultÚerror)rJ   Úrecord)r   re   r%   rf   ÚdecisionÚreasonr`   s          r   Ú_record_audit_eventz*InMemoryTaskDispatcher._record_audit_event‡   sO   € ð ×#Ñ#Ð/Ø×$Ñ$×+Ñ+ØØØ!ØØØ (ØØ (¨GÒ 3‘f¸ð ,õ 	ð 0r   c              ƒ  óJ   K  — | j                  |||||«      ƒ d{  –—†  y7 Œ­w)aÈ  Enforce identity, canonical policy, permission, approval, and audit.

        Returns nothing on purpose: the structural port the agents module uses
        for bus-delivered work declares this signature, and a bus task that clears
        the chain is not followed by a dispatched step whose payload a grant
        could describe. Callers that do own a step use :meth:`_authorize_step`,
        which also reports the approval that was obtained.
        N)Ú_authorize_step)r   re   Úregistered_agent_idr&   rf   Úresources         r   Ú
_authorizez!InMemoryTaskDispatcher._authorizež   s&   è ø€ ð  ×"Ñ" 7Ð,?ÀÈÐPXÓY×YÒYús   ‚#›!œ#c              ƒ  ó^  K  — t        |dd«      }|€"d}| j                  |||d|«       t        |«      ‚|j                  |k7  r2d|j                  ›d|›�}| j                  |||d|«       t        |«      ‚| j                  j                  |||«      }| j                  ||j                  ||j                  j                  |j                  ¬«       |j                  j                  dk(  ry|j                  j                  d	k7  rt        d
|j                  › d|› d�«      ‚| j                  €@d}| j                  ||j                  |d|t        j                  ¬«       t        d|› d�«      ‚| j                  j                  |||d|i|j                  ¬«      }	| j                  ||j                  |d|	j                  t        j                  ¬«       t        | j                   | j                  j"                  «      }
t%        j&                  «       j)                  «       |
z   }t%        j&                  «       j)                  «       |k  �r| j                  j+                  |	j                  «      }|€nÜ|j,                  t.        j0                  k(  rI| j                  ||j                  |d|j2                  xs dt        j4                  ¬«       |	j                  S |j,                  t.        j6                  k7  rnXt%        j8                  t        | j:                  |
«      «      ƒ d{  –—†  t%        j&                  «       j)                  «       |k  r�Œ| j                  j=                  «        | j                  j+                  |	j                  «      }|�B|j,                  t.        j6                  k(  r%| j                  j?                  |	j                  «       |�|j,                  j                  nd}| j                  ||j                  |dd|› �t        j                  ¬«       t        d|› d|› d�«      ‚7 �Œ­w)a”  Enforce the authorization chain and report the approval behind it.

        Returns:
            The id of the approval request a human approved, or ``None`` when the
            chain allowed the action outright. ``None`` deliberately means "no
            human decision exists here", so a caller can never turn a policy
            "allow" into an approval that authorises executable content.
        ÚidentityNzagent identity is requiredÚdenyzagent identity z does not match registered id )re   r%   rf   rk   rl   rb   Úrequire_approvalzAgent z denied for action 'ú'z"approval manager is not configuredr_   z!Approval unavailable for action 're   )Úcontextrl   ÚpendingÚapprovedzapproval grantedÚmissingz	approval z	Approval z for action ') r#   rm   r   r%   rK   Úevaluaterk   Úvaluerl   rL   r   ÚAPPROVAL_DENIEDÚcreate_requestÚ
request_idÚAPPROVAL_REQUIREDÚminrM   Útimeout_secondsÚasyncioÚget_running_loopÚtimeÚget_requestÚstatusr   ÚAPPROVEDÚreviewerÚAPPROVAL_GRANTEDÚPENDINGÚsleeprN   Úcheck_expiredÚcancel)r   re   rp   r&   rf   rq   rt   rl   rh   ÚrequestÚwait_secondsÚdeadlineÚcurrentrˆ   s                 r   ro   z&InMemoryTaskDispatcher._authorize_step°   s   è ø€ ô  ˜5 *¨dÓ3ˆØÐØ1ˆFØ×$Ñ$ WÐ.AÀ6È6ÐSYÔZÜ Ó'Ð'Ø×ÑÐ 3Ò3à! (×"3Ñ"3Ð!6ð 7!Ø!4Ð 7ð9ð ð ×$Ñ$ WÐ.AÀ6È6ÐSYÔZÜ Ó'Ð'ð ×)Ñ)×2Ñ2°8¸VÀXÓNˆØ× Ñ ØØ×&Ñ&ØØ—_‘_×*Ñ*Ø—=‘=ð 	!ô 	
ð �?‰?× Ñ  GÒ+ð Ø�?‰?× Ñ Ð$6Ò6Ü &¨×):Ñ):Ð(;Ð;OÐPVÈxÐWXÐ YÓZÐZØ×!Ñ!Ð)Ø9ˆFØ×$Ñ$ØØ×!Ñ!ØØØÜ)×9Ñ9ð %ô ô  Ð"CÀFÀ8È1Ð MÓNÐNà×(Ñ(×7Ñ7ØØØØ Ð(Ø—=‘=ð 8ó 
ˆð 	× Ñ ØØ×ÑØØØ×ÑÜ%×7Ñ7ð 	!ô 	
ô Ø×*Ñ*Ø×"Ñ"×2Ñ2ó
ˆô ×+Ñ+Ó-×2Ñ2Ó4°|ÑCˆÜ×&Ñ&Ó(×-Ñ-Ó/°(Ó:Ø×,Ñ,×8Ñ8¸×9KÑ9KÓLˆGØˆØØ�~‰~¤×!8Ñ!8Ò8Ø×(Ñ(ØØ×%Ñ%ØØØ×$Ñ$Ò:Ð(:Ü-×>Ñ>ð )ô ð ×)Ñ)Ð)Ø�~‰~¤×!7Ñ!7Ò7ØÜ—-‘-¤ D×$@Ñ$@À,Ó OÓP×PÐPô! ×&Ñ&Ó(×-Ñ-Ó/°(Ô:ð$ 	×Ñ×,Ñ,Ô.Ø×(Ñ(×4Ñ4°W×5GÑ5GÓHˆØÐ 7§>¡>´^×5KÑ5KÒ#KØ×"Ñ"×)Ñ)¨'×*<Ñ*<Ô=Ø)0Ð)<�—‘×%Ò%À)ˆØ× Ñ ØØ×ÑØØØ˜�xÐ Ü%×5Ñ5ð 	!ô 	
ô ˜i¨ x¨}¸V¸HÀAÐFÓGÐGð Qûs   ‚LP-ÌP*Ì)P-Í	C"P-c                ó‚   — t        |j                  d«      «      }|s"d}| j                  ||dd|«       t        |«      ‚|S )uK  Return the canonical action declared by the payload.

        Security rationale: the dispatcher used to invent ``"execute"`` when the
        payload carried no action. That name is in neither the scope map nor the
        sensitive-action set, so the step skipped the scope gate and was allowed
        by SAFE mode's non-sensitive rule â€” an action nobody had ever authorized.
        No default is inferred here: a payload without an explicit action states
        nothing to authorize and is refused, exactly as the CLI already refuses
        an action-less roadmap step.
        rf   zppayload declares no 'action', so there is nothing to authorize; it was refused and no default action is inferredrc   ru   )r   r.   rm   r   )r   re   r%   Úpayloadrf   rl   s         r   Ú_require_declared_actionz/InMemoryTaskDispatcher._require_declared_action   sM   € ô  " '§+¡+¨hÓ"7Ó8ˆÙðCð ð ×$Ñ$ W¨h¸¸FÀFÔKÜ Ó'Ð'Øˆr   c              ƒ  ó&  K  — | j                   j                  |«      }|€t        d|› �«      ‚| j                  |||«      }|j                  d«      }| j	                  |||||«      ƒ d {  –—† }| j                  ||||||«      ƒ d {  –—† S 7 Œ"7 Œ­w)Nzagent not found: rq   )rH   r.   rZ   r–   ro   Ú_execute_authorized)r   re   r%   r•   r&   rf   rq   Úapproval_ids           r   ÚdispatchzInMemoryTaskDispatcher.dispatch:  s¡   è ø€ Ø—‘×"Ñ" 8Ó,ˆØˆ=ÜÐ.¨x¨jÐ9Ó:Ð:à×.Ñ.¨w¸À'ÓJˆØ—;‘;˜zÓ*ˆØ ×0Ñ0°¸(ÀEÈ6ÐS[Ó\×\ˆØ×-Ñ-Ø�X˜u f¨g°{ó
÷ 
ð 	
ð ]øð
ús$   ‚A(BÁ*BÁ+BÂBÂ	BÂBc              ƒ  óN  ‡K  — | j                  |«      Št        ˆfd„| j                  j                  «       D «       d«      }| j	                  |||«      }|j                  d«      }| j                  ||‰||«      ƒ d {  –—† }| j                  ||‰|||«      ƒ d {  –—† S 7 Œ"7 Œ­w)Nc              3  ó2   •K  — | ]  \  }}|‰u sŒ|–— Œ y ­wr   rB   )Ú.0r1   Úar&   s      €r   ú	<genexpr>z:InMemoryTaskDispatcher.dispatch_to_role.<locals>.<genexpr>I  s   øè ø€ ÒG‘V�S˜!¸AÀºJŒSÑGùs   ƒ�Úunknownrq   )r^   ÚnextrH   r6   r–   r.   ro   r˜   )	r   re   r    r•   r%   rf   rq   r™   r&   s	           @r   Údispatch_to_rolez'InMemoryTaskDispatcher.dispatch_to_roleF  sª   øè ø€ Ø×*Ñ*¨4Ó0ˆÜÛG˜tŸ~™~×6Ñ6Ó8ÔGØó
ˆð
 ×.Ñ.¨w¸À'ÓJˆØ—;‘;˜zÓ*ˆØ ×0Ñ0°¸(ÀEÈ6ÐS[Ó\×\ˆØ×-Ñ-Ø�X˜u f¨g°{ó
÷ 
ð 	
ð ]øð
ús$   ƒA;B%Á>B!Á?B%ÂB#ÂB%Â#B%c                óä   — |€yt        ||||j                  d«      t        |j                  d«      |j                  d«      |j                  d«      |j                  dt        «      ¬«      |¬«      S )	a£  Return the grant to bind to this agent call, or ``None`` for none.

        The digest is taken over the payload exactly as the agent will read it:
        the same keys, and the same default timeout, that ``CoderAgent`` passes
        to the execution gateway. The two sides therefore agree on a well-behaved
        step and disagree on a tampered one, which is the property the inner gate
        relies on.
        Nrq   ÚcodeÚlanguageÚ	workspacerƒ   )r¤   r¥   r¦   rƒ   )r%   re   rf   rq   Úpayload_digestÚapproval_request_id)r	   r.   r   r   )r   re   r%   rf   r•   r™   s         r   Ú_execution_grantz'InMemoryTaskDispatcher._execution_grantT  st   € ð  Ðð Ü%ØØØØ—[‘[ Ó,Ü3Ø—[‘[ Ó(Ø Ÿ™ ZÓ0Ø!Ÿ+™+ kÓ2Ø '§¡Ø%Ô'Hó!ô	ð !,ô
ð 	
r   c           
   ƒ  ó  K  — | j                  |||ddt        j                  ¬«       	 t        | j	                  |||||«      «      5  |j                  |«      ƒ d {  –—† }d d d «       t        t        dd«      «      }	| j                  ||||	rdnd|	rdnd	t        j                  ¬«       |S 7 ŒQ# 1 sw Y   ŒPxY w# t        $ r>}| j                  |||dt        |«      j                  t        j                  ¬«       ‚ d }~ww xY w­w)
NÚstartedzagent execution startedr_   ÚfailedÚsuccessTÚ	succeededzagent execution completedzagent returned failure)rm   r   ÚAGENT_STARTEDr
   r©   ÚexecuteÚ	ExceptionÚtyper>   ÚAGENT_FINISHEDr=   r#   )
r   re   r%   r&   rf   r•   r™   rh   Úexcr®   s
             r   r˜   z*InMemoryTaskDispatcher._execute_authorizedy  s!  è ø€ ð 	× Ñ ØØØØØ%Ü%×3Ñ3ð 	!ô 	
ð	ô /Ø×%Ñ% g¨x¸ÀÈ+ÓVóñ 6ð  %Ÿ}™}¨WÓ5×5�÷6ô œ ¨°DÓ9Ó:ˆ	Ø× Ñ ØØØÙ$‰K¨(Ù+4Ñ'Ð:RÜ%×4Ñ4ð 	!ô 	
ð ˆð) 6ø÷6ð 6ûô ò 		Ø×$Ñ$ØØØØÜ�S“	×"Ñ"Ü)×8Ñ8ð %ô ð ûð		üsS   ‚&D©B< ÁB0ÁB.ÁB0Á!B< Á)ADÂ.B0Â0B9Â5B< Â<	DÃ9C>Ã>DÄD)NNNNg      >@gš™™™™™©?)rQ   zAgentRegistry | NonerR   zPolicyEngine | NonerF   zAuditLog | NonerS   zApprovalManager | NonerT   ÚfloatrU   rµ   r9   r:   r;   )r    r<   r9   r   )re   r<   r%   r<   rf   r<   rk   r<   rl   r<   r`   r   r9   r:   r   )re   r<   rp   r<   r&   r   rf   r<   rq   ú
str | Noner9   r:   )re   r<   rp   r<   r&   r   rf   r<   rq   r¶   r9   r¶   )re   r<   r%   r<   r•   údict[str, Any]r9   r<   )re   r<   r%   r<   r•   r·   r9   r   )re   r<   r    r<   r•   r·   r9   r   )re   r<   r%   r<   rf   r<   r•   r·   r™   r¶   r9   zExecutionAuthorization | None)re   r<   r%   r<   r&   r   rf   r<   r•   r·   r™   r¶   r9   r   )r>   r?   r@   rA   r   rW   r^   r   ÚPERMISSION_CHECKrm   rr   ro   r–   rš   r¢   r©   r˜   rB   r   r   rD   rD   N   s#  „ ñð* *.Ø-1Ø%)Ø37Ø*.Ø(,ð>à&ð>ð +ð>ð #ð	>ð
 1ð>ð #(ð>ð !&ð>ð 
ó>ó21óð" &4×%DÑ%Dñàðð ðð ð	ð
 ðð ðð #ðð 
óð:  $ðZàðZð !ðZð ð	Zð
 ðZð ðZð 
óZð0  $ðnHàðnHð !ðnHð ð	nHð
 ðnHð ðnHð 
ónHð`àðð ðð  ð	ð
 
óó4

ó
ð#
àð#
ð ð#
ð ð	#
ð
  ð#
ð  ð#
ð 
'ó#
ðX #'ð,àð,ð ð,ð ð	,ð
 ð,ð  ð,ð  ð,ð 
ô,r   rD   )#rA   Ú
__future__r   r„   ÚloggingÚcollectionsr   Útypingr   Ú+cyberbrain26.extension_layer.agent_registryr   r   Ú#cyberbrain26.security_plane.actionsr   r	   r
   r   r   Ú$cyberbrain26.security_plane.approvalr   r   Ú!cyberbrain26.security_plane.auditr   r   Ú&cyberbrain26.security_plane.permissionr   r   Ú"cyberbrain26.security_plane.policyr   Ú	getLoggerr>   r!   r   rD   Ú__all__rB   r   r   ú<module>rÅ      sn   ðñõ #ã Û Ý #Ý ç L÷õ ÷ Qß Fß SÝ ;à	ˆ×	Ñ	˜8Ó	$€÷,(ñ ,(÷^Wñ Wðt
 #Ð$<Ð
=�r   