
    Oej                        U d Z ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
mZ dZdZded<   d	Zd
ZdZdZdZdZdZ ed       G d d             ZddZddZded	 	 	 	 	 	 	 	 	 ddZg dZy)u  task-2693 callback authority 4-source validator (★ 회장 verbatim PR #152 hardening #4).

★ envelope 텍스트는 증거 아님 (회장 verbatim ANCHOR-2).
★ 4-source 모두 일치 시에만 PASS. 하나라도 실패 → fail-closed → HOLD_FOR_CHAIR.

Sources (4):
    1. envelope owner_key == ANU key (c119085addb0f8b7) — self-key fail-closed
    2. actual cron channel owner_key (cokacdir --cron-history 결과) == ANU key
    3. envelope 3 SID (chair_facing / collector / delivery) 모두 동일
    4. schedule_history `<sid>.log` last entry status == 'ok' AND chair_facing_session_id 필드 일치

Usage:
    validate(
        envelope=<dict>,
        actual_cron_owner_key=<str>,
        schedule_history_record=<dict>,
        anu_keys=DEFAULT_ANU_KEYS,
    ) -> Verdict

Verdict.classification ∈ {
    "AUTHORITATIVE_4SOURCE_OK",
    "ENVELOPE_OWNER_NOT_ANU",
    "ACTUAL_CRON_OWNER_NOT_ANU",
    "ENVELOPE_3SID_MISMATCH",
    "SCHEDULE_HISTORY_STATUS_FAIL",
    "SCHEDULE_HISTORY_SID_MISMATCH",
    "ENVELOPE_ACTUAL_CRON_OWNER_MISMATCH",
}

★ 본 validator 는 PR #152 expected_files 내부에서 분류만 수행한다.
  분류 결과 hold/merge 결정은 호출 측에서 회장 verbatim 도구를 통해 수행한다.
    )annotations)	dataclassfield)AnyIterableListOptionalSequencez-utils.callback_authority_4source_validator.v1)c119085addb0f8b7Sequence[str]DEFAULT_ANU_KEYSAUTHORITATIVE_4SOURCE_OKENVELOPE_OWNER_NOT_ANUACTUAL_CRON_OWNER_NOT_ANUENVELOPE_3SID_MISMATCHSCHEDULE_HISTORY_STATUS_FAILSCHEDULE_HISTORY_SID_MISMATCH#ENVELOPE_ACTUAL_CRON_OWNER_MISMATCHT)frozenc                      e Zd ZU ded<   ded<    ee      Zded<   dZded	<   dZded
<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   edd       Zy)Verdictstrschemaclassification)default_factoryz	List[str]reasonsNOptional[str]envelope_owner_keyactual_cron_owner_keychair_facing_session_idcollector_session_iddelivery_session_idschedule_history_statusschedule_history_session_idc                (    | j                   t        k(  S N)r   r   )selfs    -utils/callback_authority_4source_validator.pypassedzVerdict.passedA   s    ""&>>>    )returnbool)__name__
__module____qualname____annotations__r   listr   r   r   r    r!   r"   r#   r$   propertyr)    r*   r(   r   r   4   s{    Kt4GY4(,,+/=/-1]1*.-.)---1]1155? ?r*   r   c                Z    t        | t              sy| j                         t        |      v S )NF)
isinstancer   stripset)keyanu_keyss     r(   _is_anur:   F   s$    c399;#h-''r*   c                    t        | t              sy | j                  |      }t        |t              r |j	                         r|j	                         S d S r&   )r5   dictgetr   r6   )dr8   vs      r(   _get_strr@   L   s>    a	c
A"1c*qwwy1779BdBr*   N)schedule_history_recordr9   c           	     $   g }t        | d      }t        | d      }t        | d      }t        | d      }t        |t              r |j                         r|j                         nd}	t        |d      }
t        |d      }t	        ||	||||
|      }t        ||      s+|j                  d|d	       t        t        t        |fi |S t        |	|      s+|j                  d
|	d       t        t        t        |fi |S ||	k7  r.|j                  d|d|	d       t        t        t        |fi |S |||g}t        |      rt        t        |            dk7  r0|j                  d|d|d|       t        t        t        |fi |S |
dk7  r+|j                  d|
d       t        t        t         |fi |S |2||k7  r-|j                  d|d|       t        t        t"        |fi |S |j                  d       t        t        t$        |fi |S )ur  4-source 검증.

    envelope:
        ANU normal callback envelope (schemas/anu_normal_callback_envelope_v1.json).
        필수 필드: owner_key, chair_facing_session_id, collector_session_id,
        delivery_session_id.
    actual_cron_owner_key:
        cokacdir --cron-history <SID> 결과로 관측된 실제 cron channel owner_key
        (해당 SID 채널에 실제 등록된 key — envelope 텍스트와 무관한 actual evidence).
    schedule_history_record:
        schedule_history `<sid>.log` 최근 1줄 JSON dict.
        필수 필드: status (ok/cancelled/error), chair_facing_session_id (옵션).
    	owner_keyr    r!   r"   Nstatus)r   r   r    r!   r"   r#   r$   zenvelope.owner_key=uX    ∉ anu_keys — self-key 또는 누락 (★ envelope 텍스트만 보고 PASS 금지).zactual_cron_owner_key=um    ∉ anu_keys — cokacdir --cron-history 채널 owner 가 ANU 가 아님 (self-key 등록 또는 미등록).z != actual_cron_owner_key=u/    — envelope-actual 양방향 owner 불일치.   zenvelope 3 SID mismatch: chair=z collector=z
 delivery=okzschedule_history.status=u7    != 'ok' — cron 실행이 정상 완료되지 않음.z)schedule_history.chair_facing_session_id=z% != envelope.chair_facing_session_id=u   4-source 모두 일치: envelope.owner_key=ANU + actual_cron.owner_key=ANU + envelope 3 SID 동일 + schedule_history.status=ok (+ SID 일치).)r@   r5   r   r6   r<   r:   appendr   VALIDATOR_SCHEMAr   r   r   alllenr7   r   r   r   r   )enveloper   rA   r9   r   	env_owner	chair_sidcollector_siddelivery_sidactual_owner	sh_statussh_sidcommon_fieldssidss                 r(   validaterU   S   s   ( G;/I#<=IX'=>MH&;<L4>?TVY4Z_t_z_z_|(..0  CGL0(;I-/HIF$* )*( )$*M 9h'!) /> >	
 ')?ZMZZ <*$\$4 5j j	
 ')BG]}]] L !).HHX Y9 9	
 ')LggYfgg }l3Dt9CI!+-i]+mEV W$')	
 ')?ZMZZ D&ym3jk	
 ')Ew`R_`` f	17z B009}>	
 ')FaS`aaNN	M #%=wX-XXr*   )rH   r   r   r   r   r   r   r   r   r   rU   )r8   zOptional[Any]r9   zIterable[str]r+   r,   )r>   r   r8   r   r+   r   )
rK   r   r   r   rA   r   r9   r   r+   r   )__doc__
__future__r   dataclassesr   r   typingr   r   r   r	   r
   rH   r   r0   r   r   r   r   r   r   r   r   r:   r@   rU   __all__r3   r*   r(   <module>r[      s   @ # ( : :B "7 - 7 6 1 7 1 =  ? &K # $? ? ?"(C $(.[Y[Y )[Y !	[Y
 [Y [Y|r*   