
    T0=jt                       d Z ddlmZ ddlZddlmc mZ ddl	Z
ddlZddlZddlZddlZddlZddlmZ ddlmZ  ee      j)                         j*                  j*                  j*                  Z ee      ej0                  vr"ej0                  j3                  d ee             d<dZ edd      Z ed	d
        edd        edd        edd      Zej:                  Zej>                  Z ejB                  Z"dZ#dZ$e#dd Z%d Z&d Z'd Z(d Z)d=dZ* G d dejV                        Z, G d de,      Z- G d de,      Z. G d d e,      Z/ G d! d"e,      Z0 G d# d$e,      Z1 G d% d&e,      Z2 G d' d(e,      Z3 G d) d*e,      Z4 G d+ d,e,      Z5 G d- d.e,      Z6 G d/ d0e,      Z7 G d1 d2e,      Z8 G d3 d4e,      Z9 G d5 d6e,      Z: G d7 d8e,      Z; G d9 d:ejV                        Z<e=d;k(  r ej|                          yy)>u  task-2774+8 — D-2 fire wiring (실발사 가능하게 하는 안전 결선) 필수 regression.

목적: attempt_owner_fire 의 production 실발사 fire_fn 결선 공백 + ONESHOT_TARGET 하드코딩을
닫은 안전 결선(run_approved_oneshot_fire 전용 entrypoint + build_oneshot_cokacdir_fire_fn
production fire_fn factory)이 **우회 없이** 동작하되 본 PR 에서는 real fire 0 임을 입증한다.

★ 이 PR 은 real fire 를 쏘지 않는다 — 본 테스트는 mock fire_fn / mock flag_reader / mock
  runner 만 사용한다. 실제 cokacdir --cron subprocess 호출 0(subprocess.run/Popen 미호출
  검증 포함). ACTIVE gate 는 함수인자(flag_reader)로만 판정 — 전역 flag 파일 생성/읽기 0.

★ raw ANU key literal hygiene: ANU key / executor self-key 는 callback_owner_enforcer
  (무수정)에서 import 한다 — 테스트 소스에 raw key literal 0.

회장 필수 테스트(task md §4 11종) 매핑:
   1. fire_fn 미주입 → FIRE_BLOCKED_NO_FIRE_FN                          → Test01
   2. target 정확 일치 1건만 → mock fire_fn 정확히 1회 호출            → Test02
   3. 동일 target 2회차 → DEDUP/BLOCK, fire_fn 미호출                  → Test03
   4. target 미일치(task_id/head_sha/abs path 중 1개라도) → fire 0     → Test04
   5. ACTIVE gate OFF → NOOP_DISABLED, fire_fn 미호출                  → Test05
   6. owner-proof gate 미통과 → fire_fn 미호출                         → Test06
   7. raw key 가 argv/log/audit 에 포함되면 FAIL(노출 0 검증)          → Test07
   8. 전역 flag 파일 생성 0(함수인자 격리 검증)                        → Test08
   9. canonical backlog 13건 → 처리 대상 0(target 외 fire 0)           → Test09
  10. target manifest/인자 누락 시 fail-closed(FIRE_BLOCKED_NO_APPROVAL) → Test10
  11. 실제 cokacdir --cron 호출 0 — mock fire_fn 으로만·real fire 0    → Test11
+ wiring factory 입증: build_oneshot_cokacdir_fire_fn --once 강제·runner 격리 → Test12
    )annotationsN)Path)mockc                r   | t         j                  v rt         j                  |    S t        j                  j	                  | t
        |z        }g }d}||u}|}|r|j                  }d}||u}	|	}|slt        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }
dd|
iz  }|j                  |       |rt        j                  d	fdf      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d	z  }d
d|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                   |            dx}x}x}x}x}x}	}t        j                  j#                  |      }|t         j                  | <   |j                  j%                  |       |S )u]   실 dispatch 모듈을 canonical 이름으로 직접 로드(tests/dispatch shadowing 회피).N)is not)z%(py2)s is not %(py5)sspec)py2py5z%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16r   zassert %(py19)spy19)sysmodules	importlibutilspec_from_file_location_ROOTloader
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprappend_format_boolopAssertionError_format_explanationmodule_from_specexec_module)modnamerelpathr   @py_assert1@py_assert4@py_assert3@py_assert0@py_assert10@py_assert13@py_assert12@py_format6@py_format8@py_format15@py_format17@py_format18@py_format20mods                    B/home/jay/workspace/tests/regression/test_d2_fire_wiring_2774p8.py_loadr5   -   sI   #++{{7##>>11'57?KD7t74t77474 777774t77777747774777t77777774777777777777777477777777777777
..
)
)$
/CCKKKKC J    z dispatch.callback_owner_enforcerz#dispatch/callback_owner_enforcer.pyz(dispatch.normal_fallback_callback_helperz+dispatch/normal_fallback_callback_helper.pyz'dispatch.anu_owned_callback_enforcementz*dispatch/anu_owned_callback_enforcement.pyzdispatch.anu_collector_resultz dispatch/anu_collector_result.pyz!dispatch.anu_result_pickup_runnerz$dispatch/anu_result_pickup_runner.py(d18358f3829d4a1278b58d88bb86f89cb536d2fe(deadbeefdeadbeefdeadbeefdeadbeefdeadbeef   c                     t         S N)ANU_KEY r6   r4   _anu_loaderr>   L   s    Nr6   c                     t         S r;   )Hr=   r6   r4   _probe_HrA   P   s    Hr6   c                      y)NTr=   r=   r6   r4   _flag_onrC   T   s    r6   c                      y)NFr=   r=   r6   r4   	_flag_offrE   X   s    r6   c                &     g  fd}|fS )uR   mock fire_fn — 호출 argv 를 calls 에 기록(실 cokacdir/cron subprocess 0).c                F    j                  t        |              ddS )Nzsched-mock-1)spawnedcallback_evidencecron_registeredschedule_idr   list)argvrI   callsrJ   rH   s    r4   _fnz_fire_spy.<locals>._fn`   s*    T$Z "9J#2>S 	Sr6   r=   )rH   rI   rJ   rP   rO   s   ``` @r4   	_fire_spyrQ   \   s    ES
 #:r6   c            	      ^    e Zd Zd ZeeddddddddZeddZed	d
Z	ed	dZ
eeddZy)_Basec                     t        j                  d       _         j                   fd       t        j
                  j                   j                  d       _        y )Nt2774p8_)prefixc                 P    t        d      j                   j                  d      S )NshutilT)ignore_errors)
