# anu_v3 CLI output-path policy — task-2617 (회장 직접 승인 2026-05-19)
#
# task-2616 scan 이 확정한 Critical7 "arbitrary fs write" 3건의 출력 경로를
# 정책 허용 경로로만 제한한다. anu_v3.cli_output_path_guard 가 이 파일을
# 로드하여 fail-closed 검증을 수행한다.
#
# 적용 대상 (guard 경유 강제):
#   - anu_v3/batch_hold_adjudicator.py            (--output)
#   - anu_v3/batch_dependency_classifier.py       (--out)
#   - anu_v3/pre_authorized_evidence_bundle_builder.py (--out)
#
# 비대상 (stdout-only safe — guard 미적용·byte-0 불변):
#   - anu_v3/auto_remediation_planner.py
#   - anu_v3/codex_high_classifier.py
#   - anu_v3/critical7_classifier.py
schema: anu_v3.cli_output_path_policy.v1
task_id: task-2617

# CANONICAL_WS_ROOT — CLAUDE.md §1 / 회장 §4. 이 경로 밖 출력은 전부 거부.
canonical_ws_root: /home/jay/workspace

# 파일 출력은 아래 root 직하위로만 허용. 그 외(절대경로·anu_v3·config·
# memory/fixtures 포함)는 fail-closed.
allowed_roots:
  - memory/events
  - memory/reports

# 파일명은 task-id prefix 로 시작해야 한다 (task-2617.*, task-2613+1.* …).
task_id_prefix_required: true

filename:
  # allowed_root 직하위 단일 파일만 허용 (하위 디렉터리 중첩 금지).
  single_segment_under_allowed_root: true

# fail-closed 거부 클래스 (guard 가 코드로 강제 — 본 목록은 문서/감사용).
deny:
  - absolute_outside_ws      # 절대경로 (ws 내부라도 상대표기 강제)
  - dotdot_traversal         # '..' component
  - symlink_component        # 경로 중간 symlink (O_NOFOLLOW+lstat)
  - hardlink                 # 기존 inode 로의 link/overwrite
  - ws_escape                # 정규화 후 ws_root 이탈
  - overwrite_existing       # 기존 파일 덮어쓰기 (O_EXCL + link no-overwrite)

# TOCTOU 방어 (guard 구현 불변식 — 문서/감사용).
toctou_defense:
  - "Path.resolve() strict-prefix 단독 불충분 가정 금지"
  - "ws_root→부모 component 별 O_NOFOLLOW open + lstat"
  - "O_CREAT|O_EXCL|O_NOFOLLOW temp + fsync"
  - "os.link no-overwrite (EEXIST=fail-closed) + dir-fd 상대연산"
  - "post-resolve revalidate (/proc/self/fd) 후 ws 재확인"
  - "실패 시 write 전 차단 · 부분파일 미잔존"
