
    MjSa                       d Z ddlmZ ddlmZmZ ddlmZmZm	Z	 ddl
mZmZmZmZmZmZ ddlmZmZ dZdZd	Z eeeh      Ze G d
 d             Zddddddd ee      ddd
	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d1dZe G d d             Z ee      d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d2dZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'd Z(d!Z)d"Z*d#Z+ eh d$      Z,d3d%Z-d4d&Z.dd'd5d(Z/e G d) d*             Z0	 	 	 	 	 	 	 	 d6d+Z1ddddddd ee      d,	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d7d-Z2g d.Z3d8d9d/Z4e5d0k(  r e6 e4             y):u  dispatch.normal_fallback_callback_helper — ANU-owned normal/fallback
callback registration helper + post-registration owner cross-check.

task-2553+49 (§8 / §10 / 9-R.1 — 코드/파일 자동화).

The actual normal/fallback callback cron is registered via the external
``cokacdir --cron`` tool (a cron-direct path that ANU cannot file-patch,
9-R.1). So the owner=ANU-key pin is enforced at the **ANU control layer**,
which IS code-patchable:

  1. ``build_anu_owned_callback_request`` — the dispatch prompt generator /
     4-tuple registration step builds the callback registration request HERE.
     It is **fail-closed**: an owner key equal to the executor self key, or
     not a configured independent ANU key, or a non-ANU collector role, makes
     the request INVALID and NO command argv is produced (회장 §2/§8/§10).
  2. ``verify_post_registration_owner`` — after ``cokacdir --cron`` returns,
     the ANU control layer re-reads the schedule_history / registry owner
     binding and cross-checks key/chat/role. An owner that resolved to the
     executor key (or any non-ANU key) at registration time -> FAIL (회장 §8
     "등록 후 schedule_history/registry 에서 chat_id·key·role binding 교차
     검증").

Standalone, zero-mutation, Layer A / NO-CRON (9-R.1): this module performs
ZERO cron register/remove, ZERO dispatch, ZERO ``subprocess`` / ``cokacdir``
exec. It only *builds a request descriptor* and *validates* an owner binding.
The authorized session executes the (ANU-keyed) cron outside this module.
    )annotations)	dataclassfield)ListOptionalSequence)DEFAULT_ANU_KEYSENFORCER_SCHEMAFAILPASSenforce_callback_owner
is_anu_key)ExecutorSelfKeyForbidden'assert_collector_key_is_independent_anuz+dispatch.normal_fallback_callback_helper.v1normalfallbackc                      e Zd ZU dZded<   ded<   ded<   ded<   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	ddZ
y)CallbackRequestu  An owner-validated callback registration request descriptor.

    ``argv`` is the (data-only) ``cokacdir --cron`` argument vector an
    authorized session would execute. It is produced ONLY when the owner
    binding is fail-closed valid (owner == an independent ANU key, not the
    executor self key). On FAIL, ``argv`` is None — no registration is
    possible (회장 §2/§8/§10).
    strschemaverdictkindtask_id	owner_keychat_idOptional[str]cron_idOptional[List[str]]argvdictenforcementdefault_factory	List[str]reasonsc                (    | j                   t        k(  S Nr   r   selfs    Y/home/jay/workspace/.worktrees/task-2643-dev6/dispatch/normal_fallback_callback_helper.pyokzCallbackRequest.okW       ||t##    c                $   | j                   | j                  | j                  | j                  | j                  | j
                  | j                  | j                  t        | j                        nd | j                  t        | j                        d
S )N
r   r   r   r   r   r   r   r   r!   r%   )r   r   r   r   r   r   r   r   listr!   r%   r)   s    r+   to_jsonzCallbackRequest.to_json[   sh    kk||II||||||'+yy'<DO$++DLL)
 	
r.   Nreturnboolr4   r    )__name__
__module____qualname____doc____annotations__r   r1   r%   propertyr,   r2    r.   r+   r   r   A   s_     KL
ILNL
t4GY4$ $
r.   r   N ANUTcokacdir_cron_directF)
r   dispatch_cron_idnormal_collector_cron_idfallback_callback_cron_idcollector_roleprompt_claims_anu_collector
entry_pathanu_keysno_fallbackanu_keys_resolvablec                   | t         vr2t        t        t        | ||t	        |      |di d| dt          dg
      S 	 t        |       t        ||||||	|	n| t        k(  r|nd|
|
n| t        k(  r|nd|t	        |      |||||      }|j                  t        k7  rQt        t        |j                  | ||t	        |      |d|j                         dgt        |j                        z   
      S d	d
|d|dt	        |      d|dg
}t        t        t        | ||t	        |      |||j                         dg
      S # t        $ r4}t        t        t        | ||t	        |      |di d| g
      cY d}~S d}~ww xY w)u  Build a fail-closed normal/fallback callback registration request.

    The owner pin is enforced via ``enforce_callback_owner`` BEFORE any argv
    is produced. If the owner is the executor self key / not an independent
    ANU key / collector role != ANU -> verdict FAIL and ``argv=None`` (the
    cron-direct path therefore CANNOT register an executor-owned callback,
    회장 §2/§8/§10). HOLD propagates (§6 conditional escalation).
    Nzunknown callback kind z (expected )r0   u   dispatch_callback_contract.assert_collector_key_is_independent_anu fail-closed — owner_key 가 독립 ANU key (c119085addb0f8b7) 가 아님: )r   executor_keycollector_keycollector_owner_keyrD   rB   rC   rA   r   rE   rF   rG   rH   rI   ui   owner enforcement did not PASS — no cron-direct registration argv produced (fail-closed, §2/§8/§10).cokacdirz--cron--atz--chatz--keyz--onceu4   owner=independent ANU key — fail-closed gate PASS.)VALID_KINDSr   HELPER_SCHEMAr   r   _dcc_assert_independent_anu_DCC_ExecutorSelfKeyForbiddenr   CALLBACK_KIND_NORMALCALLBACK_KIND_FALLBACKr   r   r2   r1   r%   )r   r   rL   r   r   promptatr   rA   rB   rC   rD   rE   rF   rG   rH   rI   _dcc_excenfr   s                       r+    build_anu_owned_callback_requestr[   j   s   8 ; L-dX[QOP
 	
(
#I.& !!%% (3 %!%99't )4 &!%;;')G$?/-C2 {{d KKLK Ls{{#$
 	
( 	
GD GKKMGH W ) 
 L22:=
 	

s   D5 5	E2>)E-'E2-E2c                      e Zd ZU ded<   ded<   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ddZ	y)PostRegistrationOwnerCheckr   r   r   r   r5   expected_owner_is_anuobserved_owner_keyobserved_chat_idobserved_roler"   r$   r%   c                (    | j                   t        k(  S r'   r(   r)   s    r+   r,   zPostRegistrationOwnerCheck.ok  r-   r.   c           
         | j                   | j                  | j                  | j                  | j                  | j
                  | j                  t        | j                        dS )Nr   r   r   r^   r_   r`   ra   r%   )	r   r   r   r^   r_   r`   ra   r1   r%   r)   s    r+   r2   z"PostRegistrationOwnerCheck.to_json  sQ    kk||||%)%?%?"&"9"9 $ 5 5!//DLL)	
 		
r.   Nr3   r6   )
r7   r8   r9   r;   r   r1   r%   r<   r,   r2   r=   r.   r+   r]   r]      sO    KLLt4GY4$ $

r.   r]   )rG   c           
        g }t        ||      }|r||k(  r|j                  d       |s|j                  d|d       t        |      t        |      k7  r|j                  d|d|d       |dk7  r|j                  d|d	       |st        nt        }	|	t        k(  r|j                  d
       t        t        |	| ||t        |      ||      S )u)  회장 §8 — 등록 후 schedule_history/registry owner 교차검증.

    After ``cokacdir --cron`` registers the callback, the ANU control layer
    re-reads the owning schedule's key/chat/role and asserts it is an
    independent ANU binding. An owner that resolved to the executor key (or
    any non-ANU key), a chat mismatch, or a non-ANU role -> FAIL (a
    registered executor-self callback is detected post-hoc and rejected).
    Read-only; the observed values are supplied by the caller from
    schedule_history / the durable registry.
    u   post-registration owner key == executor self key — a cron-direct executor-self callback slipped through and is rejected (§8 post-reg owner cross-check / §2).zpost-registration owner key uA    is not a configured independent ANU key (§8 owner cross-check).zchat_id mismatch: registered=z
 expected=u    (§8 binding cross-check).r?   zregistered collector role=u5    != 'ANU' (§8 owner cross-check / §2 regression 5).ux   post-registration owner binding is an independent ANU key with matching chat_id and ANU role — cross-check PASS (§8).rd   )r   appendr   r   r   r]   rR   )