__import__rmtreetmpselfs   r4   <lambda>z_Base.setUp.<locals>.<lambda>k   s!    
8 4 ; ;DHHTX ; Y r6   zowner_pickup_gate_index.jsonl)tempfilemkdtempr\   
addCleanupospathjoinledgerr]   s   `r4   setUpz_Base.setUpi   s=    ##:6YZggll488-LMr6   FTN)task_idhead_shaauthoritativeowner_pickup_requiredowner_key_proof_presentschedule_created_by_executorcallback_fired_by_executorfnamec                   |||||||d}	t         j                  j                  | j                  |xs | d      }
t	        |
dd      5 }t        j                  |	|d       d d d        |
S # 1 sw Y   |
S xY w)N)rh   ri   rj   rk   rl   rm   rn   .result.jsonwutf-8encodingFensure_ascii)rc   rd   re   r\   openjsondump)r^   rh   ri   rj   rk   rl   rm   rn   ro   payloadpfs               r4   _write_resultz_Base._write_resultn   s~      *%:'>,H*D
 GGLL5#Dwi|,DE!S7+ 	6qIIgqu5	6	6s   
A--A7rh   c               0    t         j                  ||      S )N)rh   result_json_path)gate_modOneShotTarget)r^   rd   rh   s      r4   _target_forz_Base._target_for   s    %%g%MMr6   probec          	     T   |j                  dt               |j                  d| j                         |j                  dt               t	        j
                  |fd|i|}| j                  |j                  t        j                  d|j                   d|j                   d       |S )	Nsealed_key_loaderdedupe_ledger_pathexecutor_key
head_probeu   전제: gate READY 여야 함 (z / ))msg)

setdefaultr>   rf   EXECUTOR_KEYr   owner_proof_pickup_gateassertEqualstatusGATE_OWNER_PICKUP_READY_NO_FIREreasons)r^   rd   r   kwgs        r4   _ready_gatez_Base._ready_gate   s    
);7
*DKK8
nl3,,TJeJrJ8#K#K>qxxjAII;VWX 	 	Zr6   c                   |j                  dt               |j                  d| j                         |j                  dt               t	        j
                  |fd|i|S )Nr   r   r   r   )r   r>   rf   r   r   r   )r^   rd   r   r   s       r4   	_gate_rawz_Base._gate_raw   sM    
);7
*DKK8
nl3//MM"MMr6   )r   r   c          	         |j                  d| j                         |j                  dt               t        j                  |f|||||d|S )Nr   r   )flag_readerfire_fntargetr   r   )r   rf   r   r   run_approved_oneshot_fire)r^   gate_resultr   r   r   r   r   r   s           r4   _runz
_Base._run   sR    
*DKK8
nl311>%0'&$>:<> 	>r6   )__name__
__module____qualname__rg   TARGET_TASK_IDr@   r~   r   rA   r   r   r>   r   r=   r6   r4   rS   rS   h   sP    N
 (6$).33816d	& ,: N *2  (0 N K>r6   rS   c                      e Zd Zd Zy)Test01_NoFireFnc                   | j                         }| j                  |      }| j                  |t        d | j	                  |            }| j                  |j                  t        j                         | j                  |j                         | j                  |j                  d       | j                  t        j                  j!                  | j"                        d       y )Nr   r   r   u$   차단 시 argv 미구성(raw key 0)u8   fire_fn 미주입 → fire 0·재발사 marker 미작성)r~   r   r   rC   r   r   r   r   GATE_FIRE_BLOCKED_NO_FIRE_FN
assertTruefire_blockedassertIsNonerN   assertFalserc   rd   existsrf   )r^   r|   r   outs       r4   test_no_fire_fn_fail_closedz+Test01_NoFireFn.test_no_fire_fn_fail_closed   s     QiixdFVFVWXFYiZX%J%JK(()#(($JK4S	Ur6   N)r   r   r   r   r=   r6   r4   r   r      s    Ur6   r   c                      e Zd Zd Zy)Test02_ExactTargetFiresOncec                r   | j                         }| j                  |      }t               \  }}| j                  |t        || j                  |            }| j                  |j                  t        j                         | j                  t        |      dd       | j                  |j                         y )Nr      u,   주입형 mock fire_fn 정확히 1회 호출)r~   r   rQ   r   rC   r   r   r   r   GATE_REALFIRE_1SHOT_SUCCESSlenr   r   r^   r|   r   rO   fnr   s         r4   test_exact_match_fires_oncez7Test02_ExactTargetFiresOnce.test_exact_match_fires_once   s     QK	riixDDTDTUVDWiXX%I%IJUQ(VW))*r6   N)r   r   r   r   r=   r6   r4   r   r      s    +r6   r   c                      e Zd Zd Zy)Test03_SecondCallDedupedc                   | j                         }| j                  |      }t               \  }}| j                  |t        || j                  |            }| j                  |j                  t        j                         | j                  t        |      d       | j                  |      }| j                  |j                  t        j                  d       t               \  }}| j                  |t        || j                  |            }	| j                  |	j                  t        j                         | j                  |g d       y )Nr   r   u$   전제: 1회 소진 후 gate DEDUPEDu7   2회차 → DEDUP/BLOCK·fire_fn 미호출(재발사 0))r~   r   rQ   r   rC   r   r   r   r   r   r   r   GATE_DEDUPED)
r^   r|   g1calls1fn1firstg2calls2fn2seconds
             r4   test_refire_dedupedz,Test03_SecondCallDeduped.test_refire_deduped   s    a k		"(CHXHXYZH[	\x'K'KLVa( ^^AH$9$9;abk28SIYIYZ[I\](=(=>%^_r6   N)r   r   r   r   r=   r6   r4   r   r      s    `r6   r   c                  $    e Zd Zd Zd Zd Zd Zy)Test04_TargetMismatchBlockedc           	     .   | j                         }| j                  |      }t               \  }}| j                  |t        || j                  |d            }| j                  |j                  t        j                         | j                  |g d       y )Nztask-other-999r   r   u.   task_id mismatch → fire_fn 미호출(cron 0)
