Skip to content

BREAKING: Field alignment v2 — constraint prefixes, cnf restructure, risk_data, VCT versioning#23

Merged
genereda merged 2 commits into
mainfrom
fix/field-alignment-v2
Apr 20, 2026
Merged

BREAKING: Field alignment v2 — constraint prefixes, cnf restructure, risk_data, VCT versioning#23
genereda merged 2 commits into
mainfrom
fix/field-alignment-v2

Conversation

@genereda

@genereda genereda commented Apr 18, 2026

Copy link
Copy Markdown
Contributor

Aligns the VI SDK and specification to the updated AP2 mandate schema.
Supersedes #21.

Breaking changes

Constraint type prefixes (all under mandate.*)

Old New
mandate.checkout.allowed_merchant mandate.checkout.allowed_merchants
payment.allowed_payee mandate.payment.allowed_payees
payment.amount mandate.payment.amount_range
payment.reference mandate.payment.reference
payment.budget mandate.payment.budget
payment.recurrence mandate.payment.recurrence
payment.agent_recurrence mandate.payment.agent_recurrence

Field name normalization inside constraint dicts

Constraint Old field name New field name
mandate.checkout.allowed_merchants allowed_merchants allowed
mandate.payment.allowed_payees allowed_payees allowed

The constraint type still distinguishes merchants from payees. The
intra-dict field name collapses to the common word allowed.

cnf.kidcnf.jwk.kid

L2 cnf serialization restructured from sibling layout to nested:

// before
"cnf": { "jwk": {...}, "kid": "agent-key-1" }

// after
"cnf": { "jwk": {..., "kid": "agent-key-1"} }

Verifier now reads kid from inside the jwk object. Python field name
cnf_kid on CheckoutMandate / PaymentMandate unchanged.

Frequency enum — full ISO 20022 code set

Replaces the previous small set with the 12 ISO 20022 codes:

INDA, DAIL, WEEK, TOWK, TWMN, MNTH, TOMN, QUTR, FOMN,
SEMI, YEAR, TYEA.

Migration: MONTHLYMNTH, ANNUALLY/YEARLYYEAR, WEEKLYWEEK,
DAILYDAIL, QUARTERLYQUTR, BIWEEKLYTOWK.

VCT versioning

Every mandate VCT gains a .1 suffix.

Old New
mandate.checkout.open mandate.checkout.open.1
mandate.payment.open mandate.payment.open.1
mandate.checkout mandate.checkout.1
mandate.payment mandate.payment.1

Consumers that hardcoded VCT strings must update.

New features

  • PaymentBudgetConstraint.min — optional per-transaction minimum
    (integer minor units). Validated positive on construction.
  • check_constraints(constraint_policy=...) — per-type strictness
    override. Verifiers can opt specific constraint types into STRICT while
    remaining PERMISSIVE overall. Open mandates still reject unknown
    constraints regardless of policy.
  • CheckoutLineItemsConstraint.match_mode"minimum" (default) or
    "exact". In exact mode each items entry must be fulfilled by at
    least one of its acceptable products. Unknown values fail closed.
  • PaymentMandate.risk_data ({device_id, ip_address}) — documented
    as an optional L2 payment mandate disclosure for device signals.
  • L2 aud / kid / iss semantics documentedaud targets the
    agent at L2, the payment network at L3a, the merchant at L3b; kid
    header references the L1 device key; iss identifies the credential
    provider.

Spec clarifications

  • §3.1 — L1 signer corrected to "Issuer" (not "Credential Provider").
  • §4.1 — merchant constraint: design-rationale note explaining why
    website is REQUIRED and id is OPTIONAL (WYSIWYS — what you see is
    what you sign).
  • §5 — new "Per-Constraint Policy Overrides" subsection for
    constraint_policy.
  • §10.1 (new) — "VCT Versioning" explainer under the VCT Registry.

Testing

  • 326 tests pass (was 308 pre-PR; +18 new for constraint_policy,
    match_mode, risk_data, min on PaymentBudgetConstraint).
  • ruff check clean, ruff format --check clean.
  • Python matrix 3.10–3.13 exercised via CI on merge.

Commits

  1. 1236f6e — BREAKING: field alignment per AP2 schema updates
  2. 4ea0e5d — Add risk_data, L2 aud/kid/iss, VCT versioning,
    constraint_policy, match_mode

Rename constraint prefixes (payment.* -> mandate.payment.*),
restructure cnf.kid -> cnf.jwk.kid,
normalize allowed_payees/allowed_merchants -> allowed,
expand frequency enum to ISO 20022 codes.

