--- /tmp/pr102_otp.py	2026-05-16 12:38:10.470755771 +0900
+++ anu_v2/owner_trigger_pat.py	2026-05-16 12:35:21.468761046 +0900
@@ -322,27 +322,40 @@
 # 회장 §명시 — 본 모듈에서 실제 호출 가능한 method name 정적 검사 대상 (regression grep).
 # 호출부 / 코멘트 / docstring 에서 키워드 등장은 OK 이나 실제 gh api 호출 path 에는 X.
 # (보안 어설션 grep 카운트는 docstring/주석 포함 카운트되므로 actual call 은 0 임을 별도 검증.)
-_FORBIDDEN_ENDPOINT_FRAGMENTS: tuple[str, ...] = (
-    "/merges",
-    "/reviews",
-    "/pulls/",
-    "/branches/",
-    "/git/refs",
-)
+#: F1 (task-2553+1, 원칙 5): fragment blacklist 폐기 → default-deny allowlist.
+#: 허용되는 gh args 는 `_build_allowed_gh_args` 가 박제하는 issue comments
+#: POST 단일 형태뿐이다. 아래 정규식은 그 endpoint(`/repos/<owner>/<repo>/
+#: issues/<pr>/comments`)와 정확히 일치하는 경우에만 통과시키고, 그 외 모든
+#: endpoint(merge/review/actions/collaborators/user/labels …)는 — 구
+#: blacklist 에 없던 것을 포함해 — 전부 deny 한다.
+_ALLOWED_GH_ENDPOINT_RE = re.compile(r"^/repos/[^/]+/[^/]+/issues/[0-9]+/comments$")
 
 
 def _validate_no_forbidden_fragments(args: Sequence[str]) -> None:
-    """방어적 2차 차단: args 안에 금지 endpoint fragment 가 섞여 있는지 추가 검사.
+    """default-deny allowlist strict gate — gh_runner 실행 직전 최종 차단.
 
-    `_assert_args_allowlist` 가 이미 strict equality 로 차단하지만, 호출부가
-    내부 헬퍼를 우회해 직접 gh_runner 를 호출하더라도 본 함수가 raise 하도록 한다.
+    회장 task-2553+1 F1 / 원칙 5: 기존 5-fragment blacklist
+    (`/merges` `/reviews` `/pulls/` `/branches/` `/git/refs`) 는 그 5 개에
+    매칭되지 않는 임의의 non-allowlisted endpoint(예: `/actions/.../dispatches`,
+    `/collaborators/...`, `/user`, `/issues/<n>/labels`)를 helper 우회 시
+    그대로 통과시켰다. 이를 폐기하고 **default-deny allowlist** 로 전환한다.
+
+    `_build_allowed_gh_args` 가 박제하는 단 1 형태(issue comments POST,
+    body == `/gemini review`)와 **구조적으로 정확히 일치**하지 않는 모든
+    args 는 — 호출부가 `_assert_args_allowlist` 등 내부 헬퍼를 우회해 직접
+    gh_runner 를 호출하더라도 — 본 함수가 raise 한다 (실행 직전 strict gate).
+    함수 시그니처/호출부는 무변경 (args 만으로 구조 검증; F2 무관).
     """
-    for token in args:
-        if not isinstance(token, str):
-            continue
-        for frag in _FORBIDDEN_ENDPOINT_FRAGMENTS:
-            if frag in token:
-                raise RuntimeError(ERR_ENDPOINT_NOT_ALLOWED)
+    args_list = list(args)
+    if len(args_list) != 6 or not all(isinstance(a, str) for a in args_list):
+        raise RuntimeError(ERR_ENDPOINT_NOT_ALLOWED)
+    head, dash_x, post, endpoint, dash_f, body = args_list
+    if (head, dash_x, post, dash_f) != ("api", "-X", "POST", "-f"):
+        raise RuntimeError(ERR_ENDPOINT_NOT_ALLOWED)
+    if _ALLOWED_GH_ENDPOINT_RE.match(endpoint) is None:
+        raise RuntimeError(ERR_ENDPOINT_NOT_ALLOWED)
+    if body != f"body={ALLOWED_COMMENT_BODY}":
+        raise RuntimeError(ERR_BODY_NOT_ALLOWED)
 
 
 # ─── 본체 ────────────────────────────────────────────────────────────────────
