
     jVC                    V   U d Z ddlmZ ddlmZmZ ddlmZmZmZ dZ	de
d<   d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h      Zde
d<   dZde
d<   dZde
d<   dZde
d<   dZde
d<    G d d e      Zd*d!Zd+d"Zd,d#Zd-d$Zd.d%Zd/d&Zd0d'Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 d1d(Zy))2u  anu_v3.pre_authorized_action_gate — PRE_AUTHORIZED_CLEAN_REPLACEMENT_PR_OPEN_GATE (task-2553+4).

회장 §명시 (2026-05-16) 1:1 박제:
  목표 — GO-ready packet 이 회장 pre-authorization 범위 안에 있는지 **코드로**
  판정하고, 조건 충족 시 clean replacement PR open 까지 자동 허용하는
  decision JSON 을 생성한다. 회장은 micro decision / 문안 전달자가 아니다.

본 모듈 한정 책임 (fail-closed, 순수 결정 함수):
  - GO-ready packet 또는 pre_authorized_action_contract.json 입력 정규화
  - action_type 판정
  - clean_replacement_pr_open 자동 허용 조건 검증
  - forbidden action 검증
  - expected_files exact match 검증
  - Critical 7 / Codex verdict / credential / real write / scope expansion gate
  - callback normal+fallback required 검증
  - source PR 원본 보존 / same-branch push 금지 검증
  - decision JSON 출력 (ALLOW_PRE_AUTHORIZED_CLEAN_REPLACEMENT_PR_OPEN | HOLD_FOR_CHAIR)

운영 원칙 (회장 verbatim):
  - 이 게이트는 직접 GitHub write 를 수행하지 않는다.
  - PR open executor 앞단에서 decision JSON 을 생성하는 필수 gate 다.
  - executor 는 decision == ALLOW_PRE_AUTHORIZED_CLEAN_REPLACEMENT_PR_OPEN
    일 때만 clean replacement PR open 을 진행한다.
  - decision == HOLD_FOR_CHAIR 이면 회장 보고한다.

fail-closed: 모든 조건이 명시적으로 충족될 때만 ALLOW. 누락/모호/오류 = HOLD.
one-way isolation: anu_v3/ 외부 import 금지. GitHub API 0, token 0, 파일 쓰기 0.
    )annotations)datetimetimezone)AnyFinalMappingz(anu_v3.pre_authorized_action_contract.v1z
Final[str]CONTRACT_SCHEMA_NAMEz(anu_v3.pre_authorized_action_decision.v1DECISION_SCHEMA_NAMEz!anu_v3.pre_authorized_action_gateGATE_MODULEclean_replacement_pr_open ACTION_CLEAN_REPLACEMENT_PR_OPEN.ALLOW_PRE_AUTHORIZED_CLEAN_REPLACEMENT_PR_OPENDECISION_ALLOWHOLD_FOR_CHAIRDECISION_HOLDPASSPASS_WITH_RECOMMENDATIONSzFinal[frozenset[str]]CODEX_VERDICT_OK)branch_createcommitpushr   $result_report_evidence_marker_createnormal_completion_callback_firezFinal[tuple[str, ...]]AUTO_ALLOWED_ACTIONS)mergesource_pr_original_changesame_branch_push"expected_files_out_of_scope_changecredential_changeowner_pat_manipulationactual_api_call&real_write_or_limited_real_write_entryscope_expansiondev_status_auto_changeauto_closeout_confirmALWAYS_FORBIDDEN)schematask_idaction_type	source_prr   
fresh_baseexpected_fileseffective_diff_filesforbidden_paths_touchedeffective_diff_contamination
critical_7credential_change_requiredowner_pat_touch_requiredactual_api_call_requiredreal_write_required!limited_real_write_entry_requiredr#   codex_verdictcallbackmerge_requiredauto_closeoutdev_status_change_REQUIRED_KEYS)r   r+   r/   r0   r1   r2   r3   r4   r5   r#   r8   r9   r:   
_BOOL_KEYSc                  $     e Zd ZdZd fdZ xZS )ContractInvalidErroru   contract schema 검증 실패. fail-closed: 호출자는 절대 ALLOW 로 진행 불가.

    실패 사유 코드는 ``self.code`` 에 noted ("schema_validation_fail" 계열).
    c                L    t         |   d| d|        || _        || _        y )N[z] )super__init__codemessage)selfrC   rD   	__class__s      8/home/jay/workspace/anu_v3/pre_authorized_action_gate.pyrB   zContractInvalidError.__init__}   s+    1TF"WI./	    )rC   strrD   rI   returnNone)__name__
