feat: Introduce Actions and apply it to Checkout#553
Conversation
aneeshali
left a comment
There was a problem hiding this comment.
Thanks a lot @raginpirate for introducing the base changes separately. Left a few minor comments!
drewolson-google
left a comment
There was a problem hiding this comment.
Overall looks good, just one comment about ID uniqueness.
| Businesses **MUST** follow these rules: | ||
|
|
||
| * `id` values **MUST** be unique among outstanding actions for the containing | ||
| entity. |
There was a problem hiding this comment.
Do IDs have to be globally unique or just unique within a given action code? Said another way, are IDs automatically namespaced by code?
There was a problem hiding this comment.
Good clarifying question. I propose having them be unique to the entity they are surfaced under, not unique within a given action code. You should not risk collisions between your 3ds action and your ddc action in id.
jamesandersen
left a comment
There was a problem hiding this comment.
Overall this is looking pretty solid
afc1b74 to
6ad7efe
Compare
aneeshali
left a comment
There was a problem hiding this comment.
Thanks a lot Daniel, I think the doc update covering order of resolution is good to begin with. The changes look good overall.
|
We've been building against exactly the gap this PR names in its "known concern": an out-of-band human approval step for unattended buying agents. We shipped an open-source gateway (
All three currently collapse into As implementer feedback, here is the concrete action spec we would emit, structured per the owner obligations in
|
|
@amitpaz1 interesting and valuable to see a use case that further validates the modeling of this base actions PR Thanks @raginpirate for the work here! LGTM |
|
Approving this. Scoping it as a base envelope first is the right call, and it matches #517's own risk framing (Decision 1: "adding a config field later is non-breaking; un-hoisting an envelope field is breaking, so deferring is strictly lower risk"). The primitive is clean, forward-compatible, and the
The one thing I would ask the follow-up to be explicit about is the completion of invariant 11: when the stacked 3DS/action spec lands, it should name the PSP/handler (not the business) as the trust anchor for the executable surface and define how the platform validates that origin independently of the business, so the advisory-outcome class does not end up trusting a business-asserted URL. Non-blocking for this PR. |
igrigorik
left a comment
There was a problem hiding this comment.
@raginpirate @drewolson-google per the TC chat, ptal at this shape: #582.
I won't repeat what's there, but the key thing I'm looking for is clear integration and interop with other and existing primitive in UCP. To that end, I think negotiation/discovery is integral -- the business can emit an action, but how does it know if the platform can action it? I think the answer is simple: actions are extensions; extensions register actions.
Negotiating an extension confirms support for its complete Action contract, but it does not make every future config value or delegate trustworthy. Without an explicit boundary, open config could be mistaken for executable instructions and surface completion for a Business result. Require Platforms to process executable behavior only as defined by the active Action-type contract, allow stricter runtime policy and instance rejection, and keep later Business resource state authoritative. Carry #553's concrete security and fallback concerns into conditional Action-type authoring guidance. Extension specifications define executable fields, trust anchors, interaction controls, completion observation, failure behavior, and fallback only where relevant. This preserves the existing wire shape without introducing a generic executor, callback, or state model.
|
Closing this PR in favour of #582 which delivers the core of this PR and improves on how lifecycle and negotiation were proposed. Thanks Ilya! |
Description
Introduce the base Actions primitive for UCP. Actions are scoped, in-band instructions emitted during the lifecycle of a UCP entity when the platform needs to perform an additional step before the entity can progress. The base primitive is intentionally small:
id— stable correlation identifier for an action occurrencecode— reverse-domain action codeseverity—optional,required, orblockingconfig— owner-defined action configurationThis PR also wires actions into Checkout responses through a top-level
actions[]field and documents how actions interact with the checkout lifecycle.The design invariants for this solution are well defined in #517
What this intentionally does not take from #517
Issue #517 proposes a richer Option A execution contract for step-up actions. This PR deliberately does not include those fields in the base primitive.
Specifically, this PR does not add:
stateexpires_atmodeexecutionresultallowed_originsand supportedmodesexecution.url/visible/request_methodfieldsThose are all valid concerns for concrete step-up specs, especially 3DS, but they are intentionally deferred out of the base primitive. The tradeoff is explicit: this PR chooses the lower-risk “base envelope first” path. Standardized execution fields can still be introduced later once concrete actions prove the abstraction across multiple domains. Adding owner-defined
configfields later is non-breaking; prematurely standardizing base envelope fields would be much harder to unwind.Known concern / likely follow-up
The main concern we may continue to push on is that opaque
configmeans a generic platform cannot execute every action with one universal renderer. This PR does not claim to fully solve generic step-up execution. It establishes the shared action envelope, checkout lifecycle integration, action identity, and owner obligations. A stacked 3DS/action-specific PR should continue to iterate on the concrete execution, trust, negotiation, lifecycle, and recovery contract needed. For now, all of those validations, including trust, is expected to be uniquely defined by a given action.Category (Required)
Please select one or more categories that apply to this change.
Related Issues
#517
#458
Checklist
!for breaking changes).