|
| 1 | +"""One-shot generator for the data-driven-claims cross-lang fixture (Python side). |
| 2 | +
|
| 3 | +Writes ``tests/fixtures/cross-lang/py-data-driven-claims.json``. Unlike the |
| 4 | +other cross-lang fixtures (which hand-craft the ``agentscore-identity`` |
| 5 | +capability), this one EXERCISES ``build_ucp_profile``'s data path: it |
| 6 | +constructs a synthetic ``AssessResult`` with the API-shape "missing" sentinels |
| 7 | +(empty string for kyc_level, None for age_bracket / jurisdiction / |
| 8 | +verified_at) and lets the builder coalesce them. Both languages MUST emit |
| 9 | +identical canonical bytes for this input or cross-lang verify drifts silently |
| 10 | +in production. |
| 11 | +""" |
| 12 | + |
| 13 | +from __future__ import annotations |
| 14 | + |
| 15 | +import json |
| 16 | +from pathlib import Path |
| 17 | + |
| 18 | +from agentscore_commerce.identity import ( |
| 19 | + AssessResult, |
| 20 | + UCPService, |
| 21 | + UCPSigningKey, |
| 22 | + build_ucp_profile, |
| 23 | +) |
| 24 | +from agentscore_commerce.identity.ucp_jwks import ( |
| 25 | + build_jwks_response, |
| 26 | + generate_ucp_signing_key, |
| 27 | + sign_ucp_profile, |
| 28 | +) |
| 29 | + |
| 30 | +OUT = Path(__file__).resolve().parent.parent / "tests" / "fixtures" / "cross-lang" / "py-data-driven-claims.json" |
| 31 | + |
| 32 | +KID = "py-data-driven-claims-EdDSA" |
| 33 | + |
| 34 | + |
| 35 | +def main() -> None: |
| 36 | + key = generate_ucp_signing_key(kid=KID) |
| 37 | + |
| 38 | + result = AssessResult( |
| 39 | + allow=True, |
| 40 | + resolved_operator="op_data_driven", |
| 41 | + verify_url="https://agentscore.sh/verify/op_data_driven", |
| 42 | + raw={ |
| 43 | + "account_verification": { |
| 44 | + # Empty string is the API's "set but unknown" shape for some |
| 45 | + # columns; None is the shape for others. The builder must |
| 46 | + # coerce both to the schema default identically across node |
| 47 | + # and python. |
| 48 | + "kyc_level": "", |
| 49 | + "sanctions_clear": False, |
| 50 | + "age_bracket": None, |
| 51 | + "jurisdiction": None, |
| 52 | + "verified_at": None, |
| 53 | + }, |
| 54 | + }, |
| 55 | + ) |
| 56 | + |
| 57 | + profile = build_ucp_profile( |
| 58 | + name="Data Driven Claims Merchant", |
| 59 | + services=[UCPService(type="rest", url="https://d.example.com")], |
| 60 | + payment_handlers=[], |
| 61 | + signing_keys=[UCPSigningKey.from_jwk(key.public_jwk)], |
| 62 | + data=result, |
| 63 | + ) |
| 64 | + |
| 65 | + signed = sign_ucp_profile(profile.to_dict(), signing_key=key.private_key, kid=KID) |
| 66 | + |
| 67 | + fixture = { |
| 68 | + "profile": signed, |
| 69 | + "jwks": build_jwks_response([key.public_jwk]), |
| 70 | + "alg": "EdDSA", |
| 71 | + "kid": KID, |
| 72 | + "generator": "python", |
| 73 | + } |
| 74 | + |
| 75 | + OUT.write_text(json.dumps(fixture, indent=2) + "\n") |
| 76 | + print(f"wrote {OUT}") |
| 77 | + |
| 78 | + |
| 79 | +if __name__ == "__main__": |
| 80 | + main() |
0 commit comments