@tokenoftrust/storefront-runner 1.4.1 → 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 (474) hide show
  1. package/apps/storefront/astro.config.mjs +17 -1
  2. package/apps/storefront/env.d.ts +54 -5
  3. package/apps/storefront/integrations/materialize-guard.mjs +54 -0
  4. package/apps/storefront/migrations-apps/0002_good_switch.sql +26 -0
  5. package/apps/storefront/migrations-apps/0003_mute_marauders.sql +12 -0
  6. package/apps/storefront/migrations-apps/0004_deep_morph.sql +36 -0
  7. package/apps/storefront/migrations-apps/0005_common_mystique.sql +23 -0
  8. package/apps/storefront/migrations-apps/0006_broad_microchip.sql +16 -0
  9. package/apps/storefront/migrations-apps/0007_brave_outlaw_kid.sql +15 -0
  10. package/apps/storefront/migrations-apps/0008_blue_dazzler.sql +11 -0
  11. package/apps/storefront/migrations-apps/0009_bored_shinobi_shaw.sql +15 -0
  12. package/apps/storefront/migrations-apps/0010_ws4_verified_provider_measurement.sql +35 -0
  13. package/apps/storefront/migrations-apps/meta/0002_snapshot.json +1160 -0
  14. package/apps/storefront/migrations-apps/meta/0003_snapshot.json +1235 -0
  15. package/apps/storefront/migrations-apps/meta/0004_snapshot.json +1474 -0
  16. package/apps/storefront/migrations-apps/meta/0005_snapshot.json +1617 -0
  17. package/apps/storefront/migrations-apps/meta/0006_snapshot.json +1716 -0
  18. package/apps/storefront/migrations-apps/meta/0007_snapshot.json +1812 -0
  19. package/apps/storefront/migrations-apps/meta/0008_snapshot.json +1881 -0
  20. package/apps/storefront/migrations-apps/meta/0009_snapshot.json +1979 -0
  21. package/apps/storefront/migrations-apps/meta/_journal.json +56 -0
  22. package/apps/storefront/public/apps/tot.demo.analytics/0.1.0/entry.js +42 -0
  23. package/apps/storefront/public/js/dashboard-team.js +38 -2
  24. package/apps/storefront/public/platform/amplitude-http/v1/entry.mjs +19 -0
  25. package/apps/storefront/public/platform/google-measurement/v1/entry.mjs +19 -0
  26. package/apps/storefront/public/shared/commerce-chrome.css +20 -2
  27. package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +68 -0
  28. package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +111 -0
  29. package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +2 -0
  30. package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +247 -0
  31. package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +73 -0
  32. package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +79 -0
  33. package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +10982 -0
  34. package/apps/storefront/scripts/import-v84-through-ws2.ts +38 -0
  35. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +2 -0
  36. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +4 -0
  37. package/apps/storefront/scripts/install-v84-native-through-ws1.ts +185 -0
  38. package/apps/storefront/scripts/prove-clone-isolation.ts +506 -0
  39. package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +148 -0
  40. package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +35 -0
  41. package/apps/storefront/scripts/replay-v84-clean-clone.ts +214 -0
  42. package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +18 -0
  43. package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +18 -0
  44. package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +18 -0
  45. package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +17 -0
  46. package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +15 -0
  47. package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +21 -0
  48. package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +42 -0
  49. package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +145 -0
  50. package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +18 -0
  51. package/apps/storefront/src/components/Img.astro +1 -1
  52. package/apps/storefront/src/components/Seo.astro +65 -1
  53. package/apps/storefront/src/components/admin/AdminBlogDetailRail.astro +878 -0
  54. package/apps/storefront/src/components/admin/AdminBlogTab.astro +1435 -0
  55. package/apps/storefront/src/components/admin/AdminCustomersTab.astro +3 -7
  56. package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +105 -0
  57. package/apps/storefront/src/components/admin/AdminPublishTab.astro +1980 -2564
  58. package/apps/storefront/src/components/admin/AdminSettingsTab.astro +2 -2
  59. package/apps/storefront/src/components/admin/AdminSubscriptionsTab.astro +1 -3
  60. package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +5 -5
  61. package/apps/storefront/src/components/blog/BlogPaywall.astro +87 -0
  62. package/apps/storefront/src/components/blog/PostAccessBadge.astro +43 -0
  63. package/apps/storefront/src/components/blog/PostGrid.astro +57 -0
  64. package/apps/storefront/src/components/blog/ReactionBar.astro +214 -0
  65. package/apps/storefront/src/components/chrome/NavDropdown.astro +12 -0
  66. package/apps/storefront/src/components/chrome/SiteFooter.astro +7 -2
  67. package/apps/storefront/src/components/chrome/SiteHeader.astro +46 -10
  68. package/apps/storefront/src/components/compliance/AdultSignatureNotice.astro +1 -1
  69. package/apps/storefront/src/components/compliance/ComplianceNotice.astro +1 -2
  70. package/apps/storefront/src/components/compliance/ExciseTaxNotice.astro +1 -2
  71. package/apps/storefront/src/components/compliance/PactActNotice.astro +1 -1
  72. package/apps/storefront/src/components/compliance/Prop65Warning.astro +1 -2
  73. package/apps/storefront/src/components/compliance/PurchaseLimitNotice.astro +2 -3
  74. package/apps/storefront/src/components/compliance/ShippingRestrictionNotice.astro +2 -2
  75. package/apps/storefront/src/components/compliance/StateEligibilityNotice.astro +2 -3
  76. package/apps/storefront/src/components/content/TrustStrip.astro +4 -4
  77. package/apps/storefront/src/components/islands/MobileNav.tsx +26 -1
  78. package/apps/storefront/src/components/islands/VariantSelector.tsx +27 -2
  79. package/apps/storefront/src/components/islands/useCheckoutHandoffCorrelation.ts +75 -0
  80. package/apps/storefront/src/components/membership/IllustrativeLabel.astro +1 -2
  81. package/apps/storefront/src/components/membership/TierCards.astro +2 -2
  82. package/apps/storefront/src/components/membership/TierComparisonTable.astro +2 -2
  83. package/apps/storefront/src/components/subscription/SavingsExplainer.astro +2 -2
  84. package/apps/storefront/src/config/adminTenantLookup.ts +35 -0
  85. package/apps/storefront/src/config/devTenantSeed.ts +9 -9
  86. package/apps/storefront/src/config/resolver.ts +4 -4
  87. package/apps/storefront/src/layouts/Layout.astro +146 -21
  88. package/apps/storefront/src/lib/activity/alerts.ts +17 -19
  89. package/apps/storefront/src/lib/activity/candidateSubmitLease.ts +87 -0
  90. package/apps/storefront/src/lib/activity/changeActorAttribution.ts +89 -9
  91. package/apps/storefront/src/lib/activity/deployVersion.ts +20 -27
  92. package/apps/storefront/src/lib/activity/ingest.ts +8 -8
  93. package/apps/storefront/src/lib/activity/ingestAuth.ts +1 -1
  94. package/apps/storefront/src/lib/activity/killSwitch.ts +6 -6
  95. package/apps/storefront/src/lib/activity/query.ts +9 -9
  96. package/apps/storefront/src/lib/activity/recordActivity.ts +11 -15
  97. package/apps/storefront/src/lib/activity/store.ts +4 -6
  98. package/apps/storefront/src/lib/activity/uiActor.ts +12 -12
  99. package/apps/storefront/src/lib/activity/workerCommit.ts +6 -6
  100. package/apps/storefront/src/lib/admin/adminShell.ts +292 -0
  101. package/apps/storefront/src/lib/admin/ai/approvalMode.ts +2 -3
  102. package/apps/storefront/src/lib/admin/ai/audit.ts +3 -5
  103. package/apps/storefront/src/lib/admin/checkoutStyleInput.ts +7 -7
  104. package/apps/storefront/src/lib/admin/checkoutStyleTarget.ts +3 -3
  105. package/apps/storefront/src/lib/admin/envelope.ts +1 -2
  106. package/apps/storefront/src/lib/admin/orderClient.ts +3 -5
  107. package/apps/storefront/src/lib/admin/services/orders.ts +17 -19
  108. package/apps/storefront/src/lib/admin/viewmodels/aiWorkflows.ts +4 -6
  109. package/apps/storefront/src/lib/admin/viewmodels/settings.ts +1 -1
  110. package/apps/storefront/src/lib/apps/adminService.ts +14 -4
  111. package/apps/storefront/src/lib/apps/adminSession.ts +54 -45
  112. package/apps/storefront/src/lib/apps/apiAuth.ts +2 -2
  113. package/apps/storefront/src/lib/apps/apiRoute.ts +2 -2
  114. package/apps/storefront/src/lib/apps/appVersionStore.ts +281 -0
  115. package/apps/storefront/src/lib/apps/catalogMapper.ts +1 -1
  116. package/apps/storefront/src/lib/apps/consentConfigStore.ts +228 -0
  117. package/apps/storefront/src/lib/apps/credentials.ts +2 -2
  118. package/apps/storefront/src/lib/apps/gatewayKeys.ts +4 -4
  119. package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +447 -0
  120. package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +367 -0
  121. package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +315 -0
  122. package/apps/storefront/src/lib/apps/healthAggregate.ts +5 -5
  123. package/apps/storefront/src/lib/apps/integrationLifecycle.ts +614 -0
  124. package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +125 -0
  125. package/apps/storefront/src/lib/apps/integrationReadModel.ts +563 -0
  126. package/apps/storefront/src/lib/apps/integrationsTab.ts +547 -0
  127. package/apps/storefront/src/lib/apps/integrationsView.ts +106 -0
  128. package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +599 -0
  129. package/apps/storefront/src/lib/apps/orders/attributionService.ts +2 -2
  130. package/apps/storefront/src/lib/apps/orders/customerHash.ts +1 -1
  131. package/apps/storefront/src/lib/apps/orders/foxyOrderClient.ts +12 -12
  132. package/apps/storefront/src/lib/apps/orders/idempotency.ts +7 -7
  133. package/apps/storefront/src/lib/apps/orders/orderConversionD1.ts +150 -0
  134. package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +9 -1
  135. package/apps/storefront/src/lib/apps/orders/orderMapper.ts +2 -2
  136. package/apps/storefront/src/lib/apps/orders/ordersStore.ts +7 -7
  137. package/apps/storefront/src/lib/apps/orders/verifiedProviderMeasurement.ts +117 -0
  138. package/apps/storefront/src/lib/apps/registryService.ts +270 -16
  139. package/apps/storefront/src/lib/apps/scopes.ts +2 -2
  140. package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +170 -0
  141. package/apps/storefront/src/lib/apps/tokenIssuer.ts +4 -4
  142. package/apps/storefront/src/lib/apps/tokenVerifier.ts +6 -6
  143. package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +16 -0
  144. package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +105 -0
  145. package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +177 -0
  146. package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +251 -0
  147. package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +241 -0
  148. package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +211 -0
  149. package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +409 -0
  150. package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +368 -0
  151. package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +188 -0
  152. package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +291 -0
  153. package/apps/storefront/src/lib/apps/widgets/eligibility.ts +2 -2
  154. package/apps/storefront/src/lib/apps/widgets/frameProps.ts +3 -3
  155. package/apps/storefront/src/lib/apps/widgets/launchToken.ts +4 -4
  156. package/apps/storefront/src/lib/apps/widgets/placements.ts +2 -2
  157. package/apps/storefront/src/lib/apps/widgets/renderSlot.ts +1 -1
  158. package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +95 -0
  159. package/apps/storefront/src/lib/auth/adminApiGuard.ts +66 -0
  160. package/apps/storefront/src/lib/auth/adminEntry.ts +11 -11
  161. package/apps/storefront/src/lib/auth/adminLanding.ts +88 -0
  162. package/apps/storefront/src/lib/auth/identityToken.ts +6 -14
  163. package/apps/storefront/src/lib/auth/loginGate.ts +75 -13
  164. package/apps/storefront/src/lib/auth/mcpClientAssertion.ts +2 -4
  165. package/apps/storefront/src/lib/auth/operatorSession.ts +113 -0
  166. package/apps/storefront/src/lib/auth/session.ts +7 -8
  167. package/apps/storefront/src/lib/auth/totAccessClient.ts +8 -18
  168. package/apps/storefront/src/lib/basePath.ts +9 -2
  169. package/apps/storefront/src/lib/blog/access.ts +29 -0
  170. package/apps/storefront/src/lib/blog/collection.ts +400 -0
  171. package/apps/storefront/src/lib/blog/markdown.ts +174 -0
  172. package/apps/storefront/src/lib/blog/provider.ts +62 -3
  173. package/apps/storefront/src/lib/blog/reactions.ts +87 -0
  174. package/apps/storefront/src/lib/blog/rss.ts +92 -0
  175. package/apps/storefront/src/lib/blog/teaser.ts +83 -0
  176. package/apps/storefront/src/lib/blog/types.ts +34 -0
  177. package/apps/storefront/src/lib/blog/viewCounts.ts +243 -0
  178. package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome-assignments.example.json +6 -0
  179. package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome.example.json +79 -0
  180. package/apps/storefront/src/lib/chrome/model.ts +48 -253
  181. package/apps/storefront/src/lib/chrome/navCurrent.ts +29 -0
  182. package/apps/storefront/src/lib/chrome/parseConfig.ts +18 -32
  183. package/apps/storefront/src/lib/chrome/variant.ts +39 -0
  184. package/apps/storefront/src/lib/commerce/checkoutHandoffCorrelation.ts +105 -0
  185. package/apps/storefront/src/lib/compliance/tamper-sentinel-boot.ts +152 -0
  186. package/apps/storefront/src/lib/compliance/tamper-sentinel.ts +327 -0
  187. package/apps/storefront/src/lib/content/index.ts +5 -5
  188. package/apps/storefront/src/lib/content-edit/applyDiff.ts +1 -1
  189. package/apps/storefront/src/lib/content-edit/route.ts +1 -1
  190. package/apps/storefront/src/lib/d1/catalog.ts +14 -2
  191. package/apps/storefront/src/lib/d1/schema-apps.ts +372 -17
  192. package/apps/storefront/src/lib/dev/activityIngestToken.ts +2 -4
  193. package/apps/storefront/src/lib/dev/activityStore.ts +3 -5
  194. package/apps/storefront/src/lib/dev/apiBase.ts +1 -4
  195. package/apps/storefront/src/lib/dev/cockpit/ask.ts +49 -0
  196. package/apps/storefront/src/lib/dev/cockpit/clickToSource.ts +71 -0
  197. package/apps/storefront/src/lib/dev/cockpit/copyCommand.ts +227 -0
  198. package/apps/storefront/src/lib/dev/cockpit/files.ts +249 -0
  199. package/apps/storefront/src/lib/dev/cockpit/hostedActivity.ts +500 -0
  200. package/apps/storefront/src/lib/dev/cockpit/infoPopover.ts +12 -0
  201. package/apps/storefront/src/lib/dev/cockpit/mcpCopy.ts +34 -0
  202. package/apps/storefront/src/lib/dev/cockpit/monitor.ts +107 -0
  203. package/apps/storefront/src/lib/dev/cockpit/stepper.ts +116 -0
  204. package/apps/storefront/src/lib/dev/cockpit/themeToggle.ts +23 -0
  205. package/apps/storefront/src/lib/dev/cockpitStore.ts +1 -9
  206. package/apps/storefront/src/lib/dev/devDraft.ts +1 -1
  207. package/apps/storefront/src/lib/dev/previewStatus.ts +9 -21
  208. package/apps/storefront/src/lib/dev/rendezvousBroker.ts +9 -24
  209. package/apps/storefront/src/lib/dev/runtimeStore.ts +1 -1
  210. package/apps/storefront/src/lib/edgeCache.ts +34 -5
  211. package/apps/storefront/src/lib/email/candidateConflictEmail.ts +80 -0
  212. package/apps/storefront/src/lib/http/fetchTransport.ts +63 -0
  213. package/apps/storefront/src/lib/i18n.ts +25 -0
  214. package/apps/storefront/src/lib/integration/browserEnvironment.ts +137 -0
  215. package/apps/storefront/src/lib/integration/managedInstallDeclarations.ts +72 -0
  216. package/apps/storefront/src/lib/integration/nonceStamp.ts +49 -0
  217. package/apps/storefront/src/lib/integration/tenantDeclarations.ts +116 -0
  218. package/apps/storefront/src/lib/jsonld.ts +118 -0
  219. package/apps/storefront/src/lib/membership/eligibility.ts +1 -1
  220. package/apps/storefront/src/lib/membership/model.ts +1 -2
  221. package/apps/storefront/src/lib/monitoring/manifest.ts +11 -11
  222. package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +30 -0
  223. package/apps/storefront/src/lib/newsletter/consent.ts +23 -0
  224. package/apps/storefront/src/lib/newsletter/digest.ts +117 -0
  225. package/apps/storefront/src/lib/newsletter/resendClient.ts +79 -0
  226. package/apps/storefront/src/lib/newsletter/send.ts +265 -0
  227. package/apps/storefront/src/lib/newsletter/subscribers.ts +156 -0
  228. package/apps/storefront/src/lib/previewReload.ts +57 -1
  229. package/apps/storefront/src/lib/publish/adminPublishTab.ts +4625 -0
  230. package/apps/storefront/src/lib/publish/apex-readiness.ts +41 -18
  231. package/apps/storefront/src/lib/publish/buildStream.ts +269 -0
  232. package/apps/storefront/src/lib/publish/collapsePersistence.ts +72 -0
  233. package/apps/storefront/src/lib/publish/dispatchHealth.ts +5 -7
  234. package/apps/storefront/src/lib/publish/domainState.ts +22 -13
  235. package/apps/storefront/src/lib/publish/lifecycleState.ts +369 -0
  236. package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +29 -0
  237. package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +78 -0
  238. package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +62 -0
  239. package/apps/storefront/src/lib/publish/mergeRowFindings.ts +124 -0
  240. package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +75 -0
  241. package/apps/storefront/src/lib/publish/panelPolling.ts +78 -0
  242. package/apps/storefront/src/lib/publish/publish-guard.ts +88 -0
  243. package/apps/storefront/src/lib/publish/publishFormat.ts +165 -0
  244. package/apps/storefront/src/lib/publish/publishHero.ts +177 -0
  245. package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +66 -0
  246. package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +141 -0
  247. package/apps/storefront/src/lib/publish/reviewRelease/index.ts +41 -0
  248. package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +47 -0
  249. package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +42 -0
  250. package/apps/storefront/src/lib/publish/reviewRelease/types.ts +59 -0
  251. package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +440 -0
  252. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +161 -0
  253. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +325 -0
  254. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +241 -0
  255. package/apps/storefront/src/lib/publish/shipWorkspace.ts +121 -51
  256. package/apps/storefront/src/lib/publish/sseRoute.ts +119 -0
  257. package/apps/storefront/src/lib/publish/stageBundleUpload.ts +215 -0
  258. package/apps/storefront/src/lib/publish/streamLogConsole.ts +142 -0
  259. package/apps/storefront/src/lib/publish/versionNumber.ts +52 -0
  260. package/apps/storefront/src/lib/rate/kvWindow.ts +53 -0
  261. package/apps/storefront/src/lib/rawChrome.ts +125 -47
  262. package/apps/storefront/src/lib/rawMarketingHtml.ts +74 -3
  263. package/apps/storefront/src/lib/search/index.ts +2 -2
  264. package/apps/storefront/src/lib/seo/alternates.ts +42 -0
  265. package/apps/storefront/src/lib/seo/meta.ts +65 -0
  266. package/apps/storefront/src/lib/social/golive.ts +212 -0
  267. package/apps/storefront/src/lib/social/notify.ts +32 -0
  268. package/apps/storefront/src/lib/social/tokenStore.ts +171 -0
  269. package/apps/storefront/src/lib/storyblok/content-model.ts +7 -33
  270. package/apps/storefront/src/lib/storyblok/provider.ts +168 -60
  271. package/apps/storefront/src/lib/subscription/model.ts +4 -4
  272. package/apps/storefront/src/lib/the-build/provider.ts +32 -0
  273. package/apps/storefront/src/lib/the-build/readingTime.ts +35 -0
  274. package/apps/storefront/src/lib/the-build/toc.ts +95 -0
  275. package/apps/storefront/src/lib/tot/ToTClient.ts +1 -1
  276. package/apps/storefront/src/lib/tot/d1Client.ts +2 -2
  277. package/apps/storefront/src/lib/tot/totClientInterface.ts +3 -4
  278. package/apps/storefront/src/lib/webhooks/deliveryStore.ts +16 -17
  279. package/apps/storefront/src/middleware/index.ts +385 -52
  280. package/apps/storefront/src/pages/[...slug].astro +9 -4
  281. package/apps/storefront/src/pages/admin/review-release.astro +265 -0
  282. package/apps/storefront/src/pages/admin/select.astro +96 -0
  283. package/apps/storefront/src/pages/admin.astro +25 -1313
  284. package/apps/storefront/src/pages/api/activity.ts +8 -8
  285. package/apps/storefront/src/pages/api/admin/activity-alerts.ts +5 -20
  286. package/apps/storefront/src/pages/api/admin/orders/[id].ts +7 -2
  287. package/apps/storefront/src/pages/api/admin/orders.ts +8 -2
  288. package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +174 -0
  289. package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +96 -0
  290. package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +118 -0
  291. package/apps/storefront/src/pages/api/apps/admin/integrations.ts +89 -0
  292. package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +85 -0
  293. package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +74 -2
  294. package/apps/storefront/src/pages/api/blog/[collection]/[slug]/react.ts +104 -0
  295. package/apps/storefront/src/pages/api/commerce/checkout-handoff.ts +77 -0
  296. package/apps/storefront/src/pages/api/compliance/tamper.ts +88 -0
  297. package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +108 -0
  298. package/apps/storefront/src/pages/api/newsletter/[collection]/subscribe.ts +146 -0
  299. package/apps/storefront/src/pages/api/newsletter/confirm.ts +75 -0
  300. package/apps/storefront/src/pages/api/newsletter/unsubscribe.ts +90 -0
  301. package/apps/storefront/src/pages/api/publish/stage-bundle.ts +70 -0
  302. package/apps/storefront/src/pages/api/rum/vitals.ts +20 -2
  303. package/apps/storefront/src/pages/blog/[slug].astro +99 -19
  304. package/apps/storefront/src/pages/blog/author/[author].astro +140 -0
  305. package/apps/storefront/src/pages/blog/category/[category].astro +67 -0
  306. package/apps/storefront/src/pages/blog/index.astro +4 -2
  307. package/apps/storefront/src/pages/blog/tag/[tag].astro +65 -0
  308. package/apps/storefront/src/pages/cockpit.astro +77 -1353
  309. package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +15 -11
  310. package/apps/storefront/src/pages/index.astro +10 -5
  311. package/apps/storefront/src/pages/llms.txt.ts +1 -1
  312. package/apps/storefront/src/pages/products/[handle].astro +7 -6
  313. package/apps/storefront/src/pages/search.astro +1 -1
  314. package/apps/storefront/src/pages/sitemap.xml.ts +21 -1
  315. package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +31 -27
  316. package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +1 -1
  317. package/apps/storefront/src/pages/tenants/[id]/[...path].ts +38 -2
  318. package/apps/storefront/src/pages/the-build/[slug].astro +129 -0
  319. package/apps/storefront/src/pages/the-build/index.astro +146 -0
  320. package/apps/storefront/src/pages/the-build/rss.xml.ts +33 -0
  321. package/apps/storefront/src/styles/admin.css +1106 -0
  322. package/apps/storefront/tsconfig.json +6 -1
  323. package/package.json +1 -1
  324. package/packages/public-runtime/package.json +3 -1
  325. package/packages/public-runtime/schemas/managed-analytics/v1/adapter-definition.schema.json +427 -0
  326. package/packages/public-runtime/schemas/managed-analytics/v1/create-integration-install-request.schema.json +161 -0
  327. package/packages/public-runtime/schemas/managed-analytics/v1/create-migration-draft-request.schema.json +157 -0
  328. package/packages/public-runtime/schemas/managed-analytics/v1/delete-integration-install-request.schema.json +84 -0
  329. package/packages/public-runtime/schemas/managed-analytics/v1/delete-migration-draft-request.schema.json +84 -0
  330. package/packages/public-runtime/schemas/managed-analytics/v1/error-envelope.schema.json +180 -0
  331. package/packages/public-runtime/schemas/managed-analytics/v1/get-adapter-definition-request.schema.json +52 -0
  332. package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-install-request.schema.json +52 -0
  333. package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-revision-request.schema.json +79 -0
  334. package/packages/public-runtime/schemas/managed-analytics/v1/get-migration-draft-request.schema.json +52 -0
  335. package/packages/public-runtime/schemas/managed-analytics/v1/integration-install.schema.json +167 -0
  336. package/packages/public-runtime/schemas/managed-analytics/v1/integration-revision.schema.json +208 -0
  337. package/packages/public-runtime/schemas/managed-analytics/v1/list-adapter-definitions-request.schema.json +53 -0
  338. package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-installs-request.schema.json +53 -0
  339. package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-revisions-request.schema.json +82 -0
  340. package/packages/public-runtime/schemas/managed-analytics/v1/migration-draft.schema.json +218 -0
  341. package/packages/public-runtime/schemas/managed-analytics/v1/mutation-request.schema.json +52 -0
  342. package/packages/public-runtime/schemas/managed-analytics/v1/mutation-success-envelope.schema.json +49 -0
  343. package/packages/public-runtime/schemas/managed-analytics/v1/read-request.schema.json +20 -0
  344. package/packages/public-runtime/schemas/managed-analytics/v1/read-success-envelope.schema.json +45 -0
  345. package/packages/public-runtime/schemas/managed-analytics/v1/revise-integration-install-request.schema.json +156 -0
  346. package/packages/public-runtime/schemas/managed-analytics/v1/set-integration-install-status-request.schema.json +92 -0
  347. package/packages/public-runtime/schemas/managed-analytics/v1/update-migration-draft-request.schema.json +184 -0
  348. package/packages/public-runtime/scripts/generate-managed-analytics-api-v1-schemas.mjs +13 -0
  349. package/packages/public-runtime/src/activity/catalog.ts +89 -33
  350. package/packages/public-runtime/src/activity/event.ts +6 -6
  351. package/packages/public-runtime/src/activity/index.ts +2 -2
  352. package/packages/public-runtime/src/activity/redaction.ts +4 -4
  353. package/packages/public-runtime/src/candidate-index.ts +42 -8
  354. package/packages/public-runtime/src/catalog-d1.ts +1 -1
  355. package/packages/public-runtime/src/checkout-orders.ts +2 -2
  356. package/packages/public-runtime/src/checkout-style-publish.ts +2 -2
  357. package/packages/public-runtime/src/checkout-style.ts +7 -7
  358. package/packages/public-runtime/src/checkout.ts +3 -3
  359. package/packages/public-runtime/src/chrome.ts +777 -0
  360. package/packages/public-runtime/src/compliance-obligations.ts +310 -0
  361. package/packages/public-runtime/src/csp.ts +99 -0
  362. package/packages/public-runtime/src/customization-preview.ts +25 -2
  363. package/packages/public-runtime/src/customization-runtime.ts +156 -3
  364. package/packages/public-runtime/src/customization-versioning.ts +10 -0
  365. package/packages/public-runtime/src/destination-webhook/contract.ts +353 -0
  366. package/packages/public-runtime/src/embed-catalog.d.mts +9 -0
  367. package/packages/public-runtime/src/embed-catalog.mjs +40 -0
  368. package/packages/public-runtime/src/evidence.ts +288 -0
  369. package/packages/public-runtime/src/gtm-migration/bounds.ts +138 -0
  370. package/packages/public-runtime/src/gtm-migration/disposition-rules.ts +361 -0
  371. package/packages/public-runtime/src/gtm-migration/dispositions.ts +181 -0
  372. package/packages/public-runtime/src/gtm-migration/draft-generator.ts +400 -0
  373. package/packages/public-runtime/src/gtm-migration/graph.ts +468 -0
  374. package/packages/public-runtime/src/gtm-migration/index.ts +95 -0
  375. package/packages/public-runtime/src/gtm-migration/parse.ts +410 -0
  376. package/packages/public-runtime/src/gtm-migration/references.ts +266 -0
  377. package/packages/public-runtime/src/gtm-migration/types.ts +86 -0
  378. package/packages/public-runtime/src/index.ts +17 -1
  379. package/packages/public-runtime/src/integration/assurance-decision.ts +259 -0
  380. package/packages/public-runtime/src/integration/assurance.ts +228 -0
  381. package/packages/public-runtime/src/integration/candidate-evidence.ts +377 -0
  382. package/packages/public-runtime/src/integration/commerce-broker.ts +497 -0
  383. package/packages/public-runtime/src/integration/consent-broker.ts +337 -0
  384. package/packages/public-runtime/src/integration/consent-cmp-demand.ts +115 -0
  385. package/packages/public-runtime/src/integration/consent-config.ts +260 -0
  386. package/packages/public-runtime/src/integration/consent-preview.ts +125 -0
  387. package/packages/public-runtime/src/integration/correlation-token.ts +444 -0
  388. package/packages/public-runtime/src/integration/csp-compiler.ts +267 -0
  389. package/packages/public-runtime/src/integration/csp.ts +105 -0
  390. package/packages/public-runtime/src/integration/digest.ts +43 -0
  391. package/packages/public-runtime/src/integration/environment.ts +228 -0
  392. package/packages/public-runtime/src/integration/events-catalog.ts +186 -0
  393. package/packages/public-runtime/src/integration/events.ts +701 -0
  394. package/packages/public-runtime/src/integration/g2-action-boundary.ts +106 -0
  395. package/packages/public-runtime/src/integration/index.ts +90 -0
  396. package/packages/public-runtime/src/integration/interim-bridge.ts +138 -0
  397. package/packages/public-runtime/src/integration/lifecycle-boot.ts +317 -0
  398. package/packages/public-runtime/src/integration/lifecycle-runtime.ts +393 -0
  399. package/packages/public-runtime/src/integration/lifecycle.ts +94 -0
  400. package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.d.mts +2 -0
  401. package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.mjs +10 -0
  402. package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +382 -0
  403. package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +684 -0
  404. package/packages/public-runtime/src/integration/managed-analytics-bridge.ts +383 -0
  405. package/packages/public-runtime/src/integration/managed-analytics-value-safety.ts +14 -0
  406. package/packages/public-runtime/src/integration/managed-analytics.ts +277 -0
  407. package/packages/public-runtime/src/integration/manifest.ts +470 -0
  408. package/packages/public-runtime/src/integration/native-amplitude.ts +362 -0
  409. package/packages/public-runtime/src/integration/native-ga4.ts +352 -0
  410. package/packages/public-runtime/src/integration/observability.ts +451 -0
  411. package/packages/public-runtime/src/integration/order-conversion.ts +0 -0
  412. package/packages/public-runtime/src/integration/phases.ts +182 -0
  413. package/packages/public-runtime/src/integration/plan.ts +112 -0
  414. package/packages/public-runtime/src/integration/platform-adapter-runtime.ts +146 -0
  415. package/packages/public-runtime/src/integration/platform-adapters.ts +671 -0
  416. package/packages/public-runtime/src/integration/promotion-gate.ts +451 -0
  417. package/packages/public-runtime/src/integration/provider-checkout-extension.ts +425 -0
  418. package/packages/public-runtime/src/integration/receipt-measurement.ts +370 -0
  419. package/packages/public-runtime/src/integration/regulated-parent-cert.ts +311 -0
  420. package/packages/public-runtime/src/integration/render-phases.ts +267 -0
  421. package/packages/public-runtime/src/integration/resolve.ts +465 -0
  422. package/packages/public-runtime/src/integration/result.ts +239 -0
  423. package/packages/public-runtime/src/integration/secrets.ts +92 -0
  424. package/packages/public-runtime/src/integration/tamper-evidence.ts +205 -0
  425. package/packages/public-runtime/src/integration/tamper-recovery.ts +127 -0
  426. package/packages/public-runtime/src/integration/version.ts +92 -0
  427. package/packages/public-runtime/src/integration-capabilities.ts +520 -0
  428. package/packages/public-runtime/src/membership.ts +2 -2
  429. package/packages/public-runtime/src/raw-html-policy.ts +2 -4
  430. package/packages/public-runtime/src/regulated-commerce/broker/consent-dedupe.ts +144 -0
  431. package/packages/public-runtime/src/regulated-commerce/correlation/contract.ts +177 -0
  432. package/packages/public-runtime/src/regulated-commerce/diagnostics/local-dispatch.ts +24 -0
  433. package/packages/public-runtime/src/regulated-commerce/diagnostics/read-model.ts +69 -0
  434. package/packages/public-runtime/src/regulated-commerce/dispatch/core.ts +134 -0
  435. package/packages/public-runtime/src/regulated-commerce/events/contract.ts +113 -0
  436. package/packages/public-runtime/src/regulated-commerce/ledger/core.ts +81 -0
  437. package/packages/public-runtime/src/regulated-commerce/mappings/ga4-ads.ts +87 -0
  438. package/packages/public-runtime/src/regulated-commerce/provider-order/bridge.ts +52 -0
  439. package/packages/public-runtime/src/regulated-commerce/purchase-truth/contract.ts +252 -0
  440. package/packages/public-runtime/src/regulated-commerce/sources/accepted-browser-operation.ts +67 -0
  441. package/packages/public-runtime/src/regulated-commerce/testing/fake-destination.ts +93 -0
  442. package/packages/public-runtime/src/static-bundle.ts +357 -0
  443. package/packages/public-runtime/src/tenant-assets.ts +143 -4
  444. package/packages/public-runtime/src/tenant.ts +81 -17
  445. package/packages/public-runtime/tests/fixtures/integration/browser-environment.example.json +8 -0
  446. package/packages/public-runtime/tests/fixtures/integration/commerce-event.example.json +44 -0
  447. package/packages/public-runtime/tests/fixtures/integration/commerce-order-event.example.json +44 -0
  448. package/packages/public-runtime/tests/fixtures/integration/compliance-assurance-record.example.json +50 -0
  449. package/packages/public-runtime/tests/fixtures/integration/integration-manifest-v2.example.json +120 -0
  450. package/packages/public-runtime/tests/fixtures/integration/managed-analytics-v1/fake-adapter-catalog.json +35 -0
  451. package/packages/public-runtime/tests/fixtures/integration/tenant-action-registry.example.json +11 -0
  452. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/README.md +22 -0
  453. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/entry.js +30 -0
  454. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/manifest.json +75 -0
  455. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/public-config.json +3 -0
  456. package/packages/public-runtime/tests/fixtures/regulated-commerce/fake-destinations.ts +38 -0
  457. package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.provenance.json +29 -0
  458. package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.redacted.json +3397 -0
  459. package/scripts/build/copy-tenant-assets.mjs +14 -4
  460. package/scripts/dev/ai-edit.mjs +1 -1
  461. package/scripts/dev/checkout-watch.mjs +2 -2
  462. package/scripts/dev/file-browser.mjs +4 -6
  463. package/scripts/dev/file-writer.mjs +3 -3
  464. package/scripts/dev/git-status.mjs +2 -2
  465. package/scripts/dev/integration-guardrails.mjs +498 -0
  466. package/scripts/dev/locate-handler.mjs +3 -3
  467. package/scripts/dev/port-check.mjs +3 -3
  468. package/scripts/dev/publish.mjs +5 -9
  469. package/scripts/dev/safe-path.mjs +2 -2
  470. package/scripts/dev/shot.mjs +1 -1
  471. package/scripts/dev/tenant-source-root.mjs +1 -1
  472. package/scripts/dev/unified-diff.mjs +8 -3
  473. package/scripts/tot-dev.mjs +8 -11
  474. package/apps/storefront/src/lib/dev/vcBinding.ts +0 -80