r   rL   r_   r`   ra   expected_chat_idrG   r%   owner_is_anur   s
             r+   verify_post_registration_ownerri     s   ( G0(;L0L@6	

 *+=*@ AF F	
 $4 55+,<+? @(++FH	
 ((9 :: :	
 "dtG$M	
 &*--.#	 	r.   z/home/jay/workspacei<  z4dispatch.normal_fallback_callback_helper.launcher.v1ANU_OWNED_READYSELF_KEY_FAIL_CLOSEDCALLBACK_PROMPT_TOO_LARGECANONICAL_ROOT_INVALIDOWNER_ENFORCEMENT_FAILEDr   FAIL_CLOSEDCOLLECTOR_ANU%RECOVERY_ONLY_NO_FINAL_REPORT_TRIGGER>   rX   sha256r   summaryr   r   report_pathresult_pathcallback_kindcanonical_rootrD   c                >    t        | xs dj                  d            S )u&   callback prompt 의 UTF-8 byte 길이.r>   zutf-8)lenencode)rW   s    r+   callback_prompt_utf8_bytesr{   m  s    "$$W-..r.   c                   | xs dj                         D cg c]#  }|j                         s|j                         % }}|sy|D ]5  }d|vr y|j                  dd      d   j                         }|t        vs5 y yc c}w )u   prompt 가 envelope-only 인가 — 모든 비공백 line 이
    `key=value` 형태이고 key 가 ENVELOPE_ALLOWED_KEYS 에 속하면 True
    (자유 지시문 금지, 회장 §5.6 envelope-only).r>   F=   r   T)
splitlinesstripsplitENVELOPE_ALLOWED_KEYS)rW   lnlineskeys       r+   is_envelope_onlyr   r  s     $*<R";";"=LBRXXZLEL b=hhsAq!'')++  Ms
   A?A?require_envelopec                  t        |       }t        | xs d      }|t        kD  }t        |       }g }d}d}|r$d}t        }|j                  d| dt         d       |r|sd}|dk(  rd}|j                  d	       |||||||d
S )u   callback prompt 검증: UTF-8 ≤3900 bytes + envelope-only.
    반환 dict: ok, utf8_bytes, chars, too_large, envelope_only, status, reasons.r>   OKTFzcallback prompt z	 bytes > u5    (CALLBACK_PROMPT_TOO_LARGE fail-closed, §5.5/§10).ENVELOPE_VIOLATIONu5   callback prompt 가 envelope-only 가 아님 (§5.6).)r,   
utf8_byteschars	too_largeenvelope_onlystatusr%   )r{   ry   CALLBACK_PROMPT_MAX_BYTESr    STATUS_CALLBACK_PROMPT_TOO_LARGErf   )	rW   r   utf8r   r   env_onlyr%   r   r,   s	            r+   validate_callback_promptr     s     &f-D"E00I'HGF	B1tfI.G-H IC C	
 T>)FNOuW r.   c                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded<   ded<   ded	<   d
ed<   ded<   ded<   dZded<    ee      Zded<   edd       Z	ddZ
y)LaunchDecisionr   r   r   r   r   r   r   r   rw   r5   canonical_root_correctedr   r   r    contract_fieldsNzOptional[dict]requestr"   r$   r%   c                (    | j                   t        k(  S r'   )r   LAUNCH_PASSr)   s    r+   r,   zLaunchDecision.ok  s    ||{**r.   c                x   | j                   | j                  | j                  | j                  | j                  | j
                  t        | j                        | j                  | j                  | j                  t        | j                        nd | j                  | j                  t        | j                        dS )Nr   r   r   r   r   r   r   rw   r   r   r   r   r%   )r   r   r   r   r   r   r   r   rw   r   r   r1   r   r   r%   r)   s    r+   r2   zLaunchDecision.to_json  s    kk||kkII||4<<("11(,(E(E'+yy'<DO$#33||DLL)
 	
r.   r3   r6   )r7   r8   r9   r;   r   r   r1   r%   r<   r,   r2   r=   r.   r+   r   r     sm    KLK
ILNL""
"G^"t4GY4+ +
r.   r   c           
         t        |       t        | xs d      ||t        t        |      t        |xs d      t        |      t        d	S )u'   회장 §10 callback contract 9 fields.r>   )	r{   callback_prompt_charscallback_cron_idcallback_registration_statuscallback_roleenvelope_only_compliancefallback_prompt_utf8_bytesfallback_safety_net_registered'fallback_safety_net_role_single_purpose)r{   ry   CALLBACK_ROLE_COLLECTOR_ANUr5   FALLBACK_ROLE_SINGLE_PURPOSEcallback_promptr   r   r   r   fallback_promptfallback_registereds          r+   _contract_fieldsr     sO    
 'A&Q!$_%:!;#(.4$($7&@AVTV&W*./B*C3O
 
r.   )rw   r   rA   rB   rC   r   r   rG   c                2   g }d}|st         }d}|j                  d       nd|t         k7  r[t        || |t        t	        |      |xs dd      }t        t        t        t        | ||t        |      |dd|d|dt         d	g
      S t        ||      }|d   rLt        || |t        |d   |xs dd      }t        t        t        t        | ||t        |      ||d||d   
      S |	xs | d}	|
xs | d}
|xs | d}|| t        k(  r|
n|}t        | |||t        |      ||||	|
||      }| t        k(  xr |j                  }|j                  rt        }t         }|j                  d       nUt        }||k(  rt"        }|j                  d       nt$        }|j                  d       |j'                  |j(                         t        || |||d   |xs d|      }t        t        ||| ||t        |      |||j*                  ||j-                         |      S )uo  단일 callback/fallback 런타임 launcher (회장 §3 launcher 단일화).

    fail-closed 순서: canonical root → prompt byte/envelope → owner enforce
    (build_anu_owned_callback_request 경유). owner==executor self-key 면
    SELF_KEY_FAIL_CLOSED (argv=None). ANU key 만 PASS.
    실 cron 발사/ subprocess 0 — argv(데이터)만 생성한다.
    FTu<   canonical_root 미지정 → /home/jay/workspace 로 교정.r>   r   Nzcanonical_root=z != u    → fail-closed (§5.9).)r   r   r   r   r   r   r   rw   r   r   r   r%   r   r   r   r%   z
::dispatchz::normalz
::fallback)r   r   rL   r   r   rW   rX   r   rA   rB   rC   rG   u7   owner=ANU key — launcher PASS, ANU-owned argv 생성.uK   owner_key == executor self key → SELF_KEY_FAIL_CLOSED (argv=None, §5.3).u3   owner enforcement FAIL → fail-closed (argv=None).r   )CANONICAL_ROOTrf   r   STATUS_CANONICAL_ROOT_INVALIDr   r   LAUNCHER_SCHEMALAUNCH_FAIL_CLOSEDr   r   r   rU   r[   rV   r,   STATUS_ANU_OWNED_READYr   STATUS_SELF_KEY_FAIL_CLOSEDSTATUS_OWNER_ENFORCEMENT_FAILEDextendr%   r   r2   )r   r   rL   r   r   rW   rX   rw   r   rA   rB   rC   r   r   rG   r%   root_correctedcfpvreqr   r   r   s                          r+   launch_callbackr     ss   2 G N'UV	>	)"w0*62+1ru	N
 ",>0tWW)Er&~&8^<N O0 0 12 	2 
"&;K	LB	+"w3_-+1ru	N
 ",>3$W)Nr2i=B 	B (AgYj+A7OgYh;O 9 Sy
=S/37K/K+1 	 +7S\&R*:!9";C  #99Dcff
vv'PQ$$0FNNhi4FNNPQs{{#	T76)?;Pb/
1B T9c'l%XXr3;;='	S Sr.   )rR   r
   rU   rV   rQ   r   r[   r]   ri   r   r   r   r   r   r   r{   r   r   r   r   r   r   r   r   r   mainc                   dd l }dd l}|j                  d      }|j                  dd      }|j	                  d      }|j                  ddt        t              	       |j                  d
d       |j                  dd       |j                  dd       |j                  dd       |j                  dd       |j                  dd       |j                  dd        d}|j                  |dd        |j                  dd       |j                  |       }t        |j                  |j                  |j                  |j                  |j                  |j                  |j                   |j"                  |j$                  |j&                   
      }t)        |j+                  |j-                         d             |j.                  rdS dS )Nr   z(dispatch.normal_fallback_callback_helper)progcmdT)destrequiredlaunchz--kind)r   choicesz	--task-id)r   z--executor-keyz--owner-keyz	--chat-idz--promptrP   10m)defaultz--canonical-rootz	--cron-idr   )r   r   z--no-require-envelope
store_true)action)
r   r   rL   r   r   rW   rX   rw   r   r   F)ensure_ascii   )argparsejsonArgumentParseradd_subparsers
add_parseradd_argumentsortedrQ   
parse_argsr   r   r   rL   r   r   rW   rX   rw   r   no_require_envelopeprintdumpsr2   r,   )	r   r   _jsonapsublp
_cron_flagadecs	            r+   r   r   ^  sz   "		 	 &P	 	QB




6C		!BOOHtVK5HOIOOK$O/OO$tO4OOMDO1OOK$O/OOJO.OOFEO*OO&O5&JOOJYO=OO+LOA
dA
VVQYYQ^^++qyyadd''222	4C
 
%++ckkm%+
891Ar.   __main__)$r   r   r   r   rL   r   r   r   r   r   rW   r   rX   r   r   r   rA   r   rB   r   rC   r   rD   r   rE   r5   rF   r   rG   Sequence[str]rH   r5   rI   r5   r4   r   )r   r   rL   r   r_   r   r`   r   ra   r   rg   r   rG   r   r4   r]   )rW   r   r4   int)rW   r   r4   r5   )rW   r   r   r5   r4   r    )r   r   r   r   r   r   r   r5   r   r   r   r5   r4   r    ) r   r   r   r   rL   r   r   r   r   r   rW   r   rX   r   rw   r   r   r   rA   r   rB   r   rC   r   r   r   r   r5   rG   r   r4   r   r'   )r   r   r4   r   )7r:   
__future__r   dataclassesr   r   typingr   r   r    dispatch.callback_owner_enforcerr	   r
   r   r   r   r   !anu_v3.dispatch_callback_contractr   rT   r   rS   rR   rU   rV   	frozensetrQ   r   tupler[   r]   ri   r   r   r   r   r   r   r   r   r   r   r   r   r   r{   r   r   r   r   r   __all__r   r7   
SystemExitr=   r.   r+   <module>r      s  6 # ( + + &
 > # -/EFG %
 %
 %
b ".2/3(,,#$45 $%I
I I 	I
 I I I 	I I I ,I  -I I "&I I  !I" #I$ %I& 'IX 
 
 
F $$45:: : 	:
 : : : :  :D '  H + 4 #>   8 "< " - F  " #  /
  GK : "
 "
 "
J$(;>*.374 %)!&*.2/3%)!#$45!gS
gS gS 	gS
 gS gS gS 	gS "gS gS $gS ,gS  -gS #gS gS  !gS" #gST<4 z
TV
 r.   