@agent-cards/sdk 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/CHANGELOG.md +198 -0
  2. package/PREFLIGHT.md +314 -0
  3. package/README.md +864 -0
  4. package/dist/adyen-merchant-hosted.generated.d.ts +277 -0
  5. package/dist/adyen-merchant-hosted.generated.js +1902 -0
  6. package/dist/adyen.generated.d.ts +24 -0
  7. package/dist/adyen.generated.js +64 -0
  8. package/dist/agentcard.d.ts +72 -0
  9. package/dist/agentcard.js +71 -0
  10. package/dist/api-module.d.ts +54 -0
  11. package/dist/api-module.js +85 -0
  12. package/dist/attachment.d.ts +11 -0
  13. package/dist/attachment.js +50 -0
  14. package/dist/braintree.d.ts +2 -0
  15. package/dist/braintree.generated.d.ts +10 -0
  16. package/dist/braintree.generated.js +302 -0
  17. package/dist/braintree.js +2 -0
  18. package/dist/builtin-registry.generated.d.ts +2 -0
  19. package/dist/builtin-registry.generated.js +1 -0
  20. package/dist/buy.d.ts +374 -0
  21. package/dist/buy.js +314 -0
  22. package/dist/card-fields.generated.d.ts +3 -0
  23. package/dist/card-fields.generated.js +88 -0
  24. package/dist/cdp.d.ts +202 -0
  25. package/dist/cdp.js +2540 -0
  26. package/dist/checkout-com.generated.d.ts +4 -0
  27. package/dist/checkout-com.generated.js +183 -0
  28. package/dist/client.d.ts +929 -0
  29. package/dist/client.js +1896 -0
  30. package/dist/cse-body.d.ts +25 -0
  31. package/dist/cse-body.js +41 -0
  32. package/dist/fiserv.d.ts +65 -0
  33. package/dist/fiserv.generated.d.ts +73 -0
  34. package/dist/fiserv.generated.js +830 -0
  35. package/dist/fiserv.js +104 -0
  36. package/dist/hosted-form.d.ts +44 -0
  37. package/dist/hosted-form.js +78 -0
  38. package/dist/index.d.ts +37 -0
  39. package/dist/index.js +26 -0
  40. package/dist/languages.d.ts +23 -0
  41. package/dist/languages.js +76 -0
  42. package/dist/lifecycle.d.ts +235 -0
  43. package/dist/lifecycle.js +405 -0
  44. package/dist/mercado-checkout.d.ts +20 -0
  45. package/dist/mercado-checkout.generated.d.ts +52 -0
  46. package/dist/mercado-checkout.generated.js +198 -0
  47. package/dist/mercado-checkout.js +108 -0
  48. package/dist/merchant-handoff.d.ts +54 -0
  49. package/dist/merchant-handoff.js +100 -0
  50. package/dist/merchant-hosted.d.ts +140 -0
  51. package/dist/merchant-hosted.js +170 -0
  52. package/dist/merchant-total-watch.d.ts +115 -0
  53. package/dist/merchant-total-watch.js +268 -0
  54. package/dist/merchant-total.d.ts +257 -0
  55. package/dist/merchant-total.js +383 -0
  56. package/dist/owned-shop.generated.d.ts +24 -0
  57. package/dist/owned-shop.generated.js +108 -0
  58. package/dist/paysafe.generated.d.ts +12 -0
  59. package/dist/paysafe.generated.js +87 -0
  60. package/dist/playwright.d.ts +3 -0
  61. package/dist/playwright.js +3 -0
  62. package/dist/pre-claim.d.ts +123 -0
  63. package/dist/pre-claim.js +386 -0
  64. package/dist/preflight-capabilities.generated.d.ts +1311 -0
  65. package/dist/preflight-capabilities.generated.js +2007 -0
  66. package/dist/preflight-catalog.json +5031 -0
  67. package/dist/preflight-playwright.d.ts +34 -0
  68. package/dist/preflight-playwright.js +355 -0
  69. package/dist/preflight-schemas.json +1144 -0
  70. package/dist/preflight.d.ts +1 -0
  71. package/dist/preflight.generated.d.ts +2023 -0
  72. package/dist/preflight.generated.js +604 -0
  73. package/dist/preflight.js +2 -0
  74. package/dist/preparation.d.ts +38 -0
  75. package/dist/preparation.js +191 -0
  76. package/dist/prepared-processor.d.ts +43 -0
  77. package/dist/prepared-processor.js +172 -0
  78. package/dist/recurly.generated.d.ts +1 -0
  79. package/dist/recurly.generated.js +87 -0
  80. package/dist/registry.d.ts +145 -0
  81. package/dist/registry.js +338 -0
  82. package/dist/requests.d.ts +66 -0
  83. package/dist/requests.js +76 -0
  84. package/dist/spreedly.generated.d.ts +10 -0
  85. package/dist/spreedly.generated.js +332 -0
  86. package/dist/stripe-checkout.d.ts +81 -0
  87. package/dist/stripe-checkout.generated.d.ts +82 -0
  88. package/dist/stripe-checkout.generated.js +1153 -0
  89. package/dist/stripe-checkout.js +140 -0
  90. package/dist/substitute.d.ts +38 -0
  91. package/dist/substitute.js +23 -0
  92. package/dist/substitutions.generated.d.ts +11 -0
  93. package/dist/substitutions.generated.js +818 -0
  94. package/dist/voice-pkce.d.ts +49 -0
  95. package/dist/voice-pkce.js +147 -0
  96. package/dist/voice-retry.d.ts +6 -0
  97. package/dist/voice-retry.js +27 -0
  98. package/dist/voice-stream.generated.d.ts +118 -0
  99. package/dist/voice-stream.generated.js +170 -0
  100. package/dist/voice-types.d.ts +708 -0
  101. package/dist/voice-types.js +16 -0
  102. package/dist/voice.d.ts +365 -0
  103. package/dist/voice.js +807 -0
  104. package/dist/webhooks.d.ts +87 -0
  105. package/dist/webhooks.js +136 -0
  106. package/examples/existing-browser.mjs +62 -0
  107. package/examples/preflight/classify-direct.mjs +21 -0
  108. package/examples/preflight/classify-kernel.mjs +30 -0
  109. package/examples/preflight/inspect-browser.mjs +44 -0
  110. package/examples/preflight/kernel-native/README.md +112 -0
  111. package/examples/preflight/kernel-native/documented-adapters.json +113 -0
  112. package/examples/preflight/kernel-native/inventory.json +242 -0
  113. package/examples/preflight/kernel-native/qualification.mjs +182 -0
  114. package/examples/preflight/kernel-profile.empty.json +11 -0
  115. package/examples/preflight/mollie-hosted.observations.json +23 -0
  116. package/examples/preflight/mollie-hosted.result.json +103 -0
  117. package/examples/preflight/stripe-script.direct.result.json +92 -0
  118. package/examples/preflight/stripe-script.observations.json +16 -0
  119. package/examples/preflight/stripe-script.result.json +87 -0
  120. package/package.json +53 -0
  121. package/readme.test.mjs +53 -0
