diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index ce73c361..c965e036 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -11,6 +11,7 @@ androidx Applebot appname ASGI +autonumber bazel Blackhawk Boku @@ -19,6 +20,7 @@ celerybeat classpath CLASSPATH CMSPI +codegen cmwallet cncf Cobo @@ -35,6 +37,7 @@ davecgh dcql Dcql DCQL +datamodel deviceauth Dfile dmypy @@ -127,11 +130,14 @@ Payoneer paypal Payplug pids +pisp +pisps pmezard proguard Proguard prometheus protoc +pyca pyflow pymdownx pypa @@ -149,6 +155,8 @@ ropeproject RPCURL Rulebook screenreaders +sdjwt +SECP setlocal sharedpref Shopcider diff --git a/code/sdk/python/ap2/sdk/README.md b/code/sdk/python/ap2/sdk/README.md index 8dbc9280..41177606 100644 --- a/code/sdk/python/ap2/sdk/README.md +++ b/code/sdk/python/ap2/sdk/README.md @@ -1,3 +1,5 @@ + + # AP2 Python SDK Runtime for the Agent Payments Protocol: mandate issuance, presentation, @@ -112,10 +114,10 @@ reference = compute_sha256_b64url( | Model | `vct` | Role | | --- | --- | --- | -| `OpenPaymentMandate` | `mandate.payment.open` | Open payment mandate + constraints | -| `OpenCheckoutMandate` | `mandate.checkout.open` | Open checkout mandate + line-item rules | -| `PaymentMandate` | `mandate.payment` | Closed payment mandate | -| `CheckoutMandate` | `mandate.checkout` | Closed checkout mandate | +| `OpenPaymentMandate` | `mandate.payment.open.1` | Open payment mandate + constraints | +| `OpenCheckoutMandate` | `mandate.checkout.open.1` | Open checkout mandate + line-item rules | +| `PaymentMandate` | `mandate.payment.1` | Closed payment mandate | +| `CheckoutMandate` | `mandate.checkout.1` | Closed checkout mandate | | `PaymentReceipt` / `CheckoutReceipt` | — | Receipt payloads (discriminated success/error) | | `Amount`, `Merchant`, `PaymentInstrument`, … | — | Shared types in `ap2.sdk.generated.types` | @@ -133,7 +135,7 @@ Selective-disclosure annotations on the models: A dSD-JWT chain has arbitrary depth. Hops are joined by `~~`: -``` +```text ~~~~~~…~~~~ ``` @@ -157,7 +159,7 @@ further delegation possible), `kb+sd-jwt` otherwise (closed, terminal). ## Trust chain -``` +```text Root issuer │ signs ▼ @@ -176,7 +178,7 @@ Root issuer delegate │ typ=kb+sd-jwt │ signs ────▶ │ sd_hash, aud, nonce, iat │ │ delegate_payload = { │ - │ vct: mandate.payment, … │ + │ vct: mandate.payment.1, … │ │ } │ └─────────────────────────────┘ ``` diff --git a/code/sdk/python/ap2/sdk/generated/checkout_mandate.py b/code/sdk/python/ap2/sdk/generated/checkout_mandate.py index f78fa665..e445cf0b 100644 --- a/code/sdk/python/ap2/sdk/generated/checkout_mandate.py +++ b/code/sdk/python/ap2/sdk/generated/checkout_mandate.py @@ -16,7 +16,7 @@ class CheckoutMandate(BaseModel): vct: Literal['mandate.checkout.1'] = Field( default='mandate.checkout.1', - description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout'.", + description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout.1'.", ) checkout_jwt: str = Field( ..., diff --git a/code/sdk/python/ap2/sdk/generated/open_checkout_mandate.py b/code/sdk/python/ap2/sdk/generated/open_checkout_mandate.py index 0d85f1b7..126631fe 100644 --- a/code/sdk/python/ap2/sdk/generated/open_checkout_mandate.py +++ b/code/sdk/python/ap2/sdk/generated/open_checkout_mandate.py @@ -73,7 +73,7 @@ class OpenCheckoutMandate(BaseModel): vct: Literal['mandate.checkout.open.1'] = Field( default='mandate.checkout.open.1', - description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout.open'.", + description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout.open.1'.", ) constraints: list[AllowedMerchants | LineItems] = Field( ..., diff --git a/code/sdk/python/ap2/sdk/generated/open_payment_mandate.py b/code/sdk/python/ap2/sdk/generated/open_payment_mandate.py index 8cb4ee28..37923265 100644 --- a/code/sdk/python/ap2/sdk/generated/open_payment_mandate.py +++ b/code/sdk/python/ap2/sdk/generated/open_payment_mandate.py @@ -152,7 +152,7 @@ class OpenPaymentMandate(BaseModel): vct: Literal['mandate.payment.open.1'] = Field( default='mandate.payment.open.1', - description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment.open'.", + description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment.open.1'.", ) constraints: list[ AgentRecurrence diff --git a/code/sdk/python/ap2/sdk/generated/payment_mandate.py b/code/sdk/python/ap2/sdk/generated/payment_mandate.py index c0f8d423..797d50b8 100644 --- a/code/sdk/python/ap2/sdk/generated/payment_mandate.py +++ b/code/sdk/python/ap2/sdk/generated/payment_mandate.py @@ -20,7 +20,7 @@ class PaymentMandate(BaseModel): vct: Literal['mandate.payment.1'] = Field( default='mandate.payment.1', - description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment'.", + description="Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment.1'.", ) transaction_id: str = Field( ..., diff --git a/code/sdk/python/ap2/tests/generated_models_tests.py b/code/sdk/python/ap2/tests/generated_models_tests.py new file mode 100644 index 00000000..85752468 --- /dev/null +++ b/code/sdk/python/ap2/tests/generated_models_tests.py @@ -0,0 +1,49 @@ +"""Tests for generated model metadata.""" + +import json + +from pathlib import Path + +import pytest + +from ap2.sdk.generated.checkout_mandate import CheckoutMandate +from ap2.sdk.generated.open_checkout_mandate import OpenCheckoutMandate +from ap2.sdk.generated.open_payment_mandate import OpenPaymentMandate +from ap2.sdk.generated.payment_mandate import PaymentMandate + + +@pytest.mark.parametrize( + 'schema_name, model, expected_vct', + [ + ('payment_mandate.json', PaymentMandate, 'mandate.payment.1'), + ( + 'open_payment_mandate.json', + OpenPaymentMandate, + 'mandate.payment.open.1', + ), + ('checkout_mandate.json', CheckoutMandate, 'mandate.checkout.1'), + ( + 'open_checkout_mandate.json', + OpenCheckoutMandate, + 'mandate.checkout.open.1', + ), + ], +) +def test_vct_descriptions_include_exact_versioned_value( + schema_name, + model, + expected_vct, +): + """Schema and generated model descriptions include the exact VCT value.""" + schema_path = ( + Path(__file__).resolve().parents[3] / 'schemas' / 'ap2' / schema_name + ) + schema = json.loads(schema_path.read_text()) + schema_vct = schema['properties']['vct'] + model_vct = model.model_fields['vct'] + expected_reference = f"'{expected_vct}'" + + assert schema_vct['const'] == expected_vct + assert expected_reference in schema_vct['description'] + assert model_vct.default == expected_vct + assert expected_reference in model_vct.description diff --git a/code/sdk/schemas/ap2/checkout_mandate.json b/code/sdk/schemas/ap2/checkout_mandate.json index 8755db60..7e535ded 100644 --- a/code/sdk/schemas/ap2/checkout_mandate.json +++ b/code/sdk/schemas/ap2/checkout_mandate.json @@ -12,7 +12,7 @@ "properties": { "vct": { "type": "string", - "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout'.", + "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout.1'.", "const": "mandate.checkout.1", "default": "mandate.checkout.1" }, diff --git a/code/sdk/schemas/ap2/open_checkout_mandate.json b/code/sdk/schemas/ap2/open_checkout_mandate.json index e3d9cafa..e28d21b1 100644 --- a/code/sdk/schemas/ap2/open_checkout_mandate.json +++ b/code/sdk/schemas/ap2/open_checkout_mandate.json @@ -12,7 +12,7 @@ "properties": { "vct": { "type": "string", - "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout.open'.", + "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.checkout.open.1'.", "const": "mandate.checkout.open.1", "default": "mandate.checkout.open.1" }, diff --git a/code/sdk/schemas/ap2/open_payment_mandate.json b/code/sdk/schemas/ap2/open_payment_mandate.json index 22c9dcaa..1333c135 100644 --- a/code/sdk/schemas/ap2/open_payment_mandate.json +++ b/code/sdk/schemas/ap2/open_payment_mandate.json @@ -12,7 +12,7 @@ "properties": { "vct": { "type": "string", - "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment.open'.", + "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment.open.1'.", "const": "mandate.payment.open.1", "default": "mandate.payment.open.1" }, diff --git a/code/sdk/schemas/ap2/payment_mandate.json b/code/sdk/schemas/ap2/payment_mandate.json index fa93b0df..3d6e4ff9 100644 --- a/code/sdk/schemas/ap2/payment_mandate.json +++ b/code/sdk/schemas/ap2/payment_mandate.json @@ -14,7 +14,7 @@ "properties": { "vct": { "type": "string", - "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment'.", + "description": "Verifiable Credential Type claim as defined in SD-JWT. MUST be 'mandate.payment.1'.", "const": "mandate.payment.1", "default": "mandate.payment.1" },