r~   r   rQ   r   rC   r   r   r   r   GATE_FIRE_BLOCKED_NO_APPROVALr   s         r4   test_task_id_mismatch_blockedz:Test04_TargetMismatchBlocked.test_task_id_mismatch_blocked   s     QK	riix#//;K/L  NX%K%KL$TUr6   c                N   | j                         }| j                  d      }| j                  |      }t               \  }}| j                  |t        || j                  |            }| j                  |j                  t        j                         | j                  |g d       y )Nzother.result.json)ro   r   u/   abs path mismatch → fire_fn 미호출(cron 0)r   )r^   r|   otherr   rO   r   r   s          r4   test_abs_path_mismatch_blockedz;Test04_TargetMismatchBlocked.test_abs_path_mismatch_blocked   s     "")<"=QK	riixDDTDTUZD[i\X%K%KL$UVr6   c                   | j                  t              }| j                  |t              }t	               \  }}| j                  |t        || j                  |      d       }| j                  |j                  t        j                  t        j                  f       | j                  |j                         | j                  |g d       y )Nri   r   c                     t         S r;   )H2r=   r6   r4   r_   zMTest04_TargetMismatchBlocked.test_head_sha_mismatch_blocked.<locals>.<lambda>   s    b r6   )r   r   r   r   u6   head_sha mismatch(stale) → fire_fn 미호출(cron 0))r~   r@   r   rA   rQ   r   rC   r   assertInr   r   GATE_RESULT_NOT_PICKUP_ELIGIBLEr   r   r   r   r   s         r4   test_head_sha_mismatch_blockedz;Test04_TargetMismatchBlocked.test_head_sha_mismatch_blocked   s     *Qh/K	riixDDTDTUVDW(  *cjj8#K#K#+#I#I#K 	L(()$\]r6   c                $   | j                  t              }| j                  |t              }t	               \  }}| j                  |t        || j                  |            }| j                  |j                         | j                  |g d       y )Nr   r   r   u8   short SHA/prefix → fire_fn 미호출(완화 0·cron 0))r~   SHORTr   rA   rQ   r   rC   r   r   r   r   r   s         r4   test_short_sha_prefix_blockedz:Test04_TargetMismatchBlocked.test_short_sha_prefix_blocked   sy    .NN1HN-K	riixDDTDTUVDWiX(()$^_r6   N)r   r   r   r   r   r   r   r=   r6   r4   r   r      s    VW^`r6   r   c                      e Zd Zd Zd Zd Zy)Test05_ActiveGateOffc                `   | j                         }| j                  |      }t               \  }}| j                  |t        || j                  |            }| j                  |j                  t        j                         | j                  |g d       | j                  |j                         y )Nr   u3   ACTIVE gate OFF → fire_fn 미호출(실 발사 0))r~   r   rQ   r   rE   r   r   r   r   GATE_NOOP_DISABLEDr   rN   r   s         r4   test_gate_off_noopz'Test05_ActiveGateOff.test_gate_off_noop   s     QK	riiy"TEUEUVWEXiYX%@%@A$YZ#((#r6   c                "   | j                         }| j                  |      }t               \  }}| j                  |d || j	                  |            }| j                  |j                  t        j                         | j                  |g d       y )Nr   u(   flag_reader 부재 → fire_fn 미호출	r~   r   rQ   r   r   r   r   r   r   r   s         r4   test_flag_reader_absent_noopz1Test05_ActiveGateOff.test_flag_reader_absent_noop  sz     QK	riitR@P@PQR@SiTX%@%@A$NOr6   c                (   d }| j                         }| j                  |      }t               \  }}| j                  |||| j	                  |            }| j                  |j                  t        j                         | j                  |g d       y )Nc                     t        d      )Nzflag read error)RuntimeErrorr=   r6   r4   _boomzCTest05_ActiveGateOff.test_flag_reader_exception_noop.<locals>._boom  s    011r6   r   u5   flag_reader 예외 → fail-closed·fire_fn 미호출r   )r^   r   r|   r   rO   r   r   s          r4   test_flag_reader_exception_noopz4Test05_ActiveGateOff.test_flag_reader_exception_noop
  s    	2 QK	riiubAQAQRSATiUX%@%@A$[\r6   N)r   r   r   r   r   r   r=   r6   r4   r   r      s    $P	]r6   r   c                      e Zd Zd Zd Zy)Test06_OwnerProofFailc                d   | j                  d      }| j                  |      }| j                  |j                  t        j
                         t               \  }}| j                  |t        || j                  |            }| j                  |j                         | j                  |g d       y )NT)rj   r   u+   owner-proof 미통과 → fire_fn 미호출)r~   r   assertNotEqualr   r   r   rQ   r   rC   r   r   r   r   r   s         r4   test_ineligible_result_no_firez4Test06_OwnerProofFail.test_ineligible_result_no_fire  s     T2NN1AHHh&N&NOK	riixDDTDTUVDWiX(()$QRr6   c                   | j                         }| j                  |      }t               \  }}| j                  |t        || j                  |      d       }| j                  |j                         | j                  |g d       y )Nc                     t         S r;   )r   r=   r6   r4   r_   zGTest06_OwnerProofFail.test_self_collector_key_no_fire.<locals>.<lambda>*  s    | r6   )r   r   r   r   u;   self-collector(runtime==executor key) → fire_fn 미호출)	r~   r   rQ   r   rC   r   r   r   r   r   s         r4   test_self_collector_key_no_firez5Test06_OwnerProofFail.test_self_collector_key_no_fire$  sz     QK	riixDDTDTUVDW3  5(()$abr6   N)r   r   r   r   r   r=   r6   r4   r   r     s    
Scr6   r   c                      e Zd Zd Zy)Test07_RawKeyHygienec                   | j                         }| j                  |      }t               \  }}| j                  |t        || j                  |            }| j                  |j                  t        j                         t        j                  |j                         d      }| j                  t        |d       | j                  t        j                   |d       t#        | j$                  d      5 }|j'                         }d d d        | j                  t        d       | j                  t)        |      d	       | j                  t        |d
   d       y # 1 sw Y   VxY w)Nr   Frv   u2   persisted result.argv/reasons 에 raw key 노출 0u'   persist argv 는 placeholder key 사용rs   rt   u"   ledger marker 에 raw key 노출 0r   r   uD   실 key 는 fire_fn real_argv 경계에만 — persist 와 분리됨)r~   r   rQ   r   rC   r   r   r   r   r   ry   dumpsto_jsonassertNotInr<   r   OWNER_PICKUP_KEY_PLACEHOLDERrx   rf   readr   )	r^   r|   r   capturedr   r   	persistedr}   
