
    nai1                        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m	Z	 ddl
mZ ddlZ ed      Zedz  dz  Zd	Z ed
      dz  dz  ZefddZddZddZddZ	 d	 	 	 ddZddZdddZd Zd Zd Zy) u  tests/taskctl/test_admin_override.py
Admin Override audit log + cap 검증 (task-2467)

벨레스(개발6팀 테스터) 작성. 스바로그의 구현 완료 전 선작성(TDD).

케이스:
    1. test_admin_override_records_audit_log — chairman email로 --admin → audit log 1줄
    2. test_admin_override_non_chairman_blocked — 다른 사용자 --admin → FAIL
    3. test_admin_override_hard_cap — 90일 내 5건 채운 후 6번째 → HARD_CAP_EXCEEDED
    )annotationsN)datetime	timedeltatimezone)Pathz-/home/jay/workspace/.worktrees/task-2467-dev6scriptsz
taskctl.pyzjonghyuk.jeon@gmail.commemoryorchestration-auditzadmin-override.jsonlc                x   i t         j                  }t        |       |d<   ||d<   ||d<   t        | dz        |d<   | dz  dz  j                  dd	       | dz  d
z  j                  dd	       | dz  dz  j                  dd	       | dz  dz  j                  dd	       | dz  }|j	                  d| d       |S )u3   격리된 workspace + git config user.email 설정.WORKSPACE_ROOTGIT_AUTHOR_EMAILGIT_COMMITTER_EMAILz
.gitconfigGIT_CONFIG_GLOBAL.tasksstateTparentsexist_okevidencer	   eventsr
   z[user]
	email = z
	name = Test Chairman
)osenvironstrmkdir
write_text)tmp_pathchairman_emailenv	gitconfigs       R/home/jay/workspace/.worktrees/task-2516-dev3/tests/taskctl/test_admin_override.py_isolated_workspacer!      s    
RZZ.CMC,C!/C"8l#:;C7"))$)F:%,,TD,I8#**4$*G0077t7T <'I
^,,FG J    c                Z    t        j                  dt        t              g| z   dd|d      S )Npython3T   )capture_outputtextr   timeout)
subprocessrunr   TASKCTL)argsr   s     r    _runr-   5   s-    >>	CL!D($C r"   c                    | dz  dz  | dz  }|j                         s
J d|        t        j                  |j                               S )Nr   r   .jsonu   state 파일 없음: )existsjsonloads	read_text)r   task_idps      r    _stater6   <   sM    8g%7)5(99A88:2.qc22:::akkm$$r"   c                   | dz  dz  | dz  }t        j                  |j                               }||d<   |j                  dd       |j	                         D ci c]  \  }}|dk7  s|| }}}t        j
                  |ddd	
      }t        j                  |j                  d            j                         }	|	|d<   |j                  t        j
                  |dd             yc c}}w )u<   테스트 전용: state 강제 설정 + 체크섬 재계산.r   r   r/   current_state	_checksumNFT,:ensure_ascii	sort_keys
separatorsutf-8   r>   indent)r1   r2   r3   popitemsdumpshashlibsha256encode	hexdigestr   )
r   r4   target_stater5   r   kvpayloadcanonchecksums
             r    _force_state_with_checksumrR   B   s    8g%7)5(99AJJq{{}%E)E/	IIk4  %B1k1Aq!tBGBJJwUdzZE~~ell734>>@H!E+LLEa@A	 Cs   C**C*c           
        d|gd|gd|gd|gd|dt        |      gfD ]  }t        ||      j                  dk7  s y t        | |d	       | d
z  dz  | dz  }t	        j
                  |j                               }d|d<   |j                  dd       |j                         D ci c]  \  }}|dk7  s|| }	}}t	        j                  |	ddd      }
t        j                  |
j                  d            j                         |d<   |j                  t	        j                  |dd             t        | |      d   d	k(  S c c}}w )u*   HUMAN_APPROVED 상태까지 강제 진입.initdispatchackr*   zpr-openz--prr   FHUMAN_APPROVEDr   r   r/   Thuman_approvedr9   Nr:   r=   rA   rB   rC   r8   )r   r-   
returncoderR   r1   r2   r3   rE   rF   rG   rH   rI   rJ   rK   r   r6   )r   r   r4   	pr_numbercmdr5   r   rM   rN   rO   rP   s              r    _setup_to_human_approvedr\   O   sK    !J#8 5'"2GVS^<>  S>$$)	 x2BC8g%7)5(99AJJq{{}%E"E
	IIk4  %B1k1Aq!tBGBJJwUdzZE W(=>HHJE+LLEa@A(G$_59III Cs   %E3Ec                h   | t         z  }|j                         sg S |j                         j                         D cg c]#  }|j	                         s|j	                         % }}g }|D ]'  }	 |j                  t        j                  |             ) |S c c}w # t        j                  $ r Y Fw xY w)u   audit log JSONL 읽기.)	AUDIT_LOG_RELATIVEr0   r3   
splitlinesstripappendr1   r2   JSONDecodeError)r   	audit_loglnlinesresults        r    _read_audit_logrg   g   s    --I	"+"5"5"7"B"B"DSB
RXXZSESF 	MM$**R.)
 M T
 ## 		s   BB.$BB10B1c                   | t         z  }|j                  j                  dd       t        j                  t
        j                        }t        |dd      5 }t        |      D ]p  }|t        ||z  dz         z
  }|j                  d      d	|d
d|z   dd| d|ddg|dz   |dz   d	}|j                  t        j                  |d      dz          r 	 ddd       y# 1 sw Y   yxY w)u9   audit log에 count건 미리 기록 (rolling window 내).Tr   arA   )encoding   )daysz%Y-%m-%dT%H:%M:%SZztask-prepop-03di  chairmanzprepopulated test record #abc04dtest)	tsr4   rZ   actorreasonhead_shabypassed_checkssoft_count_this_monthhard_count_this_quarterF)r>   
N)r^   parentr   r   nowr   utcopenranger   strftimewriter1   rG   )	r   countdays_ago_maxrc   r{   firr   records	            r    _prepopulate_audit_logr   v   s    --I4$7
,,x||
$C	iw	/ C1u 	CAya,&6&:;;Bkk"67)!C1!AX#6qc:!!CM$*8)*Q+,q5
F GGDJJvE:TAB	CC C Cs   A?C!!C*c           	        t        | t              }d}d}t        | |||      }|st        j                  d       t        d|ddg|      }|j                  dk(  rt        |       }t        |      dk(  r&t        j                  d	t        | |      d
    d       |d   }dD ]*  }||v rJ d| dt        |j                                        |j                  d      |k(  sJ d|j                  d              |j                  d      dt        dhv sJ d|j                  d              t        | |      }	|	d
   }
|
dv s
J d|
        yt        j                  d|j                  dd         y)u   chairman email로 taskctl merge --admin → audit log 1줄 + ADMIN_OVERRIDE_USED.

    신규 구현 필요. MVP에서는 --admin 플래그 미구현 시 xfail.
    r   ztask-adminoverride-01i  #   HUMAN_APPROVED 상태 진입 실패merge--admin	--dry-runr   u~   --admin 플래그 인식되나 audit log 미구현 (스바로그 대기): merge 성공했지만 audit log 비어있음 (state=r8   ))rr   r4   rs   rt   rx   u   audit log에 'u
   ' 누락: r4   u   audit log task_id 불일치: rs   rn   z"chairman (jonghyuk.jeon@gmail.com)u   audit log actor 이상: >   DONEMERGEDADMIN_OVERRIDE_USEDu&   admin override 후 예상 외 상태: uQ   --admin 플래그 미구현 또는 chairman 검증 실패 (스바로그 대기): N   )r!   CHAIRMAN_EMAILr\   pytestskipr-   rY   rg   lenxfailr6   listkeysgetstderr)r   r   r4   rZ   okprocentrieslastfieldr   currents              r    %test_admin_override_records_audit_logr      s   
 h~