__module____qualname____doc__rB   __classcell__)rF   s   @rG   r>   r>   w   s    
 rH   r>   c                "    t        | t              S N)
isinstancebool)values    rG   _is_boolrV      s    eT""rH   c                 f    t        j                  t        j                        j	                  d      S )Nz%Y-%m-%dT%H:%M:%SZ)r   nowr   utcstrftime rH   rG   _now_utcr\      s!    <<%../CDDrH   c                     t         t              sy j                  d      t        k(  ryt	         fddD              S )u   입력이 GO-ready packet 형태인지 판정 (contract schema 가 아니면 packet 으로 간주 시도).

    trust boundary: obj 는 외부 JSON 파싱 결과(신뢰 불가) — 런타임 타입 가드 유지.
    Fr'   c              3  &   K   | ]  }|v  
 y wrR   r[   ).0kobjs     rG   	<genexpr>z-looks_like_go_ready_packet.<locals>.<genexpr>   s     TAqCxTs   )packet	readinessmarker_kindgo_ready)rS   r   getr	   any)ra   s   `rG   looks_like_go_ready_packetri      s9    
 c7#
wwx00T!STTTrH   c           	        t        | t              st        dd      | j                  d      }t        |t              sai dt        dt        | j                  dd            ddd	d
didddddg ddgddgddddddddddddddddddddddddS t        |      }t        |d<   |j                  dt        | j                  dd                   |S )uu  GO-ready packet → canonical contract 로 정규화. trust boundary: packet 신뢰 불가.

    fail-closed: packet 에 명시적으로 안전(ALLOW 가능) 값이 박제돼 있지 않으면
    HOLD 를 유발하는 보수적 기본값으로 매핑한다. 임의 추론 금지 —
    pre_authorized_clean_replacement 블록이 packet 에 명시돼 있어야 한다.
    schema_validation_failu&   go-ready packet 이 Mapping 이 아님 pre_authorized_clean_replacementr'   r(    r)   "UNDECLARED_NO_PRE_AUTHORIZED_BLOCKr*   	preservedFr   Tr+   r,   r-   __undeclared__r.   r/   r0   r1   r2   r3   r4   r5   r#   MISSING)normalfallback)r6   r7   r8   r9   r:   )rS   r   r>   rg   r	   rI   dict
setdefault)rc   blkouts      rG   from_go_ready_packetrx      s    fg&"$4
 	
 **7
8Cc7#
*
s6::i45
 ?
 +u-	

 
 %
 b
 #%5$6
 &(8'9
 +D
 $
 )$
 '
 '
 "4
  0!
" t#
$ '#(e<"!!%-
 	
0 s)C(CMNN9c&**Y";<=JrH   c                   t        | t              st        dd      | j                  d      t        k7  r%t        dd| j                  d      dt              t
        D cg c]	  }|| vs| }}|rt        dd|       t        D ]9  }t        | |         rt        dd|dt        | |         j                   d	       t        | d
   t              r| d
   st        dd      t        | d   t              st        dd      t        | d   t              st        dd      dD ]*  }t        | |   t        t        f      rt        d| d       | d   }t        |t              rd|vrt        dd      t        |d         st        dd      | d   }t        |t              rd|vsd|vrt        dd      t        |d         rt        |d         st        dd      yc c}w )u   canonical contract schema 정적 검증. 실패 시 ContractInvalidError (→ HOLD).

    trust boundary: contract 는 외부 입력(신뢰 불가) — 런타임 타입 가드 유지.
    rk   u   contract 가 Mapping 이 아님r'   u   schema 불일치: z != u   필수 key 누락: zkey u    는 bool 이어야 함 (got )r(   u#   task_id 는 비어있지 않은 strr)   u   action_type 는 strr6   u   codex_verdict 는 str)r,   r-   r.   u	    는 listr*   ro   u   source_pr.preserved 필수u   source_pr.preserved 는 boolr7   rr   rs   u   callback.normal/fallback 필수u!   callback.normal/fallback 는 boolN)rS   r   r>   rg   r	   r;   r<   rV   typerL   rI   listtuple)contractr`   missinglist_keyspcbs         rG   validate_contractr      s\   
 h("$&G
 	
 ||H!55"$ h!7 :$?S>VW
 	
 )>QAX,=q>G>"$(;G9&E
 	
  $&(qe8hqk9J9S9S8TTUV  hy)3/x	7J"$&K
 	
 h}-s3"$&;
 	
 h/5"$&=
 	
 Z (8,tUm<&(XJi*@ 
 
+	Bb'"k&;"$&B
 	
 B{O$"$&D
 	
 
*	Bb'"hb&8Jb<P"$&G
 	
 BxL!"Z.)A"$&I
 	
 *BU ?s   "	G',G'c                X   g }| d   t         k7  r|j                  d       | d   du r|j                  d       | d   t        vr|j                  d       t        | d         r|j                  d	       t        | d
         }t        | d         }t	        t        |            t	        t        |            k7  s|s|j                  d       | d   du r|j                  d       | d   du r|j                  d       | d   du r|j                  d       | d   du r|j                  d       | d   du r|j                  d       | d   du r|j                  d       | d   d   dur|j                  d       | d   du r|j                  d       | d   du r|j                  d       | d    du r|j                  d!       | d"   }|d#   dus|d$   dur|j                  d%       | d&   dur|j                  d'       | d(   du r|j                  d)       | d*   du r|j                  d+       |S ),uW   HOLD 조건 평가 (회장 verbatim). 하나라도 적중 시 그 사유 목록 반환.r)   zaction_type unknownr0   Tz
Critical 7r6   zCodex FAIL / HIGH / CRITICALr.   zforbidden pathr,   r-   u   expected_files 밖 diff 필요r/   zeffective diff contaminationr1   u   credential 필요r2   u   OWNER PAT 필요r3   u   actual API 필요r4   u   real write 필요r5   u    limited real write 진입 필요r*   ro   u   source PR 원본 변경 필요r   u   same-branch push 필요r8   u   merge 필요r#   zscope expansionr7   rr   rs   u   callback contract 누락r+   u   fresh base 미충족r9   u   auto_closeout 금지 위반r:   u   dev_status_change 금지 위반)r   appendr   r|   sortedset)creasonsexpected	effectiver   s        rG   _hold_reasonsr     sI   G;;,-$|$!1156A'()'(A&'(HQ-./Ic(ms9~ 66h78	'(D056	%&$.*+	#$,)*	#$,*+	4'*+	,-59:~k"$.78	$01	d"~&	t#()	
:B	(|42j>#=12d"-.T!45	%89NrH   c           
        t               }t        |       r	 t        |       }nt        | t              rt        |       ni }	 t        |       t        |      }i d|d   t        k(  d	|d
   d   du d|d   du d|d   du dt!        t#        |d               t!        t#        |d               k(  xr t%        |d         dt'        |d          d|d   du d|d   du d|d   du d|d   du d|d    du d!|d"   du xr |d#   du d$|d%   du d&|d'   t(        v d(|d)   d*   du xr
 |d)   d+   du d,|d-   du d.|d/   du d0|d1   du i}|rt	        |d   |d   t        |||      S t+        |j-                               st	        |d   |d   t        d2g||      S t	        |d   |d   t.        d3g||      S # t        $ rV}t	        t        | t              rt        | j                  dd            nddt        d|j                  g|i       cY d}~S d}~ww xY w# t        $ r]}t	        t        |j                  dd            t        |j                  dd            t        d|j                  g|i       cY d}~S d}~ww xY w)4uM  입력(contract 또는 GO-ready packet) → decision JSON. trust boundary: 입력 신뢰 불가.

    fail-closed: schema 검증 실패 또는 HOLD 조건 1개 이상 → HOLD_FOR_CHAIR.
    모든 ALLOW 조건이 명시적으로 충족될 때만 ALLOW.
    이 함수는 부작용 0 (GitHub write/파일 쓰기/네트워크 0).
    r(   rm   unknownzschema validation failr(   r)   decisionr   tschecksNr)   (action_type_is_clean_replacement_pr_opensource_pr_preservedr*   ro   Tsame_branch_push_falser   Ffresh_base_truer+   expected_files_exact_matchr,   r-   forbidden_path_zeror.   !effective_diff_contamination_zeror/   critical_7_falser0   credential_falser1   owner_pat_falser2   actual_api_falser3   real_write_falser4   r5   scope_expansion_falser#   codex_verdict_okr6   !callback_normal_and_fallback_truer7   rr   rs   merge_falser8   auto_closeout_falser9   dev_status_change_falser:   z&fail-closed: check matrix not all-truez5all ALLOW conditions satisfied (fail-closed verified))r\   ri   rx   r>   	_decisionrS   r   rI   rg   r   rC   rt   r   rD   r   r   r   r   rT   r|   r   allvaluesr   )	input_objr   r~   er   r   s         rG   evaluater   =  s    
B "),
	+I6H '1G&D4	?"

(# H%G2H]4K+5, 	x4[ATI 	!(+=">%"G	
 	8L1T9 	%f)*+'
 #h5678'9 '- *+, 	41J(K#LL 	,X*.
 .  	H\2e;!" 	H%ABeK#$ 	8$>?5H%& 	H%?@EI'( 	H%:;uD C89UB+, 	 *;!<!E-. 	H_59II/0 	,Xj-A(-K. .5Z ,456 	x 01U:78 	x8EA9: 	"8,?#@E#I;F@ Y' /"
 	
 v}}Y' /"=>
 	
 #]+HI c $ 	=G	SZ=[IMM)R89ac%&1166: 	   
