from pathlib import Path
import subprocess,sys,json,importlib.util,os,re
ROOT=Path(__file__).resolve().parents[1]; HERE=Path(__file__).resolve().parent; cp=subprocess.run([sys.executable,str(HERE/'public-contract_q1.test.py')],cwd=ROOT,text=True,capture_output=True,env={**os.environ,'PYTHONDONTWRITEBYTECODE':'1'}); print(cp.stdout,end=''); m=re.findall(r'(\d+)/(\d+) PASS',cp.stdout); bp,bt=(map(int,m[-1]) if m else (0,1)); checks=[]
def ck(n,v): checks.append((n,bool(v)))
sp=importlib.util.spec_from_file_location('wf',ROOT/'src/webauthn_fixture.py'); wf=importlib.util.module_from_spec(sp); sp.loader.exec_module(wf); b=json.loads((ROOT/'fixture/baseline-webauthn.json').read_text()); g=json.loads((ROOT/'fixture/golden-policy.json').read_text()); req=json.loads((ROOT/'requirements.json').read_text())
ck('record exact',b['record_fields']==wf.EXPECTED_RECORD_FIELDS); ck('positive exact',g['required_positive_paths']==wf.EXPECTED_POSITIVE_PATHS); ck('negative exact',g['required_negative_paths']==wf.EXPECTED_NEGATIVE_PATHS); ck('forbidden exact',g['forbidden_conclusions']==wf.EXPECTED_FORBIDDEN_CONCLUSIONS); ck('transfer exact',g['transfer_context']==wf.EXPECTED_TRANSFER_CONTEXT); ck('recovery exact',b['recovery_policy']['approved_paths']==wf.EXPECTED_APPROVED_RECOVERY_PATHS); blank={k:'x' for k in wf.EXPECTED_RECORD_FIELDS}; blank['Residual Decision']=''; ck('blank residual rejected',not wf.validate_evidence_record(blank)['pass']); ck('registration replay rejected',wf.verify_single_use_sequence('registration')['pass']); ck('authentication replay rejected',wf.verify_single_use_sequence('authentication')['pass']); alt=wf.load_baseline(); alt['synthetic_account']['credential_registered']=False; ck('unregistered auth rejected',not wf._verify_ceremony('authentication',model=alt)['ok']); ck('unknown credential rejected',not wf._verify_ceremony('authentication',credential_id='unknown')['ok']); ck('positive recovery',wf.evaluate_recovery('supervised_identity_proofing_reenrollment')['ok']); ck('recovery risk gate',not wf.evaluate_recovery('backup_authenticator',risk_decision_recorded=False)['ok']); ck('ttl exact',all(b['challenges'][k]['expires_at']-b['challenges'][k]['issued_at']==120 for k in b['challenges'])); ck('unused baseline',all(not b['challenges'][k]['used'] for k in b['challenges'])); ck('local requirements',all(req[k] is False for k in ['external_network_required','real_credentials_required','physical_authenticator_required','external_target_required','real_account_required']))
for n,v in checks: print(('PASS' if v else 'FAIL'),n)
p=bp+sum(v for _,v in checks); t=bt+len(checks); print(f'{p}/{t} PASS'); sys.exit(0 if cp.returncode==0 and p==t else 1)