@@ -1,18 +1,18 @@
1
1
  /**
2
- * FoxyOrderClient — the boundary to tot-foxycart's order-read surface
3
- * (PrivateApps epic, D6 Chunk A/B). `ordersStore.ts` and the read
4
- * routes / event receiver (later chunks) never call `fetch` directly; they go
5
- * through this seam so a fake can stand in for tot-foxycart in tests.
2
+ * FoxyOrderClient — the boundary to tot-foxycart's order-read surface.
3
+ * `ordersStore.ts` and the read routes / event receiver never call `fetch`
4
+ * directly; they go through this seam so a fake can stand in for tot-foxycart
5
+ * in tests.
6
6
  *
7
- * RECONCILED (Chunk B) against the real service —
8
- * `tot-foxycart/routes/foxyOrderApi.js` + `modules/integrations/foxyOrderMapper.node.js`:
7
+ * The service is `tot-foxycart/routes/foxyOrderApi.js` +
8
+ * `modules/integrations/foxyOrderMapper.node.js`:
9
9
  * a `GET {baseUrl}/commerce/orders?appDomain=&limit=&offset=&since=&until=&status=`
10
10
  * list endpoint returning `{ orders, limit, offset, total, hasMore }` (limit/offset,
11
- * NOT page/pageSize — chunk A guessed page/pageSize), and a
11
+ * NOT page/pageSize), and a
12
12
  * `GET {baseUrl}/commerce/orders/{externalOrderId}?appDomain=` detail endpoint
13
- * returning `{ order }` (an envelope, not the bare order — chunk A guessed bare),
13
+ * returning `{ order }` (an envelope, not the bare order),
14
14
  * both Bearer-authenticated with the tenant's Foxy partner API key. `FoxyOrder`
15
- * below now mirrors `buildOrderPayload()`'s actual normalized DTO — NOT the
15
+ * below mirrors `buildOrderPayload()`'s actual normalized DTO — NOT the
16
16
  * contract's minimized `Order` shape (`contract/openapi.yaml`); mapping one to
17
17
  * the other is `orderMapper.ts`'s job.
18
18
  *
@@ -20,8 +20,8 @@
20
20
  * factory shape and `../../webhooks/deliveryEngine.ts`'s bounded-timeout
21
21
  * `fetch` (AbortController, injectable `fetchImpl`) — but adds a settable
22
22
  * test seam (`setFoxyOrderClientForTesting`) since this client, unlike
23
- * `messagesClient.ts`, is a shared singleton multiple later chunks (read
24
- * routes, event receiver) will each independently resolve.
23
+ * `messagesClient.ts`, is a shared singleton that multiple callers (read
24
+ * routes, event receiver) each independently resolve.
25
25
  */
