LCPLegal Context Protocol

Mastercard Verifiable Intent Integration

SD-JWT credentials — there is no Tier A carrier for an LCP constraint; registration is the path.

This section is advisory and non-prescriptive. It describes what the host protocol permits, read from its own primary artifact. Where this page and the host protocol disagree, the host is correct — build from its schema, not from an example here.


What it is. An open-source cryptographic framework for consumer authorization in agent-initiated transactions, co-developed by Mastercard and Google and designed to work with AP2. Mastercard contributed it to the FIDO Alliance for community governance in April 2026 — the same announcement in which Google donated AP2 (see §C.5) — with standardization continuing in the FIDO Alliance Payments Technical Working Group. Uses an SD-JWT credential format with up to three layers: Layer 1 (Identity), Layer 2 (Intent — user-signed authorization with constraints), Layer 3 (Action — agent-signed execution record). It defines two modes: Immediate mode uses two layers (L1 + L2, with no agent delegation); Autonomous mode adds Layer 3, which itself splits into L3a (network-facing payment mandate) and L3b (merchant-facing checkout mandate). Layer 2 registers eight constraint types that verifiers MUST support — mandate.checkout.allowed_merchants, mandate.checkout.line_items, mandate.payment.allowed_payees, mandate.payment.amount_range, mandate.payment.budget, mandate.payment.recurrence, mandate.payment.agent_recurrence, and mandate.payment.reference — and explicitly permits implementations to define custom types using URN or reverse-domain naming.

Two modes, and only one carries constraints. Autonomous mode is three-layer: the user creates Layer 2 with constraints and the agent creates Layer 3 within them. Immediate mode is two-layer with no agent delegation, and the specification is explicit that it has "no agent, no constraints, no L3". Mode and mandate kind are carried by the credential's vct — there is no layer or stage member. The four vct values are mandate.checkout.open.1 and mandate.payment.open.1, which carry constraints arrays, and mandate.checkout.1 and mandate.payment.1, the Immediate-mode credentials, which carry concrete final values instead. The eight registered constraint types share only their type member; their other fields differ per type — mandate.payment.amount_range, for example, is { type, currency, min, max } with amounts as ISO 4217 integer minor units, and carries no value field at all.

Tier B — there is no Tier A carrier. An unregistered LCP constraint type has nowhere to sit where it is both carried and evaluated: the credentials that carry a constraints array are the open mandates, and the specification states that regardless of strictness mode, verifiers MUST reject open mandates containing unknown constraint types, on the stated reasoning that an unevaluable constraint leaves agent authority unbounded. The credentials that would tolerate an unknown type under a permissive verifier are the Immediate-mode ones, and they carry no constraints array at all.

PERMISSIVE is the default mode: an unrecognized type is skipped, recorded in a skipped list, and validation succeeds if the recognized constraints pass. STRICT rejects it. Verifiers MUST support both modes, and a per-constraint-type policy map MAY override the global mode. None of that rescues an unknown type in an open mandate, where the MUST-reject rule applies regardless of mode — so the skip rule has no carrier here. A deployment MUST NOT write an unregistered legal-context constraint into a VI mandate and expect it to travel.

Custom naming is available and is not the obstacle. The specification documents two models: Model A, the mandate.checkout.* and mandate.payment.* namespaces, "open for extension by implementers" and following the same dot notation as the registered types; and Model B, collision-resistant URI naming such as urn:example:loyalty-points or a reverse domain, for constraints outside those namespaces. Neither changes the rejection rule, which turns on whether the verifier recognizes the type, not on how it is spelled.

Were a legal-context type registered, it would sit in the open mandate's constraints array beside the registered types, signed by the user's device key and carried through the mandate chain — its member names defined by its own registration rather than by a generic value field:

{
  "vct": "mandate.checkout.open.1",
  "constraints": [
    { "type": "mandate.checkout.allowed_merchants", "allowed": ["..."] },
    { "type": "mandate.checkout.legal_context", "atrHash": "0x7f83b165...",
      "legalContextUrl": "https://example.com/atr/k7VdYqZw1uJmH6cnR0aA-g" }
  ]
}

Registration is what makes this work: Verifiable Intent requires implementations to support registered constraint types, so registering converts legal context from unusable to mandatory-to-evaluate, and makes it safe in open mandates and under strict verification.

Tier B — Forward work. Standardizing LCP-aware constraint types as registered Layer 2 types (rather than custom URN-named types) would give parsers standardized handling across implementations.

Conceptual relationship. Verifiable Intent captures the consumer's authorization chain — who authorized, under what constraints, whether the agent stayed within scope. LCP captures the merchant's terms — what was offered, under what conditions, with what recourse. The combined evidence package — consumer authorization chain + LCP terms record + LCP signed acceptance — provides a complete evidentiary foundation for dispute resolution.

Steward invitation. The Verifiable Intent stewards — now the FIDO Alliance Payments Technical Working Group — are invited to register LCP-aware constraint types in Layer 2 and to publish guidance on the relationship between consumer-side constraints and merchant-side LCP records.