ledger_txts	            r4   -test_no_raw_key_in_persisted_result_or_ledgerzBTest07_RawKeyHygiene.test_no_raw_key_in_persisted_result_or_ledger1  s    Q {"iixDDTDTUVDWiXX%I%IJJJs{{}5A	)-abh;;Y?	A $++0 	"AJ	"*.RSX*gx{\	^	" 	"s   5EE$N)r   r   r   r   r=   r6   r4   r   r   0  s    ^r6   r   c                      e Zd Zd Zy)Test08_NoGlobalFlagFilec                p  
 t         j                  j                  t        j                  ddd      t         j                  j                  t        j                  ddd      t         j                  j                  t        j                  ddd      g}|D ci c]"  }|t         j                  j                  |      $ }}ddi

fd}| j                         }| j                  |      }t               \  }}| j                  |||| j                  |      	      }	| j                  |	j                  t        j                         | j                  t        |      d
d       | j                  
d   d
d       |D ]8  }| j                  t         j                  j                  |      ||   d|        : y c c}w )Nmemorystatep0b_callback_launch_enabledp0b_driver_enabledp0b_real_wake_enabledrO   r   c                       dxx   dz  cc<   y)NrO   r   Tr=   )spys   r4   	_flag_spyzXTest08_NoGlobalFlagFile.test_function_arg_gate_creates_no_global_flag.<locals>._flag_spyR  s    LALr6   r   r   u.   함수인자 gate 통과 → mock fire_fn 1회u6   ACTIVE gate 는 함수인자 flag_reader 로만 판정u$   전역 flag 파일 생성 0 위반: )rc   rd   re   r   CANONICAL_ROOTr   r~   r   rQ   r   r   r   r   r   r   assertGreaterEqual)r^   	forbiddenfpbeforer  r|   r   rO   r   r   r  s             @r4   -test_function_arg_gate_creates_no_global_flagzETest08_NoGlobalFlagFile.test_function_arg_gate_creates_no_global_flagH  sq    GGLL00(GEbcGGLL00(GEYZGGLL00(GE\]
	
 4==R"bggnnR((==l	  QK	riiy"TEUEUVWEXiYX%I%IJUQ(XYGa1ij 	JBRWW^^B/CB4HJ	J >s   'F3N)r   r   r   r  r=   r6   r4   r   r   G  s    Jr6   r   c                      e Zd Zd Zy)Test09_BacklogNotProcessedc                   | j                  t        d      }| j                  |t              }t        d      D ]  }| j                  d|dd|dd      }| j	                  |      }t               \  }}| j                  |t        ||	      }| j                  |j                  t        j                  d
| d       | j                  |g d
| d        y )Nzapproved.result.json)rh   ro   r      ztask-backlog-04dzbacklog-rq   r   zbacklog[u)   ] target 외 → FIRE_BLOCKED_NO_APPROVALu*   ] → fire_fn 미호출(target 외 fire 0))r~   r   r   ranger   rQ   r   rC   r   r   r   r   )	r^   approved_pathr   ibpr   rO   r   r   s	            r4   /test_only_explicit_target_fires_backlog_blockedzJTest09_BacklogNotProcessed.test_only_explicit_target_fires_backlog_blockede  s    **>I_*`!!-!Hr 	bA##mAc7,C,4QsG<*H $ JB  $A!IE2))A8R)OCSZZ)O)O's*STVUB(1#5_(`a	br6   N)r   r   r   r  r=   r6   r4   r  r  d  s    br6   r  c                      e Zd Zd Zy)Test10_MissingTargetFailClosedc                   | j                         }| j                  |      }t               \  }}| j                  |t        |d       }| j                  |j                  t        j                         | j                  |g d       | j                  t        t        j                  |j                         d      d       y )Nr   uH   target 미주입 → fire_fn 미호출(하드코딩 자동발사 차단)Frv   u2   차단 결과에 raw key 노출 0(placeholder 만))r~   r   rQ   r   rC   r   r   r   r   r   r<   ry   r   r   r   s         r4   test_target_none_blockedz7Test10_MissingTargetFailClosed.test_target_none_blockedv  s     QK	riixDiIX%K%KL$no$**S[[]"OM	Or6   N)r   r   r   r  r=   r6   r4   r  r  u  s    	Or6   r  c                      e Zd Zd Zd Zy)Test11_NoRealCokacdirCallc           
     $   | j                         }| j                  |      }t               \  }}t        j                  d      5 }t        j                  d      5 }| j                  |t        || j                  |            }d d d        d d d        | j                  j                  t        j                         | j                  t        |      dd       j                          j                          y # 1 sw Y   xxY w# 1 sw Y   |xY w)Nsubprocess.runsubprocess.Popenr   r   u   mock fire_fn 1회만)r~   r   rQ   r   patchr   rC   r   r   r   r   r   r   assert_not_calledr^   r|   r   rO   r   m_runm_popenr   s           r4   0test_full_success_path_does_not_spawn_subprocesszJTest11_NoRealCokacdirCall.test_full_success_path_does_not_spawn_subprocess  s      QK	rZZ() 	]UDJJ?Q4R 	]V]))A8RHXHXYZH[)\C	] 	]X%I%IJUQ(>?!!!#	] 	] 	] 	]s$   D)C:D:D	?DDc           
        | j                         }| j                  |      }t               \  }}t        j                  d      5 }t        j                  d      5 }| j                  |t        || j                  |             | j                  |t        d | j                  |             | j                  |t        |d        d d d        d d d        j                          j                          y # 1 sw Y   2xY w# 1 sw Y   6xY w)Nr  r  r   )
