
    {jW*                       U d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	 ddl
mZmZmZmZmZ dZddddd	dd
Zded<   dZdZdZdZdZdZdZdddZe G d d             Zddd	 	 	 	 	 d dZe G d d             Zdd	 	 	 	 	 d!dZg dZy)"uY  utils.bot_settings_policy_loader — callback policy loader for bot lifecycle.

task-2640 Track C (회장 verbatim unfork #5) — bot_settings 정책 위치 + 정합 검증
helper. dev bot 후보 위치를 제안하고 누락 시 안전 기본값을 적용한다.

기본값 (회장 verbatim · spec §4.1):
  - require_anu_callback_on_finish: True
  - self_collector_forbidden: True
  - sendfile_only_forbidden: True
  - not_registered_forbidden: True
  - anu_key_single_source: "c119085addb0f8b7"
  - fail_closed_on_violation: True

후보 위치 (우선순위, dev bot 제안):
  1. /home/jay/workspace/config/callback_policy.json (workspace config 영역)
  2. /home/jay/.cokacdir/bot_settings.json 의 ``callback_policy`` 키
  3. /home/jay/workspace/memory/bot_settings_callback_policy.json (memory 영역)

본 loader 는 위 후보를 순차적으로 시도하여 첫 번째 존재 파일을 채택한다.
모두 부재 시 안전 기본값을 사용 (fail-closed 보장).

본 모듈은 Layer A / NO-CRON: subprocess / cokacdir / merge / cron 0 호출.
순수 데이터 로드 + 정책 검사만 수행.
    )annotationsN)	dataclassfield)Path)AnyDictListOptionalSequencez#utils.bot_settings_policy_loader.v1Tc119085addb0f8b7)require_anu_callback_on_finishself_collector_forbiddensendfile_only_forbiddennot_registered_forbiddenanu_key_single_sourcefail_closed_on_violationDict[str, Any]DEFAULT_POLICYBOT_FINALIZE_POLICY_VIOLATION!SELF_COLLECTOR_FORBIDDEN_FINALIZE SENDFILE_ONLY_FORBIDDEN_FINALIZE!NOT_REGISTERED_FORBIDDEN_FINALIZEANU_KEY_MISMATCH_FINALIZEPASSFAILc           	     N   | xsG t        t        j                  j                  dt	        t        j
                         dz                    }t        t        j                  j                  dt	        t        j
                                           }|dz  dz  |dz  dz  |dz  d	z  gS )
NWORKSPACE_ROOT	workspaceHOMEconfigzcallback_policy.jsonz	.cokacdirzbot_settings.jsonmemoryz!bot_settings_callback_policy.json)r   osenvirongetstrhome)workspace_rootwsr&   s      Q/home/jay/workspace/.worktrees/task-2717-dev1/utils/bot_settings_policy_loader.py_candidate_pathsr*   9   s    	 
4


'TYY[;-F)GHB 

vs499;'789D
X..{00
X;;     c                  Z    e Zd ZU ded<   ded<   ded<   ded<    ee      Zd	ed
<   ddZy)PolicyLoadResultr%   schemasourcer   policyboolfell_back_to_defaultdefault_factory	List[str]reasonsc                    | j                   | j                  t        | j                        | j                  t        | j                        dS )Nr.   r/   r0   r2   r6   )r.   r/   dictr0   r2   listr6   selfs    r)   to_jsonzPolicyLoadResult.to_jsonM   s;    kkkk4;;'$($=$=DLL)
 	
r+   Nreturnr9   )__name__
__module____qualname____annotations__r   r:   r6   r=    r+   r)   r-   r-   E   s,    KKt4GY4
r+   r-   )r'   candidate_pathsc           	     t   |t        |      n
t        |       }g }|D ]#  }	 |j                         s|j                  d|        *|j	                  d      }t        j                  |      }t        |t              rd|v rt        |d   t              r|d   }n)t        |t              r|}n|j                  d| d       t        t              }	|	j                  |j                         D 
ci c]  \  }
}|
t        v s|
| c}}
       |j                  d	| d
       t        t        t!        |      |	d|      c S  |j                  d       t        t        dt        t              d|      S # t        t
        j                  f$ r"}|j                  d| d|        Y d}~d}~ww xY wc c}}
w )uk  callback policy 를 후보 경로에서 순차 로드한다.

    부재 시 ``DEFAULT_POLICY`` 를 안전 기본값으로 적용한다 (fail-closed —
    require_anu_callback_on_finish=True 등 강한 정책이 기본).

    Returns:
        PolicyLoadResult — 채택 source 경로/`"default-safe"`, 최종 policy dict,
        fall-back 여부, 사유.
    Nzcandidate not present: zutf-8)encodingz
candidate z unreadable / invalid JSON: callback_policyz has non-dict root (skipped)zpolicy loaded from zG (overlay over DEFAULT_POLICY; missing keys filled with safe defaults).Fr8   u   no candidate present — using DEFAULT_POLICY (safe defaults: require_anu_callback_on_finish=True, fail_closed_on_violation=True).zdefault-safeT)r:   r*   existsappend	read_textjsonloadsOSErrorJSONDecodeError
isinstancer9   r   updateitemsr-   POLICY_LOADER_SCHEMAr%   )r'   rE   pathsr6   prawobje	extractedmergedkvs               r)   load_callback_policyr]   W   s     & 	_n- 

 G %
	88:!8<=++w+/C**S/C
 c4 %6#%=*!"DC
 -.IT"INNQC;< !%n!5'oo/Gda13FQTG	
 	!! %/ /	
  'q6!&
 	
?%
N NN	O #N#! I --. 	NNZs*FqcJK	$ Hs)   $E6'E61F4F46F1F,,F1c                      e Zd ZU ded<   ded<   ded<   ded<   ded<    ee	      Zded
<   edd       Zedd       Z	ddZ
y)PolicyCheckResultr%   r.   verdictr5   classificationsr   r0   finalize_stater3   r6   c                (    | j                   t        k(  S N)r`   r   r;   s    r)   okzPolicyCheckResult.ok   s    ||t##r+   c                <    | j                   r| j                   d   S d S )Nr   )ra   r;   s    r)   primary_classificationz(PolicyCheckResult.primary_classification   s     *.*>*>t##A&HDHr+   c           	         | j                   | j                  t        | j                        | j                  t        | j                        t        | j                        t        | j                        dS )N)r.   r`   ra   rg   r0   rb   r6   )	r.   r`   r:   ra   rg   r9   r0   rb   r6   r;   s    r)   r=   zPolicyCheckResult.to_json   sW    kk||#D$8$89&*&A&A4;;'"4#6#67DLL)
 	
r+   N)r?   r1   )r?   zOptional[str]r>   )r@   rA   rB   rC   r   r:   r6   propertyre   rg   r=   rD   r+   r)   r_   r_      sZ    KL""t4GY4$ $ I I	
r+   r_   )r0   c          	     @   |t        |      nt        t              }g }g }t        | j                  d            }| j                  d      }t        | j                  d            }t        | j                  d            }| j                  d      xs d}	| j                  d      xs d}
|j                  dd	      r*|r|s&|j	                  t
               |j	                  d
       |j                  dd	      r(|r&|j	                  t               |j	                  d       |j                  dd	      r3|
r1|	r/|
|	k(  r*|j	                  t               |j	                  d|
d       |j                  dd	      r(|r&|j	                  t               |j	                  d       |j                  dd	      r(|s&|j	                  t               |j	                  d       |j                  d      }|r4|	r2|	|k7  r-|j	                  t               |j	                  d|	d|d       t               }g }|D ])  }||vs|j                  |       |j	                  |       + |st        nt        }|t        k(  r|j	                  d       t        t        |||t        |       |      S )u  봇 lifecycle finalize 진입점에서 정책 필드 검사 (fail-closed).

    ``finalize_state`` 는 봇이 finalize 직전에 수집한 callback 상태:
        - callback_registered: bool — ANU normal callback cron 등록 여부
        - schedule_id: Optional[str] — 등록된 cron schedule id (non-null 필요)
        - sendfile_only: bool — sendfile 만 수행하고 cron 0 (NOT_REGISTERED 변종)
        - self_collector_attempted: bool — executor self-key 로 등록 시도
        - anu_key: str — 등록에 사용된 collector key
        - executor_key: str — executor self key (anu_key 와 달라야 함)

    Returns:
        PolicyCheckResult — verdict + classifications + reasons.
    callback_registeredschedule_idsendfile_onlyself_collector_attemptedanu_key executor_keyr   Tuo   require_anu_callback_on_finish=True but callback NOT registered (or schedule_id null) — finalize fail-closed.r   u{   self_collector_forbidden=True but executor self-key collector attempted — SELF_COLLECTOR 변종 차단 (회장 §2/§10).zexecutor_key == anu_key (u+   ) at finalize — SELF_COLLECTOR_FORBIDDEN.r   uv   sendfile_only_forbidden=True but sendfile-only path observed (cron 등록 0 + sendfile 만) — NOT_REGISTERED 변종.r   u[   not_registered_forbidden=True but callback NOT registered — NOT_REGISTERED 변종 차단.r   zanu_key_used z != single source u"    — ANU key 단일 출처 위반.u   finalize policy PASS — callback registered with schedule_id, no self_collector / sendfile_only / not_registered violation, anu_key 단일 출처 일치.)r.   r`   ra   r0   rb   r6   )r9   r   r1   r$   rJ   r   r   r   r   r   setaddr   r   r_   rS   )rb   r0   polclsr6   rk   rl   rm   rn   anu_key_usedrq   expected_anu_keyseenorderedcr`   s                   r)   check_finalize_policyr{      s   $ !,$v,$~2FCCG~112GHI $$]3K++O<=M#56  "%%i06BL!%%n5;L
ww/6"+JJ45NNM
 ww)405M

45L	

 ww)40\lWcgsWs

45''7 8( (	

 ww($/M

34H	

 ww)409L

45,	

 ww67L\=M-M

,-L++=""DF	

 DG D=HHQKNN1
 "dtG$,	
 #N+ r+   )rS   r   r   r   r   r   r   r   r   r-   r]   r_   r{   rd   )r'   Optional[Path]r?   z
List[Path])r'   r|   rE   zOptional[Sequence[Path]]r?   r-   )rb   r   r0   zOptional[Dict[str, Any]]r?   r_   ) __doc__
__future__r   rL   r"   dataclassesr   r   pathlibr   typingr   r   r	   r
   r   rS   r   rC   r   r   r   r   r   r   r   r*   r-   r]   r_   r{   __all__rD   r+   r)   <module>r      s  0 #  	 (  6 6<  '+ $# $/ $"  !@ $G !#E  $G !7 	 
 
 
& &*04F"F .F 	FR 
 
 
> (,a"a %a 	aHr+   