Y34HLL	BC"-qyy9
 	

s=   F< H <	HAHHH	J'AI?9J?Jc                    t         t        | |||t        |      t        |      |t        k(  rt        t
              ng t        t              dddS )NTu   executor 는 decision == ALLOW_PRE_AUTHORIZED_CLEAN_REPLACEMENT_PR_OPEN 일 때만 clean replacement PR open 진행. HOLD_FOR_CHAIR 이면 회장 보고.)r'   gate_moduler(   ts_utcr)   r   r   r   auto_allowed_actionsalways_forbiddenno_github_write_performedexecutor_contract)r
   r   r|   rt   r   r   r&   r   s         rG   r   r     sV     '""=v,~% !%%9 : !12%)` rH   N)rU   objectrJ   rT   )rJ   rI   )ra   r   rJ   rT   )rc   r   rJ   dict[str, Any])r~   r   rJ   rK   )r   Mapping[str, Any]rJ   	list[str])r   r   rJ   r   )r(   rI   r)   rI   r   rI   r   r   r   rI   r   r   rJ   r   ) rO   
__future__r   r   r   typingr   r   r   r	   __annotations__r
   r   r   r   r   	frozensetr   r   r&   r;   r<   
ValueErrorr>   rV   r\   ri   rx   r   r   r   r   r[   rH   rG   <module>r      s5  : # ' & & $N j M#M j M=Z =/J  * JM
 M,z , +4()+ ' 
0 , , (  *& 2&
" "	: 	#
E
U*Z;
|6reP  	
  	  rH   