@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
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Storefront-side resolution of the renderer-owned four-stage browser
3
+ * environment (`@tot/public-runtime` `resolveBrowserEnvironment`). This is the ONE
4
+ * place request state is turned into the authoritative environment object; both
5
+ * document mounts (Layout.astro and `rawHtmlResponse`) serialize the result, so
6
+ * the object is identical in both by construction.
7
+ *
8
+ * The stage is derived from server facts only — `import.meta.env.DEV`, the request
9
+ * host, the resolved customization environment, and whether this is a per-change
10
+ * candidate render — never a client-supplied value. A candidate render is always
11
+ * `candidate` and never `live`; anything unresolved stays non-live.
12
+ */
13
+ import {
14
+ resolveBrowserEnvironment,
15
+ resolveEnvironmentOnlyPlan,
16
+ type BrowserEnvironment,
17
+ type EffectivePlan,
18
+ type IntegrationSiteSurface,
19
+ } from "@tot/public-runtime";
20
+ import { isAdminPath } from "@/lib/auth/loginGate";
21
+
22
+ /**
23
+ * The non-secret render revision: the commit SHA this build was cut from (baked at
24
+ * build time, the same value GET /health reports), or `"local"` when there is no
25
+ * git context (dev, vitest). Never a token or signed URL.
26
+ */
27
+ function platformRevision(): string {
28
+ return typeof __GIT_SHA__ !== "undefined" && __GIT_SHA__ ? __GIT_SHA__ : "local";
29
+ }
30
+
31
+ /** A request host is local when it is served on loopback (`astro dev` or a local built Worker). */
32
+ function isLocalHost(host: string): boolean {
33
+ return host.startsWith("localhost") || host.startsWith("127.0.0.1");
34
+ }
35
+
36
+ /**
37
+ * Map the resolved tenant + request path to a document surface. Admin/cockpit
38
+ * paths are `admin`; cart/checkout paths are `checkout`; a catalog tenant is
39
+ * `storefront`; a marketing tenant (no catalog) is `marketing`.
40
+ */
41
+ export function deriveSiteSurface(input: {
42
+ catalog: boolean;
43
+ pathname: string;
44
+ }): IntegrationSiteSurface {
45
+ // Admin + the cockpit control-plane panel (host-routed `/cockpit` or tenant-first
46
+ // `/<tenant>/cockpit`) are the `admin` surface.
47
+ if (isAdminPath(input.pathname) || /^\/(?:[^/]+\/)?cockpit(?:\/|$)/.test(input.pathname)) {
48
+ return "admin";
49
+ }
50
+ if (/^\/(checkout|cart)(\/|$)/.test(input.pathname)) return "checkout";
51
+ return input.catalog ? "storefront" : "marketing";
52
+ }
53
+
54
+ /**
55
+ * The normal (non-candidate) per-request environment object, computed once by the
56
+ * middleware. `astro dev` and a Worker served on localhost both resolve to `local`
57
+ * (their CSP-enforcement mode differs — report-only vs enforced — but that is a
58
+ * response-header concern, not part of this object).
59
+ */
60
+ export function requestBrowserEnvironment(input: {
61
+ host: string;
62
+ isPreviewHost: boolean;
63
+ customizationEnv: "live" | "test";
64
+ canonicalHost: string;
65
+ siteSurface: IntegrationSiteSurface;
66
+ }): BrowserEnvironment {
67
+ return resolveBrowserEnvironment({
68
+ dev: import.meta.env.DEV,
69
+ localHost: isLocalHost(input.host),
70
+ candidate: false,
71
+ previewHost: input.isPreviewHost,
72
+ customizationEnv: input.customizationEnv,
73
+ siteSurface: input.siteSurface,
74
+ canonicalHost: input.canonicalHost,
75
+ revision: platformRevision(),
76
+ });
77
+ }
78
+
79
+ /**
80
+ * CSP enforcement mode for this runtime — the axis that stays DISTINCT from the
81
+ * `local` stage. `astro dev` (Node) serves un-nonced Vite `<style>`/`<script>`, so a
82
+ * strict nonce policy would blank the site: it is REPORT-ONLY there (violations
83
+ * still surface). The built Worker is CSP-clean, so the strict policy is ENFORCED —
84
+ * including the built Worker run locally, which is how enforced CSP is proven.
85
+ * Report-only-dev and enforced-built-Worker are both correct; only the mode differs,
86
+ * never the four-stage environment object.
87
+ */
88
+ export type CspEnforcementMode = "report-only" | "enforced";
89
+
90
+ export function cspEnforcementMode(dev: boolean): CspEnforcementMode {
91
+ return dev ? "report-only" : "enforced";
92
+ }
93
+
94
+ /** The response header name that carries the mode: report-only in dev, enforced otherwise. */
95
+ export function cspHeaderName(
96
+ dev: boolean,
97
+ ): "Content-Security-Policy-Report-Only" | "Content-Security-Policy" {
98
+ return dev ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy";
99
+ }
100
+
101
+ /**
102
+ * The environment object for a per-change candidate render (the cockpit candidate
103
+ * renderer, the revision renderer, and the not-yet-built PR page). The stage is
104
+ * always `candidate` — never `live`, even when the underlying tenant is live — and
105
+ * `revision` is the candidate's own version identity (a versionId / head sha), a
106
+ * public, non-secret value.
107
+ */
108
+ export function candidateBrowserEnvironment(input: {
109
+ canonicalHost: string;
110
+ revision: string;
111
+ siteSurface?: IntegrationSiteSurface;
112
+ }): BrowserEnvironment {
113
+ return resolveBrowserEnvironment({
114
+ dev: import.meta.env.DEV,
115
+ localHost: false,
116
+ candidate: true,
117
+ previewHost: true,
118
+ customizationEnv: "test",
119
+ siteSurface: input.siteSurface ?? "marketing",
120
+ canonicalHost: input.canonicalHost,
121
+ revision: input.revision,
122
+ });
123
+ }
124
+
125
+ /**
126
+ * The resolved effective plan for a candidate render — the `candidate`-stage
127
+ * environment wrapped in an environment-only plan so `rawHtmlResponse` (the raw
128
+ * mount of the fixed-phase engine) renders the same renderer-owned phases a live
129
+ * page gets. No integration declarations are materialized on the candidate hot
130
+ * path, so this is environment-only until that wiring lands.
131
+ */
132
+ export function candidateIntegrationPlan(
133
+ input: { canonicalHost: string; revision: string; siteSurface?: IntegrationSiteSurface },
134
+ tenantPublicId: string,
135
+ ): EffectivePlan {
136
+ return resolveEnvironmentOnlyPlan(candidateBrowserEnvironment(input), tenantPublicId);
137
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Materialize active managed-analytics installs into the render plane's existing
3
+ * declaration seam. `app_installs` owns status/manifest and MAX(seq) owns the
4
+ * active public config; candidates and drafts are never read here.
5
+ */
6
+ import {
7
+ ENVIRONMENT_SCHEMA_VERSION,
8
+ buildPlatformAdapterDeclaration,
9
+ validateIntegrationManifest,
10
+ type IntegrationDeclarationInput,
11
+ } from "@tot/public-runtime";
12
+ import { AppVersionStore } from "../apps/appVersionStore.js";
13
+ import type { Queryable } from "../d1/catalog.js";
14
+
15
+ const MANAGED_KIND = "managed-analytics-v1";
16
+
17
+ interface ActiveManagedRow {
18
+ install_id: string;
19
+ app_id: string;
20
+ app_version: string;
21
+ manifest: string;
22
+ }
23
+
24
+ /**
25
+ * Return only declarations whose canonical row, current immutable activation,
26
+ * and reviewed platform-adapter rebuild agree. Malformed/stale rows fail closed
27
+ * individually; an unavailable database is handled by the caller as no effects.
28
+ */
29
+ export async function loadActiveManagedInstallDeclarations(
30
+ db: Queryable,
31
+ tenantPublicId: string,
32
+ ): Promise<IntegrationDeclarationInput[]> {
33
+ const rows = await db.all<ActiveManagedRow>(
34
+ `SELECT install_id, app_id, app_version, manifest
35
+ FROM app_installs
36
+ WHERE tenant_id = ? AND managed_kind = ? AND status = 'active'
37
+ ORDER BY install_id`,
38
+ tenantPublicId,
39
+ MANAGED_KIND,
40
+ );
41
+ const versions = new AppVersionStore(db);
42
+ const declarations: IntegrationDeclarationInput[] = [];
43
+ for (const row of rows) {
44
+ try {
45
+ const manifest = validateIntegrationManifest(JSON.parse(row.manifest) as unknown);
46
+ const current = await versions.currentVersion(row.install_id);
47
+ if (!manifest.ok || !current || current.tenantId !== tenantPublicId) continue;
48
+ if (current.appVersion !== row.app_version || current.facets.appVersion !== row.app_version) continue;
49
+ if (current.facets.digest !== manifest.value.app.digest || manifest.value.app.id !== row.app_id) continue;
50
+ const destinationId = current.facets.publicConfig["destinationId"];
51
+ if (typeof destinationId !== "string") continue;
52
+ const built = buildPlatformAdapterDeclaration({
53
+ adapterId: row.app_id,
54
+ ids: { live: destinationId },
55
+ tenantPublicId,
56
+ environment: {
57
+ schemaVersion: ENVIRONMENT_SCHEMA_VERSION,
58
+ siteSurface: "storefront",
59
+ environment: "live",
60
+ canonicalHost: tenantPublicId,
61
+ revision: `managed-live:${current.seq}`,
62
+ },
63
+ });
64
+ if (!built.ok || built.declaration.manifest.app.digest !== manifest.value.app.digest) continue;
65
+ declarations.push({ ...built.declaration, ref: `managed-install:${row.install_id}` });
66
+ } catch {
67
+ // Persisted JSON/version corruption must disable this install, never widen
68
+ // CSP or partially materialize a subscription.
69
+ }
70
+ }
71
+ return declarations;
72
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Per-response CSP-nonce stamping (ADR 0018 nonce non-serialization; ext-kernel-04).
3
+ *
4
+ * The renderer emits a nonce-free template: every platform inline tag and the CSP
5
+ * header carry {@link INTEGRATION_NONCE_PLACEHOLDER}, never a live nonce. This is
6
+ * what the edge cache stores — a nonce-free artifact. At serve time (a cold render
7
+ * OR a warm cache hit) this stamps ONE fresh per-response nonce into both the HTML
8
+ * body and the CSP header, so every response gets a fresh, matching nonce/CSP pair
9
+ * and no nonce is ever reused across responses.
10
+ */
11
+ import { INTEGRATION_NONCE_PLACEHOLDER, stampNonce } from "@tot/public-runtime";
12
+
13
+ const CSP_HEADERS = [
14
+ "content-security-policy",
15
+ "content-security-policy-report-only",
16
+ ] as const;
17
+
18
+ /** A fresh, non-guessable per-response nonce. */
19
+ export function freshNonce(): string {
20
+ return crypto.randomUUID();
21
+ }
22
+
23
+ /**
24
+ * Replace the nonce placeholder with a fresh `nonce` in a response's CSP header(s)
25
+ * and — for an HTML response — its body. Non-HTML responses keep their (streamed)
26
+ * body untouched; their CSP header is still stamped. A response with no placeholder
27
+ * (a static-bundle body, an API JSON) is returned effectively unchanged.
28
+ */
29
+ export async function stampResponseNonce(
30
+ response: Response,
31
+ nonce: string,
32
+ ): Promise<Response> {
33
+ for (const header of CSP_HEADERS) {
34
+ const value = response.headers.get(header);
35
+ if (value && value.includes(INTEGRATION_NONCE_PLACEHOLDER)) {
36
+ response.headers.set(header, stampNonce(value, nonce));
37
+ }
38
+ }
39
+
40
+ const contentType = response.headers.get("content-type") ?? "";
41
+ if (!contentType.includes("text/html")) return response;
42
+
43
+ const body = await response.text();
44
+ return new Response(stampNonce(body, nonce), {
45
+ status: response.status,
46
+ statusText: response.statusText,
47
+ headers: response.headers,
48
+ });
49
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Tenant-local integration declaration materialization (ext-kernel-09).
3
+ *
4
+ * This is the ONE production seam that turns a tenant's OWN declared, exact-version
5
+ * integrations into the already-materialized {@link IntegrationDeclarationInput} set
6
+ * the render hot path consumes. The interim marketing bridge
7
+ * ({@link resolveInterimBridgePlan}) resolves that set into the effective plan the
8
+ * fixed-phase engine serves — refusing a regulated tenant, resolving an eligible
9
+ * unregulated one — so a declared tenant boots its integration on-by-default
10
+ * (consent-gated) with no page edit and no vendor branch.
11
+ *
12
+ * A tenant with no declaration returns the empty set, so the bridge resolves an
13
+ * environment-only plan and the request is byte-identical to non-integration
14
+ * behavior (zero cost). The declarations are already materialized in tenant config
15
+ * (the manifest, the resolved public config, the set of asset paths present for the
16
+ * version); this loader only reads them, fail-closed — resolution is the bridge's
17
+ * job, materialization is config's, and the two never blur.
18
+ */
19
+ import type { IntegrationDeclarationInput, IntegrationManifest, TenantConfig } from "@tot/public-runtime";
20
+
21
+ const NO_DECLARATIONS: readonly IntegrationDeclarationInput[] = Object.freeze([]);
22
+
23
+ /**
24
+ * Read a tenant's already-materialized tenant-local declarations. Returns the empty
25
+ * set (never throws) when the tenant declares none or the field is malformed — an
26
+ * undeclared tenant must resolve to the environment-only plan, never an error.
27
+ */
28
+ export function loadTenantIntegrationDeclarations(
29
+ tenant: Pick<TenantConfig, "integrations">,
30
+ ): readonly IntegrationDeclarationInput[] {
31
+ const declared = tenant.integrations;
32
+ if (!Array.isArray(declared) || declared.length === 0) return NO_DECLARATIONS;
33
+ return declared;
34
+ }
35
+
36
+ // ---------------------------------------------------------------------------
37
+ // Demo tenant-local declaration — a same-origin sandbox analytics adapter.
38
+ //
39
+ // Seeded on the unregulated marketing demo/home tenants so a preview deploy
40
+ // DEMONSTRABLY materializes a real integration on-by-default: its exact-version
41
+ // entry module (committed under `public/apps/…`, so always materialized and served
42
+ // same-origin) flows the declaration → interim bridge → effective plan → boot
43
+ // descriptor → lifecycle import. Loading is consent-gated (purpose `analytics`,
44
+ // held back under the default-deny snapshot until granted), and the declared
45
+ // beacon origin reaches the strict CSP via `cspNeeds`. A regulated tenant carrying
46
+ // the same declaration is still REFUSED by the bridge.
47
+ // ---------------------------------------------------------------------------
48
+
49
+ /** The demo adapter's app id — a same-origin, sandbox-tier marketing analytics adapter. */
50
+ export const DEMO_ANALYTICS_APP_ID = "tot.demo.analytics";
51
+ /** The demo adapter's exact pinned version. */
52
+ export const DEMO_ANALYTICS_VERSION = "0.1.0";
53
+ /**
54
+ * The same-origin, exact-version entry module the lifecycle runtime dynamically
55
+ * imports. Committed under `apps/storefront/public/apps/…` so it is served verbatim
56
+ * at this root-absolute URL and is ALWAYS materialized (no R2 pointer needed).
57
+ */
58
+ export const DEMO_ANALYTICS_ENTRY_URL = `/apps/${DEMO_ANALYTICS_APP_ID}/${DEMO_ANALYTICS_VERSION}/entry.js`;
59
+ /** The beacon endpoint the demo declaration reserves in CSP (`connect-src`). */
60
+ export const DEMO_ANALYTICS_BEACON_ORIGIN = "https://demo-analytics.tokenoftrust.com";
61
+
62
+ /** The demo adapter's shared browser manifest (ext-kernel-01 v2). */
63
+ const DEMO_ANALYTICS_MANIFEST: IntegrationManifest = {
64
+ schemaVersion: 2,
65
+ app: {
66
+ id: DEMO_ANALYTICS_APP_ID,
67
+ name: "ToT Demo Analytics",
68
+ version: DEMO_ANALYTICS_VERSION,
69
+ digest: `sha256:${DEMO_ANALYTICS_APP_ID}-${DEMO_ANALYTICS_VERSION}`,
70
+ publisher: "Token of Trust",
71
+ },
72
+ compatibility: { storefrontBrowserContract: ">=2.0.0 <3.0.0", configurationSchemaVersion: 1 },
73
+ browser: {
74
+ executionTier: "sandbox",
75
+ entry: { asset: DEMO_ANALYTICS_ENTRY_URL, format: "module", phase: "document.deferred" },
76
+ contributions: [],
77
+ dependencies: [],
78
+ publicConfigSchema: {
79
+ type: "object",
80
+ additionalProperties: false,
81
+ required: ["siteId"],
82
+ properties: { siteId: { type: "string" } },
83
+ },
84
+ consent: {
85
+ purposes: ["analytics"],
86
+ loadWhen: "all-declared-purposes-eligible",
87
+ unknownState: "block",
88
+ },
89
+ // Same-origin entry loads under the strict base `'self'`; the declared beacon
90
+ // origin is the advanced exact source the compiler folds into `connect-src`.
91
+ csp: { profiles: [], sources: { "connect-src": [DEMO_ANALYTICS_BEACON_ORIGIN] } },
92
+ permissions: { events: ["storefront.page.viewed.v1"], data: [], actions: [], domIntent: "none" },
93
+ performanceBudget: {
94
+ maxTransferredBytes: 20000,
95
+ maxAdditionalRequests: 1,
96
+ maxMainThreadMilliseconds: 20,
97
+ mustBeAsyncOrDeferred: true,
98
+ },
99
+ },
100
+ server: { topics: [], secretRequirements: [] },
101
+ assurance: { requestedClassification: "baseline", regulatedTenantDefault: "disabled-until-certified" },
102
+ configurationMigrations: [],
103
+ };
104
+
105
+ /**
106
+ * The demo tenant-local declaration seeded on the unregulated marketing demo tenants.
107
+ * `materializedAssets` names the committed same-origin entry module, so the resolver's
108
+ * fail-closed materialized-asset check passes without any R2/publish step.
109
+ */
110
+ export const DEMO_ANALYTICS_DECLARATION: IntegrationDeclarationInput = {
111
+ origin: "tenant-local",
112
+ ref: "config/tenants:demo-analytics",
113
+ manifest: DEMO_ANALYTICS_MANIFEST,
114
+ publicConfig: { siteId: "tot-demo" },
115
+ materializedAssets: [DEMO_ANALYTICS_ENTRY_URL],
116
+ };
@@ -81,6 +81,124 @@ export function breadcrumbLd(
81
81
  };
82
82
  }
83
83
 
84
+ /** Words in rendered HTML — tags/entities stripped. Feeds `BlogPosting.wordCount`. */
85
+ export function wordCount(html: string): number {
86
+ const text = html
87
+ .replace(/<[^>]+>/g, " ")
88
+ .replace(/&[a-z#0-9]+;/gi, " ");
89
+ return text.match(/\S+/g)?.length ?? 0;
90
+ }
91
+
92
+ /** The subset of a blog post `blogPostingLd` reads — kept structural so the
93
+ * builder doesn't couple `jsonld.ts` to the blog module. */
94
+ export interface BlogPostingInput {
95
+ title: string;
96
+ description: string;
97
+ publishedAt: string;
98
+ modifiedAt: string;
99
+ author: string;
100
+ categories: string[];
101
+ tags: string[];
102
+ contentHtml: string;
103
+ inLanguage?: string;
104
+ featuredImage?: { src: string; alt?: string; width?: number; height?: number };
105
+ }
106
+
107
+ /**
108
+ * Enriched `BlogPosting` graph (B1.6): adds `wordCount`, `articleSection`,
109
+ * `keywords`, `inLanguage` (default "en"), an `author.url`, and an `ImageObject`
110
+ * `image` with dimensions — on top of the baseline
111
+ * headline/description/dates/publisher.
112
+ */
113
+ export function blogPostingLd(
114
+ post: BlogPostingInput,
115
+ opts: { url: string; canonicalBase: string; publisherName: string; authorUrl?: string },
116
+ ) {
117
+ const { url, canonicalBase, publisherName, authorUrl } = opts;
118
+ const image = post.featuredImage
119
+ ? {
120
+ "@type": "ImageObject",
121
+ url: new URL(post.featuredImage.src, canonicalBase + "/").toString(),
122
+ ...(post.featuredImage.alt ? { caption: post.featuredImage.alt } : {}),
123
+ ...(post.featuredImage.width ? { width: post.featuredImage.width } : {}),
124
+ ...(post.featuredImage.height ? { height: post.featuredImage.height } : {}),
125
+ }
126
+ : undefined;
127
+ return {
128
+ "@context": "https://schema.org",
129
+ "@type": "BlogPosting",
130
+ headline: post.title,
131
+ description: post.description,
132
+ url,
133
+ mainEntityOfPage: url,
134
+ datePublished: post.publishedAt,
135
+ dateModified: post.modifiedAt,
136
+ author: {
137
+ "@type": "Person",
138
+ name: post.author,
139
+ ...(authorUrl ? { url: authorUrl } : {}),
140
+ },
141
+ publisher: { "@type": "Organization", name: publisherName, url: canonicalBase },
142
+ wordCount: wordCount(post.contentHtml),
143
+ ...(post.categories[0] ? { articleSection: post.categories[0] } : {}),
144
+ ...(post.tags.length ? { keywords: post.tags.join(", ") } : {}),
145
+ inLanguage: post.inLanguage ?? "en",
146
+ ...(image ? { image } : {}),
147
+ };
148
+ }
149
+
150
+ /**
151
+ * `CollectionPage` + embedded `ItemList` for a category/tag/author archive
152
+ * (B1.2/B1.3 opt in — this composes with them without requiring their routes
153
+ * exist yet). `items` are already absolute URLs.
154
+ */
155
+ export function collectionPageLd(opts: {
156
+ name: string;
157
+ url: string;
158
+ description?: string;
159
+ items: { title: string; url: string }[];
160
+ }) {
161
+ return {
162
+ "@context": "https://schema.org",
163
+ "@type": "CollectionPage",
164
+ name: opts.name,
165
+ url: opts.url,
166
+ ...(opts.description ? { description: opts.description } : {}),
167
+ mainEntity: {
168
+ "@type": "ItemList",
169
+ numberOfItems: opts.items.length,
170
+ itemListElement: opts.items.map((it, i) => ({
171
+ "@type": "ListItem",
172
+ position: i + 1,
173
+ name: it.title,
174
+ url: it.url,
175
+ })),
176
+ },
177
+ };
178
+ }
179
+
180
+ /**
181
+ * `Person` graph for an author page (B1.3) — the E-E-A-T signal Google weights
182
+ * for author authority. `sameAs` carries the author's social-profile URLs.
183
+ */
184
+ export function personLd(opts: {
185
+ name: string;
186
+ url?: string;
187
+ description?: string;
188
+ sameAs?: string[];
189
+ image?: string;
190
+ }) {
191
+ return {
192
+ "@context": "https://schema.org",
193
+ "@type": "Person",
194
+ name: opts.name,
195
+ ...(opts.url ? { url: opts.url } : {}),
196
+ ...(opts.description ? { description: opts.description } : {}),
197
+ ...(opts.sameAs && opts.sameAs.length ? { sameAs: opts.sameAs } : {}),
198
+ ...(opts.image ? { image: opts.image } : {}),
199
+ };
200
+ }
201
+
84
202
  export function productLd(
85
203
  p: CatalogProduct,
86
204
  tenant: TenantConfig,
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Shopper membership eligibility — the request-scoped seam that resolves whether
3
- * the current shopper is a member, and which tier (F10).
3
+ * the current shopper is a member, and which tier.
4
4
  *
5
5
  * Phase 1 storefronts have NO shopper-login/account source (member accounts are
6
6
  * a Phase-2 managed-checkout capability), so this resolves anonymous
@@ -11,8 +11,7 @@
11
11
  * a tier explicitly asserts `real: true`, the widget marks its figures as
12
12
  * illustrative ("e.g." affordance + a group-level "Illustrative figures" label)
13
13
  * so example numbers are never presented as a live offer. This mirrors the
14
- * platform-owned / never-faked discipline of the compliance widgets (decision
15
- * `compliance-widgets-platform-owned`).
14
+ * platform-owned / never-faked discipline of the compliance widgets.
16
15
  */
17
16
 
18
17
  /**
@@ -1,21 +1,21 @@
1
1
  /**
2
- * Monitoring contract (spec §F16 — monitors, alerts, operator runbooks).
2
+ * Monitoring contract (monitors, alerts, operator runbooks).
3
3
  *
4
4
  * This is the CHECKED-IN source of truth for "what do we watch, at what
5
5
  * threshold, at what severity, and which runbook fires when it trips." It is
6
- * deliberately data, not wiring: Phase 1 ships the *contract* so operators can
6
+ * deliberately data, not wiring: this file ships the *contract* so operators can
7
7
  * see coverage and reviewers can diff it; the actual alert providers (Cloudflare
8
8
  * Health Checks / Workers metrics / Logpush alerts / a RUM sink) are provisioned
9
- * out-of-band and each monitor records whether it is `in-code` today or still
9
+ * out-of-band and each monitor records whether it is `in-code` or still
10
10
  * `needs-external` / `needs-secret`.
11
11
  *
12
12
  * Signal sources are named against real code where it exists in this repo
13
13
  * (`/health` → lib/health.ts, CSP → pages/api/csp-report.ts + CSP_REPORT_PATH,
14
14
  * commerce events → lib/analytics). Signals owned by sibling units are referenced
15
- * by CONTRACT NAME, not imported — Core Web Vitals come from F14's RUM beacon,
16
- * and age-verification / restricted-state denials come from F12's compliance
17
- * evidence signals. This file does not edit or depend on those units; when they
18
- * land, point the corresponding monitor's `observe` at the real sink.
15
+ * by CONTRACT NAME, not imported — Core Web Vitals come from the RUM beacon,
16
+ * and age-verification / restricted-state denials come from the compliance
17
+ * evidence signals. This file does not edit or depend on those units; point the
18
+ * corresponding monitor's `observe` at the real sink where one exists.
19
19
  *
20
20
  * The companion operator doc renders this for humans and lists the external
21
21
  * wiring/secrets checklist: docs/epics/sample-store-migration/monitoring-and-runbooks.md.
@@ -89,9 +89,9 @@ export interface Monitor {
89
89
  }
90
90
 
91
91
  /**
92
- * The ten launch-critical monitors from spec §F16. Order is presentation order.
93
- * Thresholds are the go-live defaults; tune against the 24h post-cutover soak
94
- * (T10) and record any change here — this file is the audit trail.
92
+ * The ten launch-critical monitors. Order is presentation order.
93
+ * Thresholds are defaults; tune against the 24h post-cutover soak
94
+ * and record any change here — this file is the audit trail.
95
95
  */
96
96
  export const MONITORS: readonly Monitor[] = [
97
97
  {
@@ -264,7 +264,7 @@ export const MONITORS: readonly Monitor[] = [
264
264
  ] as const;
265
265
 
266
266
  /**
267
- * The monitors §F16 requires by name. The test asserts MONITORS covers exactly
267
+ * The monitors this contract requires by name. The test asserts MONITORS covers exactly
268
268
  * these — so dropping or misnaming one fails CI, and adding a new monitor is a
269
269
  * deliberate edit here.
270
270
  */
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Double-opt-in confirmation mail — STUB.
3
+ *
4
+ * The storefront Worker sends no email itself: every existing "email" flow is
5
+ * delegated over HTTP to tot20, and there is no bulk/marketing sender in-repo
6
+ * (docs/plans/2026-08-22-newsletter-send-spike.md §1). Wiring the real send is
7
+ * the ESP-pipeline's job — it replaces the body of this function with a
8
+ * transactional send (confirm link in the body). Until then we only LOG intent,
9
+ * and never let a send failure fail the subscribe (the pending row + returned
10
+ * token are the durable state; the mail is a follow-up).
11
+ */
12
+
13
+ export interface ConfirmationEmailRequest {
14
+ email: string;
15
+ collection: string;
16
+ /** Absolute confirm URL the recipient clicks: `…/api/newsletter/confirm?token=…`. */
17
+ confirmUrl: string;
18
+ }
19
+
20
+ /**
21
+ * N4 REPLACES THIS with a real ESP send. Today: log the intent and return.
22
+ * Best-effort by contract — callers do not await deliverability, and this never
23
+ * throws.
24
+ */
25
+ export async function sendConfirmationEmail(req: ConfirmationEmailRequest): Promise<void> {
26
+ console.log(
27
+ `[newsletter] confirmation email STUB — would send to ${req.email} ` +
28
+ `(collection: ${req.collection}) confirm: ${req.confirmUrl}`,
29
+ );
30
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Consent-record primitives for the newsletter double-opt-in flow.
3
+ *
4
+ * `randomToken` mints the opaque per-subscriber secret that both the confirm and
5
+ * unsubscribe links carry — Web Crypto only (no `node:*`) so it runs
6
+ * identically in the Worker and in tests. `hashConsentIp` is the GDPR-safe IP
7
+ * record: we store `sha256(ip + ":" + salt)`, NEVER the raw IP (repo convention:
8
+ * opaque hashes only, cf. `apps/orders/customerHash.ts`).
9
+ */
10
+ import { sha256Hex } from "@tot/public-runtime";
11
+
12
+ /** 32 bytes of CSPRNG entropy, hex-encoded — an opaque, unguessable link token. */
13
+ export function randomToken(): string {
14
+ const bytes = crypto.getRandomValues(new Uint8Array(32));
15
+ let hex = "";
16
+ for (const b of bytes) hex += b.toString(16).padStart(2, "0");
17
+ return hex;
18
+ }
19
+
20
+ /** Salted one-way hash of the client IP — the consent record's IP evidence. */
21
+ export function hashConsentIp(ip: string, salt: string): Promise<string> {
22
+ return sha256Hex(`${ip}:${salt}`);
23
+ }