feat(embedded): add link delegation extension#247
feat(embedded): add link delegation extension#247westeezy wants to merge 2 commits intoUniversal-Commerce-Protocol:mainfrom
Conversation
Embedded Checkout can present links from the business (e.g., privacy policy, terms of service). By default, the checkout handles these internally. Link delegation lets the host claim control: when ec_delegate=link.open is set, the Embedded Checkout MUST send ec.link.open_request on buyer link activation, and the host MUST present the content or respond with a link_rejected error.
| - **MUST** present the buyer with visible feedback for every | ||
| `ec.link.open_request` — either the content itself (e.g., in a modal, | ||
| side panel, or new tab) or a notification that their link request was | ||
| rejected |
There was a problem hiding this comment.
Do we want to mandate the Host to show an error to the Buyer for invalid links? I think that's more of an implementation choice. I'd suggest this
- SHOULD validate the requested URL against host security policies (e.g., verifying origins).
- MUST present the content to the buyer for every approved request (e.g., in a modal, new tab, or etc).
- MUST respond with a JSON-RPC success (result) when the request was processed, or
link_rejectedif host policy prevented the navigation. - MAY notify the buyer if the request was rejected.
|
Hey Westin, thank you so much for putting this together on such a short time! The design is very clean! As I was reading through your proposal, I realized we have two potential paths we can take here depending on how dynamic we want this delegation to be. I’d love to get your thoughts on which direction feels better to you: A:
|
|
Overall the proposal makes sense to me! Just 2 fly-by generic thoughts/questions:
|
|
Following @mmohades' (#247 (comment)) feedback, I’m leaning toward Option B ( As noted, Option A is problematic for dynamic redirects like 3DS, but also for other exceptions like payment provider redirects (PayPal/Klarna). These redirects often involve 'create Intent' calls for tokenized sessions generated on click, preventing the final URL from being whitelisted in advance. Allowing the host to handle these scenarios addresses the nested Iframe problem on web and the session/bridge limitations of WebViews on mobile. Even with a correct merchant whitelist, browser security policies ( Even with Option B, using link delegation for the Navigation Exception cases will require separate consideration that need not block this PR. Specifically, it would require defining a generalized propagation pattern to return resulting tokens back to the iframe and evaluating the impact on PCI scope. Nonetheless, this affords a standardized escape hatch out and a functional channel back in. |
| "schema": { | ||
| "type": "object", | ||
| "description": "Acknowledgement that the host handled the link.", | ||
| "additionalProperties": false |
There was a problem hiding this comment.
Per #247 (comment), let's hold off on marking additionalProperties: false to maintain forward compatibility?
If we eventually want to use this pattern for Navigation Constraints/Permitted Exceptions, the host will need a way to pass data back to the iframe. Leaving the result object open allows for that future extensibility without breaking the core schema.
Description
Embedded Checkout can present links from the business (e.g., privacy policy, terms of service). By default, the checkout handles these internally. Link delegation lets the host claim control: when
ec_delegate=link.openis set, the Embedded Checkout MUST sendec.link.open_requeston buyer link activation, and the host MUST present the content or respond with alink_rejectederror.Type of change
Please delete options that are not relevant.
functionality to not work as expected, including removal of schema files
or fields)
Is this a Breaking Change or Removal?
If you checked "Breaking change" above, or if you are removing any schema
files or fields:
!to my PR title (e.g.,feat!: remove field).Checklist