Co-authored-by: fahads9 <fahads9@users.noreply.github.com>
Co-authored-by: GarethCOliver <GarethCOliver@users.noreply.github.com>

@fahads9 fahads9 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Just one correction:

In credential-format.md:

  1. Section 4.4.2, mandate.payment.1: The currency and amount must be within a 'payment_amount' object.

Approved outside of this.

…ch_mode

New L2 fields (aud targets agent, kid references L1 device key,
iss from PR #21). risk_data disclosure for payment mandates.
VCT version indicators (.1 suffix). Per-constraint policy and
exact match mode.  Fix §3.1 L1 signer terminology.

Co-authored-by: fahads9 <fahads9@users.noreply.github.com>
Co-authored-by: GarethCOliver <GarethCOliver@users.noreply.github.com>
@genereda genereda force-pushed the fix/field-alignment-v2 branch from 4ea0e5d to ba1e409 Compare April 20, 2026 18:44
@genereda

Copy link
Copy Markdown
Contributor Author

Thanks Fahad, fixed.

§4.4.2 (Immediate Payment Mandate) now uses the nested payment_amount object to match §5.6 (L3a) and the SDK's PaymentMandate.to_dict() output.

I also updated three spots that carried the same legacy flat shape, so the doc reads consistently:

  • spec/credential-format.md §11.1, Payment Mandate Disclosure (Immediate) JSON example
  • spec/credential-format.md §11.2, L3a payment mandate disclosure JSON example
  • spec/README.md, Immediate mode walkthrough narrative bullet

Folded into the features commit as a fixup. Diff stays at 2 commits. PTAL.

@genereda genereda requested a review from fahads9 April 20, 2026 19:05
@genereda genereda merged commit 356c296 into main Apr 20, 2026
13 checks passed
@genereda genereda deleted the fix/field-alignment-v2 branch April 20, 2026 19:08
LembaGang added a commit to LembaGang/verifiable-intent that referenced this pull request Apr 23, 2026
First coordination commit following Mastercard's PR agent-intent#23 merge into upstream/main.
Aligns environment-state RFC with the field-alignment-v2 normative changes from
agent-intent#23 (Reda, Apr 20 2026).

No semantic changes to `environment.market_state` itself. Purely downstream
propagation of transactional-constraint renames that appear in examples and
prose cross-references within this RFC:

- VCT version suffix: `mandate.checkout.open` → `mandate.checkout.open.1`
  (4 occurrences: §3 dual-mode prose, §4 Appears In, §5.5 wallet example,
  §5.5 multi-exchange example)
- VCT version suffix: `mandate.payment.open` → `mandate.payment.open.1`
  (2 occurrences: §3 dual-mode prose, §4 Appears In)
- Constraint type pluralisation: `mandate.checkout.allowed_merchant` →
  `mandate.checkout.allowed_merchants` (2 occurrences in §5.5 examples)
- Constraint field generalisation: `allowed_merchants` → `allowed`
  (2 occurrences, paired with the pluralisation above)
- §5.5 Block 3 prose collapse: `(mandate.*, payment.*)` → `(mandate.*)`
  (reflects PR agent-intent#23's move of payment constraints under the mandate.* prefix)

Additive PR agent-intent#23 fields (match_mode, constraint_policy, risk_data) are out of
scope for this RFC — they belong to transactional constraint types, not the
environment.* family.

Signed-off-by: Michael Msebenzi <127877551+LembaGang@users.noreply.github.com>
douglasborthwick-crypto added a commit to douglasborthwick-crypto/verifiable-intent that referenced this pull request Apr 23, 2026
First coordination commit following Mastercard's PR agent-intent#23 merge into upstream/main.
Aligns environment.wallet_state RFC with the field-alignment-v2 normative changes
from agent-intent#23 (Reda, Apr 20 2026).

No semantic changes to `environment.wallet_state` itself. Purely downstream
propagation of transactional-constraint renames that appear in examples and
prose cross-references within this RFC:

- VCT version suffix: `mandate.checkout.open` -> `mandate.checkout.open.1`
  (3 occurrences: §2.2 dual-mode prose, §4 Appears In, §4.5 composition example)
- VCT version suffix: `mandate.payment.open` -> `mandate.payment.open.1`
  (2 occurrences: §2.2 dual-mode prose, §4 Appears In)
- Constraint type pluralisation: `mandate.checkout.allowed_merchant` ->
  `mandate.checkout.allowed_merchants` (1 occurrence in §4.5 composition example)
- Constraint field generalisation: `allowed_merchants` -> `allowed`
  (1 occurrence, paired with the pluralisation above)
- §5.5 Block 3 prose collapse: `(mandate.*, payment.*)` -> `(mandate.*)`
  (reflects PR agent-intent#23's move of payment constraints under the mandate.* prefix)

Additive PR agent-intent#23 fields (match_mode, constraint_policy, risk_data) are out of
scope for this RFC — they belong to transactional constraint types, not the
environment.* family.

Signed-off-by: Douglas Borthwick <256362537+douglasborthwick-crypto@users.noreply.github.com>
LembaGang added a commit to LembaGang/verifiable-intent that referenced this pull request May 3, 2026
Stacked on v0.5.7-draft-implementation-status (commit 21a156c). Catches the
spec text at §7.1 up to the live deployment state surfaced in Appendix D.1
shipped at v0.5.7, and backfills the previously omitted v0.5.6 changelog row.

Scope of this revision:

- §7.1 reference implementation table: "Supported exchanges" row updated
  from "23 global exchanges" to "28 global exchanges" — the §7.1 text was
  a stale residue from the v0.1-draft (Mar 17 2026) which described
  coverage of 23 exchanges before the XCBT, XNYM, XCBO, XCOI, and XBIN
  extensions landed in the live deployment. Spec text catches up; no
  semantic change.
- §7.1 prose MIC enumeration: replaced 23-MIC list with the verified
  28-MIC list (XNYS, XNAS, XLON, XJPX, XPAR, XHKG, XSES, XASX, XBOM,
  XNSE, XSHG, XSHE, XKRX, XJSE, XBSP, XSWX, XMIL, XIST, XSAU, XDFM,
  XNZE, XHEL, XSTO, XCBT, XNYM, XCBO, XCOI, XBIN) matching Appendix
  D.1 verbatim.
- §9 Changelog v0.5.6 row backfill: inserts the previously omitted
  v0.5.6-draft row between v0.5.7 and v0.5.5. Body summarises commit
  68f4db4 (PR agent-intent#23 field-alignment-v2 propagation: VCT version suffix
  .1 added to mandate.checkout.open and mandate.payment.open in
  examples; mandate.checkout.allowed_merchant pluralised; allowed_merchants
  generalised to allowed; §5.5 Block 3 prose collapsed for PR agent-intent#23's
  move of payment constraints under the mandate.* prefix). Date for
  v0.5.6 row derived from the commit author date (2026-04-23).
- §9 Changelog v0.5.8 row added at top of table.

Cross-section structural alignment between §7.1 and Appendix D.1 — adding
Reference verifier, Architectural rationale, or x402 settlement validation
rows to the §7.1 table mirroring D.1 — is intentionally out of scope for
this revision and left for a future v0.5.9+ patch. v0.5.8 is scoped strictly
to the count, MIC list, and changelog backfill.

Document header stays at 0.5-draft; v0.5.8 is a patch-level refinement
stacked on v0.5.7 (not independent). No algorithm changes, no security-model
changes, no §4 schema changes, no Headless Oracle code changes required,
test count unchanged (1031+ baseline).
douglasborthwick-crypto added a commit to douglasborthwick-crypto/verifiable-intent that referenced this pull request May 12, 2026
First coordination commit following Mastercard's PR agent-intent#23 merge into upstream/main.
Aligns environment.wallet_state RFC with the field-alignment-v2 normative changes
from agent-intent#23 (Reda, Apr 20 2026).

No semantic changes to `environment.wallet_state` itself. Purely downstream
propagation of transactional-constraint renames that appear in examples and
prose cross-references within this RFC:

- VCT version suffix: `mandate.checkout.open` -> `mandate.checkout.open.1`
  (3 occurrences: §2.2 dual-mode prose, §4 Appears In, §4.5 composition example)
- VCT version suffix: `mandate.payment.open` -> `mandate.payment.open.1`
  (2 occurrences: §2.2 dual-mode prose, §4 Appears In)
- Constraint type pluralisation: `mandate.checkout.allowed_merchant` ->
  `mandate.checkout.allowed_merchants` (1 occurrence in §4.5 composition example)
- Constraint field generalisation: `allowed_merchants` -> `allowed`
  (1 occurrence, paired with the pluralisation above)
- §5.5 Block 3 prose collapse: `(mandate.*, payment.*)` -> `(mandate.*)`
  (reflects PR agent-intent#23's move of payment constraints under the mandate.* prefix)

Additive PR agent-intent#23 fields (match_mode, constraint_policy, risk_data) are out of
scope for this RFC — they belong to transactional constraint types, not the
environment.* family.

Signed-off-by: Douglas Borthwick <256362537+douglasborthwick-crypto@users.noreply.github.com>
LembaGang added a commit to LembaGang/verifiable-intent that referenced this pull request May 31, 2026
First coordination commit following Mastercard's PR agent-intent#23 merge into upstream/main.
Aligns environment-state RFC with the field-alignment-v2 normative changes from
agent-intent#23 (Reda, Apr 20 2026).

No semantic changes to `environment.market_state` itself. Purely downstream
propagation of transactional-constraint renames that appear in examples and
prose cross-references within this RFC:

- VCT version suffix: `mandate.checkout.open` → `mandate.checkout.open.1`
  (4 occurrences: §3 dual-mode prose, §4 Appears In, §5.5 wallet example,
  §5.5 multi-exchange example)
- VCT version suffix: `mandate.payment.open` → `mandate.payment.open.1`
  (2 occurrences: §3 dual-mode prose, §4 Appears In)
- Constraint type pluralisation: `mandate.checkout.allowed_merchant` →
  `mandate.checkout.allowed_merchants` (2 occurrences in §5.5 examples)
- Constraint field generalisation: `allowed_merchants` → `allowed`
  (2 occurrences, paired with the pluralisation above)
- §5.5 Block 3 prose collapse: `(mandate.*, payment.*)` → `(mandate.*)`
  (reflects PR agent-intent#23's move of payment constraints under the mandate.* prefix)

Additive PR agent-intent#23 fields (match_mode, constraint_policy, risk_data) are out of
scope for this RFC — they belong to transactional constraint types, not the
environment.* family.

Signed-off-by: Michael Msebenzi <127877551+LembaGang@users.noreply.github.com>
LembaGang added a commit to LembaGang/verifiable-intent that referenced this pull request May 31, 2026
Stacked on v0.5.7-draft-implementation-status (commit 21a156c). Catches the
spec text at §7.1 up to the live deployment state surfaced in Appendix D.1
shipped at v0.5.7, and backfills the previously omitted v0.5.6 changelog row.

Scope of this revision:

- §7.1 reference implementation table: "Supported exchanges" row updated
  from "23 global exchanges" to "28 global exchanges" — the §7.1 text was
  a stale residue from the v0.1-draft (Mar 17 2026) which described
  coverage of 23 exchanges before the XCBT, XNYM, XCBO, XCOI, and XBIN
  extensions landed in the live deployment. Spec text catches up; no
  semantic change.
- §7.1 prose MIC enumeration: replaced 23-MIC list with the verified
  28-MIC list (XNYS, XNAS, XLON, XJPX, XPAR, XHKG, XSES, XASX, XBOM,
  XNSE, XSHG, XSHE, XKRX, XJSE, XBSP, XSWX, XMIL, XIST, XSAU, XDFM,
  XNZE, XHEL, XSTO, XCBT, XNYM, XCBO, XCOI, XBIN) matching Appendix
  D.1 verbatim.
- §9 Changelog v0.5.6 row backfill: inserts the previously omitted
  v0.5.6-draft row between v0.5.7 and v0.5.5. Body summarises commit
  68f4db4 (PR agent-intent#23 field-alignment-v2 propagation: VCT version suffix
  .1 added to mandate.checkout.open and mandate.payment.open in
  examples; mandate.checkout.allowed_merchant pluralised; allowed_merchants
  generalised to allowed; §5.5 Block 3 prose collapsed for PR agent-intent#23's
  move of payment constraints under the mandate.* prefix). Date for
  v0.5.6 row derived from the commit author date (2026-04-23).
- §9 Changelog v0.5.8 row added at top of table.

Cross-section structural alignment between §7.1 and Appendix D.1 — adding
Reference verifier, Architectural rationale, or x402 settlement validation
rows to the §7.1 table mirroring D.1 — is intentionally out of scope for
this revision and left for a future v0.5.9+ patch. v0.5.8 is scoped strictly
to the count, MIC list, and changelog backfill.

Document header stays at 0.5-draft; v0.5.8 is a patch-level refinement
stacked on v0.5.7 (not independent). No algorithm changes, no security-model
changes, no §4 schema changes, no Headless Oracle code changes required,
test count unchanged (1031+ baseline).

Signed-off-by: Michael Msebenzi <127877551+LembaGang@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants