import datetime,json,os,re,subprocess
from pathlib import Path
os.umask(0o077)
HERE=Path(__file__).parent
REPO=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
JOB='20260918-contextra-media-lan-r01'
ROOT=Path('/tmp/codex/ltb1021/git-closeout')/JOB;ROOT.mkdir(mode=0o700)
def cmd(a):
    p=subprocess.run(a,text=True,capture_output=True,timeout=60)
    assert p.returncode==0,p.stdout+p.stderr
    return p.stdout
paths=cmd(['git','-C',str(REPO),'diff','--name-only']).splitlines()+cmd(['git','-C',str(REPO),'ls-files','--others','--exclude-standard']).splitlines()
assert len(paths)==8 and not cmd(['git','-C',str(REPO),'diff','--cached','--name-only']).strip(),paths
cmd(['git','-C',str(REPO),'diff','--check'])
for name in paths:
    f=REPO/name
    if f.suffix=='.md':
        for target in re.findall(r'\]\(([^)]+)\)',f.read_text()):
            if '://' in target or target.startswith('#'):continue
            assert (f.parent/target.split('#',1)[0]).exists(),(name,target)
receipt=dict(schema_version='ltb1021.codex_hub.report_receipt.v1',receipt_id=JOB,
 timestamp=datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).isoformat(),
 session_alias='work-session',task='Contextra 내부망 파일 조회 정책 반영',
 results=['내부망 전용 무토큰 조회를 기본값으로 추가하고 Gateway만 반영했다.',
          '외부 주소/위조 헤더/비공개 파일과 무인증 제어 거부를 유지하고 채널을 보존했다.'],
 verify=['표적2개와 두 정책 nginx -t PASS. 실제 TLS검증 GET/HEAD200, Range206, 비허용주소403.',
         '보호파일404/제어401 및 컨테이너·채널 보존 확인, WSS 연결 정상.'],
 commits=[],remaining=['사용자 브라우저 CA 신뢰 및 영상 재생 확인'])
receipt_path=HERE/'report-receipt.json'
with receipt_path.open('x') as f:json.dump(receipt,f,ensure_ascii=False,indent=2)
print(cmd(['codex-report-receipt','--profile','ltb1021','--session-alias','work-session','--receipt',str(receipt_path)]))
mf=ROOT/'manifest.json'
args=['codex-git-closeout','prepare','--repository',str(REPO),'--output',str(mf),'--job-id',JOB,
 '--profile','ltb1021','--session-alias','work-session','--title','feat(gateway): 내부망 Artifact 무토큰 조회 정책 적용',
 '--message','Why=승인된 내부망 브라우저와 관제에서 파일 조회 토큰 연계 없이 클립과 썸네일을 확인한다.',
 '--message','What=lan_public/authenticated 선택과 내부망 기본값을 추가하고 Gateway만 반영했다. IP는 socket peer로 판정한다.',
 '--message','Impact=HTTPS와 경로 보호 및 제어 인증은 유지하며 Analytics/Sidecar/Redis와 채널 PID/run을 보존했다.',
 '--message','Verify=표적2개/두 정책 nginx -t PASS, 실제 CA검증 GET·HEAD200/Range206/비허용주소 및 위조헤더403/보호파일404/제어401. 브라우저 재생은 미검증.',
 '--message','Rollback=authenticated로 기존 Manager 토큰 정책을 선택 가능하다. 자동 rollback은 하지 않았고 활성 설정과 evidence를 보존했다.',
 '--verify','2 targeted tests and nginx -t for both policies PASS; CA-verified GET/HEAD/Range PASS',
 '--verify','Outside-LAN namespace and spoofed headers denied; control/private paths protected; channels preserved; WSS connected',
 '--verify','git diff --check and Markdown links PASS','--expires-in-seconds','86400']
for p in sorted(paths):args+=['--path',p]
print(cmd(args))
batch=ROOT/'batch.json'
print(cmd(['codex-git-closeout','batch-prepare','--output',str(batch),'--batch-id',JOB,'--profile','ltb1021',
 '--session-alias','work-session','--expected-group-count','1','--repository-label','contextra-analytics',
 '--manifest',str(mf),'--expect-plan-hash',json.loads(mf.read_text())['plan_hash'],'--expires-in-seconds','86400']))
h=json.loads(batch.read_text())['plan_hash']
print(cmd(['codex-git-closeout','batch-plan','--batch-manifest',str(batch),'--expect-batch-plan-hash',h]))
print(cmd(['codex-git-closeout','batch-present','--batch-manifest',str(batch),'--expect-batch-plan-hash',h]))
