Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .cspell/custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ androidx
Applebot
appname
ASGI
autonumber
bazel
Blackhawk
Boku
Expand All @@ -19,6 +20,7 @@ celerybeat
classpath
CLASSPATH
CMSPI
codegen
cmwallet
cncf
Cobo
Expand All @@ -35,6 +37,7 @@ davecgh
dcql
Dcql
DCQL
datamodel
deviceauth
Dfile
dmypy
Expand Down Expand Up @@ -127,11 +130,14 @@ Payoneer
paypal
Payplug
pids
pisp
pisps
pmezard
proguard
Proguard
prometheus
protoc
pyca
pyflow
pymdownx
pypa
Expand All @@ -149,6 +155,8 @@ ropeproject
RPCURL
Rulebook
screenreaders
sdjwt
SECP
setlocal
sharedpref
Shopcider
Expand Down
16 changes: 9 additions & 7 deletions code/sdk/python/ap2/sdk/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!-- markdownlint-disable MD013 -->

# AP2 Python SDK

Runtime for the Agent Payments Protocol: mandate issuance, presentation,
Expand Down Expand Up @@ -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` |

Expand All @@ -133,7 +135,7 @@ Selective-disclosure annotations on the models:

A dSD-JWT chain has arbitrary depth. Hops are joined by `~~`:

```
```text
<root_SD-JWT>~<disc…>~~<KB-SD-JWT+KB_1>~<disc…>~~…~~<closed_KB-SD-JWT>~<disc…>~
```

Expand All @@ -157,7 +159,7 @@ further delegation possible), `kb+sd-jwt` otherwise (closed, terminal).

## Trust chain

```
```text
Root issuer
│ signs
▼
Expand All @@ -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, … │
│ } │
└─────────────────────────────┘
```
Expand Down
2 changes: 1 addition & 1 deletion code/sdk/python/ap2/sdk/generated/checkout_mandate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
...,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
...,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion code/sdk/python/ap2/sdk/generated/payment_mandate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
...,
Expand Down
49 changes: 49 additions & 0 deletions code/sdk/python/ap2/tests/generated_models_tests.py
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion code/sdk/schemas/ap2/checkout_mandate.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion code/sdk/schemas/ap2/open_checkout_mandate.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion code/sdk/schemas/ap2/open_payment_mandate.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
2 changes: 1 addition & 1 deletion code/sdk/schemas/ap2/payment_mandate.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
Loading