26
26
  import { readEnv } from "@/lib/env";
27
27
 
@@ -174,7 +174,7 @@ export class HttpFoxyOrderClient implements FoxyOrderClient {
174
174
  }
175
175
 
176
176
  // --- Test seam ---------------------------------------------------------------
177
- // Later chunks (read routes, event receiver) each resolve their own client
177
+ // Callers (read routes, event receiver) each resolve their own client
178
178
  // instance via `getFoxyOrderClient()`; a module-level override lets a single
179
179
  // `setFoxyOrderClientForTesting` call stand in for tot-foxycart across all of
180
180
  // them in one test, without threading a fake through every call site.
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Idempotency-Key ledger — PrivateApps epic, D6 (Chunk C). Backs the
3
- * `idempotency_keys` table `schema.ts` declares: the FIRST real (not
2
+ * Idempotency-Key ledger. Backs the
3
+ * `idempotency_keys` table `schema.ts` declares: the one real (not
4
4
  * presence-only) idempotency ledger in this codebase, and the one
5
5
  * `POST /attribution` (`docs/private-apps/contract/openapi.yaml`'s
6
6
  * `writeAttribution`) requires — a reused key with a body hash that doesn't
7
7
  * match the one first stored is a 409, not a silent overwrite or a second
8
- * row. Contrast D4's replay endpoint (`webhooks/deliveries/{id}/replay.ts`),
8
+ * row. Contrast the webhook replay endpoint (`webhooks/deliveries/{id}/replay.ts`),
9
9
  * which only checks the header's presence because it has no request body to
10
- * hash and no table backing it yet.
10
+ * hash and no table backing it.
11
11
  *
12
- * Pure over the `Queryable` seam, same shape every other D6 store uses.
13
- * Route-agnostic by design: `attribution.ts` is the first caller, but any
14
- * future idempotent write route can reuse this unchanged.
12
+ * Pure over the `Queryable` seam, same shape every other orders store uses.
13
+ * Route-agnostic by design: `attribution.ts` is one caller, but any
14
+ * idempotent write route can reuse this.
15
15
  */
16
16
  import { sha256Hex } from "@tot/public-runtime";
17
17
  import type { Queryable } from "../../d1/catalog.js";
@@ -0,0 +1,150 @@
1
+ /**
2
+ * The D1-backed durable seams the verified-order conversion join
3
+ * (`@tot/public-runtime`'s `computeOrderConversion`) needs in the Worker, plus the
4
+ * thin wrapper the order-forward receiver route calls to run the join.
5
+ *
6
+ * Two durable stores on `STOREFRONT_APPS_DB` (the same D1 the order rows live in, so
7
+ * attribution and the order it attributes share one database):
8
+ * - `correlation_replay` — the single-use `jti` ledger behind the injected
9
+ * {@link CorrelationReplayGuard}: a correlation token is honored exactly once, and
10
+ * a replay of a consumed `jti` is refused. Rows are pruned once past their `exp`
11
+ * (a past-`exp` token is already rejected `expired` before the guard is reached).
12
+ * - `order_attribution` — the per-`(tenant, orderId)` attribution ledger: the order's
13
+ * attribution is fixed on its first conversion and reused for later lifecycle events.
14
+ *
15
+ * Both run over the `Queryable` seam, so they serve real D1 in the Worker and an
16
+ * in-memory `node:sqlite` in tests unchanged.
17
+ */
18
+ import type { Queryable } from "../../d1/catalog.js";
19
+ import { readEnv } from "@/lib/env";
20
+ import {
21
+ computeOrderConversion,
22
+ resolveConversionEnvironment,
23
+ readEchoedCorrelation,
24
+ type CorrelationReplayGuard,
25
+ type OrderConversionAttributionStore,
26
+ type OrderConversionResult,
27
+ type StoredAttribution,
28
+ } from "@tot/public-runtime";
29
+ import type { OrderForwardInput, OrderForwardResult } from "./orderForwardReceiver.js";
30
+
31
+ /** The server-only correlation-signing key binding, distinct from the cart secret. */
32
+ const CORRELATION_SECRET_ENV = "COMMERCE_CORRELATION_SECRET";
33
+
34
+ /**
35
+ * Durable single-use `jti` guard over `correlation_replay`. `seen` is an existence
36
+ * check; `remember` prunes any past-`exp` rows (bounded growth) then records the `jti`
37
+ * idempotently.
38
+ */
39
+ export class D1CorrelationReplayGuard implements CorrelationReplayGuard {
40
+ constructor(
41
+ private readonly db: Queryable,
42
+ private readonly nowSec: () => number = () => Math.floor(Date.now() / 1000),
43
+ ) {}
44
+
45
+ async seen(jti: string): Promise<boolean> {
46
+ const row = await this.db.first<{ one: number }>(
47
+ `SELECT 1 AS one FROM correlation_replay WHERE jti = ?`,
48
+ jti,
49
+ );
50
+ return row != null;
51
+ }
52
+
53
+ async remember(jti: string, expiresAtSec: number): Promise<void> {
54
+ const now = this.nowSec();
55
+ await this.db.run(`DELETE FROM correlation_replay WHERE expires_at <= ?`, now);
56
+ await this.db.run(
57
+ `INSERT OR IGNORE INTO correlation_replay (jti, expires_at, consumed_at) VALUES (?, ?, ?)`,
58
+ jti,
59
+ expiresAtSec,
60
+ new Date(now * 1000).toISOString(),
61
+ );
62
+ }
63
+ }
64
+
65
+ interface OrderAttributionRow {
66
+ attributed: number;
67
+ correlation_id: string | null;
68
+ correlation_expires_at: string | null;
69
+ reason: string | null;
70
+ }
71
+
72
+ /** Durable per-`(tenant, orderId)` attribution ledger over `order_attribution`. */
73
+ export class D1OrderConversionAttributionStore implements OrderConversionAttributionStore {
74
+ constructor(
75
+ private readonly db: Queryable,
76
+ private readonly now: () => string = () => new Date().toISOString(),
77
+ ) {}
78
+
79
+ async get(tenant: string, orderId: string): Promise<StoredAttribution | null> {
80
+ const row = await this.db.first<OrderAttributionRow>(
81
+ `SELECT attributed, correlation_id, correlation_expires_at, reason
82
+ FROM order_attribution WHERE tenant_id = ? AND external_order_id = ?`,
83
+ tenant,
84
+ orderId,
85
+ );
86
+ return row ? toStored(row) : null;
87
+ }
88
+
89
+ async putIfAbsent(
90
+ tenant: string,
91
+ orderId: string,
92
+ record: StoredAttribution,
93
+ ): Promise<StoredAttribution> {
94
+ await this.db.run(
95
+ `INSERT OR IGNORE INTO order_attribution
96
+ (tenant_id, external_order_id, attributed, correlation_id, correlation_expires_at, reason, recorded_at)
97
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
98
+ tenant,
99
+ orderId,
100
+ record.attributed ? 1 : 0,
101
+ record.correlationId,
102
+ record.correlationExpiresAt,
103
+ record.reason,
104
+ this.now(),
105
+ );
106
+ // Return the EFFECTIVE row: a concurrent first-writer's record wins over this one.
107
+ const stored = await this.get(tenant, orderId);
108
+ return stored ?? record;
109
+ }
110
+ }
111
+
112
+ function toStored(row: OrderAttributionRow): StoredAttribution {
113
+ return {
114
+ attributed: row.attributed === 1,
115
+ correlationId: row.correlation_id,
116
+ correlationExpiresAt: row.correlation_expires_at,
117
+ reason: (row.reason as StoredAttribution["reason"]) ?? null,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Run the verified-order → server conversion join for one forwarded order: read the
123
+ * echoed correlation the provider carried back, resolve the durable guard + attribution
124
+ * ledger over `db`, and produce the canonical server conversion event(s) plus the
125
+ * explicit attribution outcome. The correlation is verified against the ORDER's own
126
+ * tenant/environment, so a cross-tenant/stage token can never attribute.
127
+ */
128
+ export async function joinForwardedOrderConversion(
129
+ db: Queryable,
130
+ input: OrderForwardInput,
131
+ receiverResult: OrderForwardResult,
132
+ ): Promise<OrderConversionResult> {
133
+ const correlationSecret = await readEnv(CORRELATION_SECRET_ENV);
134
+ return computeOrderConversion({
135
+ order: {
136
+ tenant: input.tenantId,
137
+ externalOrderId: input.externalOrderId,
138
+ status: receiverResult.order.status,
139
+ currency: input.currency,
140
+ total: input.total,
141
+ lineItems: input.lineItems,
142
+ },
143
+ environment: resolveConversionEnvironment(input.env),
144
+ emittedTopics: receiverResult.emitted,
145
+ echoedCorrelation: readEchoedCorrelation(input.providerFields),
146
+ correlationSecret,
147
+ guard: new D1CorrelationReplayGuard(db),
148
+ attributionStore: new D1OrderConversionAttributionStore(db),
149
+ });
150
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Inbound order-forward receiver — PrivateApps epic, D6 (Chunk D). The
2
+ * Inbound order-forward receiver. The
3
3
  * transport-free core `pages/api/apps/internal/order-forward.ts` calls once
4
4
  * it has verified the HMAC signature: given one reconciled order from
5
5
  * tot-foxycart, upsert it into `ordersStore.ts` and decide whether that write
@@ -51,6 +51,14 @@ export interface OrderForwardInput {
51
51
  rawCustomerId?: string;
52
52
  /** ISO timestamp the order was actually created at tot-foxycart. Defaults to receipt time when omitted (e.g. a backfill missing it) — only matters for a brand-new row; ignored on an update. */
53
53
  createdAt?: string;
54
+ /** The provider's echoed custom cart fields (e.g. `h:tot_correlation`) the order-conversion join reads the correlation token from. Absent → the conversion is explicitly unattributed. */
55
+ providerFields?: Record<string, unknown>;
56
+ /** Opaque provider event identity. Missing legacy forwards are never measured. */
57
+ providerEventId?: string;
58
+ /** Exact provider event instant; measurement rejects non-canonical/missing values. */
59
+ occurredAt?: string;
60
+ /** Provider-authoritative non-negative minor-unit total; no float conversion is used. */
61
+ amountMinor?: number;
54
62
  }
55
63
 
56
64
  export interface OrderForwardResult {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Pure mapper: `FoxyOrderClient`'s `FoxyOrder` (tot-foxycart's normalized
3
- * transaction DTO) -> the contract's minimized `Order` shape (PrivateApps
4
- * epic, D6 Chunk B; `docs/private-apps/contract/openapi.yaml`'s `Order`).
3
+ * transaction DTO) -> the contract's minimized `Order` shape
4
+ * (`docs/private-apps/contract/openapi.yaml`'s `Order`).
5
5
  *
6
6
  * Drops everything the contract's `additionalProperties: false` Order
7
7
  * doesn't declare — no raw checkout payload, no signed-cart material, no tax
@@ -1,9 +1,9 @@
1
1
  /**
2
- * `orders` read-model store — PrivateApps epic, D6 (Chunk A). Owns the
3
- * `orders` rows `schema.ts` declares: the diffing surface a later chunk's
4
- * event emission reads (`upsertOrder`'s returned `previousStatus` is how it
2
+ * `orders` read-model store. Owns the
3
+ * `orders` rows `schema.ts` declares: the diffing surface the event emission
4
+ * reads (`upsertOrder`'s returned `previousStatus` is how it
5
5
  * detects a created→fulfilled transition without a second query) and the
6
- * lookup surface the attribution route (also later) uses for its cross-tenant
6
+ * lookup surface the attribution route uses for its cross-tenant
7
7
  * ownership check.
8
8
  *
9
9
  * Pure over the `Queryable` seam (see `../../d1/catalog.ts`) — same shape
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import type { Queryable } from "../../d1/catalog.js";
14
14
 
15
- export type OrderStatus = "created" | "fulfilled" | "cancelled";
15
+ export type OrderStatus = "created" | "fulfilled" | "refunded" | "cancelled";
16
16
 
17
17
  /** One order line item (JSON-as-text in the row; see `Order.lineItems` in the contract). */
18
18
  export interface OrderLineItem {
@@ -54,8 +54,8 @@ export interface UpsertOrderInput {
54
54
 
55
55
  /**
56
56
  * `upsertOrder`'s return: the row's status BEFORE this write (`null` for a
57
- * brand-new order) alongside the row as it now stands — the diffing signal a
58
- * later chunk's event emission needs to tell "just created" apart from
57
+ * brand-new order) alongside the row as it now stands — the diffing signal the
58
+ * event emission needs to tell "just created" apart from
59
59
  * "created → fulfilled" apart from "no-op re-delivery of the same status",
60
60
  * without a second round trip.
61
61
  */
@@ -0,0 +1,117 @@
1
+ /** Durable WS4 adapter for the already HMAC-verified Foxy order-forward path.
2
+ * It has no browser, GTM, dataLayer, receipt-DOM, destination, or admin capability.
3
+ * The caller catches every error, so a measurement-store outage cannot block commerce. */
4
+ import {
5
+ intentFromVerifiedProviderTruth,
6
+ } from "../../../../../../packages/public-runtime/src/regulated-commerce/provider-order/bridge.js";
7
+ import {
8
+ parseVerifiedOrderTruth,
9
+ resolveVerifiedOrderTruth,
10
+ verifiedOrderTruthFingerprint,
11
+ type VerifiedOrderSnapshot,
12
+ type VerifiedOrderTruth,
13
+ type VerifiedOrderTruthResolution,
14
+ } from "../../../../../../packages/public-runtime/src/regulated-commerce/purchase-truth/contract.js";
15
+ import type { RegulatedCommerceIntent } from "../../../../../../packages/public-runtime/src/regulated-commerce/events/contract.js";
16
+ import type { Queryable } from "../../d1/catalog.js";
17
+ import type { OrderForwardInput } from "./orderForwardReceiver.js";
18
+
19
+ const FOXY_PROVIDER = "foxycart";
20
+ const LIVE_ENVS = new Set(["live", "production"]);
21
+ type ProviderEventRow = { fingerprint: string; receipt_id: string };
22
+ type ProviderOrderRow = { provider: string; provider_order_id: string; tenant_id: string; state: "purchased" | "refunded" | "cancelled" };
23
+
24
+ export type VerifiedProviderMeasurementOutcome =
25
+ | "recorded" | "duplicate" | "replay-conflict" | "stale-transition" | "ignored-non-live" | "ignored-malformed";
26
+ export interface VerifiedProviderMeasurementResult { readonly outcome: VerifiedProviderMeasurementOutcome; readonly intent: RegulatedCommerceIntent | null; }
27
+
28
+ function snapshot(row: ProviderOrderRow | null): VerifiedOrderSnapshot | null {
29
+ return row ? { provider: row.provider, providerOrderId: row.provider_order_id, tenant: row.tenant_id, state: row.state } : null;
30
+ }
31
+ function isIsoInstant(value: unknown): value is string {
32
+ return typeof value === "string" && Number.isFinite(Date.parse(value)) && new Date(Date.parse(value)).toISOString() === value;
33
+ }
34
+
35
+ /** Missing event identity/minor units fails closed. Legacy forwards still ACK as
36
+ * commerce, but cannot become regulated measurement. */
37
+ export function verifiedTruthFromForwardedOrder(input: OrderForwardInput): VerifiedOrderTruth | null {
38
+ if (!LIVE_ENVS.has(input.env)) return null;
39
+ if (typeof input.providerEventId !== "string" || !isIsoInstant(input.occurredAt) || typeof input.amountMinor !== "number" || !Number.isSafeInteger(input.amountMinor) || input.amountMinor < 0) return null;
40
+ const parsed = parseVerifiedOrderTruth({
41
+ schemaVersion: "1", authority: "verified-provider", provider: FOXY_PROVIDER,
42
+ providerEventId: input.providerEventId, providerOrderId: input.externalOrderId,
43
+ tenant: input.tenantId, status: input.status, occurredAt: input.occurredAt,
44
+ currency: input.currency, amountMinor: input.amountMinor,
45
+ });
46
+ return parsed.ok ? parsed.value : null;
47
+ }
48
+
49
+ /** Server-only D1 ledger/outbox. Event insertion uses a receipt id plus RETURNING,
50
+ * giving concurrent identical deliveries one winner. The order state change is a
51
+ * guarded SQL CAS, so a race cannot overwrite a refund/cancel with a purchase. */
52
+ export class D1VerifiedProviderMeasurementStore {
53
+ constructor(
54
+ private readonly db: Queryable,
55
+ private readonly receiptId: () => string = () => crypto.randomUUID(),
56
+ private readonly now: () => string = () => new Date().toISOString(),
57
+ ) {}
58
+
59
+ async record(input: OrderForwardInput): Promise<VerifiedProviderMeasurementResult> {
60
+ if (!LIVE_ENVS.has(input.env)) return { outcome: "ignored-non-live", intent: null };
61
+ const record = verifiedTruthFromForwardedOrder(input);
62
+ if (!record) return { outcome: "ignored-malformed", intent: null };
63
+ const fingerprint = verifiedOrderTruthFingerprint(record);
64
+ const receiptId = this.receiptId();
65
+ const inserted = await this.db.all<{ receipt_id: string }>(
66
+ `INSERT INTO regulated_commerce_provider_events
67
+ (provider, provider_event_id, fingerprint, receipt_id, received_at)
68
+ VALUES (?, ?, ?, ?, ?) ON CONFLICT(provider, provider_event_id) DO NOTHING RETURNING receipt_id`,
69
+ record.provider, record.providerEventId, fingerprint, receiptId, this.now(),
70
+ );
71
+ if (inserted.length === 0) {
72
+ const existing = await this.event(record.provider, record.providerEventId);
73
+ return { outcome: existing?.fingerprint === fingerprint ? "duplicate" : "replay-conflict", intent: null };
74
+ }
75
+ for (let attempts = 0; attempts < 3; attempts++) {
76
+ const resolution = resolveVerifiedOrderTruth({ record, existingEvent: null, existingOrder: snapshot(await this.order(record)) });
77
+ if (resolution.outcome !== "accepted") return { outcome: resolution.outcome === "stale-transition" ? "stale-transition" : "replay-conflict", intent: null };
78
+ if (!(await this.claimTransition(record, resolution))) continue;
79
+ const built = intentFromVerifiedProviderTruth(record, resolution);
80
+ if (!built.intent) return { outcome: "recorded", intent: null };
81
+ await this.db.run(
82
+ `INSERT OR IGNORE INTO regulated_commerce_intent_outbox
83
+ (intent_id, tenant_id, provider, provider_event_id, payload, created_at) VALUES (?, ?, ?, ?, ?, ?)`,
84
+ built.intent.id, record.tenant, record.provider, record.providerEventId, JSON.stringify(built.intent), this.now(),
85
+ );
86
+ return { outcome: "recorded", intent: built.intent };
87
+ }
88
+ return { outcome: "stale-transition", intent: null };
89
+ }
90
+
91
+ /** Local/admin-safe test surface: only the minimized semantic outbox. */
92
+ async intents(): Promise<RegulatedCommerceIntent[]> {
93
+ const rows = await this.db.all<{ payload: string }>(`SELECT payload FROM regulated_commerce_intent_outbox ORDER BY created_at, intent_id`);
94
+ return rows.map((row) => JSON.parse(row.payload) as RegulatedCommerceIntent);
95
+ }
96
+
97
+ private event(provider: string, providerEventId: string): Promise<ProviderEventRow | null> {
98
+ return this.db.first<ProviderEventRow>(`SELECT fingerprint, receipt_id FROM regulated_commerce_provider_events WHERE provider = ? AND provider_event_id = ?`, provider, providerEventId);
99
+ }
100
+ private order(record: VerifiedOrderTruth): Promise<ProviderOrderRow | null> {
101
+ return this.db.first<ProviderOrderRow>(`SELECT provider, provider_order_id, tenant_id, state FROM regulated_commerce_provider_orders WHERE provider = ? AND provider_order_id = ? AND tenant_id = ?`, record.provider, record.providerOrderId, record.tenant);
102
+ }
103
+ private async claimTransition(record: VerifiedOrderTruth, resolution: Extract<VerifiedOrderTruthResolution, { outcome: "accepted" }>): Promise<boolean> {
104
+ const rows = await this.db.all<{ provider_event_id: string }>(
105
+ `INSERT INTO regulated_commerce_provider_orders
106
+ (provider, provider_order_id, tenant_id, state, provider_event_id, updated_at)
107
+ VALUES (?, ?, ?, ?, ?, ?)
108
+ ON CONFLICT(provider, provider_order_id, tenant_id) DO UPDATE SET
109
+ state = excluded.state, provider_event_id = excluded.provider_event_id, updated_at = excluded.updated_at
110
+ WHERE regulated_commerce_provider_orders.state = 'purchased'
111
+ AND excluded.state IN ('purchased', 'refunded', 'cancelled')
112
+ RETURNING provider_event_id`,
113
+ record.provider, record.providerOrderId, record.tenant, resolution.nextOrder.state, record.providerEventId, this.now(),
114
+ );
115
+ return rows.some((row) => row.provider_event_id === record.providerEventId);
116
+ }
117
+ }