#!/usr/bin/env python3
"""Four Passport routes with real HTTP sequence and explicitly posthoc row checks."""
import hashlib
import json
from pathlib import Path
import integrate_20261010 as tool
from integrate_20261011_batches46_48 import item

HERE=Path(__file__).resolve().parent
PRIVATE=Path('/Users/wiscourper/Documents/workspace/local/dm8-resume-connect-20261012.q6m3ar')
B=Path('/private/tmp/cdx-ai-hk-course-b.Kmdirn/runtime')
BASE='work_ai_api/2026-10-12-dm8-hk-course-batch/'
REPORT=BASE+'PASSPORT_OWN_ACCOUNT_BC.md'
PINS={B/'passport-http-redacted-private.jsonl':'d5eb8703b818c1359d350f795f8ec0fd52fc0aca5a8148cd56388a57577d7ab6',
 PRIVATE/'passport-C.jsonl':'2b4bd4de568a6928036cf9bdccf16b71bdda2573c1c5d1f263a6c75e127a6385',
 B/'passport-posthoc-readback-private.json':'0a46721cb611a5ead9e5f31df6712979529646ababe7595dce0027af0eaad612',
 PRIVATE/'passport-readback-C.json':'ec68addf27a3357686c538eee3aff130c15d84e5b38bfed40872d00635ffff5c'}

def verify():
    for path,pin in PINS.items():assert hashlib.sha256(path.read_bytes()).hexdigest()==pin
    for file,pin in {'app/api/controller/Passport.php':'06d6e4b4891776d5a9ca347bbbe46d766bb309123a2be80f5b969a8069aec1b8','app/api/service/passport/Login.php':'90cca88e572003eeacf74aa2d28c75bf1cca25d6dbb3482b124cefa86bbbb597'}.items():
        assert hashlib.sha256((tool.source_root('ai_api')/file).read_bytes()).hexdigest()==pin
    canonical=[]
    for lane,path,posthoc,actor in [('B',B/'passport-http-redacted-private.jsonl',B/'passport-posthoc-readback-private.json',46919),('C',PRIVATE/'passport-C.jsonl',PRIVATE/'passport-readback-C.json',1934)]:
        rows=[json.loads(x) for x in path.read_text().splitlines() if x]
        assert len(rows)==6
        body_list=[]
        for i,r in enumerate(rows):
            assert r['case']==['loginAccount','loginNumber','loginDepartment','changePassword','loginAccount','loginAccount'][i]
            assert r['http']==200
            b=r['response_redacted'];assert b['status']==[200,200,200,200,500,200][i]
            if i in [0,1,2,5]:
                assert type(b['data']['userId']) is int and b['data']['userId']==actor
                assert b['data']['token']=='<redacted-token>'
                b['data']['userId']='<own-actor>'
            b.pop('trace_id',None);body_list.append(b)
        canonical.append(json.dumps(body_list,sort_keys=True,ensure_ascii=False))
        r=json.loads(posthoc.read_text())
        assert r['status']=='own_passport_rows_consistent' and r['own_ai_user_id']==actor
        assert r['label']=='new_posthoc_read_only_receipt_not_original_execution_stdout'
        assert r['ai_last_login_time_positive'] and r['store_password_hash_md5_shape'] and r['store_staff_and_department_relationships_match']
        assert r['store_password_status']==2 and r['store_password_version']==1
        assert r['ai_oauth_rows']==r['ai_healthkit_binding_rows']==r['business_http_sent']==r['dml_sent']==0
        assert not r['password_or_token_value_saved']
    assert canonical[0]==canonical[1]

def targets():
    out=[]
    for action in ['loginAccount','loginNumber','loginDepartment','changePassword']:
        kw={}
        if action in ['loginAccount','changePassword']:
            kw['invalid_type']='partial-evidence-original-password-rejected-new-password-accepted-after-one-change'
        out.append(item('ai_api','POST','/api/Passport/'+action,BASE,evidence=REPORT,
            readback='partial-evidence-new-timepoint-own-user-staff-department-password-version-readback-original-before-SQL-stdout-only',
            mysql_readback='partial-evidence-posthoc-own-row-relations-password-version-and-HTTP-old-reject-new-success',
            dm_readback='partial-evidence-posthoc-own-row-relations-password-version-and-HTTP-old-reject-new-success',
            parity='partial-evidence-full-redacted-business-JSON-equal-userId-original-integer-token-redacted',
            success_case='partial-evidence-owned-account-number-department-login-no-WeChat-and-one-password-change',
            cleanup='owned-users-retained-executor-reported-issued-tokens-revoked-no-external-call',**kw))
    return out

if __name__=='__main__':
    audit=HERE/'integration-20261012-batch111.json'
    assert not audit.exists(),'Preserve original transition'
    tool.main(targets(),audit,verify)