r~   r   rQ   r   r  r   rE   r   rC   r   )r^   r|   r   _r   r"  r#  s          r4   *test_blocked_paths_do_not_spawn_subprocesszDTest11_NoRealCokacdirCall.test_blocked_paths_do_not_spawn_subprocess  s     Q2ZZ() 	HUDJJ?Q4R 	HV]IIaY4CSCSTUCVIWIIaXtDDTDTUVDWIXIIaXr$IG	H 	H 	!!!#	H 	H 	H 	Hs%   DA*C5D5C>	:DD
N)r   r   r   r$  r'  r=   r6   r4   r  r    s    $	$r6   r  c                      e Zd Zd Zd Zd Zy)Test12_FireFnFactoryc                    g t         j                  fd      } |g d      }| j                  |d          | j                  |j	                  d      d       | j                  g d       y )Nc                &    j                  |       S r;   )r   )arunner_callss    r4   r_   zKTest12_FireFnFactory.test_factory_recurring_guard_no_once.<locals>.<lambda>  s    lFYFYZ[F\ r6   runner)cokacdir--cronx--at2mrJ   errorONESHOT_FIRE_ARGV_INVALIDu,   --once 부재 → runner 미호출(실행 0))r   build_oneshot_cokacdir_fire_fnr   r   get)r^   r   r   r-  s      @r4   $test_factory_recurring_guard_no_oncez9Test12_FireFnFactory.test_factory_recurring_guard_no_once  sh    44<\4]:;./0)+FGr+YZr6   c                   g fd}t         j                  |      }t        j                  d      5 }t        j                  d      5 } |ddddd	d
dt        g      }d d d        d d d        | j                  t              dd       | j                  d          j                          j                          y # 1 sw Y   bxY w# 1 sw Y   fxY w)Nc                F    j                  t        |              dddddS )NTzsid-x)rH   rJ   rI   rK   rL   rN   seens    r4   _runnerzVTest12_FireFnFactory.test_factory_runner_injection_no_real_subprocess.<locals>._runner  s)    KKT
##)-gG Gr6   r.  r  r  r0  r1  r2  r3  r4  --once--keyr   u   runner 정확히 1회 위임rJ   )	r   r7  r   r  r<   r   r   r   r   )r^   r>  r   r"  r#  r   r=  s         @r4   0test_factory_runner_injection_no_real_subprocesszETest12_FireFnFactory.test_factory_runner_injection_no_real_subprocess  s    	G
 44G4DZZ() 	\UDJJ?Q4R 	\V]j(CxRYZ[C	\ 	\TA'EF-./!!!#	\ 	\ 	\ 	\s#   C
C C C		CCc                    t         j                  d      }| j                  |d          | j                  |d   d       | j	                  |d   d       y )Nz5{"status":"ok","id":"sched-42","prompt":"[redacted]"}rJ   rK   zsched-42rH   u7   등록 시점 spawn 미관측(late spawn → reconcile))r   _parse_cokacdir_cron_stdoutr   r   r   r^   r   s     r4   %test_factory_stdout_parse_no_key_leakz:Test12_FireFnFactory.test_factory_stdout_parse_no_key_leak  sR    22CE-./]+Z8Y)bcr6   N)r   r   r   r9  rA  rE  r=   r6   r4   r)  r)    s    [$"dr6   r)  c                  H    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zy)Test13_CronIdFailClosedc                    t         j                  d      }| j                  |d   d       | j                  |d   d       | j                  |j	                  d      t         j
                         y )N{"status":"ok"}rJ   u   id 부재 → fail-closedrK    r5  r   rC  r   r   r8  FIRE_BLOCKED_NO_CRON_IDrD  s     r4   test_id_key_absent_fail_closedz6Test13_CronIdFailClosed.test_id_key_absent_fail_closed  s^    223DE./1LM]+R0)8+K+KLr6   c                    t         j                  d      }| j                  |d   d       | j                  |d   d       | j                  |j	                  d      t         j
                         y )Nz{"status":"ok","id":""}rJ   u   id='' → fail-closedrK   rJ  r5  rK  rD  s     r4    test_id_empty_string_fail_closedz8Test13_CronIdFailClosed.test_id_empty_string_fail_closed  s^    223LM./1HI]+R0)8+K+KLr6   c                    t         j                  d      }| j                  |d          | j                  |d   d       | j                  |j	                  d      t         j
                         y )Nz{"status":"ok","id":"   "}rJ   rK   rJ  r5  rK  rD  s     r4   #test_id_whitespace_only_fail_closedz;Test13_CronIdFailClosed.test_id_whitespace_only_fail_closed  s[    223OP./0]+R0)8+K+KLr6   c                    t         j                  d      }| j                  |d   d       | j                  |d   d       | j                  |j	                  d      t         j
                         y )Nz{"status":"ok","id":null}rJ   u   id=None → fail-closedrK   rJ  r5  rK  rD  s     r4   test_id_none_fail_closedz0Test13_CronIdFailClosed.test_id_none_fail_closed  s^    223NO./1JK]+R0)8+K+KLr6   c                    t         j                  d      }| j                  |d   d       | j                  |d   d       | j	                  d|d       y )Nz{"status":"ok","id":"sched-9"}rJ   u"   유효 id → 성공 경로 유지rK   zsched-9r5  *   성공 경로엔 fail-closed 라벨 없음r   rC  r   r   r   rD  s     r4   test_valid_id_registered_truez5Test13_CronIdFailClosed.test_valid_id_registered_true  sP    223ST-.0TU]+Y7#'STr6   c                    t         j                  d      }| j                  |d          | j                  |j	                  d      t         j
                         y )Nz {"status":"error","message":"x"}rJ   r5  r   rC  r   r   r8  FIRE_REGISTRATION_FAILEDrD  s     r4   test_status_not_ok_fail_closedz6Test13_CronIdFailClosed.test_status_not_ok_fail_closed  sF    223UV./0)8+L+LMr6   c                    t         j                  d      }| j                  |d          | j                  |d   d       | j                  |j	                  d      t         j
                         y )Nznot-json-at-allrJ   rK   rJ  r5  rY  rD  s     r4   #test_unparseable_stdout_fail_closedz;Test13_CronIdFailClosed.test_unparseable_stdout_fail_closed  s[    223DE./0]+R0)8+L+LMr6   c                    t         j                  d      }t         j                  |      }|d   |d   }}| j                  |d       | j	                  |d       y )NrI        u;   id 부재 응답이 등록 성공으로 오판되지 않음rJ  )r   rC  _read_fire_outcomer   r   )r^   rawoutcomerJ   rK   s        r4   /test_failclosed_normalized_by_read_fire_outcomezGTest13_CronIdFailClosed.test_failclosed_normalized_by_read_fire_outcome  sU    223DE--c2'.qz71:*ghb)r6   c           
        | j                         }| j                  |      }g fd}t        j                  |      }t	        j
                  d      5 }t	        j
                  d      5 }| j                  |t        || j                  |            }d d d        d d d        | j                  j                  t        j                  d       | j                  |j                  t        j                  d       | j                  |j                  d       | j                  t!              d	d
       j#                          j#                          y # 1 sw Y   xY w# 1 sw Y   xY w)Nc                b    j                  t        |              t        j                  d      S )NrI  r   rM   r   rC  r<  s    r4   r>  zUTest13_CronIdFailClosed.test_id_absent_not_misjudged_as_fire_success.<locals>._runner  s%    KKT
#778IJJr6   r.  r  r  r   uB   id 없는 등록은 PARTIAL_FIRE_NO_SPAWN(등록 실패)로 기록u>   미등록을 fire 성공으로 기록 금지(duplicate fire 0)u0   미등록 → fire_blocked=True(성공 기록 0)r   u-   runner 정확히 1회 위임(중복 발사 0))r~   r   r   r7  r   r  r   rC   r   r   r   GATE_PARTIAL_FIRE_NO_SPAWNr   r   r   r   r   r   )	r^   r|   r   r>  r   r"  r#  r   r=  s	           @r4   ,test_id_absent_not_misjudged_as_fire_successzDTest13_CronIdFailClosed.test_id_absent_not_misjudged_as_fire_success  s9     Q	K
 44G4DZZ() 	]UDJJ?Q4R 	]V]))A8RHXHXYZH[)\C	] 	]X%H%H]	_CJJ(L(L\	^((*\]TA'VW!!!#	] 	] 	] 	]s$   E+)EEE	EE(c                   d}t         j                  |      }| j                  |d          |j                         D ]  }| j	                  dt        |      d         | j                  |j                  d      t         j                         y )Nz5{"status":"ok","prompt":"--key SECRET_KEY_TOKEN_XYZ"}rJ   SECRET_KEY_TOKEN_XYZu   raw stdout 미노출(raw key 0)r5  )	r   rC  r   valuesr   strr   r8  rL  )r^   leakyr   vs       r4   *test_no_raw_key_leak_in_failclosed_outcomezBTest13_CronIdFailClosed.test_no_raw_key_leak_in_failclosed_outcome  sy    G2259./0 	`A3SV=^_	`)8+K+KLr6   N)r   r   r   rM  rO  rQ  rS  rW  r[  r]  rd  ri  rp  r=   r6   r4   rG  rG    s<    MMMMUNN*$0Mr6   rG  c                  6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	$Test14_StdoutBytesEncodingFailClosedc                    t         j                  d      }| j                  |d   d       | j                  |d   d       | j	                  d|d       y )Ns$   {"status":"ok","id":"sched-bytes-1"}rJ   u3   bytes 입력에서도 정상 id → registered=TruerK   zsched-bytes-1r5  rU  rV  rD  s     r4   !test_bytes_stdout_valid_id_parseszFTest14_StdoutBytesEncodingFailClosed.test_bytes_stdout_valid_id_parses"  sP    223Z[-.0ef]+_=#'STr6   c                    d}t         j                  |      }| j                  |t        d       | j	                  d|d       | j                  |d   d       | j                  |d   dd       y )	Ns$   
{"status":"ok","id":"sched-good"}u>   invalid UTF-8 바이트가 있어도 예외 없이 dict 반환rJ   u   fail-closed 표준 키 보존u\   invalid 바이트 앞줄 후 유효 JSON 마지막 라인 → registered=True(오류 없음)rK   z
sched-goodu=   errors='replace' 처리 후 마지막 라인 id 정상 취득)r   rC  assertIsInstancedictr   r   r   )r^   badr   s      r4   .test_bytes_stdout_invalid_utf8_no_decode_errorzSTest14_StdoutBytesEncodingFailClosed.test_bytes_stdout_invalid_utf8_no_decode_error)  sr     C2237c4)ij'.MN-.v	x]+\X	Zr6   c                    t         j                  d      }| j                  |d   d       | j                  |j	                  d      t         j
                  d       y )Ns   not-json-bytes-at-allrJ   u/   비JSON bytes → fail-closed(registered=False)r5  u8   비JSON bytes → FIRE_REGISTRATION_FAILED 고정 라벨rY  rD  s     r4   test_non_json_bytes_fail_closedzDTest14_StdoutBytesEncodingFailClosed.test_non_json_bytes_fail_closed7  sO    223KL./1bc)8+L+LS	Ur6   c                    t         j                  d      }| j                  |d   d       | j                  |j	                  d      t         j
                  d       y )Nr6   rJ   u+   빈 bytes → fail-closed(registered=False)r5  u;   빈 bytes stdout → FIRE_REGISTRATION_FAILED 고정 라벨rY  rD  s     r4   test_empty_bytes_fail_closedzATest14_StdoutBytesEncodingFailClosed.test_empty_bytes_fail_closed>  sN    2237./1^_)8+L+LV	Xr6   c                    t         j                  d      }| j                  |d   d       | j                  |j	                  d      t         j
                  d       | j                  |d   dd       y )	Ns   {"status":"ok"}rJ   u+   bytes 입력 id 부재 → registered=Falser5  uE   id 없음 → FIRE_BLOCKED_NO_CRON_ID(미등록 성공 오판 차단)rK   rJ  u    id 부재 시 schedule_id 빈값rK  rD  s     r4   %test_bytes_id_absent_registered_falsezJTest14_StdoutBytesEncodingFailClosed.test_bytes_id_absent_registered_falseE  sg    223EF./1^_)8+K+K`	b]+R1STr6   c                   g fd}t         j                  |      }ddddddd	t        g}t        j                  d
      5 }t        j                  d      5 } ||      }d d d        d d d        j                          j                          | j                  t              dd       | j                  d   d       | j                  |d   d       y # 1 sw Y   xxY w# 1 sw Y   |xY w)Nc                b    j                  t        |              t        j                  d      S )Ns   {"status":"ok","id":"sched-b9"}rg  )rN   r-  s    r4   r>  zgTest14_StdoutBytesEncodingFailClosed.test_fire_fn_with_bytes_runner_no_real_subprocess.<locals>._runnerR  s'    T
+778Z[[r6   r.  r0  r1  r2  r3  r4  r?  r@  r  r  r   u-   runner 정확히 1회 호출(중복 발사 0)rJ   uC   bytes runner 통과 후 registered=True(bytes 경로 정상 연결)rK   zsched-b9)	r   r7  r<   r   r  r   r   r   r   )r^   r>  r   rN   r"  r#  r   r-  s          @r4   1test_fire_fn_with_bytes_runner_no_real_subprocesszVTest14_StdoutBytesEncodingFailClosed.test_fire_fn_with_bytes_runner_no_real_subprocessM  s     	\
 44G4DHc647GTZZ() 	UDJJ?Q4R 	V]T(C	 	 	!!!#\*A/^_-.]	_]+Z8	 	 	 	s$   C$	C!C$C!	C$$C-c                $   d}t         j                  |      }| j                  |d   d       | j                  |j	                  d      t         j
                  d       |j                         D ]!  }| j                  dt        |      d|       # y )Ns7   {"status":"ok","prompt":"--key SECRET_BYTES_TOKEN_ZZZ"}rJ   u<   id 부재 bytes 입력 → fail-closed(성공 오판 차단)r5  uD   id 없는 ok 응답(bytes) → FIRE_BLOCKED_NO_CRON_ID 고정 라벨SECRET_BYTES_TOKEN_ZZZu7   bytes stdout 내 토큰이 반환 value 에 노출됨: )	r   rC  r   r   r8  rL  rl  r   rm  )r^   leaky_bytesr   ro  s       r4   !test_stderr_bytes_no_raw_key_leakzFTest14_StdoutBytesEncodingFailClosed.test_stderr_bytes_no_raw_key_leakd  s     Q22;?./W	Y)8+K+K_	a  	^A5s1vVWXV[\^	^r6   N)
r   r   r   rt  ry  r{  r}  r  r  r  r=   r6   r4   rr  rr  !  s+    UZUXU9.^r6   rr  c                  6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	Test09_InvalidFlagReaderc                   | j                         }| j                  |      }t               \  }}| j                  |d|| j	                  |            }| j                  |j                  t        j                         | j                  |j                         | j                  |j                  d       | j                  |g d       y )NTr   u6   non-callable flag_reader → argv 미구성(raw key 0)u<   non-callable flag_reader → fire_fn 미호출(실 발사 0))r~   r   rQ   r   r   r   r   r   GATE_INVALID_FLAG_READERr   r   r   rN   r   s         r4   test_flag_reader_true_invalidz6Test09_InvalidFlagReader.test_flag_reader_true_invalidv  s     QK	riitR@P@PQR@SiTX%F%FG(()#(($\]$bcr6   c                2   | j                         }| j                  |      }t               \  }}| j                  |t	               || j                  |            }| j                  |j                  t        j                         | j                  |g d       y )Nr   u*   object() flag_reader → fire_fn 미호출)
r~   r   rQ   r   objectr   r   r   r   r  r   s         r4   test_flag_reader_object_invalidz8Test09_InvalidFlagReader.test_flag_reader_object_invalid  s|     QK	riivxDDTDTUVDWiXX%F%FG$PQr6   c                "   | j                         }| j                  |      }t               \  }}| j                  |d|| j	                  |            }| j                  |j                  t        j                         | j                  |g d       y )Nr   r   u+   0(falsy non-callable) → fire_fn 미호출)	r~   r   rQ   r   r   r   r   r   r  r   s         r4   !test_flag_reader_int_zero_invalidz:Test09_InvalidFlagReader.test_flag_reader_int_zero_invalid  sy     QK	riiq"T=M=Ma=PiQX%F%FG$QRr6   c           
     
   | j                         }| j                  |      }t               \  }}t        j                  d      5 }t        j                  d      5 }| j                  |d|| j                  |            }d d d        d d d        | j                  j                  t        j                         j                          j                          | j                  |g d       y # 1 sw Y   oxY w# 1 sw Y   sxY w)Nr  r  Tr   u5   non-callable → subprocess·fire_fn 모두 미호출)r~   r   rQ   r   r  r   r   r   r   r   r  r   r!  s           r4   &test_invalid_flag_reader_no_subprocessz?Test09_InvalidFlagReader.test_invalid_flag_reader_no_subprocess  s     QK	rZZ() 	YUDJJ?Q4R 	YV]))A4DDTDTUVDW)XC	Y 	YX%F%FG!!!#$[\	Y 	Y 	Y 	Ys$   C9%C-?C9-C6	2C99Dc                    | j                         }| j                  |      }t               \  }}| j                  |d|| j	                  |            }t        j                  |j                         d      }| j                  t        |d       y )NTr   Frv   u)   INVALID 차단 결과에 raw key 노출 0)
r~   r   rQ   r   r   ry   r   r   r   r<   )r^   r|   r   r&  r   r   r   s          r4   #test_invalid_flag_reader_no_raw_keyz<Test09_InvalidFlagReader.test_invalid_flag_reader_no_raw_key  sv     Q2iitR@P@PQR@SiTJJs{{}5A	)-XYr6   c                `    | j                  t        j                  t        j                         y r;   )r   r   r  GATE_ONESHOT_WRAPPER_STATUSESr]   s    r4   ,test_invalid_flag_reader_in_wrapper_statuseszETest09_InvalidFlagReader.test_invalid_flag_reader_in_wrapper_statuses  s    h77<<	>r6   c                   | j                  t        j                  t        j                         | j                  t        j                  t        j                         | j                  t        j                  t        j
                         | j                  t        j                  t        j                         | j                  t        j                  t        j                         y r;   )	r   r   r  GATE_TERMINAL_STATUSESGATE_ONESHOT_FIRE_STATUSESGATE_ALL_TERMINAL_STATUSESr   r   r   r]   s    r4   *test_invalid_flag_reader_no_enum_collisionzCTest09_InvalidFlagReader.test_invalid_flag_reader_no_enum_collision  s    ::H<[<[\::H<_<_`::H<_<_`H==x?Z?Z[H==$AA	Cr6   N)
r   r   r   r  r  r  r  r  r  r  r=   r6   r4   r  r  u  s+    	dRS
]Z>
Cr6   r  c                  T    e Zd ZdZddddZd Zd Zd Zd Zd	 Z	d
 Z
d Zd Zd Zy)!Test15_NoneFieldsSafetyRegressionuM  _fire_blocked_no_approval / _oneshot_wrapper_block 의 None 안전성 회귀 테스트.

    두 빌더 함수는 fire_fn / subprocess 를 호출하지 않는 순수 block-result 빌더이므로
    실 발사 경로를 일절 건드리지 않는다(Test15_8 에서 명시 입증).
    raw ANU key 노출 0 도 검증(Test15_9).
    Neligibilityr   c                   t         j                  t         j                  t         j                  t        dt
        ddddt         j                  ||      S )u  eligibility / reasons 를 파라미터로 받는 더미 OwnerProofGateResult 생성.

        필수 필드(schema, status, task_id, result_json_path, head_sha, argv,
        fire_blocked, active, owner_key_proof_present, schedule_owner_proof,
        eligibility)는 모두 더미 값 — eligibility/reasons 만 파라미터화.
        None 을 그대로 넘겨 None-safety 를 검증하는 것이 이 헬퍼의 목적.
        z/tmp/dummy.result.jsonNFT)schemar   rh   r   ri   rN   r   activerl   schedule_owner_proofr  r   )r   OwnerProofGateResultGATE_SCHEMAr   r   r@   GATE_OWNER_PROOF_ANU)r^   r  r   s      r4   