@@ -0,0 +1,604 @@
1
+ // Generated from @agent-cards/payment-core. Do not edit.
2
+ // source-sha256: 667b42af10e827f2c772927b1ff5491e5775a7d6b397ca72c8ddd093cdce2005
3
+ import { CHECKOUT_PREFLIGHT_CAPABILITIES } from './preflight-capabilities.generated.js';
4
+ /** Advisory page discovery. These rules never admit a payment destination. */
5
+ export const CHECKOUT_PREFLIGHT_VERSION = '1';
6
+ export const CHECKOUT_PREFLIGHT_CATALOG_VERSION = '2026-09-15.1';
7
+ // `url_length` bounds the origin and path that discovery matches. `raw_url_length` bounds the
8
+ // observed location including its query, which never takes part in matching or evidence.
9
+ export const CHECKOUT_PREFLIGHT_LIMITS = Object.freeze({ frames: 64, signals: 2048, snapshot_bytes: 262144, url_length: 4096, raw_url_length: 65536 });
10
+ // Identification-only IDs, checked against the canonical catalog by the core tests.
11
+ // No card destination, request method, or request body pattern lives here.
12
+ const KNOWN_PSPS = CHECKOUT_PREFLIGHT_CAPABILITIES.processors.map(processor => processor.psp);
13
+ const PROCESSOR_BY_ID = new Map(CHECKOUT_PREFLIGHT_CAPABILITIES.processors.map(processor => [processor.psp, processor]));
14
+ const KINDS = ['document', 'frame', 'script', 'iframe', 'form'];
15
+ const SCENARIOS = ['one_time', 'save_card', 'subscription_initial', 'subscription_renewal'];
16
+ const OBSERVATION_REASONS = ['collection_timeout', 'frame_limit', 'signal_limit', 'snapshot_limit', 'frame_unavailable', 'navigation_changed', 'invalid_observation', 'invalid_url', 'card_entry_unrecognized', 'collection_incomplete'];
17
+ const RULES = [
18
+ { id: 'stripe-js-v3', psp: 'stripe', kinds: ['script', 'frame', 'iframe'], hostname: /^js\.stripe\.com$/, pathname: /^\/v3(?:\/|$)/, origin: 'https://js.stripe.com', path_pattern: '/v3/*' },
19
+ { id: 'square-web-sdk', psp: 'square', kinds: ['script', 'frame', 'iframe'], hostname: /^web\.squarecdn\.com$/, pathname: /^\/v1\/square\.js$/, origin: 'https://web.squarecdn.com', path_pattern: '/v1/square.js' },
20
+ { id: 'mollie-components-script', psp: 'mollie', kinds: ['script'], hostname: /^js\.mollie\.com$/, pathname: /^\/v2\/mollie\.js$/, origin: 'https://js.mollie.com', path_pattern: '/v2/mollie.js' },
21
+ { id: 'mollie-components-v1-script', psp: 'mollie', kinds: ['script'], hostname: /^js\.mollie\.com$/, pathname: /^\/v1\/mollie\.js$/, origin: 'https://js.mollie.com', path_pattern: '/v1/mollie.js' },
22
+ { id: 'mollie-hosted-credit-card', psp: 'mollie', kinds: ['document', 'frame', 'iframe'], hostname: /^www\.mollie\.com$/, pathname: /^\/checkout\/credit-card\/session\/[A-Za-z0-9_-]+\/?$/, origin: 'https://www.mollie.com', path_pattern: '/checkout/credit-card/session/:session', flow: 'mollie.hosted_components' },
23
+ { id: 'braintree-web-sdk', psp: 'braintree', kinds: ['script'], hostname: /^js\.braintreegateway\.com$/, pathname: /^\/web\/[^/]+\/js\//, origin: 'https://js.braintreegateway.com', path_pattern: '/web/:version/js/*' },
24
+ { id: 'braintree-hosted-fields', psp: 'braintree', kinds: ['frame', 'iframe'], hostname: /^assets\.braintreegateway\.com$/, pathname: /^\/web\//, origin: 'https://assets.braintreegateway.com', path_pattern: '/web/*' },
25
+ { id: 'paysafe-js', psp: 'paysafe', kinds: ['script', 'frame', 'iframe'], hostname: /^hosted\.paysafe\.com$/, pathname: /^\/(?:js|checkout)\//, origin: 'https://hosted.paysafe.com', path_pattern: '/{js,checkout}/*' },
26
+ { id: 'worldpay-checkout-sdk', psp: 'worldpay', kinds: ['script', 'frame', 'iframe'], hostname: /^access\.worldpay\.com$/, pathname: /^\/access-checkout\//, origin: 'https://access.worldpay.com', path_pattern: '/access-checkout/*' },
27
+ { id: 'authorize-net-accept', psp: 'authorize_net', kinds: ['script'], hostname: /^js\.authorize\.net$/, pathname: /^\/v[13]\/Accept(?:UI)?\.js$/, origin: 'https://js.authorize.net', path_pattern: '/v{1,3}/Accept{UI}.js' },
28
+ { id: 'razorpay-checkout-script', psp: 'razorpay', kinds: ['script'], hostname: /^checkout\.razorpay\.com$/, pathname: /^\/v1\/checkout\.js$/, origin: 'https://checkout.razorpay.com', path_pattern: '/v1/checkout.js' },
29
+ { id: 'vgs-collect-script', psp: 'vgs', kinds: ['script'], hostname: /^js\.verygoodvault\.com$/, pathname: /^\/vgs-collect\//, origin: 'https://js.verygoodvault.com', path_pattern: '/vgs-collect/*' },
30
+ { id: 'vgs-collect-frame', psp: 'vgs', kinds: ['frame', 'iframe'], hostname: /^[a-z0-9-]+\.(?:live|sandbox)\.verygoodproxy\.com$/, pathname: /^\//, origin: 'https://:tenant.:environment.verygoodproxy.com', path_pattern: '/*' },
31
+ ];
32
+ // SDK/page fingerprints identify implemented processor families, not an active payment operation.
33
+ RULES.push({ "id": "checkout-frames-v2-script", "psp": "checkout_com", "kinds": ["script"], "origin": "https://cdn.checkout.com", "path_pattern": "^/js/framesv2\\.min\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://checkoutdocs.readme.io/docs/frames-reference", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://cdn.checkout.com/js/framesv2.min.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^cdn\\.checkout\\.com$"), pathname: new RegExp("^/js/framesv2\\.min\\.js$") }, { "id": "adyen-web-legacy-live", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-live.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/web-best-practices/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-live\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-secured-fields-live", "psp": "adyen", "kinds": ["frame", "iframe", "document"], "origin": "https://checkoutshopper-live.adyen.com", "path_pattern": "^/checkoutshopper/securedfields/[^/]+/[0-9]+\\.[0-9]+\\.[0-9]+/securedFields\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://checkoutshopper-live.cdn.adyen.com/checkoutshopper/sdk/6.11.0/adyen.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/development-resources/live-endpoints/", "reviewed_on": "2026-09-15" }, { "kind": "partner_observation", "reference": "kernel-discovery-2026-09-14:adyen-secured-fields-4.9.0-live-us", "reviewed_on": "2026-09-15" }], hostname: new RegExp("^checkoutshopper\\-live\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/securedfields/[^/]+/[0-9]+\\.[0-9]+\\.[0-9]+/securedFields\\.html$") }, { "id": "adyen-web-legacy-test", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-test.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/web-best-practices/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-test\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-secured-fields-test", "psp": "adyen", "kinds": ["frame", "iframe", "document"], "origin": "https://checkoutshopper-test.adyen.com", "path_pattern": "^/checkoutshopper/securedfields/[^/]+/[0-9]+\\.[0-9]+\\.[0-9]+/securedFields\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://checkoutshopper-live.cdn.adyen.com/checkoutshopper/sdk/6.11.0/adyen.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/development-resources/live-endpoints/", "reviewed_on": "2026-09-15" }], hostname: new RegExp("^checkoutshopper\\-test\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/securedfields/[^/]+/[0-9]+\\.[0-9]+\\.[0-9]+/securedFields\\.html$") }, { "id": "stripe-js-named", "psp": "stripe", "kinds": ["script"], "origin": "https://js.stripe.com", "path_pattern": "^/(?:acacia|basil|clover|dahlia)/stripe\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.stripe.com/sdks/stripejs-versioning", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.stripe.com/sdks/stripejs-versioning?locale=en-GB", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.stripe.com/checkout/elements-with-checkout-sessions-api/changelog?locale=en-GB", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.stripe\\.com$"), pathname: new RegExp("^/(?:acacia|basil|clover|dahlia)/stripe\\.js$") }, { "id": "shopify-card-fields-script", "psp": "shopify", "kinds": ["script"], "origin": "https://checkout.pci.shopifyinc.com", "path_pattern": "^/build/[a-f0-9]+/card_fields\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://checkout.pci.shopifyinc.com/build/04ed4e1/card_fields.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\.pci\\.shopifyinc\\.com$"), pathname: new RegExp("^/build/[a-f0-9]+/card_fields\\.js$") }, { "id": "shopify-card-number-frame", "psp": "shopify", "kinds": ["frame", "iframe", "document"], "origin": "https://checkout.pci.shopifyinc.com", "path_pattern": "^/build/[a-f0-9]+/number-(?:ltr|rtl)\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://checkout.pci.shopifyinc.com/build/04ed4e1/card_fields.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\.pci\\.shopifyinc\\.com$"), pathname: new RegExp("^/build/[a-f0-9]+/number-(?:ltr|rtl)\\.html$") }, { "id": "shopify-card-fields-legacy-script", "psp": "shopify", "kinds": ["script"], "origin": "https://checkout.shopifycs.com", "path_pattern": "^/dist/card_fields\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://checkout.shopifycs.com/dist/card_fields.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\.shopifycs\\.com$"), pathname: new RegExp("^/dist/card_fields\\.js$") }, { "id": "stripe-js-script", "psp": "stripe", "kinds": ["script"], "origin": "https://js.stripe.com", "path_pattern": "^/v3/?$", "sources": [{ "kind": "primary_source", "reference": "https://docs.stripe.com/js/including", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.stripe\\.com$"), pathname: new RegExp("^/v3/?$") }, { "id": "braintree-dropin-script", "psp": "braintree", "kinds": ["script"], "origin": "https://js.braintreegateway.com", "path_pattern": "^/web/dropin/[0-9]+\\.[0-9]+\\.[0-9]+/js/dropin(?:\\.min)?\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.paypal.com/braintree/docs/start/hello-client/javascript/v3/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.braintreegateway\\.com$"), pathname: new RegExp("^/web/dropin/[0-9]+\\.[0-9]+\\.[0-9]+/js/dropin(?:\\.min)?\\.js$") }, { "id": "checkout-flow-script", "psp": "checkout_com", "kinds": ["script"], "origin": "https://checkout-web-components.checkout.com", "path_pattern": "^/index\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://www.checkout.com/docs/get-started", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://checkout-web-components.checkout.com/index.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\-web\\-components\\.checkout\\.com$"), pathname: new RegExp("^/index\\.js$") }, { "id": "checkout-flow-frame", "psp": "checkout_com", "kinds": ["frame", "iframe", "document"], "origin": "https://checkout-web-components.checkout.com", "path_pattern": "^/pages/[0-9]+\\.[0-9]+\\.[0-9]+/index\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://checkout-web-components.checkout.com/index.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\-web\\-components\\.checkout\\.com$"), pathname: new RegExp("^/pages/[0-9]+\\.[0-9]+\\.[0-9]+/index\\.html$") }, { "id": "adyen-web-script", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-live.cdn.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/standard/integration/drop-in/best-practices", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/build-your-integration/sessions-flow/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-live\\.cdn\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-web-script-host-2", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-test.cdn.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/standard/integration/drop-in/best-practices", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/build-your-integration/sessions-flow/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-test\\.cdn\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-web-script-host-3", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-live-us.cdn.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/standard/integration/drop-in/best-practices", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/build-your-integration/sessions-flow/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-live\\-us\\.cdn\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-web-script-host-4", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-live-au.cdn.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/standard/integration/drop-in/best-practices", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/build-your-integration/sessions-flow/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-live\\-au\\.cdn\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-web-script-host-5", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-live-nea.cdn.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/standard/integration/drop-in/best-practices", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/build-your-integration/sessions-flow/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-live\\-nea\\.cdn\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "adyen-web-script-host-6", "psp": "adyen", "kinds": ["script"], "origin": "https://checkoutshopper-live-in.cdn.adyen.com", "path_pattern": "^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.adyen.com/standard/integration/drop-in/best-practices", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.adyen.com/online-payments/build-your-integration/sessions-flow/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkoutshopper\\-live\\-in\\.cdn\\.adyen\\.com$"), pathname: new RegExp("^/checkoutshopper/sdk/[0-9]+\\.[0-9]+\\.[0-9]+/adyen\\.js$") }, { "id": "tranzila-hosted-page", "psp": "tranzila", "kinds": ["frame", "iframe", "document", "form"], "origin": "https://direct.tranzila.com", "path_pattern": "^/[A-Za-z0-9_-]+/iframenew\\.php$", "sources": [{ "kind": "primary_source", "reference": "https://docs.tranzila.com/docs/payments-and-billing/iframe-integration", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.tranzila.com/docs/payments-and-billing/iframe-integration-directng", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.tranzila.com/docs/emv-pinpad/emv-iframe-integration", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^direct\\.tranzila\\.com$"), pathname: new RegExp("^/[A-Za-z0-9_-]+/iframenew\\.php$") }, { "id": "tranzila-hosted-page-host-2", "psp": "tranzila", "kinds": ["frame", "iframe", "document", "form"], "origin": "https://directng.tranzila.com", "path_pattern": "^/[A-Za-z0-9_-]+/iframenew\\.php$", "sources": [{ "kind": "primary_source", "reference": "https://docs.tranzila.com/docs/payments-and-billing/iframe-integration", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.tranzila.com/docs/payments-and-billing/iframe-integration-directng", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.tranzila.com/docs/emv-pinpad/emv-iframe-integration", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^directng\\.tranzila\\.com$"), pathname: new RegExp("^/[A-Za-z0-9_-]+/iframenew\\.php$") }, { "id": "square-web-script", "psp": "square", "kinds": ["script"], "origin": "https://web.squarecdn.com", "path_pattern": "^/v1/square\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.squareup.com/docs/web-payments/quickstart/add-sdk-to-web-client", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^web\\.squarecdn\\.com$"), pathname: new RegExp("^/v1/square\\.js$") }, { "id": "square-web-script-host-2", "psp": "square", "kinds": ["script"], "origin": "https://sandbox.web.squarecdn.com", "path_pattern": "^/v1/square\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.squareup.com/docs/web-payments/quickstart/add-sdk-to-web-client", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^sandbox\\.web\\.squarecdn\\.com$"), pathname: new RegExp("^/v1/square\\.js$") }, { "id": "authorize-net-accept-script", "psp": "authorize_net", "kinds": ["script"], "origin": "https://js.authorize.net", "path_pattern": "^/v1/Accept\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.authorize.net/api/reference/features/acceptjs.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.authorize\\.net$"), pathname: new RegExp("^/v1/Accept\\.js$") }, { "id": "authorize-net-accept-script-host-2", "psp": "authorize_net", "kinds": ["script"], "origin": "https://jstest.authorize.net", "path_pattern": "^/v1/Accept\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.authorize.net/api/reference/features/acceptjs.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^jstest\\.authorize\\.net$"), pathname: new RegExp("^/v1/Accept\\.js$") }, { "id": "authorize-net-acceptui-script", "psp": "authorize_net", "kinds": ["script"], "origin": "https://js.authorize.net", "path_pattern": "^/v3/AcceptUI\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.authorize.net/api/reference/features/acceptjs.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.authorize\\.net$"), pathname: new RegExp("^/v3/AcceptUI\\.js$") }, { "id": "authorize-net-acceptui-script-host-2", "psp": "authorize_net", "kinds": ["script"], "origin": "https://jstest.authorize.net", "path_pattern": "^/v3/AcceptUI\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.authorize.net/api/reference/features/acceptjs.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^jstest\\.authorize\\.net$"), pathname: new RegExp("^/v3/AcceptUI\\.js$") }, { "id": "worldpay-checkout-script", "psp": "worldpay", "kinds": ["script"], "origin": "https://access.worldpay.com", "path_pattern": "^/access-checkout/v2/checkout\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.worldpay.com/access/products/checkout/web", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^access\\.worldpay\\.com$"), pathname: new RegExp("^/access-checkout/v2/checkout\\.js$") }, { "id": "worldpay-checkout-script-host-2", "psp": "worldpay", "kinds": ["script"], "origin": "https://try.access.worldpay.com", "path_pattern": "^/access-checkout/v2/checkout\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.worldpay.com/access/products/checkout/web", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^try\\.access\\.worldpay\\.com$"), pathname: new RegExp("^/access-checkout/v2/checkout\\.js$") }, { "id": "nuvei-websdk-script", "psp": "nuvei", "kinds": ["script"], "origin": "https://cdn.safecharge.com", "path_pattern": "^/safecharge_resources/v1/websdk/safecharge\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.nuvei.com/documentation/accept-payment/web-sdk/quick-start-for-web-sdk/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://cdn.safecharge.com/safecharge_resources/v1/websdk/safecharge.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^cdn\\.safecharge\\.com$"), pathname: new RegExp("^/safecharge_resources/v1/websdk/safecharge\\.js$") }, { "id": "nuvei-card-fields-frame", "psp": "nuvei", "kinds": ["frame", "iframe", "document"], "origin": "https://cdn.safecharge.com", "path_pattern": "^/safecharge_resources/v1/websdk/sfc_inner_card\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://docs.nuvei.com/documentation/accept-payment/web-sdk/nuvei-fields/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://cdn.safecharge.com/safecharge_resources/v1/websdk/sfc_inner_card.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^cdn\\.safecharge\\.com$"), pathname: new RegExp("^/safecharge_resources/v1/websdk/sfc_inner_card\\.html$") }, { "id": "airwallex-components-script", "psp": "airwallex", "kinds": ["script"], "origin": "https://static.airwallex.com", "path_pattern": "^/components/sdk/v1/index\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://www.airwallex.com/docs/payments/get-started/quickstart", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://www.airwallex.com/docs/payments/test-and-go-live/upgrade-to-airwallex.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://www.airwallex.com/docs/payouts/test-and-go-live/upgrade-to-airwallex.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^static\\.airwallex\\.com$"), pathname: new RegExp("^/components/sdk/v1/index\\.js$") }, { "id": "airwallex-elements-legacy-script", "psp": "airwallex", "kinds": ["script"], "origin": "https://checkout.airwallex.com", "path_pattern": "^/assets/elements\\.bundle\\.min\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://www.airwallex.com/docs/payments/test-and-go-live/upgrade-to-airwallex.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\.airwallex\\.com$"), pathname: new RegExp("^/assets/elements\\.bundle\\.min\\.js$") }, { "id": "rapyd-checkout-toolkit-script", "psp": "rapyd", "kinds": ["script"], "origin": "https://checkouttoolkit.rapyd.net", "path_pattern": "^/$", "sources": [{ "kind": "primary_source", "reference": "https://docs.rapyd.net/en/checkout-toolkit-integration.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkouttoolkit\\.rapyd\\.net$"), pathname: new RegExp("^/$") }, { "id": "rapyd-checkout-toolkit-script-host-2", "psp": "rapyd", "kinds": ["script"], "origin": "https://sandboxcheckouttoolkit.rapyd.net", "path_pattern": "^/$", "sources": [{ "kind": "primary_source", "reference": "https://docs.rapyd.net/en/checkout-toolkit-integration.html", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^sandboxcheckouttoolkit\\.rapyd\\.net$"), pathname: new RegExp("^/$") }, { "id": "dlocal-smart-fields-script", "psp": "dlocal", "kinds": ["script"], "origin": "https://js.dlocal.com", "path_pattern": "^/$", "sources": [{ "kind": "primary_source", "reference": "https://docs.dlocal.com/docs/set-up-smart-fields", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.dlocal.com/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://static.dlocal.com/modules/fields/6.18.2/iframe.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.dlocal\\.com$"), pathname: new RegExp("^/$") }, { "id": "dlocal-smart-fields-sandbox-script", "psp": "dlocal", "kinds": ["script"], "origin": "https://js-sandbox.dlocal.com", "path_pattern": "^/$", "sources": [{ "kind": "primary_source", "reference": "https://docs.dlocal.com/docs/set-up-smart-fields", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.dlocal.com/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://static.dlocal.com/modules/fields/6.18.2/iframe.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\-sandbox\\.dlocal\\.com$"), pathname: new RegExp("^/$") }, { "id": "dlocal-smart-fields-parent-6-18-2", "psp": "dlocal", "kinds": ["script"], "origin": "https://static.dlocal.com", "path_pattern": "^/modules/fields/6\\.18\\.2/parent\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.dlocal.com/docs/set-up-smart-fields", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.dlocal.com/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://static.dlocal.com/modules/fields/6.18.2/iframe.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^static\\.dlocal\\.com$"), pathname: new RegExp("^/modules/fields/6\\.18\\.2/parent\\.js$") }, { "id": "dlocal-smart-card-fields-6-18-2", "psp": "dlocal", "kinds": ["frame", "iframe", "document"], "origin": "https://static.dlocal.com", "path_pattern": "^/modules/fields/6\\.18\\.2/inner-(?:pan|card)\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://docs.dlocal.com/docs/set-up-smart-fields", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.dlocal.com/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://static.dlocal.com/modules/fields/6.18.2/iframe.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^static\\.dlocal\\.com$"), pathname: new RegExp("^/modules/fields/6\\.18\\.2/inner-(?:pan|card)\\.html$") }, { "id": "ebanx-js-latest", "psp": "ebanx", "kinds": ["script"], "origin": "https://ebanx-js.ebanx.com", "path_pattern": "^/latest/dist/ebanx\\.min\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.ebanx.com/docs/pay-in/features/cards/tokenization/tokenization-ebanx-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://ebanx-js.ebanx.com/latest/dist/ebanx.min.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^ebanx\\-js\\.ebanx\\.com$"), pathname: new RegExp("^/latest/dist/ebanx\\.min\\.js$") }, { "id": "mercado-pago-sdk-v2", "psp": "mercado_pago", "kinds": ["script"], "origin": "https://sdk.mercadopago.com", "path_pattern": "^/js/v2$", "sources": [{ "kind": "primary_source", "reference": "https://github.com/mercadopago/sdk-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://sdk.mercadopago.com/js/v2", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^sdk\\.mercadopago\\.com$"), pathname: new RegExp("^/js/v2$") }, { "id": "payu-gpo-sdk", "psp": "payu", "kinds": ["script"], "origin": "https://secure.payu.com", "path_pattern": "^/javascript/sdk$", "sources": [{ "kind": "primary_source", "reference": "https://developers.payu.com/europe/docs/checkout/secure-elements/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://secure.payu.com/javascript/sdk", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^secure\\.payu\\.com$"), pathname: new RegExp("^/javascript/sdk$") }, { "id": "payu-gpo-sdk-sandbox", "psp": "payu", "kinds": ["script"], "origin": "https://secure.snd.payu.com", "path_pattern": "^/javascript/sdk$", "sources": [{ "kind": "primary_source", "reference": "https://developers.payu.com/europe/docs/checkout/secure-elements/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://secure.payu.com/javascript/sdk", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^secure\\.snd\\.payu\\.com$"), pathname: new RegExp("^/javascript/sdk$") }, { "id": "payu-gpo-sdk-sandbox-host-2", "psp": "payu", "kinds": ["script"], "origin": "https://merch-prod.snd.payu.com", "path_pattern": "^/javascript/sdk$", "sources": [{ "kind": "primary_source", "reference": "https://developers.payu.com/europe/docs/checkout/secure-elements/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://secure.payu.com/javascript/sdk", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^merch\\-prod\\.snd\\.payu\\.com$"), pathname: new RegExp("^/javascript/sdk$") }, { "id": "payu-gpo-secure-form", "psp": "payu", "kinds": ["frame", "iframe", "document"], "origin": "https://secure.payu.com", "path_pattern": "^/front/secure-form/form/$", "sources": [{ "kind": "primary_source", "reference": "https://developers.payu.com/europe/docs/checkout/secure-elements/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://secure.payu.com/javascript/sdk", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^secure\\.payu\\.com$"), pathname: new RegExp("^/front/secure-form/form/$") }, { "id": "razorpay-standard-checkout-v1", "psp": "razorpay", "kinds": ["script"], "origin": "https://checkout.razorpay.com", "path_pattern": "^/v1/checkout\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://razorpay.com/docs/payments/payment-gateway/web-integration/standard/integration-steps/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://checkout.razorpay.com/v1/checkout.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^checkout\\.razorpay\\.com$"), pathname: new RegExp("^/v1/checkout\\.js$") }, { "id": "mollie-components-v1", "psp": "mollie", "kinds": ["script"], "origin": "https://js.mollie.com", "path_pattern": "^/v1/mollie\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.mollie.com/docs/mollie-components", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.mollie.com/docs/custom-checkout-components", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.mollie.com/v2/mollie.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.mollie\\.com$"), pathname: new RegExp("^/v1/mollie\\.js$") }, { "id": "mollie-components-v2", "psp": "mollie", "kinds": ["script"], "origin": "https://js.mollie.com", "path_pattern": "^/v2/mollie\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.mollie.com/docs/mollie-components", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://docs.mollie.com/docs/custom-checkout-components", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.mollie.com/v2/mollie.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.mollie\\.com$"), pathname: new RegExp("^/v2/mollie\\.js$") }, { "id": "paysafe-js-v1-latest", "psp": "paysafe", "kinds": ["script"], "origin": "https://hosted.paysafe.com", "path_pattern": "^/js/v1/latest/paysafe\\.min\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.paysafe.com/en/api-docs/paysafe-js/overview/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://hosted.paysafe.com/js/v1/latest/paysafe.min.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://developer.paysafe.com/en/api-docs/3ds/using-the-sdk/including-the-3d-secure-2-sdk/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^hosted\\.paysafe\\.com$"), pathname: new RegExp("^/js/v1/latest/paysafe\\.min\\.js$") }, { "id": "paysafe-js-v1-fields", "psp": "paysafe", "kinds": ["frame", "iframe", "document"], "origin": "https://hosted.paysafe.com", "path_pattern": "^/js/v1/latest/index\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://developer.paysafe.com/en/api-docs/paysafe-js/overview/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://hosted.paysafe.com/js/v1/latest/paysafe.min.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://developer.paysafe.com/en/api-docs/3ds/using-the-sdk/including-the-3d-secure-2-sdk/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^hosted\\.paysafe\\.com$"), pathname: new RegExp("^/js/v1/latest/index\\.html$") }, { "id": "paysafe-js-v1-fields-host-2", "psp": "paysafe", "kinds": ["frame", "iframe", "document"], "origin": "https://hosted.test.paysafe.com", "path_pattern": "^/js/v1/latest/index\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://developer.paysafe.com/en/api-docs/paysafe-js/overview/", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://hosted.paysafe.com/js/v1/latest/paysafe.min.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://developer.paysafe.com/en/api-docs/3ds/using-the-sdk/including-the-3d-secure-2-sdk/", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^hosted\\.test\\.paysafe\\.com$"), pathname: new RegExp("^/js/v1/latest/index\\.html$") }, { "id": "spreedly-iframe-v1-script", "psp": "spreedly", "kinds": ["script"], "origin": "https://core.spreedly.com", "path_pattern": "^/iframe/iframe-v1\\.min\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://core.spreedly.com/iframe/iframe-v1.min.js", "reviewed_on": "2026-09-16" }], hostname: new RegExp("^core\\.spreedly\\.com$"), pathname: new RegExp("^/iframe/iframe-v1\\.min\\.js$") }, { "id": "spreedly-native-card-frame", "psp": "spreedly", "kinds": ["frame", "iframe", "document"], "origin": "https://core.spreedly.com", "path_pattern": "^/v1/embedded/(?:number|cvv)-frame-1\\.[0-9]{1,4}\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://core.spreedly.com/iframe/iframe-v1.min.js", "reviewed_on": "2026-09-16" }], hostname: new RegExp("^core\\.spreedly\\.com$"), pathname: new RegExp("^/v1/embedded/(?:number|cvv)-frame-1\\.[0-9]{1,4}\\.html$") }, { "id": "recurly-js-v4", "psp": "recurly", "kinds": ["script"], "origin": "https://js.recurly.com", "path_pattern": "^/v4/recurly\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://recurly.com/developers/reference/recurly-js/index.html", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://github.com/recurly/recurly-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.recurly.com/v4/recurly.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.recurly\\.com$"), pathname: new RegExp("^/v4/recurly\\.js$") }, { "id": "recurly-hosted-field-v1", "psp": "recurly", "kinds": ["frame", "iframe", "document"], "origin": "https://api.recurly.com", "path_pattern": "^/js/v1/field\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://recurly.com/developers/reference/recurly-js/index.html", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://github.com/recurly/recurly-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.recurly.com/v4/recurly.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^api\\.recurly\\.com$"), pathname: new RegExp("^/js/v1/field\\.html$") }, { "id": "recurly-hosted-field-v1-host-2", "psp": "recurly", "kinds": ["frame", "iframe", "document"], "origin": "https://api.eu.recurly.com", "path_pattern": "^/js/v1/field\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://recurly.com/developers/reference/recurly-js/index.html", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://github.com/recurly/recurly-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.recurly.com/v4/recurly.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^api\\.eu\\.recurly\\.com$"), pathname: new RegExp("^/js/v1/field\\.html$") }, { "id": "moneris-hosted-tokenization", "psp": "moneris", "kinds": ["frame", "iframe", "document"], "origin": "https://www3.moneris.com", "path_pattern": "^/HPPtoken/index\\.php$", "sources": [{ "kind": "primary_source", "reference": "https://developer.moneris.com/hosted-solutions/docs/setup-guide-tokenization", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://developer.moneris.com/moneris-api/docs/purchase-with-payment-token", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://www3.moneris.com/HPPtoken/hpp_common.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^www3\\.moneris\\.com$"), pathname: new RegExp("^/HPPtoken/index\\.php$") }, { "id": "moneris-hosted-tokenization-host-2", "psp": "moneris", "kinds": ["frame", "iframe", "document"], "origin": "https://esqa.moneris.com", "path_pattern": "^/HPPtoken/index\\.php$", "sources": [{ "kind": "primary_source", "reference": "https://developer.moneris.com/hosted-solutions/docs/setup-guide-tokenization", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://developer.moneris.com/moneris-api/docs/purchase-with-payment-token", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://www3.moneris.com/HPPtoken/hpp_common.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^esqa\\.moneris\\.com$"), pathname: new RegExp("^/HPPtoken/index\\.php$") }, { "id": "moneris-new-io-hosted-tokenization", "psp": "moneris", "kinds": ["frame", "iframe", "document"], "origin": "https://mpg1t.moneris.io", "path_pattern": "^/HPPtoken/index\\.php$", "sources": [{ "kind": "primary_source", "reference": "https://developer.moneris.com/hosted-solutions/docs/setup-guide-tokenization", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://developer.moneris.com/moneris-api/docs/purchase-with-payment-token", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://www3.moneris.com/HPPtoken/hpp_common.js", "reviewed_on": "2026-09-11" }], "variant_unverified": "The current canonical Moneris recognizer contains moneris.com hosts only; moneris.io is not admitted.", hostname: new RegExp("^mpg1t\\.moneris\\.io$"), pathname: new RegExp("^/HPPtoken/index\\.php$") }, { "id": "bambora-na-custom-checkout-1", "psp": "bambora", "kinds": ["script"], "origin": "https://libs.na.bambora.com", "path_pattern": "^/customcheckout/1/customcheckout\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://docs.na.worldline-solutions.com/build-your-integration/checkout-form/custom-checkout/reference", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://libs.na.bambora.com/customcheckout/1/customcheckout.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://libs.na.bambora.com/customcheckout/1.0.5-39/customcheckoutremote.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^libs\\.na\\.bambora\\.com$"), pathname: new RegExp("^/customcheckout/1/customcheckout\\.js$") }, { "id": "bambora-na-fields-1-0-5-39", "psp": "bambora", "kinds": ["frame", "iframe", "document"], "origin": "https://libs.na.bambora.com", "path_pattern": "^/customcheckout/1\\.0\\.5-39/iframe\\.html$", "sources": [{ "kind": "primary_source", "reference": "https://docs.na.worldline-solutions.com/build-your-integration/checkout-form/custom-checkout/reference", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://libs.na.bambora.com/customcheckout/1/customcheckout.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://libs.na.bambora.com/customcheckout/1.0.5-39/customcheckoutremote.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^libs\\.na\\.bambora\\.com$"), pathname: new RegExp("^/customcheckout/1\\.0\\.5-39/iframe\\.html$") }, { "id": "global-payments-js-4-1-3", "psp": "global_payments", "kinds": ["script"], "origin": "https://js.globalpay.com", "path_pattern": "^/4\\.1\\.3/globalpayments\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.globalpayments.com/docs/integration-options/sdk/javascript", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://github.com/globalpayments/globalpayments-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.globalpay.com/4.1.3/globalpayments.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.globalpay.com/v1/globalpayments.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.globalpay\\.com$"), pathname: new RegExp("^/4\\.1\\.3/globalpayments\\.js$") }, { "id": "global-payments-js-v1-alias", "psp": "global_payments", "kinds": ["script"], "origin": "https://js.globalpay.com", "path_pattern": "^/v1/globalpayments\\.js$", "sources": [{ "kind": "primary_source", "reference": "https://developer.globalpayments.com/docs/integration-options/sdk/javascript", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://github.com/globalpayments/globalpayments-js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.globalpay.com/4.1.3/globalpayments.js", "reviewed_on": "2026-09-11" }, { "kind": "primary_source", "reference": "https://js.globalpay.com/v1/globalpayments.js", "reviewed_on": "2026-09-11" }], hostname: new RegExp("^js\\.globalpay\\.com$"), pathname: new RegExp("^/v1/globalpayments\\.js$") });
34
+ // Hosted, regional and versioned product variants seen on live checkouts (Kernel discovery report,
35
+ // 2026-09-14). A variant the implemented adapter does not admit still identifies its processor and
36
+ // stays unknown through `variant_unverified`; no entry here expands a recognized card destination.
37
+ const documented = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-15' });
38
+ const observed = (reference) => ({ kind: 'partner_observation', reference: `kernel-discovery-2026-09-14:${reference}`, reviewed_on: '2026-09-15' });
39
+ RULES.push({ id: 'tranzila-terminal-hosted-page', psp: 'tranzila', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^direct\.tranzila\.com$/, pathname: /^\/(?!process(?:\/|$)|done(?:\/|$))[A-Za-z0-9_-]+\/?$/, origin: 'https://direct.tranzila.com', path_pattern: '/:terminal/',
40
+ sources: [documented('https://docs.tranzila.com/docs/payments-and-billing/hosted-payment-page'), observed('tranzila-terminal-root-hosted-page')],
41
+ variant_unverified: 'The implemented Tranzila hosted form covers direct.tranzila.com/:terminal/iframenew.php; a terminal-root hosted payment page is not admitted.' }, { id: 'square-card-element-frame', psp: 'square', kinds: ['frame', 'iframe'], hostname: /^web\.squarecdn\.com$/, pathname: /^\/[0-9]+\.[0-9]+\.[0-9]+\/single-card-element-iframe\.html$/, origin: 'https://web.squarecdn.com', path_pattern: '/:version/single-card-element-iframe.html',
42
+ sources: [documented('https://developer.squareup.com/docs/web-payments/take-card-payment'), observed('square-single-card-element-iframe-1.84.5')] }, { id: 'authorize-net-sim-hosted-form', psp: 'authorize_net', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^secure\.authorize\.net$/, pathname: /^\/gateway\/transact\.dll$/, origin: 'https://secure.authorize.net', path_pattern: '/gateway/transact.dll',
43
+ sources: [documented('https://developer.authorize.net/api/upgrade_guide.html'), observed('authorize-net-hosted-transact-form')],
44
+ variant_unverified: 'The implemented Authorize.Net adapter covers Accept.js card requests; the hosted SIM payment form at secure.authorize.net/gateway/transact.dll posts the card as a top-level form and is not admitted.' }, { id: 'worldpay-hosted-payment-page', psp: 'worldpay', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^secure\.worldpay\.com$/, pathname: /^\/wcc\/(?:purchase|card)$/, origin: 'https://secure.worldpay.com', path_pattern: '/wcc/{purchase,card}',
45
+ sources: [documented('https://docs.worldpay.com/access/products/checkout/web'), observed('worldpay-hosted-payment-page-card')],
46
+ variant_unverified: 'The implemented Worldpay adapter covers Access Checkout card sessions; Worldpay hosted payment pages under secure.worldpay.com/wcc post the card to Worldpay directly and are not admitted.' }, { id: 'rapyd-hosted-checkout-page', psp: 'rapyd', kinds: ['document', 'frame', 'iframe'], hostname: /^checkout\.rapyd\.net$/, pathname: /^\/$/, origin: 'https://checkout.rapyd.net', path_pattern: '/',
47
+ sources: [documented('https://docs.rapyd.net/en/hosted-checkout-page.html'), observed('rapyd-hosted-checkout-page')] }, { id: 'dlocal-smart-fields-parent', psp: 'dlocal', kinds: ['script'], hostname: /^static\.dlocal\.com$/, pathname: /^\/modules\/fields\/[0-9]+\.[0-9]+\.[0-9]+\/(?:parent|iframe)\.js$/, origin: 'https://static.dlocal.com', path_pattern: '/modules/fields/:version/{parent,iframe}.js',
48
+ sources: [documented('https://docs.dlocal.com/docs/set-up-smart-fields'), observed('dlocal-smart-fields-6.8.3')] }, { id: 'dlocal-smart-card-fields', psp: 'dlocal', kinds: ['frame', 'iframe', 'document'], hostname: /^static\.dlocal\.com$/, pathname: /^\/modules\/fields\/[0-9]+\.[0-9]+\.[0-9]+\/inner-(?:pan|card)\.html$/, origin: 'https://static.dlocal.com', path_pattern: '/modules/fields/:version/inner-{pan,card}.html',
49
+ sources: [documented('https://docs.dlocal.com/docs/set-up-smart-fields'), observed('dlocal-smart-fields-6.8.3')] }, { id: 'mercado-pago-secure-fields-frame', psp: 'mercado_pago', kinds: ['frame', 'iframe', 'document'], hostname: /^secure-fields\.mercadopago\.com$/, pathname: /^\/$/, origin: 'https://secure-fields.mercadopago.com', path_pattern: '/',
50
+ sources: [documented('https://sdk.mercadopago.com/js/v2'), observed('mercado-pago-secure-fields-frames')] }, { id: 'mercado-pago-checkout-pro-card-form', psp: 'mercado_pago', kinds: ['document', 'frame', 'iframe'], hostname: /^www\.mercadopago\.com\.ar$/, pathname: /^\/checkout\/v1\/payment\/redirect\/[^/]+\/card-form\/?$/, origin: 'https://www.mercadopago.com.ar', path_pattern: '/checkout/v1/payment/redirect/:preference/card-form/',
51
+ sources: [documented('https://www.mercadopago.com.ar/developers/es/docs/checkout-pro/landing'), observed('mercado-pago-checkout-pro-guest-card-form')] },
52
+ // Gravy (Gr4vy) Secure Fields: the merchant page loads secure-fields.js from the
53
+ // merchant's own CDN host, cdn.<merchant>.gr4vy.app, or cdn.sandbox.<merchant>.gr4vy.app
54
+ // in test. The bounded merchant label mirrors the recognizer's api.<merchant> hosts and
55
+ // the VGS tenant rule above; gr4vy.app is Gravy's own domain, so no third party can
56
+ // stand up a host that satisfies it. Written from the published integration contract,
57
+ // not yet confirmed against a live merchant page.
58
+ { id: 'gravy-secure-fields-script', psp: 'gravy', kinds: ['script'], hostname: /^cdn\.[a-z0-9-]+\.gr4vy\.app$/, pathname: /^\/secure-fields\.js$/, origin: 'https://cdn.:merchant.gr4vy.app', path_pattern: '/secure-fields.js',
59
+ sources: [documented('https://docs.gr4vy.com/guides/payments/secure-fields')] }, { id: 'gravy-secure-fields-script-sandbox', psp: 'gravy', kinds: ['script'], hostname: /^cdn\.sandbox\.[a-z0-9-]+\.gr4vy\.app$/, pathname: /^\/secure-fields\.js$/, origin: 'https://cdn.sandbox.:merchant.gr4vy.app', path_pattern: '/secure-fields.js',
60
+ sources: [documented('https://docs.gr4vy.com/guides/payments/secure-fields')] });
61
+ // Fiserv Commerce Hub, read 2026-09-23 from Home Depot's OrangePay frame and Fiserv's
62
+ // docs: payment-fields.js renders one Secure Data Capture iframe per card field, and
63
+ // the Checkout JS SDK is Commerce Hub's other browser entry. Fiserv ships dark (its
64
+ // definition names a capability), so the bundled catalog declares no support for it:
65
+ // these assets identify fiserv and the result stays unknown.
66
+ const fiservSource = (reference) => ({ kind: 'primary_source', reference, reviewed_on: '2026-09-23' });
67
+ RULES.push({ id: 'fiserv-commercehub-payment-fields', psp: 'fiserv', kinds: ['script'], hostname: /^commercehub-checkout\.fiservapps\.com$/, pathname: /^\/sdk\/[0-9]+\.[0-9]+\.[0-9]+\/payment-fields\.js$/, origin: 'https://commercehub-checkout.fiservapps.com', path_pattern: '/sdk/:version/payment-fields.js',
68
+ sources: [fiservSource('https://commercehub-checkout.fiservapps.com/sdk/3.8.14/payment-fields.js'), fiservSource('https://orangepay-ecommerce.hdpayments.homedepot.com/env.js')] }, { id: 'fiserv-commercehub-checkout-script', psp: 'fiserv', kinds: ['script'], hostname: /^commercehub-checkout\.fiservapps\.com$/, pathname: /^\/sdk\/[0-9]+\.[0-9]+\.[0-9]+\/checkout\.js$/, origin: 'https://commercehub-checkout.fiservapps.com', path_pattern: '/sdk/:version/checkout.js',
69
+ sources: [fiservSource('https://developer.fiserv.com/product/CommerceHub/docs/Online-Commerce/Integration-Options/Hosted-Checkout/Hosted-Checkout-Version-Release')] }, { id: 'fiserv-secure-data-capture-frame', psp: 'fiserv', kinds: ['frame', 'iframe', 'document'], hostname: /^commercehub-secure-data-capture\.fiservapps\.com$/, pathname: /^\/sdk-secure\/[0-9]+\.[0-9]+\.[0-9]+\/iframe\.html$/, origin: 'https://commercehub-secure-data-capture.fiservapps.com', path_pattern: '/sdk-secure/:version/iframe.html',
70
+ sources: [fiservSource('https://commercehub-checkout.fiservapps.com/sdk/3.8.14/payment-fields.js'), fiservSource('https://commercehub-secure-data-capture.fiservapps.com/sdk-secure/3.8.14/iframe.html')] });
71
+ // GMO Payment Gateway PG Multipayment (dark: its processor declares a capability, so the bundled
72
+ // catalog does not list it and these signals stay unknown until a client opts in). Token v2's
73
+ // mp-token.js identifies the processor. Token v1's ext/js/token.js (a JSONP GET), GMO Elements'
74
+ // card iframe and Link-type hosted pages identify it too, but no Vault mode covers them, so each
75
+ // keeps the result unknown through `variant_unverified`. Sources: the reviewed SDK bundles
76
+ // (mp-token.js sha256 1fedeab0...dbe0f7, test 9e6cd8a3...56e2aa) and GMO's public token docs.
77
+ const gmoSources = [
78
+ { kind: 'primary_source', reference: 'https://static.mul-pay.jp/payment/js/mp-token.js', reviewed_on: '2026-09-25' },
79
+ { kind: 'official_documentation', reference: 'https://docs.gmo-pg.com/mulpay/docs/developer-support/mp-token/overview', reviewed_on: '2026-09-25' },
80
+ ];
81
+ RULES.push({ id: 'gmo-mp-token-script', psp: 'gmo_pg', kinds: ['script'], hostname: /^static\.mul-pay\.jp$/, pathname: /^\/payment\/js\/mp-token\.js$/, origin: 'https://static.mul-pay.jp', path_pattern: '/payment/js/mp-token.js',
82
+ sources: gmoSources }, { id: 'gmo-token-v1-script', psp: 'gmo_pg', kinds: ['script'], hostname: /^static\.mul-pay\.jp$/, pathname: /^\/ext\/js\/token\.js$/, origin: 'https://static.mul-pay.jp', path_pattern: '/ext/js/token.js',
83
+ sources: [{ kind: 'primary_source', reference: 'https://static.mul-pay.jp/ext/js/token.js', reviewed_on: '2026-09-25' }],
84
+ variant_unverified: 'GMO token v1 (ext/js/token.js) sends the card as a JSONP GET; only token v2 (mp-token.js) getToken on the shared-key path is admitted.' }, { id: 'gmo-elements-card-frame', psp: 'gmo_pg', kinds: ['frame', 'iframe', 'document'], hostname: /^static\.mul-pay\.jp$/, pathname: /^\/payment\/js\/elements\/static\/formElement\.html$/, origin: 'https://static.mul-pay.jp', path_pattern: '/payment/js/elements/static/formElement.html',
85
+ sources: gmoSources,
86
+ variant_unverified: 'GMO Elements takes the card in GMO\'s own iframes and encrypts it under a merchant-registered key; it is not admitted.' }, { id: 'gmo-link-hosted-page', psp: 'gmo_pg', kinds: ['document', 'frame', 'iframe', 'form'], hostname: /^p01\.mul-pay\.jp$/, pathname: /^\/link\//, origin: 'https://p01.mul-pay.jp', path_pattern: '/link/*',
87
+ sources: [{ kind: 'official_documentation', reference: 'https://docs.gmo-pg.com/mulpay/docs/developer-support/test-environment/overview', reviewed_on: '2026-09-25' }],
88
+ variant_unverified: 'A GMO Link-type payment page takes the card on GMO\'s own hosted page; it is not admitted.' });
89
+ // Keep sandbox evidence truthful instead of labelling it with a production origin.
90
+ for (const [baseId, suffix, hostname, origin] of [
91
+ ['gmo-mp-token-script', 'test', /^stg\.static\.mul-pay\.jp$/, 'https://stg.static.mul-pay.jp'],
92
+ ['gmo-token-v1-script', 'test', /^stg\.static\.mul-pay\.jp$/, 'https://stg.static.mul-pay.jp'],
93
+ ['gmo-elements-card-frame', 'test', /^stg\.static\.mul-pay\.jp$/, 'https://stg.static.mul-pay.jp'],
94
+ ['gmo-link-hosted-page', 'test', /^pt01\.mul-pay\.jp$/, 'https://pt01.mul-pay.jp'],
95
+ ['square-web-sdk', 'sandbox', /^sandbox\.web\.squarecdn\.com$/, 'https://sandbox.web.squarecdn.com'],
96
+ ['paysafe-js', 'test', /^hosted\.test\.paysafe\.com$/, 'https://hosted.test.paysafe.com'],
97
+ ['worldpay-checkout-sdk', 'try', /^try\.access\.worldpay\.com$/, 'https://try.access.worldpay.com'],
98
+ ['authorize-net-accept', 'test', /^jstest\.authorize\.net$/, 'https://jstest.authorize.net'],
99
+ ['tranzila-terminal-hosted-page', 'directng', /^directng\.tranzila\.com$/, 'https://directng.tranzila.com'],
100
+ ['square-card-element-frame', 'sandbox', /^sandbox\.web\.squarecdn\.com$/, 'https://sandbox.web.squarecdn.com'],
101
+ ['authorize-net-sim-hosted-form', 'secure2', /^secure2\.authorize\.net$/, 'https://secure2.authorize.net'],
102
+ ['worldpay-hosted-payment-page', 'test', /^secure-test\.worldpay\.com$/, 'https://secure-test.worldpay.com'],
103
+ ['rapyd-hosted-checkout-page', 'sandbox', /^sandboxcheckout\.rapyd\.net$/, 'https://sandboxcheckout.rapyd.net'],
104
+ // Adyen's regional live hosts (docs.adyen.com/development-resources/live-endpoints/).
105
+ ['adyen-secured-fields-live', 'us', /^checkoutshopper-live-us\.adyen\.com$/, 'https://checkoutshopper-live-us.adyen.com'],
106
+ ['adyen-secured-fields-live', 'au', /^checkoutshopper-live-au\.adyen\.com$/, 'https://checkoutshopper-live-au.adyen.com'],
107
+ ['adyen-secured-fields-live', 'apse', /^checkoutshopper-live-apse\.adyen\.com$/, 'https://checkoutshopper-live-apse.adyen.com'],
108
+ ['adyen-secured-fields-live', 'in', /^checkoutshopper-live-in\.adyen\.com$/, 'https://checkoutshopper-live-in.adyen.com'],
109
+ ['adyen-secured-fields-live', 'nea', /^checkoutshopper-live-nea\.adyen\.com$/, 'https://checkoutshopper-live-nea.adyen.com'],
110
+ // Commerce Hub's "Sandbox and Cert" environment (payment-fields.js 3.8.14 environment table).
111
+ ['fiserv-commercehub-payment-fields', 'cert', /^commercehub-checkout-cert\.fiservapps\.com$/, 'https://commercehub-checkout-cert.fiservapps.com'],
112
+ ['fiserv-commercehub-checkout-script', 'cert', /^commercehub-checkout-cert\.fiservapps\.com$/, 'https://commercehub-checkout-cert.fiservapps.com'],
113
+ ['fiserv-secure-data-capture-frame', 'cert', /^commercehub-secure-data-capture-cert\.fiservapps\.com$/, 'https://commercehub-secure-data-capture-cert.fiservapps.com'],
114
+ ]) {
115
+ RULES.push({ ...RULES.find(rule => rule.id === baseId), id: `${baseId}-${suffix}`, hostname, origin });
116
+ }
117
+ const SOURCES = {
118
+ stripe: [{ kind: 'official_documentation', reference: 'https://docs.stripe.com/js/including', reviewed_on: '2026-09-11' }],
119
+ square: [{ kind: 'official_documentation', reference: 'https://developer.squareup.com/docs/web-payments/quickstart/add-sdk-to-web-client', reviewed_on: '2026-09-11' }],
120
+ mollie: [{ kind: 'saved_observation', reference: 'mollie-haak-2026-09-11:hosted-credit-card-document-and-v2-script', reviewed_on: '2026-09-11' }],
121
+ braintree: [{ kind: 'official_documentation', reference: 'https://developer.paypal.com/braintree/docs/start/hello-client/javascript/v3/', reviewed_on: '2026-09-11' }],
122
+ paysafe: [{ kind: 'official_documentation', reference: 'https://developer.paysafe.com/en/api-docs/paysafe-js/overview/', reviewed_on: '2026-09-11' }],
123
+ worldpay: [{ kind: 'official_documentation', reference: 'https://developer.worldpay.com/products/checkout/web', reviewed_on: '2026-09-11' }],
124
+ authorize_net: [{ kind: 'official_documentation', reference: 'https://developer.authorize.net/api/reference/features/acceptjs.html', reviewed_on: '2026-09-11' }],
125
+ razorpay: [{ kind: 'official_documentation', reference: 'https://razorpay.com/docs/payments/payment-gateway/web-integration/standard/integration-steps/', reviewed_on: '2026-09-11' }],
126
+ vgs: [{ kind: 'official_documentation', reference: 'https://docs.verygoodsecurity.com/vault/developer-tools/vgs-collect/js/integration', reviewed_on: '2026-09-11' }],
127
+ };
128
+ const FLOWS = [
129
+ { id: 'mollie.hosted_components', psp: 'mollie', operation: 'mollie.card_request', operation_version: 1, mode: 'token', server_constraint: 'eligible', limitations: [
130
+ 'The payment request must match the supported Mollie Components card-token format.',
131
+ 'Authentication and merchant confirmation must finish in the merchant browser.',
132
+ 'Merchant configuration, card eligibility and processor approval still determine whether the purchase succeeds.',
133
+ ] },
134
+ { id: 'vgs.iframe_bound_tokenization', psp: 'vgs', operation: 'vgs.iframe_bound_tokenization', operation_version: 1, mode: 'token', server_constraint: 'unsupported', limitations: [
135
+ 'VGS requires tokenization from its own iframe; the Vault cannot replay this flow from the approval page.',
136
+ ] },
137
+ ];
138
+ const FLOW_BY_ID = new Map(FLOWS.map(flow => [flow.id, flow]));
139
+ const RULE_BY_ID = new Map(RULES.map(rule => [rule.id, rule]));
140
+ const DEFAULT_PROFILE = {
141
+ schema_version: 1, profile_version: 'preflight-2', catalog_version: CHECKOUT_PREFLIGHT_CATALOG_VERSION,
142
+ integration: { id: 'direct_sdk', version: 'bundled' },
143
+ // The bundled profile repeats each processor's projected status. A processor whose card
144
+ // request the SDK cannot pause at all, Gravy's PUT today, is declared unsupported here
145
+ // as well as in its scenarios, so the exported profile never contradicts the assessment.
146
+ processor_entries: CHECKOUT_PREFLIGHT_CAPABILITIES.processors.map(processor => ({
147
+ psp: processor.psp, mode: processor.mode, scenario: 'one_time', status: processor.status,
148
+ })),
149
+ entries: [{ flow: 'mollie.hosted_components', operation: 'mollie.card_request', operation_version: 1, mode: 'token', scenario: 'one_time', status: 'supported' }],
150
+ };
151
+ const clone = (value) => JSON.parse(JSON.stringify(value));
152
+ const record = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
153
+ const exactKeys = (value, keys) => Object.keys(value).every(key => keys.includes(key));
154
+ const id = (value) => typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._+-]{0,119}$/.test(value);
155
+ const frameId = (value) => Number.isSafeInteger(value) && value >= 0 && value < CHECKOUT_PREFLIGHT_LIMITS.frames;
156
+ const unique = (items) => [...new Set(items)];
157
+ function dateTime(value) {
158
+ if (typeof value !== 'string' || value.length > 40)
159
+ return false;
160
+ const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,9})?(?:Z|[+-](\d{2}):(\d{2}))$/.exec(value);
161
+ if (!match)
162
+ return false;
163
+ const [year, month, day, hour, minute, second, zoneHour = 0, zoneMinute = 0] = match.slice(1).map(part => part === undefined ? 0 : Number(part));
164
+ const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
165
+ const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
166
+ return month >= 1 && month <= 12 && day >= 1 && day <= days[month - 1] && hour <= 23 && minute <= 59 && second <= 59
167
+ && zoneHour <= 23 && zoneMinute <= 59 && Number.isFinite(Date.parse(value));
168
+ }
169
+ function metadata(value) {
170
+ return KINDS.includes(value.kind) && frameId(value.frame_id) && (value.parent_frame_id === null || frameId(value.parent_frame_id))
171
+ && (value.frame_id !== 0 || value.parent_frame_id === null)
172
+ && value.parent_frame_id !== value.frame_id && (value.visible === null || typeof value.visible === 'boolean');
173
+ }
174
+ function consistentParents(signals) {
175
+ const parents = new Map();
176
+ for (const signal of signals) {
177
+ if (parents.has(signal.frame_id) && parents.get(signal.frame_id) !== signal.parent_frame_id)
178
+ return false;
179
+ parents.set(signal.frame_id, signal.parent_frame_id);
180
+ }
181
+ for (const frame of parents.keys()) {
182
+ const visited = new Set();
183
+ let current = frame;
184
+ while (current !== null && current !== undefined) {
185
+ if (visited.has(current))
186
+ return false;
187
+ visited.add(current);
188
+ current = parents.get(current);
189
+ }
190
+ }
191
+ return true;
192
+ }
193
+ function cleanObservation(input) {
194
+ if (!record(input) || !exactKeys(input, ['complete', 'truncated', 'reasons']) || typeof input.complete !== 'boolean' || typeof input.truncated !== 'boolean'
195
+ || !Array.isArray(input.reasons) || input.reasons.length > 32 || Array.from(input.reasons).some(reason => !OBSERVATION_REASONS.includes(reason))) {
196
+ return { complete: false, truncated: false, reasons: ['invalid_observation'] };
197
+ }
198
+ const reasons = unique(input.reasons);
199
+ const complete = input.complete && !input.truncated && reasons.length === 0;
200
+ return { complete, truncated: input.truncated, reasons: complete ? [] : unique([...reasons, 'collection_incomplete']) };
201
+ }
202
+ const byteLength = (value) => new TextEncoder().encode(JSON.stringify(value)).length;
203
+ function incomplete(observation, reason, truncated = false) {
204
+ observation.complete = false;
205
+ observation.truncated ||= truncated;
206
+ observation.reasons = unique([...observation.reasons, reason]);
207
+ }
208
+ /** Normalize observations locally. Unknown assets are omitted; no URL leaves this function. */
209
+ export function normalizeCheckoutSignals(input) {
210
+ const snapshot = { schema_version: 1, catalog_version: CHECKOUT_PREFLIGHT_CATALOG_VERSION, signals: [], observation: cleanObservation(record(input) ? input.observation : null) };
211
+ if (!record(input) || !exactKeys(input, ['signals', 'observation']) || !Array.isArray(input.signals)) {
212
+ incomplete(snapshot.observation, 'invalid_observation');
213
+ return snapshot;
214
+ }
215
+ if (input.signals.length > CHECKOUT_PREFLIGHT_LIMITS.signals)
216
+ incomplete(snapshot.observation, 'signal_limit', true);
217
+ const seen = new Set();
218
+ for (const raw of input.signals.slice(0, CHECKOUT_PREFLIGHT_LIMITS.signals)) {
219
+ if (!record(raw) || !exactKeys(raw, ['kind', 'url', 'frame_id', 'parent_frame_id', 'visible']) || !metadata(raw)) {
220
+ incomplete(snapshot.observation, 'invalid_observation');
221
+ continue;
222
+ }
223
+ if (typeof raw.url !== 'string' || raw.url.length > CHECKOUT_PREFLIGHT_LIMITS.raw_url_length) {
224
+ incomplete(snapshot.observation, 'invalid_url');
225
+ continue;
226
+ }
227
+ let url;
228
+ try {
229
+ url = new URL(raw.url);
230
+ }
231
+ catch {
232
+ incomplete(snapshot.observation, 'invalid_url');
233
+ continue;
234
+ }
235
+ // Matching reads the origin and path only. A long query string on an unrelated wallet or
236
+ // widget frame is dropped here rather than invalidating the whole observation.
237
+ if (url.origin.length + url.pathname.length > CHECKOUT_PREFLIGHT_LIMITS.url_length) {
238
+ incomplete(snapshot.observation, 'invalid_url');
239
+ continue;
240
+ }
241
+ // Non-HTTPS local/blank frames provide no PSP evidence. Credentials and nondefault ports are refused.
242
+ if (url.protocol !== 'https:' || url.username || url.password || url.port)
243
+ continue;
244
+ for (const rule of RULES) {
245
+ if (!rule.kinds.includes(raw.kind) || !rule.hostname.test(url.hostname) || !rule.pathname.test(url.pathname))
246
+ continue;
247
+ const signal = { rule_id: rule.id, kind: raw.kind, frame_id: raw.frame_id, parent_frame_id: raw.parent_frame_id, visible: raw.visible };
248
+ const key = JSON.stringify(signal);
249
+ if (!seen.has(key)) {
250
+ // One observed asset can match more than one reviewed fingerprint.
251
+ // Bound normalized evidence independently of the raw observation count.
252
+ if (snapshot.signals.length >= CHECKOUT_PREFLIGHT_LIMITS.signals) {
253
+ incomplete(snapshot.observation, 'signal_limit', true);
254
+ continue;
255
+ }
256
+ snapshot.signals.push(signal);
257
+ seen.add(key);
258
+ }
259
+ }
260
+ }
261
+ while (byteLength(snapshot) > CHECKOUT_PREFLIGHT_LIMITS.snapshot_bytes && snapshot.signals.length) {
262
+ snapshot.signals.pop();
263
+ incomplete(snapshot.observation, 'snapshot_limit', true);
264
+ }
265
+ if (!consistentParents(snapshot.signals))
266
+ incomplete(snapshot.observation, 'invalid_observation');
267
+ return snapshot;
268
+ }
269
+ /** The returned catalog is metadata only. It does not change card destination recognition. */
270
+ export function getCheckoutPreflightCatalog() {
271
+ return clone({
272
+ schema_version: 1, catalog_version: CHECKOUT_PREFLIGHT_CATALOG_VERSION, scope: 'preflight_hint',
273
+ integration_version_note: 'bundled describes the capabilities accompanying this helper, not a claim about another installed SDK version.',
274
+ limits: CHECKOUT_PREFLIGHT_LIMITS,
275
+ known_psps: KNOWN_PSPS.map(psp => ({ psp, detection: RULES.some(rule => rule.psp === psp) ? 'reviewed_rules' : 'unknown' })),
276
+ rules: RULES.map(({ hostname, pathname, ...rule }) => ({ ...rule, hostname_pattern: hostname.source, pathname_pattern: pathname.source, sources: rule.sources ?? SOURCES[rule.psp] })),
277
+ processors: CHECKOUT_PREFLIGHT_CAPABILITIES.processors, exclusions: CHECKOUT_PREFLIGHT_CAPABILITIES.exclusions,
278
+ flows: FLOWS, direct_sdk_profile: DEFAULT_PROFILE,
279
+ kernel_profile_template: { schema_version: 1, profile_version: 'kernel-template-1', catalog_version: CHECKOUT_PREFLIGHT_CATALOG_VERSION,
280
+ integration: { id: 'kernel_native', version: 'REPLACE-WITH-ADAPTER-VERSION' }, entries: [], processor_entries: [] },
281
+ observation_reason_codes: OBSERVATION_REASONS,
282
+ });
283
+ }
284
+ // Registrable-site approximation for provider hosts; a public-suffix list is deliberately not bundled.
285
+ function site(hostname) {
286
+ const labels = hostname.toLowerCase().split('.').filter(Boolean);
287
+ const secondLevel = ['com', 'co', 'net', 'org', 'gov', 'edu', 'ac', 'or', 'ne'];
288
+ const count = labels.length > 2 && labels[labels.length - 1].length === 2 && secondLevel.includes(labels[labels.length - 2]) ? 3 : 2;
289
+ return labels.slice(-count).join('.');
290
+ }
291
+ /**
292
+ * Whether a visible card-entry frame on `hostname` can belong to a processor already evidenced in the
293
+ * snapshot. A collector reports `card_entry_unrecognized` when this is false, so co-loaded SDK scripts
294
+ * cannot be presented as the processor behind card controls that no reviewed fingerprint explains, and
295
+ * a card form with no processor evidence at all is reported rather than passing as an empty page.
296
+ * The hostname stays local to the caller; nothing here enters evidence.
297
+ */
298
+ export function cardEntryAttributable(input, hostname) {
299
+ if (!validSnapshot(input) || typeof hostname !== 'string' || !hostname)
300
+ return false;
301
+ const evidenced = new Set(input.signals.map(signal => RULE_BY_ID.get(signal.rule_id).psp));
302
+ if (!evidenced.size)
303
+ return false;
304
+ const target = site(hostname);
305
+ return RULES.some(rule => {
306
+ if (!evidenced.has(rule.psp))
307
+ return false;
308
+ if (rule.hostname.test(hostname))
309
+ return true;
310
+ // A templated origin (the VGS tenant frame) is covered by its hostname pattern above.
311
+ try {
312
+ return site(new URL(rule.origin).hostname) === target;
313
+ }
314
+ catch {
315
+ return false;
316
+ }
317
+ });
318
+ }
319
+ function validSnapshot(input) {
320
+ return record(input) && exactKeys(input, ['schema_version', 'catalog_version', 'signals', 'observation'])
321
+ && input.schema_version === 1 && input.catalog_version === CHECKOUT_PREFLIGHT_CATALOG_VERSION
322
+ && Array.isArray(input.signals) && input.signals.length <= CHECKOUT_PREFLIGHT_LIMITS.signals
323
+ && Array.from(input.signals).every(signal => record(signal) && exactKeys(signal, ['rule_id', 'kind', 'frame_id', 'parent_frame_id', 'visible']) && metadata(signal)
324
+ && id(signal.rule_id) && !!RULE_BY_ID.get(signal.rule_id)?.kinds.includes(signal.kind))
325
+ && consistentParents(input.signals)
326
+ && record(input.observation) && exactKeys(input.observation, ['complete', 'truncated', 'reasons'])
327
+ && typeof input.observation.complete === 'boolean' && typeof input.observation.truncated === 'boolean'
328
+ && Array.isArray(input.observation.reasons) && input.observation.reasons.length <= 32
329
+ && Array.from(input.observation.reasons).every(reason => OBSERVATION_REASONS.includes(reason))
330
+ && byteLength(input) <= CHECKOUT_PREFLIGHT_LIMITS.snapshot_bytes;
331
+ }
332
+ function validIntegration(value) {
333
+ return record(value) && exactKeys(value, ['id', 'version']) && ['direct_sdk', 'kernel_native'].includes(value.id) && (value.version === null || id(value.version));
334
+ }
335
+ function profileError(profile, integration, now) {
336
+ if (!record(profile) || !exactKeys(profile, ['schema_version', 'profile_version', 'catalog_version', 'integration', 'entries', 'processor_entries', 'expires_at'])
337
+ || profile.schema_version !== 1 || !id(profile.profile_version) || !validIntegration(profile.integration) || !id(profile.integration.version)
338
+ || !Array.isArray(profile.entries) || profile.entries.length > 256
339
+ || (profile.processor_entries !== undefined && (!Array.isArray(profile.processor_entries) || profile.processor_entries.length > 256)))
340
+ return 'integration_profile_invalid';
341
+ if (profile.catalog_version !== CHECKOUT_PREFLIGHT_CATALOG_VERSION)
342
+ return 'integration_profile_incompatible';
343
+ if (profile.integration.id !== integration.id || profile.integration.version !== integration.version)
344
+ return 'integration_profile_mismatch';
345
+ if (profile.expires_at !== undefined) {
346
+ const expires = dateTime(profile.expires_at) ? Date.parse(profile.expires_at) : NaN;
347
+ const time = now === undefined ? Date.now() : dateTime(now) ? Date.parse(now) : NaN;
348
+ if (!Number.isFinite(expires) || !Number.isFinite(time))
349
+ return 'integration_profile_invalid';
350
+ if (expires <= time)
351
+ return 'integration_profile_expired';
352
+ }
353
+ const entries = new Set();
354
+ for (const entry of profile.entries) {
355
+ if (!record(entry) || !exactKeys(entry, ['flow', 'operation', 'operation_version', 'mode', 'scenario', 'status', 'limitations'])
356
+ || !id(entry.flow) || !id(entry.operation) || !SCENARIOS.includes(entry.scenario) || !['supported', 'unsupported'].includes(entry.status)
357
+ || (entry.limitations !== undefined && (!Array.isArray(entry.limitations) || entry.limitations.length > 16 || Array.from(entry.limitations).some(text => typeof text !== 'string' || text.length > 256 || /[\x00-\x1f]/.test(text)))))
358
+ return 'integration_profile_invalid';
359
+ const flow = FLOW_BY_ID.get(entry.flow);
360
+ if (!flow || entry.operation !== flow.operation || entry.operation_version !== flow.operation_version || entry.mode !== flow.mode)
361
+ return 'integration_profile_incompatible';
362
+ const key = `${entry.flow}:${entry.scenario}`;
363
+ if (entries.has(key))
364
+ return 'integration_profile_invalid';
365
+ entries.add(key);
366
+ }
367
+ const processors = new Set();
368
+ for (const entry of profile.processor_entries ?? []) {
369
+ if (!record(entry) || !exactKeys(entry, ['psp', 'mode', 'scenario', 'status', 'limitations'])
370
+ || !id(entry.psp) || !SCENARIOS.includes(entry.scenario) || !['supported', 'unsupported'].includes(entry.status)
371
+ || (entry.limitations !== undefined && (!Array.isArray(entry.limitations) || entry.limitations.length > 16 || Array.from(entry.limitations).some(text => typeof text !== 'string' || text.length > 256 || /[\x00-\x1f]/.test(text)))))
372
+ return 'integration_profile_invalid';
373
+ const processor = PROCESSOR_BY_ID.get(entry.psp);
374
+ if (!processor || processor.mode !== entry.mode)
375
+ return 'integration_profile_incompatible';
376
+ const key = `${entry.psp}:${entry.scenario}`;
377
+ if (processors.has(key))
378
+ return 'integration_profile_invalid';
379
+ processors.add(key);
380
+ }
381
+ return null;
382
+ }
383
+ /** Classify a sanitized snapshot. No browser, HTTP, or payment operations occur here. */
384
+ export function assessCheckoutSupport(input, options = {}) {
385
+ const opts = record(options) ? options : {};
386
+ const fallbackIntegrationId = record(opts.integration) && opts.integration.id === 'kernel_native' ? 'kernel_native' : 'direct_sdk';
387
+ const integration = validIntegration(opts.integration) ? clone(opts.integration) : {
388
+ id: fallbackIntegrationId,
389
+ version: opts.integration === undefined ? 'bundled' : null,
390
+ };
391
+ const result = {
392
+ schema_version: 1, catalog_version: CHECKOUT_PREFLIGHT_CATALOG_VERSION, integration,
393
+ scenario: opts.scenario !== undefined && SCENARIOS.includes(opts.scenario) ? opts.scenario : 'one_time', scenario_defaulted: opts.scenario === undefined,
394
+ psp: null, flow: null, mode: null, status: 'unknown', support_scope: null, checkout_flow_status: 'unknown', candidates: [], reason_codes: [], limitations: [], missing_evidence: [],
395
+ observation: { complete: false, truncated: false, reasons: ['invalid_observation'] }, scope: 'preflight_hint', merchant_confirmation_required: true,
396
+ };
397
+ if (!record(options) || !exactKeys(opts, ['scenario', 'integration', 'profile', 'now']) || (opts.scenario !== undefined && !SCENARIOS.includes(opts.scenario))
398
+ || (opts.integration !== undefined && !validIntegration(opts.integration)) || (opts.now !== undefined && !dateTime(opts.now))) {
399
+ result.reason_codes = ['invalid_options'];
400
+ return result;
401
+ }
402
+ if (!validSnapshot(input)) {
403
+ result.reason_codes = [record(input) && input.catalog_version !== CHECKOUT_PREFLIGHT_CATALOG_VERSION ? 'catalog_incompatible' : 'invalid_snapshot'];
404
+ return result;
405
+ }
406
+ result.observation = cleanObservation(input.observation);
407
+ const candidates = new Map();
408
+ const activeFlows = new Set();
409
+ const activePsps = new Set();
410
+ const activeFlowFrames = new Set();
411
+ let missingCorroboration = false;
412
+ for (const signal of input.signals) {
413
+ const rule = RULE_BY_ID.get(signal.rule_id);
414
+ const active = signal.visible === true && (['frame', 'iframe', 'form'].includes(signal.kind)
415
+ || signal.kind === 'document' && signal.frame_id === 0 && signal.parent_frame_id === null);
416
+ const candidate = candidates.get(rule.psp) ?? { psp: rule.psp, relevance: 'undetermined', evidence: [] };
417
+ candidate.evidence.push({ ...clone(signal), origin: rule.origin, path_pattern: rule.path_pattern });
418
+ if (active) {
419
+ candidate.relevance = 'active';
420
+ activePsps.add(rule.psp);
421
+ if (rule.flow) {
422
+ // A hosted route can also display an expired/error page. Require the reviewed
423
+ // Components script in that document; a similarly named asset elsewhere is insufficient.
424
+ const corroborated = rule.flow !== 'mollie.hosted_components' || signal.kind !== 'iframe' && input.signals.some(other => other.rule_id === 'mollie-components-script' && other.kind === 'script' && other.frame_id === signal.frame_id && other.parent_frame_id === signal.parent_frame_id);
425
+ if (corroborated) {
426
+ activeFlows.add(rule.flow);
427
+ activeFlowFrames.add(signal.frame_id);
428
+ }
429
+ else
430
+ missingCorroboration = true;
431
+ }
432
+ }
433
+ candidates.set(rule.psp, candidate);
434
+ }
435
+ result.candidates = [...candidates.values()].sort((a, b) => a.psp.localeCompare(b.psp));
436
+ if (missingCorroboration && activeFlows.size === 0)
437
+ result.reason_codes.push('flow_corroboration_missing');
438
+ if (activePsps.size === 1)
439
+ result.psp = [...activePsps][0];
440
+ // Script-only evidence names the processor only when the scan saw everything. On a partial scan
441
+ // the sole candidate stays listed as undetermined instead of becoming the selected route.
442
+ else if (activePsps.size === 0 && candidates.size === 1 && result.observation.complete)
443
+ result.psp = [...candidates.keys()][0];
444
+ if (!result.observation.complete)
445
+ result.reason_codes.push('observation_incomplete');
446
+ if (!input.signals.length) {
447
+ result.reason_codes.push('psp_not_detected');
448
+ result.missing_evidence.push('payment_page_signal');
449
+ }
450
+ if (activePsps.size > 1 || activeFlows.size > 1 || activeFlowFrames.size > 1 || activePsps.size === 0 && candidates.size > 1)
451
+ result.reason_codes.push('ambiguous_checkout');
452
+ if (activeFlows.size !== 1 || result.psp === null) {
453
+ result.reason_codes.push('checkout_flow_unidentified');
454
+ result.missing_evidence.push('active_checkout_flow');
455
+ }
456
+ else {
457
+ const flow = FLOW_BY_ID.get([...activeFlows][0]);
458
+ if (flow.psp === result.psp) {
459
+ result.flow = flow.id;
460
+ result.mode = flow.mode;
461
+ result.limitations.push(...flow.limitations);
462
+ }
463
+ }
464
+ if (!result.flow && result.candidates.length)
465
+ result.limitations.push('Processor assets alone do not establish the active card payment flow.');
466
+ const profile = opts.profile === undefined ? (integration.id === 'direct_sdk' && integration.version === 'bundled' ? DEFAULT_PROFILE : undefined) : opts.profile;
467
+ let error = profile === undefined ? 'integration_profile_missing' : profileError(profile, integration, opts.now);
468
+ if (integration.version === null)
469
+ error = 'integration_version_missing';
470
+ if (error) {
471
+ result.reason_codes.push(error);
472
+ result.missing_evidence.push('compatible_integration_profile');
473
+ }
474
+ result.reason_codes = unique(result.reason_codes);
475
+ const ambiguous = result.reason_codes.includes('ambiguous_checkout');
476
+ result.checkout_flow_status = ambiguous ? 'ambiguous' : result.flow ? 'identified' : 'unknown';
477
+ // Processor capability and observed checkout compatibility answer different questions.
478
+ // Missing flow evidence is advisory when an identified processor has an explicit
479
+ // implementation declaration. Incomplete, contradictory or invalid input stays unknown.
480
+ if (!result.observation.complete || ambiguous || error || !result.psp || missingCorroboration && !result.flow)
481
+ return result;
482
+ const flow = result.flow ? FLOW_BY_ID.get(result.flow) : undefined;
483
+ if (flow?.server_constraint === 'unsupported') {
484
+ result.status = 'unsupported';
485
+ result.support_scope = 'checkout_flow';
486
+ result.reason_codes.push('vault_flow_unsupported');
487
+ return result;
488
+ }
489
+ // A hidden document cannot lend its scripts to a visible card checkout. Script-only
490
+ // observations with no known hidden container can still identify an available adapter.
491
+ const eligible = input.signals.some(signal => RULE_BY_ID.get(signal.rule_id).psp === result.psp
492
+ && (signal.kind === 'script' ? signal.visible !== false && !input.signals.some(container => container.frame_id === signal.frame_id && ['document', 'frame'].includes(container.kind) && container.visible !== true)
493
+ : signal.visible === true));
494
+ if (!eligible) {
495
+ result.reason_codes.push('payment_signal_inactive');
496
+ return result;
497
+ }
498
+ {
499
+ // A native declaration cannot expand the shared Vault's admitted processor variants.
500
+ const incompatible = input.signals.map(signal => ({ signal, rule: RULE_BY_ID.get(signal.rule_id) }))
501
+ .filter(({ signal, rule }) => rule.psp === result.psp && rule.variant_unverified
502
+ && (signal.kind === 'script' ? signal.visible !== false : signal.visible === true));
503
+ if (incompatible.length) {
504
+ result.reason_codes.push('processor_variant_unverified');
505
+ result.limitations.push(...incompatible.map(({ rule }) => rule.variant_unverified));
506
+ return result;
507
+ }
508
+ }
509
+ const processor = PROCESSOR_BY_ID.get(result.psp);
510
+ const scenario = processor?.scenarios[result.scenario];
511
+ if (processor) {
512
+ const bundledSdk = integration.id === 'direct_sdk' && integration.version === 'bundled';
513
+ if (bundledSdk)
514
+ result.limitations.push(...processor.limitations);
515
+ for (const variant of processor.unsupported_variants) {
516
+ if (bundledSdk || variant.constraint === 'vault')
517
+ result.limitations.push(variant.reason);
518
+ }
519
+ }
520
+ if (scenario && (scenario.status === 'unsupported' || scenario.status === 'outside_vault')) {
521
+ result.status = 'unsupported';
522
+ result.mode = processor.mode;
523
+ result.support_scope = 'processor_integration';
524
+ result.reason_codes.push(scenario.reason);
525
+ return result;
526
+ }
527
+ const profileValue = profile;
528
+ const entry = flow && profileValue.entries.find(entry => entry.flow === flow.id && entry.scenario === result.scenario);
529
+ if (entry) {
530
+ result.status = entry.status;
531
+ result.support_scope = 'checkout_flow';
532
+ result.reason_codes.push(entry.status === 'supported' ? 'flow_supported_by_integration' : 'integration_flow_unsupported');
533
+ result.limitations.push(...(entry.limitations ?? []));
534
+ return result;
535
+ }
536
+ if (!processor)
537
+ return result;
538
+ result.mode = processor.mode;
539
+ const processorEntry = profileValue.processor_entries?.find(entry => entry.psp === processor.psp && entry.scenario === result.scenario);
540
+ if (!processorEntry) {
541
+ result.reason_codes.push(flow ? 'integration_flow_undeclared' : 'integration_processor_undeclared');
542
+ result.missing_evidence.push(flow ? 'integration_flow_capability' : 'integration_processor_capability');
543
+ return result;
544
+ }
545
+ result.status = processorEntry.status;
546
+ result.support_scope = 'processor_integration';
547
+ result.reason_codes.push(processorEntry.status === 'supported' ? 'processor_supported_by_integration' : 'integration_processor_unsupported');
548
+ result.limitations.push(...(processorEntry.limitations ?? []));
549
+ result.limitations = unique(result.limitations);
550
+ return result;
551
+ }
552
+ /** Machine-readable transport shapes; semantic compatibility is checked by the classifier. */
553
+ export function getCheckoutPreflightSchemas() {
554
+ const text = { type: 'string', minLength: 1, maxLength: 120, pattern: '^[A-Za-z0-9][A-Za-z0-9._+-]{0,119}$' };
555
+ const integration = { type: 'object', additionalProperties: false, required: ['id', 'version'], properties: { id: { enum: ['direct_sdk', 'kernel_native'] }, version: { anyOf: [text, { type: 'null' }] } } };
556
+ const observation = { type: 'object', additionalProperties: false, required: ['complete', 'truncated', 'reasons'], properties: { complete: { type: 'boolean' }, truncated: { type: 'boolean' }, reasons: { type: 'array', maxItems: 32, uniqueItems: true, items: { enum: OBSERVATION_REASONS } } } };
557
+ const signal = { type: 'object', additionalProperties: false, required: ['rule_id', 'kind', 'frame_id', 'parent_frame_id', 'visible'], properties: {
558
+ rule_id: { enum: RULES.map(rule => rule.id) }, kind: { enum: KINDS }, frame_id: { type: 'integer', minimum: 0, maximum: 63 },
559
+ parent_frame_id: { anyOf: [{ type: 'integer', minimum: 0, maximum: 63 }, { type: 'null' }] }, visible: { type: ['boolean', 'null'] },
560
+ } };
561
+ const profile = { $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'object', additionalProperties: false,
562
+ required: ['schema_version', 'profile_version', 'catalog_version', 'integration', 'entries'], properties: {
563
+ schema_version: { const: 1 }, profile_version: text, catalog_version: { const: CHECKOUT_PREFLIGHT_CATALOG_VERSION }, integration,
564
+ processor_entries: { type: 'array', maxItems: 256, items: {
565
+ type: 'object', additionalProperties: false, required: ['psp', 'mode', 'scenario', 'status'], properties: {
566
+ psp: { enum: KNOWN_PSPS }, mode: { enum: ['token', 'cse', 'hosted_form'] }, scenario: { enum: SCENARIOS }, status: { enum: ['supported', 'unsupported'] },
567
+ limitations: { type: 'array', maxItems: 16, items: { type: 'string', maxLength: 256, pattern: '^[^\\u0000-\\u001f]*$' } },
568
+ },
569
+ } },
570
+ expires_at: { type: 'string', format: 'date-time', maxLength: 40 }, entries: { type: 'array', maxItems: 256, items: {
571
+ type: 'object', additionalProperties: false, required: ['flow', 'operation', 'operation_version', 'mode', 'scenario', 'status'], properties: {
572
+ flow: { enum: FLOWS.map(flow => flow.id) }, operation: { enum: FLOWS.map(flow => flow.operation) }, operation_version: { const: 1 },
573
+ mode: { enum: ['token', 'cse', 'hosted_form'] }, scenario: { enum: SCENARIOS }, status: { enum: ['supported', 'unsupported'] },
574
+ limitations: { type: 'array', maxItems: 16, items: { type: 'string', maxLength: 256, pattern: '^[^\\u0000-\\u001f]*$' } },
575
+ },
576
+ } },
577
+ } };
578
+ const snapshot = { $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'object', additionalProperties: false,
579
+ required: ['schema_version', 'catalog_version', 'signals', 'observation'], properties: {
580
+ schema_version: { const: 1 }, catalog_version: { const: CHECKOUT_PREFLIGHT_CATALOG_VERSION },
581
+ signals: { type: 'array', maxItems: CHECKOUT_PREFLIGHT_LIMITS.signals, items: signal }, observation,
582
+ } };
583
+ const evidence = { ...signal, required: [...signal.required, 'origin', 'path_pattern'], properties: { ...signal.properties, origin: { type: 'string', maxLength: 256 }, path_pattern: { type: 'string', maxLength: 256 } } };
584
+ const result = { $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'object', additionalProperties: false,
585
+ required: ['schema_version', 'catalog_version', 'integration', 'scenario', 'scenario_defaulted', 'psp', 'flow', 'mode', 'status', 'support_scope', 'checkout_flow_status', 'candidates', 'reason_codes', 'limitations', 'missing_evidence', 'observation', 'scope', 'merchant_confirmation_required'], properties: {
586
+ schema_version: { const: 1 }, catalog_version: { const: CHECKOUT_PREFLIGHT_CATALOG_VERSION }, integration,
587
+ scenario: { enum: SCENARIOS }, scenario_defaulted: { type: 'boolean' }, psp: { type: ['string', 'null'] }, flow: { type: ['string', 'null'] }, mode: { enum: ['token', 'cse', 'hosted_form', null] },
588
+ support_scope: { enum: ['processor_integration', 'checkout_flow', null] }, checkout_flow_status: { enum: ['identified', 'unknown', 'ambiguous'] },
589
+ status: { enum: ['supported', 'unsupported', 'unknown'] }, candidates: { type: 'array', items: { type: 'object', additionalProperties: false, required: ['psp', 'relevance', 'evidence'], properties: {
590
+ psp: { type: 'string' }, relevance: { enum: ['active', 'undetermined'] }, evidence: { type: 'array', items: evidence },
591
+ } } }, reason_codes: { type: 'array', items: { type: 'string' } }, limitations: { type: 'array', items: { type: 'string' } }, missing_evidence: { type: 'array', items: { type: 'string' } }, observation,
592
+ scope: { const: 'preflight_hint' }, merchant_confirmation_required: { const: true },
593
+ } };
594
+ const rawSignalProperties = { ...signal.properties, url: { type: 'string', maxLength: CHECKOUT_PREFLIGHT_LIMITS.raw_url_length } };
595
+ delete rawSignalProperties.rule_id;
596
+ const observations = { $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'object', additionalProperties: false,
597
+ required: ['signals', 'observation'], properties: { signals: { type: 'array', maxItems: CHECKOUT_PREFLIGHT_LIMITS.signals, items: {
598
+ type: 'object', additionalProperties: false, required: ['url', 'kind', 'frame_id', 'parent_frame_id', 'visible'], properties: rawSignalProperties,
599
+ } }, observation } };
600
+ const options = { $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'object', additionalProperties: false, properties: {
601
+ scenario: { enum: SCENARIOS }, integration, profile, now: { type: 'string', format: 'date-time', maxLength: 40 },
602
+ } };
603
+ return clone({ observations, options, snapshot, profile, result });
604
+ }