
    j.                       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
mZ ddlZ ee      j                         j                  d   Z ee      e	j$                  vr"e	j$                  j'                  d ee             ddlmZmZmZmZmZ d\  ZZZ ej:                  dd	d
de de ddde gd       ej:                  dd	dde de dddgd       ej:                  g dd       ej:                  dd	d
de de de dddgd       ej:                  dd	dde de dgd       ej:                  dd	d
de de de ddd gd!      gZ ej:                  dd	dde de d"e d#gd$       ej:                  dd	d
de de d"e d%dd&gd'       ej:                  dd	d(de de d)gd*      gZej@                  jC                  d+e      d,        Z"ej@                  jC                  d+e      d-        Z#d. Z$d/ Z%y)0u  task-2553+1 F1 negative regression — 원칙 5 forbidden API hard-block.

배경
----
PR #102 의 ``_validate_no_forbidden_fragments`` 는 5 개 endpoint fragment
blacklist (``/merges`` / ``/reviews`` / ``/pulls/`` / ``/branches/`` /
``/git/refs``) 만 차단했다. 호출부가 내부 헬퍼(``_assert_args_allowlist``)
를 우회해 ``gh_runner`` 를 직접 호출하면, **blacklist 에 없는 임의의
non-allowlisted endpoint** (예: ``/repos/o/r/actions/.../dispatches``,
``/repos/o/r/collaborators/u``, ``/user``) 가 그대로 통과했다 (원칙 5 FAIL).

F1 fix = fragment blacklist 폐기 → **default-deny allowlist**. 허용되는 단
1 형태(``_build_allowed_gh_args`` 가 박제하는 issue comments POST)와
구조적으로 정확히 일치하지 않는 모든 args 는 — 호출부가 내부 헬퍼를
우회하더라도 — ``gh_runner`` 실행 직전 ``_validate_no_forbidden_fragments``
가 deny 한다.

본 파일은 helper-bypass 경로에서 non-allowlisted endpoint 전건 deny 를
입증하는 단일 negative regression (RED→GREEN). 기존 79 tests 의 정상
호출 경로(``/gemini review`` 단일 endpoint)는 영향 0 — 본 파일은 정상
경로가 여전히 통과함도 함께 고정한다.
    )annotationsN)Path   )ALLOWED_COMMENT_BODYERR_BODY_NOT_ALLOWEDERR_ENDPOINT_NOT_ALLOWED_build_allowed_gh_args _validate_no_forbidden_fragments)zJeon-Jonghyukdev_workspacef   api-XPOSTz/repos//z$/actions/workflows/ci.yml/dispatchesz-fzbody=zactions-workflow-dispatch)idPUTz/collaborators/attackerzpermission=adminzadd-collaborator-admin)r   r   GETz/userzwhoami-token-probez/issues/z/labelszlabels[]=auto-mergezissue-labels-injectionDELETEz/issues/comments/999zdelete-commentz	/commentsz'body=/gemini review please also approvezbody-suffix-injectionz/pulls/z/mergezpulls-mergez/reviewszevent=APPROVEzpull-review-approvePATCHz/git/refs/heads/mainzgit-refs-force-pushargsc                   t        j                  t              5 }t        |        ddd       j                  }t        |      }t        t        f}||v }|s
t        j                  d|fd||f      dt        j                         v st        j                  t
              rt        j                  t
              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y# 1 sw Y   GxY w)	u   helper 우회 → blacklist 에 없던 non-allowlisted endpoint 전건 deny.

    fix 전(RED): blacklist 미매칭 → raise 없이 통과 → DID NOT RAISE 실패.
    fix 후(GREEN): default-deny → RuntimeError.
    N)in)zK%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.value
})
} in %(py8)sstrexc)py0py1py3py5py8zassert %(py10)spy10)pytestraisesRuntimeErrorr
   valuer   r   r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)r   r   @py_assert2@py_assert4@py_assert7@py_assert6@py_format9@py_format11s           g/home/jay/workspace/.worktrees/task-2553p1-dev2-f1/tests/regression/test_owner_trigger_2553_plus1_f1.py8test_f1_helper_bypass_non_allowlisted_endpoint_is_deniedr4   a   s     
|	$ /(./yyM3y>M68LMM>MMMMM>MMMMMMM3MMM3MMMMMMsMMMsMMMyMMM>MMMMMMMMMMM/ /s   E++E5c                v    t        j                  t              5  t        |        ddd       y# 1 sw Y   yxY w)uT   구 blacklist 가 막던 merge/approve/force-push 는 fix 후에도 deny (회귀 0).N)r!   r"   r#   r
   r   s    r3   ,test_f1_old_blacklist_fragments_still_deniedr7   m   s-     
|	$ /(./ / /s   /8c                 L    t        t        t        t              } t	        |        y)u   정상 경로(`_build_allowed_gh_args` 박제 args)는 fix 후에도 통과.

    기존 79 tests 의 정상 `/gemini review` 호출 경로 영향 0 을 고정.
    N)r	   _OWNER_REPO_PRr
   r6   s    r3   /test_f1_allowed_args_still_pass_zero_regressionr<   t   s    
 "&%5D$T*    c                     t        t        t        t              dgz   } t	        j
                  t              5  t        |        ddd       y# 1 sw Y   yxY w)u\   allowlist strict-equality: 정상 args 에 무해해 보이는 flag 1 개만 더해도 deny.z--silentN)r	   r9   r:   r;   r!   r"   r#   r
   r6   s    r3   1test_f1_allowed_args_exact_shape_is_the_only_passr?   ~   s@    !&%5DD	|	$ /(./ / /s   AA)&__doc__
__future__r   builtinsr'   _pytest.assertion.rewrite	assertionrewriter%   syspathlibr   r!   __file__resolveparentsWORKSPACE_ROOTr   pathinsertanu_v2.owner_trigger_patr   r   r   r	   r
   r9   r:   r;   param_BYPASS_NON_ALLOWLISTED_OLD_BLACKLIST_STILL_DENIEDmarkparametrizer4   r7   r<   r?    r=   r3   <module>rU      s  . #   
  h'')11!4~chh&HHOOAs>*+  ; s FLL	fxq7[\	+,-	/&
 FLL	ewvhaw6MNPTVhi# FLL% FLL	fxqxuGL	$	&#
 FLL	h'&5'9M NO FLL	fxqxuIN	8	:"/ @ FLL	ewvhawgcU&IJ FLL	fxqwse8L		  
 FLL	g%8LMN  " !89N :N !<=/ >/+/r=   