@tokenoftrust/storefront-runner 1.4.2-rc.0 → 2.0.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 (363) hide show
  1. package/apps/storefront/astro.config.mjs +3 -3
  2. package/apps/storefront/env.d.ts +54 -5
  3. package/apps/storefront/integrations/materialize-guard.mjs +12 -14
  4. package/apps/storefront/migrations-apps/0004_deep_morph.sql +36 -0
  5. package/apps/storefront/migrations-apps/0005_common_mystique.sql +23 -0
  6. package/apps/storefront/migrations-apps/0006_broad_microchip.sql +16 -0
  7. package/apps/storefront/migrations-apps/0007_brave_outlaw_kid.sql +15 -0
  8. package/apps/storefront/migrations-apps/0008_blue_dazzler.sql +11 -0
  9. package/apps/storefront/migrations-apps/0009_bored_shinobi_shaw.sql +15 -0
  10. package/apps/storefront/migrations-apps/0010_ws4_verified_provider_measurement.sql +35 -0
  11. package/apps/storefront/migrations-apps/meta/0004_snapshot.json +1474 -0
  12. package/apps/storefront/migrations-apps/meta/0005_snapshot.json +1617 -0
  13. package/apps/storefront/migrations-apps/meta/0006_snapshot.json +1716 -0
  14. package/apps/storefront/migrations-apps/meta/0007_snapshot.json +1812 -0
  15. package/apps/storefront/migrations-apps/meta/0008_snapshot.json +1881 -0
  16. package/apps/storefront/migrations-apps/meta/0009_snapshot.json +1979 -0
  17. package/apps/storefront/migrations-apps/meta/_journal.json +42 -0
  18. package/apps/storefront/public/apps/tot.demo.analytics/0.1.0/entry.js +42 -0
  19. package/apps/storefront/public/platform/amplitude-http/v1/entry.mjs +19 -0
  20. package/apps/storefront/public/platform/google-measurement/v1/entry.mjs +19 -0
  21. package/apps/storefront/public/shared/commerce-chrome.css +20 -2
  22. package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +68 -0
  23. package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +111 -0
  24. package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +2 -0
  25. package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +247 -0
  26. package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +73 -0
  27. package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +79 -0
  28. package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +10982 -0
  29. package/apps/storefront/scripts/import-v84-through-ws2.ts +38 -0
  30. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +2 -0
  31. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +4 -0
  32. package/apps/storefront/scripts/install-v84-native-through-ws1.ts +185 -0
  33. package/apps/storefront/scripts/prove-clone-isolation.ts +506 -0
  34. package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +148 -0
  35. package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +35 -0
  36. package/apps/storefront/scripts/replay-v84-clean-clone.ts +214 -0
  37. package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +18 -0
  38. package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +18 -0
  39. package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +18 -0
  40. package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +17 -0
  41. package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +15 -0
  42. package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +21 -0
  43. package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +42 -0
  44. package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +145 -0
  45. package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +18 -0
  46. package/apps/storefront/src/components/Img.astro +1 -1
  47. package/apps/storefront/src/components/admin/AdminBlogTab.astro +19 -16
  48. package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +105 -0
  49. package/apps/storefront/src/components/admin/AdminPublishTab.astro +1057 -412
  50. package/apps/storefront/src/components/admin/AdminSettingsTab.astro +2 -2
  51. package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +5 -5
  52. package/apps/storefront/src/components/chrome/NavDropdown.astro +12 -0
  53. package/apps/storefront/src/components/chrome/SiteFooter.astro +7 -2
  54. package/apps/storefront/src/components/chrome/SiteHeader.astro +46 -10
  55. package/apps/storefront/src/components/compliance/AdultSignatureNotice.astro +1 -1
  56. package/apps/storefront/src/components/compliance/ComplianceNotice.astro +1 -2
  57. package/apps/storefront/src/components/compliance/ExciseTaxNotice.astro +1 -2
  58. package/apps/storefront/src/components/compliance/PactActNotice.astro +1 -1
  59. package/apps/storefront/src/components/compliance/Prop65Warning.astro +1 -2
  60. package/apps/storefront/src/components/compliance/PurchaseLimitNotice.astro +2 -3
  61. package/apps/storefront/src/components/compliance/ShippingRestrictionNotice.astro +2 -2
  62. package/apps/storefront/src/components/compliance/StateEligibilityNotice.astro +2 -3
  63. package/apps/storefront/src/components/content/TrustStrip.astro +4 -4
  64. package/apps/storefront/src/components/islands/MobileNav.tsx +26 -1
  65. package/apps/storefront/src/components/islands/VariantSelector.tsx +27 -2
  66. package/apps/storefront/src/components/islands/useCheckoutHandoffCorrelation.ts +75 -0
  67. package/apps/storefront/src/components/membership/IllustrativeLabel.astro +1 -2
  68. package/apps/storefront/src/components/membership/TierCards.astro +2 -2
  69. package/apps/storefront/src/components/membership/TierComparisonTable.astro +2 -2
  70. package/apps/storefront/src/components/subscription/SavingsExplainer.astro +2 -2
  71. package/apps/storefront/src/config/adminTenantLookup.ts +35 -0
  72. package/apps/storefront/src/config/devTenantSeed.ts +9 -9
  73. package/apps/storefront/src/config/resolver.ts +4 -4
  74. package/apps/storefront/src/layouts/Layout.astro +100 -20
  75. package/apps/storefront/src/lib/activity/candidateSubmitLease.ts +87 -0
  76. package/apps/storefront/src/lib/activity/changeActorAttribution.ts +86 -6
  77. package/apps/storefront/src/lib/activity/deployVersion.ts +1 -1
  78. package/apps/storefront/src/lib/admin/adminShell.ts +2 -0
  79. package/apps/storefront/src/lib/admin/envelope.ts +1 -2
  80. package/apps/storefront/src/lib/apps/adminService.ts +10 -0
  81. package/apps/storefront/src/lib/apps/adminSession.ts +1 -1
  82. package/apps/storefront/src/lib/apps/appVersionStore.ts +281 -0
  83. package/apps/storefront/src/lib/apps/consentConfigStore.ts +228 -0
  84. package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +447 -0
  85. package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +367 -0
  86. package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +315 -0
  87. package/apps/storefront/src/lib/apps/integrationLifecycle.ts +614 -0
  88. package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +125 -0
  89. package/apps/storefront/src/lib/apps/integrationReadModel.ts +563 -0
  90. package/apps/storefront/src/lib/apps/integrationsTab.ts +547 -0
  91. package/apps/storefront/src/lib/apps/integrationsView.ts +106 -0
  92. package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +599 -0
  93. package/apps/storefront/src/lib/apps/orders/orderConversionD1.ts +150 -0
  94. package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +8 -0
  95. package/apps/storefront/src/lib/apps/orders/ordersStore.ts +1 -1
  96. package/apps/storefront/src/lib/apps/orders/verifiedProviderMeasurement.ts +117 -0
  97. package/apps/storefront/src/lib/apps/registryService.ts +264 -10
  98. package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +170 -0
  99. package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +16 -0
  100. package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +105 -0
  101. package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +177 -0
  102. package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +251 -0
  103. package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +241 -0
  104. package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +211 -0
  105. package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +409 -0
  106. package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +368 -0
  107. package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +188 -0
  108. package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +291 -0
  109. package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +95 -0
  110. package/apps/storefront/src/lib/auth/adminApiGuard.ts +66 -0
  111. package/apps/storefront/src/lib/auth/adminEntry.ts +2 -2
  112. package/apps/storefront/src/lib/auth/adminLanding.ts +88 -0
  113. package/apps/storefront/src/lib/blog/collection.ts +97 -10
  114. package/apps/storefront/src/lib/blog/markdown.ts +1 -1
  115. package/apps/storefront/src/lib/blog/provider.ts +57 -3
  116. package/apps/storefront/src/lib/blog/types.ts +9 -9
  117. package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome-assignments.example.json +6 -0
  118. package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome.example.json +79 -0
  119. package/apps/storefront/src/lib/chrome/model.ts +48 -253
  120. package/apps/storefront/src/lib/chrome/navCurrent.ts +29 -0
  121. package/apps/storefront/src/lib/chrome/parseConfig.ts +18 -32
  122. package/apps/storefront/src/lib/chrome/variant.ts +39 -0
  123. package/apps/storefront/src/lib/commerce/checkoutHandoffCorrelation.ts +105 -0
  124. package/apps/storefront/src/lib/compliance/tamper-sentinel-boot.ts +152 -0
  125. package/apps/storefront/src/lib/compliance/tamper-sentinel.ts +327 -0
  126. package/apps/storefront/src/lib/content/index.ts +5 -5
  127. package/apps/storefront/src/lib/content-edit/applyDiff.ts +1 -1
  128. package/apps/storefront/src/lib/content-edit/route.ts +1 -1
  129. package/apps/storefront/src/lib/d1/catalog.ts +12 -0
  130. package/apps/storefront/src/lib/d1/schema-apps.ts +276 -0
  131. package/apps/storefront/src/lib/dev/cockpit/ask.ts +49 -0
  132. package/apps/storefront/src/lib/dev/cockpit/clickToSource.ts +71 -0
  133. package/apps/storefront/src/lib/dev/cockpit/copyCommand.ts +227 -0
  134. package/apps/storefront/src/lib/dev/cockpit/files.ts +249 -0
  135. package/apps/storefront/src/lib/dev/cockpit/hostedActivity.ts +500 -0
  136. package/apps/storefront/src/lib/dev/cockpit/infoPopover.ts +12 -0
  137. package/apps/storefront/src/lib/dev/cockpit/mcpCopy.ts +34 -0
  138. package/apps/storefront/src/lib/dev/cockpit/monitor.ts +107 -0
  139. package/apps/storefront/src/lib/dev/cockpit/stepper.ts +116 -0
  140. package/apps/storefront/src/lib/dev/cockpit/themeToggle.ts +23 -0
  141. package/apps/storefront/src/lib/dev/runtimeStore.ts +1 -1
  142. package/apps/storefront/src/lib/edgeCache.ts +18 -6
  143. package/apps/storefront/src/lib/email/candidateConflictEmail.ts +80 -0
  144. package/apps/storefront/src/lib/integration/browserEnvironment.ts +137 -0
  145. package/apps/storefront/src/lib/integration/managedInstallDeclarations.ts +72 -0
  146. package/apps/storefront/src/lib/integration/nonceStamp.ts +49 -0
  147. package/apps/storefront/src/lib/integration/tenantDeclarations.ts +116 -0
  148. package/apps/storefront/src/lib/membership/eligibility.ts +1 -1
  149. package/apps/storefront/src/lib/membership/model.ts +1 -2
  150. package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +2 -2
  151. package/apps/storefront/src/lib/newsletter/consent.ts +2 -2
  152. package/apps/storefront/src/lib/newsletter/send.ts +3 -3
  153. package/apps/storefront/src/lib/previewReload.ts +57 -1
  154. package/apps/storefront/src/lib/publish/adminPublishTab.ts +1775 -669
  155. package/apps/storefront/src/lib/publish/buildStream.ts +269 -0
  156. package/apps/storefront/src/lib/publish/collapsePersistence.ts +72 -0
  157. package/apps/storefront/src/lib/publish/lifecycleState.ts +369 -0
  158. package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +29 -0
  159. package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +78 -0
  160. package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +62 -0
  161. package/apps/storefront/src/lib/publish/mergeRowFindings.ts +124 -0
  162. package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +75 -0
  163. package/apps/storefront/src/lib/publish/publish-guard.ts +88 -0
  164. package/apps/storefront/src/lib/publish/publishFormat.ts +165 -0
  165. package/apps/storefront/src/lib/publish/publishHero.ts +177 -0
  166. package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +66 -0
  167. package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +141 -0
  168. package/apps/storefront/src/lib/publish/reviewRelease/index.ts +41 -0
  169. package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +47 -0
  170. package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +42 -0
  171. package/apps/storefront/src/lib/publish/reviewRelease/types.ts +59 -0
  172. package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +440 -0
  173. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +161 -0
  174. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +325 -0
  175. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +241 -0
  176. package/apps/storefront/src/lib/publish/shipWorkspace.ts +22 -3
  177. package/apps/storefront/src/lib/publish/sseRoute.ts +119 -0
  178. package/apps/storefront/src/lib/publish/streamLogConsole.ts +142 -0
  179. package/apps/storefront/src/lib/publish/versionNumber.ts +52 -0
  180. package/apps/storefront/src/lib/rawChrome.ts +125 -47
  181. package/apps/storefront/src/lib/rawMarketingHtml.ts +74 -3
  182. package/apps/storefront/src/lib/seo/alternates.ts +1 -1
  183. package/apps/storefront/src/lib/social/notify.ts +4 -4
  184. package/apps/storefront/src/lib/storyblok/content-model.ts +7 -33
  185. package/apps/storefront/src/lib/storyblok/provider.ts +168 -60
  186. package/apps/storefront/src/lib/subscription/model.ts +4 -4
  187. package/apps/storefront/src/lib/the-build/provider.ts +9 -4
  188. package/apps/storefront/src/middleware/index.ts +273 -51
  189. package/apps/storefront/src/pages/[...slug].astro +9 -4
  190. package/apps/storefront/src/pages/admin/review-release.astro +265 -0
  191. package/apps/storefront/src/pages/admin/select.astro +96 -0
  192. package/apps/storefront/src/pages/admin.astro +16 -2
  193. package/apps/storefront/src/pages/api/activity.ts +8 -8
  194. package/apps/storefront/src/pages/api/admin/activity-alerts.ts +5 -20
  195. package/apps/storefront/src/pages/api/admin/orders/[id].ts +7 -2
  196. package/apps/storefront/src/pages/api/admin/orders.ts +8 -2
  197. package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +174 -0
  198. package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +96 -0
  199. package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +118 -0
  200. package/apps/storefront/src/pages/api/apps/admin/integrations.ts +89 -0
  201. package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +85 -0
  202. package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +74 -2
  203. package/apps/storefront/src/pages/api/commerce/checkout-handoff.ts +77 -0
  204. package/apps/storefront/src/pages/api/compliance/tamper.ts +88 -0
  205. package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +108 -0
  206. package/apps/storefront/src/pages/api/rum/vitals.ts +1 -2
  207. package/apps/storefront/src/pages/blog/[slug].astro +5 -5
  208. package/apps/storefront/src/pages/blog/author/[author].astro +3 -3
  209. package/apps/storefront/src/pages/blog/category/[category].astro +2 -2
  210. package/apps/storefront/src/pages/blog/index.astro +2 -2
  211. package/apps/storefront/src/pages/blog/tag/[tag].astro +2 -2
  212. package/apps/storefront/src/pages/cockpit.astro +61 -1362
  213. package/apps/storefront/src/pages/index.astro +10 -5
  214. package/apps/storefront/src/pages/llms.txt.ts +1 -1
  215. package/apps/storefront/src/pages/products/[handle].astro +7 -6
  216. package/apps/storefront/src/pages/sitemap.xml.ts +2 -2
  217. package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +31 -27
  218. package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +1 -1
  219. package/apps/storefront/src/pages/tenants/[id]/[...path].ts +38 -2
  220. package/apps/storefront/src/pages/the-build/[slug].astro +4 -4
  221. package/apps/storefront/src/pages/the-build/index.astro +2 -2
  222. package/apps/storefront/src/pages/the-build/rss.xml.ts +2 -2
  223. package/apps/storefront/src/styles/admin.css +27 -1
  224. package/apps/storefront/tsconfig.json +1 -1
  225. package/package.json +1 -1
  226. package/packages/public-runtime/package.json +2 -1
  227. package/packages/public-runtime/schemas/managed-analytics/v1/adapter-definition.schema.json +427 -0
  228. package/packages/public-runtime/schemas/managed-analytics/v1/create-integration-install-request.schema.json +161 -0
  229. package/packages/public-runtime/schemas/managed-analytics/v1/create-migration-draft-request.schema.json +157 -0
  230. package/packages/public-runtime/schemas/managed-analytics/v1/delete-integration-install-request.schema.json +84 -0
  231. package/packages/public-runtime/schemas/managed-analytics/v1/delete-migration-draft-request.schema.json +84 -0
  232. package/packages/public-runtime/schemas/managed-analytics/v1/error-envelope.schema.json +180 -0
  233. package/packages/public-runtime/schemas/managed-analytics/v1/get-adapter-definition-request.schema.json +52 -0
  234. package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-install-request.schema.json +52 -0
  235. package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-revision-request.schema.json +79 -0
  236. package/packages/public-runtime/schemas/managed-analytics/v1/get-migration-draft-request.schema.json +52 -0
  237. package/packages/public-runtime/schemas/managed-analytics/v1/integration-install.schema.json +167 -0
  238. package/packages/public-runtime/schemas/managed-analytics/v1/integration-revision.schema.json +208 -0
  239. package/packages/public-runtime/schemas/managed-analytics/v1/list-adapter-definitions-request.schema.json +53 -0
  240. package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-installs-request.schema.json +53 -0
  241. package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-revisions-request.schema.json +82 -0
  242. package/packages/public-runtime/schemas/managed-analytics/v1/migration-draft.schema.json +218 -0
  243. package/packages/public-runtime/schemas/managed-analytics/v1/mutation-request.schema.json +52 -0
  244. package/packages/public-runtime/schemas/managed-analytics/v1/mutation-success-envelope.schema.json +49 -0
  245. package/packages/public-runtime/schemas/managed-analytics/v1/read-request.schema.json +20 -0
  246. package/packages/public-runtime/schemas/managed-analytics/v1/read-success-envelope.schema.json +45 -0
  247. package/packages/public-runtime/schemas/managed-analytics/v1/revise-integration-install-request.schema.json +156 -0
  248. package/packages/public-runtime/schemas/managed-analytics/v1/set-integration-install-status-request.schema.json +92 -0
  249. package/packages/public-runtime/schemas/managed-analytics/v1/update-migration-draft-request.schema.json +184 -0
  250. package/packages/public-runtime/scripts/generate-managed-analytics-api-v1-schemas.mjs +13 -0
  251. package/packages/public-runtime/src/activity/catalog.ts +41 -37
  252. package/packages/public-runtime/src/activity/event.ts +6 -6
  253. package/packages/public-runtime/src/activity/index.ts +2 -2
  254. package/packages/public-runtime/src/activity/redaction.ts +4 -4
  255. package/packages/public-runtime/src/candidate-index.ts +42 -8
  256. package/packages/public-runtime/src/checkout-orders.ts +2 -2
  257. package/packages/public-runtime/src/checkout-style-publish.ts +2 -2
  258. package/packages/public-runtime/src/checkout-style.ts +7 -7
  259. package/packages/public-runtime/src/checkout.ts +3 -3
  260. package/packages/public-runtime/src/chrome.ts +777 -0
  261. package/packages/public-runtime/src/compliance-obligations.ts +310 -0
  262. package/packages/public-runtime/src/csp.ts +99 -0
  263. package/packages/public-runtime/src/customization-runtime.ts +32 -1
  264. package/packages/public-runtime/src/destination-webhook/contract.ts +353 -0
  265. package/packages/public-runtime/src/embed-catalog.d.mts +9 -0
  266. package/packages/public-runtime/src/embed-catalog.mjs +40 -0
  267. package/packages/public-runtime/src/evidence.ts +288 -0
  268. package/packages/public-runtime/src/gtm-migration/bounds.ts +138 -0
  269. package/packages/public-runtime/src/gtm-migration/disposition-rules.ts +361 -0
  270. package/packages/public-runtime/src/gtm-migration/dispositions.ts +181 -0
  271. package/packages/public-runtime/src/gtm-migration/draft-generator.ts +400 -0
  272. package/packages/public-runtime/src/gtm-migration/graph.ts +468 -0
  273. package/packages/public-runtime/src/gtm-migration/index.ts +95 -0
  274. package/packages/public-runtime/src/gtm-migration/parse.ts +410 -0
  275. package/packages/public-runtime/src/gtm-migration/references.ts +266 -0
  276. package/packages/public-runtime/src/gtm-migration/types.ts +86 -0
  277. package/packages/public-runtime/src/index.ts +16 -1
  278. package/packages/public-runtime/src/integration/assurance-decision.ts +259 -0
  279. package/packages/public-runtime/src/integration/assurance.ts +228 -0
  280. package/packages/public-runtime/src/integration/candidate-evidence.ts +377 -0
  281. package/packages/public-runtime/src/integration/commerce-broker.ts +497 -0
  282. package/packages/public-runtime/src/integration/consent-broker.ts +337 -0
  283. package/packages/public-runtime/src/integration/consent-cmp-demand.ts +115 -0
  284. package/packages/public-runtime/src/integration/consent-config.ts +260 -0
  285. package/packages/public-runtime/src/integration/consent-preview.ts +125 -0
  286. package/packages/public-runtime/src/integration/correlation-token.ts +444 -0
  287. package/packages/public-runtime/src/integration/csp-compiler.ts +267 -0
  288. package/packages/public-runtime/src/integration/csp.ts +105 -0
  289. package/packages/public-runtime/src/integration/digest.ts +43 -0
  290. package/packages/public-runtime/src/integration/environment.ts +228 -0
  291. package/packages/public-runtime/src/integration/events-catalog.ts +186 -0
  292. package/packages/public-runtime/src/integration/events.ts +701 -0
  293. package/packages/public-runtime/src/integration/g2-action-boundary.ts +106 -0
  294. package/packages/public-runtime/src/integration/index.ts +90 -0
  295. package/packages/public-runtime/src/integration/interim-bridge.ts +138 -0
  296. package/packages/public-runtime/src/integration/lifecycle-boot.ts +317 -0
  297. package/packages/public-runtime/src/integration/lifecycle-runtime.ts +393 -0
  298. package/packages/public-runtime/src/integration/lifecycle.ts +94 -0
  299. package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.d.mts +2 -0
  300. package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.mjs +10 -0
  301. package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +382 -0
  302. package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +684 -0
  303. package/packages/public-runtime/src/integration/managed-analytics-bridge.ts +383 -0
  304. package/packages/public-runtime/src/integration/managed-analytics-value-safety.ts +14 -0
  305. package/packages/public-runtime/src/integration/managed-analytics.ts +277 -0
  306. package/packages/public-runtime/src/integration/manifest.ts +470 -0
  307. package/packages/public-runtime/src/integration/native-amplitude.ts +362 -0
  308. package/packages/public-runtime/src/integration/native-ga4.ts +352 -0
  309. package/packages/public-runtime/src/integration/observability.ts +451 -0
  310. package/packages/public-runtime/src/integration/order-conversion.ts +0 -0
  311. package/packages/public-runtime/src/integration/phases.ts +182 -0
  312. package/packages/public-runtime/src/integration/plan.ts +112 -0
  313. package/packages/public-runtime/src/integration/platform-adapter-runtime.ts +146 -0
  314. package/packages/public-runtime/src/integration/platform-adapters.ts +671 -0
  315. package/packages/public-runtime/src/integration/promotion-gate.ts +451 -0
  316. package/packages/public-runtime/src/integration/provider-checkout-extension.ts +425 -0
  317. package/packages/public-runtime/src/integration/receipt-measurement.ts +370 -0
  318. package/packages/public-runtime/src/integration/regulated-parent-cert.ts +311 -0
  319. package/packages/public-runtime/src/integration/render-phases.ts +267 -0
  320. package/packages/public-runtime/src/integration/resolve.ts +465 -0
  321. package/packages/public-runtime/src/integration/result.ts +239 -0
  322. package/packages/public-runtime/src/integration/secrets.ts +92 -0
  323. package/packages/public-runtime/src/integration/tamper-evidence.ts +205 -0
  324. package/packages/public-runtime/src/integration/tamper-recovery.ts +127 -0
  325. package/packages/public-runtime/src/integration/version.ts +92 -0
  326. package/packages/public-runtime/src/integration-capabilities.ts +520 -0
  327. package/packages/public-runtime/src/membership.ts +2 -2
  328. package/packages/public-runtime/src/raw-html-policy.ts +2 -4
  329. package/packages/public-runtime/src/regulated-commerce/broker/consent-dedupe.ts +144 -0
  330. package/packages/public-runtime/src/regulated-commerce/correlation/contract.ts +177 -0
  331. package/packages/public-runtime/src/regulated-commerce/diagnostics/local-dispatch.ts +24 -0
  332. package/packages/public-runtime/src/regulated-commerce/diagnostics/read-model.ts +69 -0
  333. package/packages/public-runtime/src/regulated-commerce/dispatch/core.ts +134 -0
  334. package/packages/public-runtime/src/regulated-commerce/events/contract.ts +113 -0
  335. package/packages/public-runtime/src/regulated-commerce/ledger/core.ts +81 -0
  336. package/packages/public-runtime/src/regulated-commerce/mappings/ga4-ads.ts +87 -0
  337. package/packages/public-runtime/src/regulated-commerce/provider-order/bridge.ts +52 -0
  338. package/packages/public-runtime/src/regulated-commerce/purchase-truth/contract.ts +252 -0
  339. package/packages/public-runtime/src/regulated-commerce/sources/accepted-browser-operation.ts +67 -0
  340. package/packages/public-runtime/src/regulated-commerce/testing/fake-destination.ts +93 -0
  341. package/packages/public-runtime/src/static-bundle.ts +5 -5
  342. package/packages/public-runtime/src/tenant-assets.ts +143 -4
  343. package/packages/public-runtime/src/tenant.ts +45 -9
  344. package/packages/public-runtime/tests/fixtures/integration/browser-environment.example.json +8 -0
  345. package/packages/public-runtime/tests/fixtures/integration/commerce-event.example.json +44 -0
  346. package/packages/public-runtime/tests/fixtures/integration/commerce-order-event.example.json +44 -0
  347. package/packages/public-runtime/tests/fixtures/integration/compliance-assurance-record.example.json +50 -0
  348. package/packages/public-runtime/tests/fixtures/integration/integration-manifest-v2.example.json +120 -0
  349. package/packages/public-runtime/tests/fixtures/integration/managed-analytics-v1/fake-adapter-catalog.json +35 -0
  350. package/packages/public-runtime/tests/fixtures/integration/tenant-action-registry.example.json +11 -0
  351. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/README.md +22 -0
  352. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/entry.js +30 -0
  353. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/manifest.json +75 -0
  354. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/public-config.json +3 -0
  355. package/packages/public-runtime/tests/fixtures/regulated-commerce/fake-destinations.ts +38 -0
  356. package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.provenance.json +29 -0
  357. package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.redacted.json +3397 -0
  358. package/scripts/dev/file-browser.mjs +2 -2
  359. package/scripts/dev/file-writer.mjs +2 -2
  360. package/scripts/dev/integration-guardrails.mjs +498 -0
  361. package/scripts/dev/safe-path.mjs +2 -2
  362. package/scripts/dev/tenant-source-root.mjs +1 -1
  363. package/scripts/tot-dev.mjs +2 -2