_make_gatez,Test15_NoneFieldsSafetyRegression._make_gate  sR     ,,'';;"5$(!)!>!># - 
 	
r6   c                &   | j                  d dg      }t        j                  |d      }| j                  |j                  t
               | j                  |j                  i        | j                  |j                  t        j                         y )Nr1r  Fr  )	r  r   _fire_blocked_no_approvalrv  r  rw  r   r   r   r^   r   r   s      r4   1test_01_fire_blocked_no_approval_eligibility_nonezSTest15_NoneFieldsSafetyRegression.test_01_fire_blocked_no_approval_eligibility_none  so     OOtfO=0050Acoot4"-X%K%KLr6   c                    | j                  i d       }t        j                  |ddg      }| j                  |j                  t
               | j                  d|j                         y )Nr  FXr  extra_reasons)r  r   r  rv  r   rM   r   r  s      r4   -test_02_fire_blocked_no_approval_reasons_nonezOTest15_NoneFieldsSafetyRegression.test_02_fire_blocked_no_approval_reasons_none  sW     OODO9005QTPU0Vckk40c3;;'r6   c                h   | j                  d d       }t        j                  |ddg      }| j                  |j                  t
               | j                  |j                  t               | j                  d|j                         | j                  |j                  t        j                         y )Nr  TYr  )r  r   r  rv  r  rw  r   rM   r   r   r   r   r  s      r4   *test_03_fire_blocked_no_approval_both_nonezLTest15_NoneFieldsSafetyRegression.test_03_fire_blocked_no_approval_both_none  s    OOdO;004PSu0Ucoot4ckk40c3;;'X%K%KLr6   c                   | j                  d dg      }t        j                  |t        j                  d      }| j	                  |j
                  t               | j                  |j
                  i        | j                  |j                         | j                  |j                         | j                  |j                         y )Nr  r  test_reasonr   reason)r  r   _oneshot_wrapper_blockr   rv  r  rw  r   r   rN   r   r   r   r  r  s      r4   .test_04_oneshot_wrapper_block_eligibility_nonezPTest15_NoneFieldsSafetyRegression.test_04_oneshot_wrapper_block_eligibility_none   s     OOtfO=--h<<] . 
 	coot4"-#((#(()$r6   c                    | j                  i d       }t        j                  |t        j                  d      }| j	                  |j
                  t               | j                  d|j
                         y )Nr  block_because_noner  )r  r   r  r   rv  r   rM   r   r  s      r4   *test_05_oneshot_wrapper_block_reasons_nonezLTest15_NoneFieldsSafetyRegression.test_05_oneshot_wrapper_block_reasons_none  sb     OODO9--h11:N . 
 	ckk40*CKK8r6   c                .   | j                  d d       }t        j                  |t        j                  d      }| j	                  |j
                  t               | j	                  |j                  t               | j                  d|j                         y )Nr  	both_noner  )
r  r   r  r   rv  r  rw  r   rM   r   r  s      r4   'test_06_oneshot_wrapper_block_both_nonezITest15_NoneFieldsSafetyRegression.test_06_oneshot_wrapper_block_both_none  sr    OOdO;--h;;K . 
 	coot4ckk40k3;;/r6   c                z   ddd}ddg}| j                  ||      }t        j                  |ddg	      }| j                  |j                  |       | j                  d|j                         | j                  d|j                         | j                  d|j                         t        j                  |t        j                  d
      }| j                  |j                  |       | j                  d|j                         | j                  d|j                         | j                  d
|j                         y )Nro  T)kflagr  r2r  Fextrar  wrap_reasonr  )	r  r   r  r   r  r   r   r  r   )r^   eligrsnsr   out_blockedout_wrappers         r4   test_07_normal_values_preservedzATest15_NoneFieldsSafetyRegression.test_07_normal_values_preserved!  s    $'d|OOdO;885Y`Xa8b00$7dK//0dK//0g{22355h<<] 6 
 	00$7dK//0dK//0m[%8%89r6   c                   | j                  d d       }t        j                  d      5 }t        j                  d      5 }t        j	                  |ddg       t        j                  |t        j                  d       |j                          |j                          d d d        d d d        y # 1 sw Y   xY w# 1 sw Y   y xY w)	Nr  r  r  Ftestr  pure_builderr  )r  r   r  r   r  r  r   r   )r^   r   mock_run
mock_popens       r4   ,test_08_none_inputs_do_not_invoke_subprocesszNTest15_NoneFieldsSafetyRegression.test_08_none_inputs_do_not_invoke_subprocess6  s     OOdO;JJ'(		+,4JJ)*		+.8..qvh.W++(55n ,  &&(((*		+ 		+ 		+ 		+ 		+ 		+s#   B<A B0B<0B9	5B<<Cc                   | j                  d d       }t        j                  |d      }t        j                  |j                         d      }| j                  t        |d       t        j                  |t        j                  d      }t        j                  |j                         d      }| j                  t        |d       y )	Nr  Fr  rv   u4   _fire_blocked_no_approval 결과에 raw key 노출 0no_keyr  u1   _oneshot_wrapper_block 결과에 raw key 노출 0)
r  r   r  ry   r   r   r   r<   r  r   )r^   r   r  blocked_jsonr  wrapper_jsons         r4   %test_09_none_input_no_raw_key_in_jsonzGTest15_NoneFieldsSafetyRegression.test_09_none_input_no_raw_key_in_jsonF  s     OOdO;8858Izz+"5"5"7eL,0fg55h<<X 6 
 zz+"5"5"7eL,0cdr6   )r   r   r   __doc__r  r  r  r  r  r  r  r  r  r  r=   r6   r4   r  r    sC     )-d 
2M(M%90:*+ er6   r  __main__)r$   rm  r%   rm  )TTT)?r  
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   importlib.utilr   ry   rc   r   r`   unittestpathlibr   r   __file__resolveparentr   rm  rd   insertr5   _ENFr   ANU_KEY_2553r<   EXECUTOR_SELF_KEY_EXAMPLEr   ONESHOT_TARGET_TASK_IDr   r@   r   r   r>   rA   rC   rE   rQ   TestCaserS   r   r   r   r   r   r   r   r   r  r  r  r)  rG  rr  r  r  r   mainr=   r6   r4   <module>r     s.  6 #      	 
    X ''..55u:SXXHHOOAs5z"	 /1VW 02_ ` /1] ^ %'I J46\] 

--00 //	"1	1>H 1>j	Ue 	U+% +`u `&*`5 *`\]5 ]@cE c2^5 ^.Je J:b b"
OU 
O$ $6!d5 !dNUMe UMxP^5 P^h@Cu @CVSe(9(9 Sel zHMMO r6   