FC%GI	!(C)	DB9: '9k:C@D!!(+w<1LLGGMhX_G`apGqFrrsu
 r{ U 	XED=WN5'DDUCV"WW=	X xx	"g- 	
+DHHY,?+@A	
- xx ZAe$ff 	
&txx'8&9:	
f
 x)(CC 	
4WI>	
C 	_{{4C !#	
r"   c                   d}t        | |      }d}d}t        | |||      }|st        j                  d       t	        d|ddg|      }|j
                  d	k(  r0t        j                  d
|j                   d|j                          y|j                  |j                  z   }d|j                         v xs: d|j                         v xs& d|j                         v xs d|j                         v }d|j                         v xs& d|j                         v xs d|j                         v }	|	r|st        j                  d       |j
                  d	k7  sJ y)uy   다른 사용자가 --admin 시도 → FAIL ("chairman only").

    git config user.email을 다른 email로 설정.
    znon-chairman@example.comr   ztask-adminoverride-02i  r   r   r   r   r   u5   non-chairman이 --admin 성공: returncode=0
stdout: 	
stderr: rn   unauthorized
permissiononlyunknownunrecognized1   --admin 플래그 미구현 (스바로그 대기)N)r!   r\   r   r   r-   rY   failstdoutr   lowerr   )
r   non_chairman_emailr   r4   rZ   r   r   combinedis_chairman_blockedis_not_implementeds
             r    (test_admin_override_non_chairman_blockedr      sX   
 4
h7I
JC%GI	!(C)	DB9:'9k:C@D!{{m:dkk]<	
 ;;,(..** *!11*x~~//* ))	 	 )) 2HNN,,2!11 	 &9LLLM !###r"   c                <   t        | t              }d}d}t        | |||      }|st        j                  d       t        | dd       t        |       }t        |      dk(  sJ dt        |       d	       t        d
|ddg|      }|j                  dk(  rkt        |       }t        |      dkD  r<t        j                  dt        |       d|j                   d|j                          yt        j                  d       y|j                  |j                  z   }d|j                         v xs@ d|j                         v xs, d|j                         v xs d|j                         v xs d|v }	d|j                         v xs& d|j                         v xs d|j                         v }
|
r|	st        j                  d       |	s|
st        j                  d|dd         |j                  dk7  sJ t        |       }t        |      dk  sJ dt        |       d	       y)u   audit log에 90일 내 5건 미리 채운 후 6번째 시도 → FAIL (HARD_CAP_EXCEEDED).

    명세 §6.2: hard_count >= 5 → "HARD_CAP_EXCEEDED".
    r   ztask-adminoverride-03i  r      Y   )r   r   u   prepopulate 실패: u   건r   r   r   r   u7   hard cap 초과에도 admin override 성공: audit log u   건
stdout: r   u/   hard cap 검사 미구현 (스바로그 대기)HARD_CAPcapexceededlimit5r   r   r   uE   hard cap 관련 메시지 없음 (chairman 검증 실패 가능성): Ni,  u2   hard cap 초과 후에도 audit log에 기록됨: )r!   r   r\   r   r   r   rg   r   r-   rY   r   r   r   r   upperr   )r   r   r4   rZ   r   entries_beforer   entries_afterr   is_cap_exceededr   s              r    test_admin_override_hard_capr      s8   
 h~
FC%GI	!(C)	DB9: 812>$X.N~!#T';C<O;PPS%TT# '9k:C@D!'1}!KK /0 1;;-z$++@ LLJK;;, (..** ((X^^-- (..** h 	 )) 2HNN,,2!11 	 oLLLM'9LLWX`aebeXfWgh
 !### (1=!Q& 	
@]AS@TTWX	
&r"   )r   r   r   r   returndict)r,   z	list[str]r   r   r   zsubprocess.CompletedProcess)r   r   r4   r   r   r   )r   r   r4   r   rL   r   r   None)rk   )
r   r   r   r   r4   r   rZ   intr   bool)r   r   r   z
list[dict])r%   )r   r   r   r   r   r   r   r   )__doc__
__future__r   rH   r1   r   r)   r   r   r   pathlibr   r   	WORKSPACEr+   r   r^   r!   r-   r6   rR   r\   rg   r   r   r   r    r"   r    <module>r      s   	 #   	  2 2  @A	
i
,
. +(^&;;>TT  ?M .%
B 01J),J59J0C44
v)$`A
r"   