@@ -0,0 +1,425 @@
1
+ /**
2
+ * Certified provider-checkout-extension contract.
3
+ *
4
+ * The managed checkout is PROVIDER-HOSTED (Foxy): the payment form, card fields,
5
+ * and the money-bearing hosted checkout page live on the provider's origin, never
6
+ * on the storefront. The storefront's only reach into checkout is a small set of
7
+ * BRANDING/PRESENTATION seams — a themed in-page cart drawer and CSS/asset tokens
8
+ * pushed to the hosted checkout template. This module declares the CLOSED set of
9
+ * those seams and the fail-closed validator a CERTIFIED extension is bound by.
10
+ *
11
+ * It is a SPECIALIZATION of the integration capability model
12
+ * (`../integration-capabilities.ts`), not a competing one:
13
+ * - The surface is PINNED to `checkout-payment` — the strictly-most-protected
14
+ * sub-surface (sandbox-only, elevated-parent prohibited). A caller cannot pick
15
+ * another surface; there is no surface field on the request.
16
+ * - Attachment is the closed {@link CHECKOUT_EXTENSION_SEAMS} registry. Every
17
+ * seam is a presentation seam (style tokens, scoped CSS, an asset ref, a
18
+ * curated template region, a non-payment custom field). NONE reads or writes
19
+ * card data, the signed cart, checkout totals, or the payment DOM — those live
20
+ * only in `FORBIDDEN_CAPABILITIES` and are structurally absent here.
21
+ * - Any registry capability a checkout extension additionally requests must be in
22
+ * the tight, read-mostly {@link CHECKOUT_ELIGIBLE_CAPABILITIES} allowlist; the
23
+ * request is then delegated to `validateIntegrationCapabilities`, so the
24
+ * tenant-tier matrix, forbidden set, binding, and origin grammar are the ONE
25
+ * source of truth. Two gates (checkout-eligibility + the capability model) both
26
+ * have to pass.
27
+ * - Certification is server-resolved and defaults OFF: an uncertified request is
28
+ * denied. "Certified" here is the checkout-extension vetting gate — distinct
29
+ * from the capability model's `certifiedImmutable` (which governs regulated
30
+ * elevated-parent code, a tier that is prohibited on this surface anyway).
31
+ *
32
+ * Compliance obligations (policy-04, `../compliance-obligations.ts`) are unchanged
33
+ * by anything here: they are server-derived from tenant config and no seam is an
34
+ * input to their resolution. The platform-owned `checkout-controls` / `cart-preflight`
35
+ * anchors are `PROTECTED_SURFACES` there; this contract exposes no seam that reaches
36
+ * them.
37
+ *
38
+ * Provenance discipline: each seam is tagged `repo-confirmed` (backed by the
39
+ * storefront's existing Foxy integration) or `foxy-doc-assumption` (plausible from
40
+ * Foxy's model but NOT evidenced in this repo — needs external Foxy-doc verification
41
+ * before it is treated as delivered). Assumptions are in the contract as declared,
42
+ * validator-gated placeholders, not as confirmed capabilities.
43
+ *
44
+ * Pure and edge-safe (no node, no I/O): validators, CLI, docs, and admin review all
45
+ * read this one source of truth.
46
+ */
47
+ import {
48
+ FORBIDDEN_CAPABILITIES,
49
+ isGrantableCapability,
50
+ validateIntegrationCapabilities,
51
+ type CapabilityDenial,
52
+ type CodeForm,
53
+ type ConsentPurpose,
54
+ type Enforcement,
55
+ type GrantedCapability,
56
+ type IntegrationBinding,
57
+ type Surface,
58
+ type TenantTier,
59
+ } from "../integration-capabilities.js";
60
+ import type { ExecutionTier } from "./phases.js";
61
+
62
+ /** Contract token — bump the minor for additive seams, the major for a break (ADR 0006 semver). */
63
+ export const PROVIDER_CHECKOUT_EXTENSION_CONTRACT = "provider-checkout-extension@1" as const;
64
+ export type ProviderCheckoutExtensionContract = typeof PROVIDER_CHECKOUT_EXTENSION_CONTRACT;
65
+
66
+ /**
67
+ * The surface is PINNED. Every certified checkout extension resolves against the
68
+ * strictly-most-protected `checkout-payment` cell — sandbox-only, elevated-parent
69
+ * prohibited (see the D-R2 matrix). It is not caller-selectable.
70
+ */
71
+ export const CHECKOUT_EXTENSION_SURFACE: Surface = "checkout-payment";
72
+
73
+ // ── Seam vocabulary ──────────────────────────────────────────────────────────
74
+
75
+ /** Where a seam attaches. Both are presentation-only surfaces the storefront controls. */
76
+ export const CHECKOUT_SEAM_LOCATIONS = ["in-page-cart-drawer", "hosted-checkout-page"] as const;
77
+ export type CheckoutSeamLocation = (typeof CHECKOUT_SEAM_LOCATIONS)[number];
78
+
79
+ /**
80
+ * How a seam contributes. Every kind is presentation/data-collection that stays on
81
+ * the storefront's side of the PCI boundary — none is executable parent code on the
82
+ * payment DOM (that is the elevated-parent tier, prohibited on this surface).
83
+ */
84
+ export const CHECKOUT_ATTACHMENT_KINDS = [
85
+ "style-tokens", // CSS custom properties (`--tot-*`) the drawer/template references.
86
+ "scoped-css", // Bespoke CSS, scoped to the storefront's own drawer root.
87
+ "raw-css", // ASCII-safe raw CSS appended to the hosted checkout content.
88
+ "asset-ref", // An absolute-https asset URL (e.g. a logo) referenced by the template.
89
+ "template-content", // Curated content injected into a NAMED hosted-checkout region.
90
+ "custom-field", // A non-payment field collected at checkout, posted only to our server.
91
+ ] as const;
92
+ export type CheckoutAttachmentKind = (typeof CHECKOUT_ATTACHMENT_KINDS)[number];
93
+
94
+ /**
95
+ * Whether a seam is grounded in this repo's existing Foxy integration
96
+ * (`repo-confirmed`) or is a plausible Foxy mechanism NOT yet evidenced here
97
+ * (`foxy-doc-assumption`) and gated behind external Foxy-doc verification.
98
+ */
99
+ export const SEAM_EVIDENCE = ["repo-confirmed", "foxy-doc-assumption"] as const;
100
+ export type SeamEvidence = (typeof SEAM_EVIDENCE)[number];
101
+
102
+ export interface CheckoutSeamDef {
103
+ /** Stable, wire-serialized seam id. */
104
+ id: string;
105
+ /** Operator-facing label. */
106
+ label: string;
107
+ location: CheckoutSeamLocation;
108
+ attachment: CheckoutAttachmentKind;
109
+ evidence: SeamEvidence;
110
+ /**
111
+ * For `repo-confirmed`: the code path that proves the seam exists.
112
+ * For `foxy-doc-assumption`: the exact external verification still owed.
113
+ */
114
+ provenance: string;
115
+ /** Consent purpose the seam's runtime effect depends on, when any (broker-enforced). */
116
+ requiresConsent?: ConsentPurpose;
117
+ }
118
+
119
+ function seam(def: CheckoutSeamDef): CheckoutSeamDef {
120
+ return def;
121
+ }
122
+
123
+ /**
124
+ * The CLOSED set of checkout UI seams a certified extension may attach to. Anything
125
+ * not here is unknown and fails closed. Every entry is presentation-only and, by
126
+ * construction, card-data-free: there is deliberately NO seam for the payment form,
127
+ * the card fields, the signed cart, or checkout totals.
128
+ */
129
+ export const CHECKOUT_EXTENSION_SEAMS: Readonly<Record<string, CheckoutSeamDef>> = Object.freeze(
130
+ Object.fromEntries(
131
+ [
132
+ // ── repo-confirmed: backed by the existing Foxy integration ──────────────
133
+ seam({
134
+ id: "cart-drawer.style-tokens",
135
+ label: "Theme the in-page cart drawer via CSS custom properties",
136
+ location: "in-page-cart-drawer",
137
+ attachment: "style-tokens",
138
+ evidence: "repo-confirmed",
139
+ provenance:
140
+ "checkout.ts — the Foxy loader renders the cart into the storefront's own light DOM (root `#fc`), so it inherits the theme's CSS custom properties; `<CartDrawerStyles>` emits the brand baseline.",
141
+ }),
142
+ seam({
143
+ id: "cart-drawer.scoped-css",
144
+ label: "Bespoke CSS overrides for the in-page cart drawer",
145
+ location: "in-page-cart-drawer",
146
+ attachment: "scoped-css",
147
+ evidence: "repo-confirmed",
148
+ provenance:
149
+ "checkout.ts `ManagedCheckoutConfig.cartDrawerCss` — per-tenant CSS appended after the brand baseline; rules scope under `#fc`.",
150
+ }),
151
+ seam({
152
+ id: "hosted-checkout.style-tokens",
153
+ label: "Theme the hosted checkout page via CSS custom-property tokens",
154
+ location: "hosted-checkout-page",
155
+ attachment: "style-tokens",
156
+ evidence: "repo-confirmed",
157
+ provenance:
158
+ "checkout-style.ts `checkoutStyleToCss` — emits `--tot-checkout-*` tokens served at the storefront URL Foxy pulls as its theme `content_url` (`/theme/foxy`).",
159
+ }),
160
+ seam({
161
+ id: "hosted-checkout.raw-css",
162
+ label: "ASCII-safe raw-CSS override appended to the hosted checkout content",
163
+ location: "hosted-checkout-page",
164
+ attachment: "raw-css",
165
+ evidence: "repo-confirmed",
166
+ provenance:
167
+ "checkout-style.ts `buildCheckoutStyleCss` / `checkout.css` artifact — appended only when `isAsciiSafe` (the checkout cache pass is not Unicode-safe).",
168
+ }),
169
+ seam({
170
+ id: "hosted-checkout.logo",
171
+ label: "Brand logo shown on the hosted checkout header",
172
+ location: "hosted-checkout-page",
173
+ attachment: "asset-ref",
174
+ evidence: "repo-confirmed",
175
+ provenance:
176
+ "checkout-style.ts `CheckoutStyle.logoUrl` → `--tot-checkout-logo` — accepted only as an absolute https URL.",
177
+ }),
178
+
179
+ // ── foxy-doc-assumption: NOT evidenced in this repo; gated on verification ─
180
+ seam({
181
+ id: "hosted-checkout.template-region",
182
+ label: "Curated content injected into a named hosted-checkout template region",
183
+ location: "hosted-checkout-page",
184
+ attachment: "template-content",
185
+ evidence: "foxy-doc-assumption",
186
+ provenance:
187
+ "ASSUMPTION — Foxy's checkout template is customizable, but the named content regions, whether arbitrary HTML is permitted under our ASCII/CSP discipline, and how tokens are substituted are NOT evidenced in this repo. Verify against Foxy's checkout-template docs before treating as delivered.",
188
+ }),
189
+ seam({
190
+ id: "hosted-checkout.custom-field",
191
+ label: "A non-payment custom field collected at checkout",
192
+ location: "hosted-checkout-page",
193
+ attachment: "custom-field",
194
+ evidence: "foxy-doc-assumption",
195
+ provenance:
196
+ "ASSUMPTION — Foxy supports custom checkout fields, but this repo has no such integration. Verify the field never sits in the card-data/PCI path and posts back only to our own order webhook (not a third party) before treating as delivered.",
197
+ }),
198
+ ].map((s) => [s.id, s]),
199
+ ),
200
+ );
201
+
202
+ const SEAM_IDS: ReadonlySet<string> = new Set(Object.keys(CHECKOUT_EXTENSION_SEAMS));
203
+
204
+ /** True when an id is in the closed checkout-seam registry. */
205
+ export function isCheckoutExtensionSeam(id: string): boolean {
206
+ return SEAM_IDS.has(id);
207
+ }
208
+
209
+ /** All checkout-seam ids, in declaration order. */
210
+ export function checkoutExtensionSeamIds(): string[] {
211
+ return Object.keys(CHECKOUT_EXTENSION_SEAMS);
212
+ }
213
+
214
+ /** Seam ids whose delivery is still gated on external Foxy-doc verification. */
215
+ export function assumptionSeamIds(): string[] {
216
+ return checkoutExtensionSeamIds().filter(
217
+ (id) => CHECKOUT_EXTENSION_SEAMS[id]!.evidence === "foxy-doc-assumption",
218
+ );
219
+ }
220
+
221
+ // ── Checkout-eligible capability allowlist ───────────────────────────────────
222
+
223
+ /**
224
+ * The ONLY registry capabilities a certified checkout extension may additionally
225
+ * request on the `checkout-payment` surface. Deliberately tight and read-mostly:
226
+ * anonymous reads, consent-gated checkout analytics, and the app's own public
227
+ * config. A capability outside this allowlist is denied `capability-not-checkout-
228
+ * eligible` even if the general capability model would otherwise grant it — so a
229
+ * future registry addition can never become silently checkout-reachable.
230
+ *
231
+ * Excluded on purpose: `broker:cart.add-line` (mutation on the payment surface),
232
+ * `broker:navigate`, any `lifecycle:*` (checkout is provider-hosted — no phase
233
+ * attach on the hosted page), and every `assurance:*` / `consent:*` declaration.
234
+ */
235
+ export const CHECKOUT_ELIGIBLE_CAPABILITIES: readonly string[] = Object.freeze([
236
+ "broker:cart.read",
237
+ "broker:consent.read",
238
+ "broker:page-context.read",
239
+ "broker:analytics.emit",
240
+ "event:cart.viewed",
241
+ "event:checkout.started",
242
+ "event:order.completed",
243
+ "config:public.read",
244
+ "config:public.write",
245
+ ]);
246
+
247
+ const ELIGIBLE_CAPABILITY_IDS: ReadonlySet<string> = new Set(CHECKOUT_ELIGIBLE_CAPABILITIES);
248
+
249
+ /** True when a capability id may be requested by a checkout extension. */
250
+ export function isCheckoutEligibleCapability(id: string): boolean {
251
+ return ELIGIBLE_CAPABILITY_IDS.has(id);
252
+ }
253
+
254
+ // ── Request / result contract ────────────────────────────────────────────────
255
+
256
+ export interface CheckoutExtensionRequest {
257
+ binding: IntegrationBinding;
258
+ /** Execution tier. checkout-payment caps at sandbox; server/elevated-parent are denied. */
259
+ tier: ExecutionTier;
260
+ codeForm: CodeForm;
261
+ /** Requested seam ids from {@link CHECKOUT_EXTENSION_SEAMS}. */
262
+ seams: readonly string[];
263
+ /** Optional registry capabilities; each must be in {@link CHECKOUT_ELIGIBLE_CAPABILITIES}. */
264
+ capabilities?: readonly string[];
265
+ /** Requested exact-HTTPS CSP origins (shape-validated by the capability model). */
266
+ origins?: readonly string[];
267
+ }
268
+
269
+ /** Server-resolved evaluation context. Certification defaults OFF (fail-closed). */
270
+ export interface CheckoutExtensionContext {
271
+ tenantTier: TenantTier;
272
+ /**
273
+ * A green, current checkout-extension certification for THIS binding. Server-
274
+ * resolved from authoritative state; never taken from the request. Absent → denied.
275
+ */
276
+ certified?: boolean;
277
+ }
278
+
279
+ export type CheckoutExtensionDenialReason =
280
+ | "uncertified"
281
+ | "unknown-seam"
282
+ | "capability-not-checkout-eligible"
283
+ | "capability"; // a passthrough denial from the underlying capability model.
284
+
285
+ export interface CheckoutExtensionDenial {
286
+ reason: CheckoutExtensionDenialReason;
287
+ /** The offending seam or capability id, when one applies. */
288
+ subject?: string;
289
+ /** The underlying capability-model denial, when `reason` is `capability`. */
290
+ capabilityDenial?: CapabilityDenial;
291
+ }
292
+
293
+ export interface GrantedCheckoutSeam {
294
+ id: string;
295
+ location: CheckoutSeamLocation;
296
+ attachment: CheckoutAttachmentKind;
297
+ evidence: SeamEvidence;
298
+ requiresConsent?: ConsentPurpose;
299
+ }
300
+
301
+ export type CheckoutExtensionResult =
302
+ | {
303
+ ok: true;
304
+ contract: ProviderCheckoutExtensionContract;
305
+ binding: IntegrationBinding;
306
+ surface: Surface;
307
+ tier: ExecutionTier;
308
+ /** Honest enforcement for the granted tier (sandbox/adapter → enforced). */
309
+ enforcement: Enforcement;
310
+ seams: GrantedCheckoutSeam[];
311
+ capabilities: GrantedCapability[];
312
+ origins: string[];
313
+ }
314
+ | { ok: false; code: "checkout_extension_denied"; denials: CheckoutExtensionDenial[] };
315
+
316
+ /**
317
+ * Validate a certified provider-checkout-extension request. Fail-closed and
318
+ * all-or-nothing: an uncertified binding, an unknown seam, a non-eligible
319
+ * capability, or any denial from the underlying capability model (tier above
320
+ * sandbox, forbidden/card-data scope, unbound binding, out-of-matrix surface,
321
+ * malformed origin) denies the WHOLE request — never a partial grant.
322
+ */
323
+ export function validateCheckoutExtension(
324
+ request: CheckoutExtensionRequest,
325
+ context: CheckoutExtensionContext,
326
+ ): CheckoutExtensionResult {
327
+ const denials: CheckoutExtensionDenial[] = [];
328
+
329
+ // 1. Certification is mandatory and server-resolved.
330
+ if (!context.certified) {
331
+ denials.push({ reason: "uncertified" });
332
+ }
333
+
334
+ // 2. Every seam must be in the closed registry.
335
+ const grantedSeams: GrantedCheckoutSeam[] = [];
336
+ for (const id of request.seams) {
337
+ const def = CHECKOUT_EXTENSION_SEAMS[id];
338
+ if (!def) {
339
+ denials.push({ reason: "unknown-seam", subject: id });
340
+ continue;
341
+ }
342
+ grantedSeams.push({
343
+ id: def.id,
344
+ location: def.location,
345
+ attachment: def.attachment,
346
+ evidence: def.evidence,
347
+ requiresConsent: def.requiresConsent,
348
+ });
349
+ }
350
+
351
+ // 3. Partition requested capabilities into checkout-eligible (delegated) and
352
+ // ineligible (denied here). A forbidden/card-data capability is never in the
353
+ // allowlist, so it is caught here AND, defensively, by the delegated model.
354
+ const eligible: string[] = [];
355
+ for (const id of request.capabilities ?? []) {
356
+ if (isCheckoutEligibleCapability(id)) {
357
+ eligible.push(id);
358
+ } else {
359
+ denials.push({ reason: "capability-not-checkout-eligible", subject: id });
360
+ }
361
+ }
362
+
363
+ // 4. Delegate binding / tier / surface / capability / origin validation to the
364
+ // ONE capability model, with the surface pinned to checkout-payment.
365
+ const capResult = validateIntegrationCapabilities(
366
+ {
367
+ binding: request.binding,
368
+ tier: request.tier,
369
+ surface: CHECKOUT_EXTENSION_SURFACE,
370
+ codeForm: request.codeForm,
371
+ capabilities: eligible,
372
+ origins: request.origins,
373
+ },
374
+ { tenantTier: context.tenantTier },
375
+ );
376
+
377
+ if (!capResult.ok) {
378
+ for (const d of capResult.denials) {
379
+ denials.push({ reason: "capability", subject: d.subject, capabilityDenial: d });
380
+ }
381
+ }
382
+
383
+ if (denials.length > 0 || !capResult.ok) {
384
+ return { ok: false, code: "checkout_extension_denied", denials };
385
+ }
386
+
387
+ return {
388
+ ok: true,
389
+ contract: PROVIDER_CHECKOUT_EXTENSION_CONTRACT,
390
+ binding: request.binding,
391
+ surface: CHECKOUT_EXTENSION_SURFACE,
392
+ tier: capResult.tier,
393
+ enforcement: capResult.enforcement,
394
+ seams: grantedSeams,
395
+ capabilities: capResult.capabilities,
396
+ origins: capResult.origins,
397
+ };
398
+ }
399
+
400
+ // ── Structural boundary invariant ────────────────────────────────────────────
401
+
402
+ /**
403
+ * Assert (at module-load and in tests) that the checkout-extension vocabulary can
404
+ * never reach card data. Structurally: no eligible capability is a forbidden scope,
405
+ * and every eligible capability is a real, grantable registry id. This is the
406
+ * belt-and-suspenders check behind the "an extension cannot request card data"
407
+ * invariant — the primary enforcement is the allowlist + the capability model.
408
+ */
409
+ export function assertCheckoutExtensionCardDataFree(): void {
410
+ const forbidden = new Set<string>(FORBIDDEN_CAPABILITIES as readonly string[]);
411
+ for (const id of CHECKOUT_ELIGIBLE_CAPABILITIES) {
412
+ if (forbidden.has(id)) {
413
+ throw new Error(
414
+ `checkout-eligible capability "${id}" is a forbidden scope — the card-data boundary is broken`,
415
+ );
416
+ }
417
+ if (!isGrantableCapability(id)) {
418
+ throw new Error(
419
+ `checkout-eligible capability "${id}" is not a grantable registry capability`,
420
+ );
421
+ }
422
+ }
423
+ }
424
+
425
+ assertCheckoutExtensionCardDataFree();