@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,227 @@
1
+ /**
2
+ * Copy the one command. Two behaviours:
3
+ * · fastpath (signed-in dev): mint a single-use `tot login --code … && tot start` from
4
+ * /api/dev/cli-signin-code, reveal it (textContent, never innerHTML — it carries a
5
+ * live code), and copy the whole thing.
6
+ * · otherwise: copy the generic install-and-run command directly.
7
+ *
8
+ * Also drives rendezvous approval: after a command is generated, the
9
+ * terminal ATTACHES its own PKCE key and prints a fingerprint; the developer
10
+ * confirms it here — the load-bearing anti-interception step, since
11
+ * approving the wrong fingerprint is how a hijack is caught.
12
+ *
13
+ * Imported from a processed `<script>` in cockpit.astro. The values below are
14
+ * carried as data-attrs on #copyCmd because this module runs standalone (not
15
+ * inside the same closure as hostedActivity.ts's basePath).
16
+ */
17
+ export function initCopyCommand(): void {
18
+ const btn: any = document.getElementById("copyCmd");
19
+ const textEl = document.getElementById("cli-cmd-text");
20
+ const note = document.getElementById("cli-cmd-note");
21
+ const toast = document.getElementById("toast");
22
+ const toastMsg = document.getElementById("toastMsg");
23
+ const copyIcon: any = document.getElementById("copyIcon");
24
+ if (!btn || !textEl) return;
25
+ const generic = btn.getAttribute("data-generic") || "";
26
+ const fastpath = btn.getAttribute("data-fastpath") === "1";
27
+ // The request's tenant prefix ("" host-routed, "/<tenant>" path-routed). Carried
28
+ // as a data-attr because `basePath` is otherwise defined only inside the SEPARATE
29
+ // hostedActivity module (hostedActivity.ts) — referencing it here (the
30
+ // cli-signin-code / -status / -approve fetches below) was a ReferenceError that
31
+ // the mint's catch surfaced as the opaque "Couldn't reach the sign-in service"
32
+ // with no request ever sent.
33
+ const basePath = btn.getAttribute("data-base-path") || "";
34
+ let tT: ReturnType<typeof setTimeout>;
35
+ function ping(m: string) {
36
+ if (!toast) return;
37
+ if (toastMsg) toastMsg.textContent = m;
38
+ toast.classList.add("show");
39
+ clearTimeout(tT); tT = setTimeout(() => { toast.classList.remove("show"); }, 1900);
40
+ }
41
+ function copy(text: string): Promise<boolean> {
42
+ if (navigator.clipboard) return navigator.clipboard.writeText(text).then(() => true).catch(() => false);
43
+ return Promise.resolve(false);
44
+ }
45
+ function label(s: string) { btn.childNodes[btn.childNodes.length - 1].textContent = s; }
46
+
47
+ // Standard copy-icon affordance on the terminal box. Once the command is
48
+ // revealed, this is the obvious, always-there way to (re)copy it — the
49
+ // icon→check swap is its own inline confirmation, so copying no longer
50
+ // depends on the transient toast being noticed.
51
+ let iconT: ReturnType<typeof setTimeout>;
52
+ function flashCopied() {
53
+ if (!copyIcon) return;
54
+ copyIcon.setAttribute("data-copied", "1");
55
+ copyIcon.setAttribute("aria-label", "Copied");
56
+ copyIcon.setAttribute("title", "Copied");
57
+ clearTimeout(iconT);
58
+ iconT = setTimeout(() => {
59
+ copyIcon.removeAttribute("data-copied");
60
+ copyIcon.setAttribute("aria-label", "Copy the command");
61
+ copyIcon.setAttribute("title", "Copy the command");
62
+ }, 1600);
63
+ }
64
+ function revealIcon() {
65
+ if (copyIcon) copyIcon.hidden = false;
66
+ }
67
+ if (copyIcon) {
68
+ copyIcon.addEventListener("click", () => {
69
+ copy(textEl.textContent || "").then((ok) => {
70
+ if (ok) { flashCopied(); ping("Copied — paste & press Enter"); }
71
+ else ping("Select the command above to copy");
72
+ });
73
+ });
74
+ }
75
+
76
+ // ── Rendezvous approval: after a command is generated, the terminal ATTACHES
77
+ // its own PKCE key and prints a fingerprint; the developer confirms it HERE. This
78
+ // is the load-bearing anti-interception step — approving the wrong fingerprint is
79
+ // how a hijack is caught, so the confirm is an explicit, human decision.
80
+ const rzvRoot: any = document.getElementById("rzvApprove");
81
+ const rzvWait: any = document.getElementById("rzvWait");
82
+ const rzvConfirm: any = document.getElementById("rzvConfirm");
83
+ const rzvFp: any = document.getElementById("rzvFp");
84
+ const rzvApproveBtn: any = document.getElementById("rzvApproveBtn");
85
+ const rzvDenyBtn: any = document.getElementById("rzvDenyBtn");
86
+ const rzvDone: any = document.getElementById("rzvDone");
87
+ let rzvTimer: ReturnType<typeof setTimeout> | null = null;
88
+ let rzvCode: string | null = null;
89
+ let rzvDecided = false;
90
+ function rzvShow(el: any) { if (el) el.hidden = false; }
91
+ function rzvHide(el: any) { if (el) el.hidden = true; }
92
+ // Once the terminal has ATTACHED, the command has plainly been pasted and
93
+ // run — hide the copy affordances so the approve prompt is the page's
94
+ // single focus (DZ 2026-08-18). An EXPIRED sign-in restores the generate
95
+ // button (a fresh mint is needed); the stale command's copy icon stays gone.
96
+ function rzvHideCopyCtas() {
97
+ if (btn) btn.hidden = true;
98
+ if (copyIcon) copyIcon.hidden = true;
99
+ }
100
+ function rzvRestoreGenerate() {
101
+ if (btn) btn.hidden = false;
102
+ }
103
+ function rzvStopPoll() { if (rzvTimer) { clearTimeout(rzvTimer); rzvTimer = null; } }
104
+ function rzvFinish(msg: string) {
105
+ rzvStopPoll(); rzvDecided = true;
106
+ rzvHide(rzvWait); rzvHide(rzvConfirm);
107
+ if (rzvDone) { rzvDone.textContent = msg; rzvDone.hidden = false; }
108
+ }
109
+ async function rzvPoll(): Promise<void> {
110
+ if (rzvDecided) return;
111
+ let r: Response, b: any;
112
+ try {
113
+ r = await fetch(basePath + "/api/dev/cli-signin-status", {
114
+ method: "POST", headers: { "content-type": "application/json" },
115
+ body: JSON.stringify({ rendezvousCode: rzvCode }),
116
+ });
117
+ b = await r.json().catch(() => ({}));
118
+ } catch (e) { rzvTimer = setTimeout(rzvPoll, 2800); return; }
119
+ if (!r || !r.ok) { rzvTimer = setTimeout(rzvPoll, 3200); return; }
120
+ if (b.state === "attached" && b.fingerprint) {
121
+ rzvHideCopyCtas();
122
+ rzvHide(rzvWait); rzvShow(rzvConfirm);
123
+ if (rzvFp) { rzvFp.textContent = b.fingerprint; rzvFp.setAttribute("data-fp", b.fingerprint); }
124
+ return; // stop polling — wait for the human decision
125
+ }
126
+ if (b.state === "approved") { rzvHideCopyCtas(); rzvFinish("Signed in ✓ — your terminal is good to go."); return; }
127
+ if (b.state === "denied") { rzvHideCopyCtas(); rzvFinish("Rejected — that terminal wasn't approved. You're safe; generate a fresh command to try again."); return; }
128
+ if (b.state === "expired") { rzvRestoreGenerate(); rzvFinish("This sign-in expired. Generate a fresh setup command above."); return; }
129
+ rzvTimer = setTimeout(rzvPoll, 2500); // pending → keep watching
130
+ }
131
+ function rzvStart(code: string) {
132
+ rzvCode = code; rzvDecided = false;
133
+ if (rzvApproveBtn) rzvApproveBtn.disabled = false;
134
+ if (rzvDenyBtn) rzvDenyBtn.disabled = false;
135
+ rzvShow(rzvRoot); rzvShow(rzvWait); rzvHide(rzvConfirm); rzvHide(rzvDone);
136
+ rzvStopPoll(); rzvPoll();
137
+ }
138
+ async function rzvDecide(decision: string): Promise<void> {
139
+ if (rzvDecided) return;
140
+ const fp = rzvFp ? (rzvFp.getAttribute("data-fp") || "") : "";
141
+ if (rzvApproveBtn) rzvApproveBtn.disabled = true;
142
+ if (rzvDenyBtn) rzvDenyBtn.disabled = true;
143
+ let r: Response;
144
+ try {
145
+ r = await fetch(basePath + "/api/dev/cli-signin-approve", {
146
+ method: "POST", headers: { "content-type": "application/json" },
147
+ body: JSON.stringify({ rendezvousCode: rzvCode, fingerprint: fp, decision: decision }),
148
+ });
149
+ } catch (e) {
150
+ if (rzvApproveBtn) rzvApproveBtn.disabled = false;
151
+ if (rzvDenyBtn) rzvDenyBtn.disabled = false;
152
+ return;
153
+ }
154
+ if (decision === "deny") { rzvFinish("Rejected — that terminal wasn't approved."); return; }
155
+ if (r.ok) { rzvFinish("Signed in ✓ — your terminal is good to go."); return; }
156
+ if (rzvApproveBtn) rzvApproveBtn.disabled = false;
157
+ if (rzvDenyBtn) rzvDenyBtn.disabled = false;
158
+ const m = r.status === 403 ? "That didn't match your identity — generate a fresh command and try again."
159
+ : r.status === 409 ? "That code didn't match a waiting terminal — re-check it, or generate a fresh command."
160
+ : "Couldn't complete approval — try again.";
161
+ if (rzvDone) { rzvDone.textContent = m; rzvDone.hidden = false; }
162
+ }
163
+ if (rzvApproveBtn) rzvApproveBtn.addEventListener("click", () => { rzvDecide("approve"); });
164
+ if (rzvDenyBtn) rzvDenyBtn.addEventListener("click", () => { rzvDecide("deny"); });
165
+
166
+ if (!fastpath) {
167
+ btn.addEventListener("click", () => {
168
+ copy(generic).then((ok) => {
169
+ label(ok ? " Copied — paste & press Enter" : " Copy the command");
170
+ ping(ok ? "Copied the command" : "Select the command to copy");
171
+ setTimeout(() => { label(" Copy the command"); }, 2600);
172
+ });
173
+ });
174
+ return;
175
+ }
176
+
177
+ let busy = false;
178
+ btn.addEventListener("click", async () => {
179
+ if (busy) return;
180
+ busy = true;
181
+ label(" …"); btn.disabled = true;
182
+ let res: Response, body: any;
183
+ try {
184
+ res = await fetch(basePath + "/api/dev/cli-signin-code", {
185
+ method: "POST",
186
+ headers: { "content-type": "application/json" },
187
+ body: "{}",
188
+ });
189
+ body = await res.json().catch(() => ({}));
190
+ } catch (err) {
191
+ if (note) note.textContent = "Couldn't reach the sign-in service — try again in a moment.";
192
+ label(" Copy the command"); btn.disabled = false; busy = false;
193
+ return;
194
+ }
195
+ if (!res.ok || !body.command) {
196
+ const byStatus: Record<number, string> = {
197
+ 401: "Your session expired — reload the page and sign in again.",
198
+ 403: "This account doesn't have developer access to a store yet.",
199
+ 409: "Your store isn't set up yet — reload this page for its status.",
200
+ 502: "The sign-in service is having a moment — try again.",
201
+ 503: "Terminal sign-in isn't configured on this environment.",
202
+ };
203
+ if (note) note.textContent = byStatus[res.status] || "Couldn't mint a sign-in command — try again.";
204
+ label(" Copy the command"); btn.disabled = false; busy = false;
205
+ return;
206
+ }
207
+ // Reveal the real command (carries the non-secret rendezvous handle) as a pure
208
+ // text node, then copy it.
209
+ textEl.textContent = body.command;
210
+ textEl.classList.remove("is-placeholder");
211
+ revealIcon();
212
+ // Start watching for the terminal to attach so we can prompt for approval.
213
+ if (body.rendezvousCode) rzvStart(body.rendezvousCode);
214
+ const ok = await copy(body.command);
215
+ if (ok) flashCopied();
216
+ label(ok ? " Copied ✓" : " Select & copy");
217
+ ping(ok ? "Copied — paste & press Enter" : "Select the command above to copy");
218
+ if (note) {
219
+ note.textContent = ok
220
+ ? "Copied. Paste into your terminal and press Enter — it signs you in, runs your store, and opens your browser. Single-use, short-lived code."
221
+ : "Select the command above and copy it, then paste into your terminal and press Enter. Single-use, short-lived code.";
222
+ }
223
+ btn.disabled = false;
224
+ setTimeout(() => { label(" Copy the command"); }, 4000);
225
+ busy = false;
226
+ });
227
+ }
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Files tab — in-browser file tree + LIVE EDITOR. Rendered only when
3
+ * isLocalDevLoop; reads /__tot/tree + /__tot/file and writes /__tot/write
4
+ * (dev-plugins/dev-file-browser + dev-write). Writable files (content HTML +
5
+ * theme.json) become an editable textarea with ~600ms debounce autosave +
6
+ * Cmd/Ctrl+S; the save carries the baseVersion so a concurrent
7
+ * $EDITOR/git change is caught (409) instead of clobbered. Dynamic values go
8
+ * through .value / textContent (never innerHTML).
9
+ * Imported from a processed `<script>` in cockpit.astro (ADR 0013). apiBase
10
+ * and isDev are read from `document.body.dataset` (cp-env: same client JS,
11
+ * environment-aware endpoint base — see resolveDevApiBase).
12
+ */
13
+ export function initFiles(): void {
14
+ const apiBase = document.body.dataset.cockpitApiBase || "";
15
+ const isDev = document.body.dataset.cockpitIsDev === "true";
16
+ const offlineMsg = isDev ? "Could not reach the dev server." : "Not available on the hosted panel yet — check back soon.";
17
+ const treeEl: any = document.getElementById("filesTree");
18
+ const viewEl: any = document.getElementById("filesView");
19
+ const pathEl = document.getElementById("filesPath");
20
+ const editbar = document.getElementById("filesEditbar");
21
+ const statusEl: any = document.getElementById("filesStatus");
22
+ const conflictEl = document.getElementById("filesConflict");
23
+ const reloadBtn = document.getElementById("filesReload");
24
+ const forceBtn = document.getElementById("filesForce");
25
+ const diffBtn: any = document.getElementById("filesDiffBtn");
26
+ const diffEl: any = document.getElementById("filesDiff");
27
+ const publishBtn: any = document.getElementById("filesPublishBtn");
28
+ if (!treeEl || !viewEl) return;
29
+ let selected: any = null;
30
+ let cur: { path: string; baseVersion: number | null; writable: boolean } | null = null;
31
+ let saveTimer: ReturnType<typeof setTimeout> | null = null;
32
+ let diffOn = false;
33
+ let rowByPath: Record<string, any> = {}; // path -> tree row element, for programmatic open
34
+
35
+ function setStatus(txt: string, cls?: string) {
36
+ if (!statusEl) return;
37
+ statusEl.textContent = txt || "";
38
+ statusEl.className = "df-status" + (cls ? " " + cls : "");
39
+ }
40
+ function showConflict(show: boolean) { if (conflictEl) (conflictEl as any).hidden = !show; }
41
+ function showBar(show: boolean) { if (editbar) (editbar as any).hidden = !show; }
42
+
43
+ function openFile(path: string, row: any, afterLoad?: () => void) {
44
+ if (selected) selected.classList.remove("sel");
45
+ selected = row; row.classList.add("sel");
46
+ if (pathEl) pathEl.textContent = path;
47
+ showConflict(false); showBar(true);
48
+ setDiffMode(false); if (diffBtn) diffBtn.hidden = true;
49
+ if (publishBtn) publishBtn.hidden = true;
50
+ viewEl.readOnly = true;
51
+ setStatus("Loading…");
52
+ fetch(apiBase + "/file?path=" + encodeURIComponent(path))
53
+ .then((r) => r.json())
54
+ .then((d) => {
55
+ if (!d || !d.ok) { viewEl.value = ""; cur = null; setStatus((d && d.message) || "Could not open that file.", "warn"); return; }
56
+ if (d.binary) { viewEl.value = "(binary file — " + (d.size || 0) + " bytes)"; cur = null; setStatus("Binary — not editable"); return; }
57
+ if (d.tooBig) { viewEl.value = "(file too large to show — " + (d.size || 0) + " bytes)"; cur = null; setStatus("Too large — not editable"); return; }
58
+ viewEl.value = d.content == null ? "" : d.content;
59
+ cur = { path: path, baseVersion: (typeof d.mtimeMs === "number" ? d.mtimeMs : null), writable: !!d.writable };
60
+ viewEl.readOnly = !cur.writable;
61
+ if (diffBtn) diffBtn.hidden = false;
62
+ if (publishBtn) publishBtn.hidden = !cur.writable;
63
+ setStatus(cur.writable ? "Editable — edits save + reload your store" : "Read-only");
64
+ if (typeof afterLoad === "function") afterLoad();
65
+ })
66
+ .catch(() => { viewEl.value = ""; cur = null; setStatus(offlineMsg, "warn"); });
67
+ }
68
+
69
+ // Place the textarea caret at a 1-based line:col and scroll it into view. Used by
70
+ // the click-to-source jump; a textarea has no CodeMirror EditorView, so we map
71
+ // (line,col) to a character offset + setSelectionRange, then center by scrollTop.
72
+ function placeCursor(line: number, col: number) {
73
+ const text = viewEl.value;
74
+ const lines = text.split("\n");
75
+ const ln = Math.min(Math.max(1, line || 1), lines.length);
76
+ let offset = 0;
77
+ for (let i = 0; i < ln - 1; i++) offset += lines[i].length + 1; // +1 for the newline
78
+ offset += Math.min(Math.max(1, col || 1), (lines[ln - 1] || "").length + 1) - 1;
79
+ viewEl.focus();
80
+ try { viewEl.setSelectionRange(offset, offset); } catch (e) { /* not focusable yet */ }
81
+ // Center the target line: approximate line height from the rendered content.
82
+ const lh = viewEl.scrollHeight / Math.max(1, lines.length);
83
+ viewEl.scrollTop = Math.max(0, (ln - 1) * lh - viewEl.clientHeight / 2);
84
+ }
85
+
86
+ // Capstone entry point: open <path> and drop the caret at line:col. Invoked by
87
+ // the cockpit's origin-checked tot:locate listener when a click lands in the
88
+ // live-preview iframe. Finds the file's tree row (built by renderNodes); if the
89
+ // tree hasn't loaded yet, no-ops gracefully.
90
+ (window as any).__totOpenFileAt = function (path: string, line: number, col: number) {
91
+ const row = rowByPath[path];
92
+ if (!row) return false;
93
+ if (typeof row.scrollIntoView === "function") row.scrollIntoView({ block: "nearest" });
94
+ openFile(path, row, () => { placeCursor(line, col); });
95
+ return true;
96
+ };
97
+
98
+ function doSave(force?: boolean) {
99
+ if (!cur || !cur.writable) return;
100
+ setStatus("Saving…");
101
+ const body: any = { path: cur.path, content: viewEl.value };
102
+ if (!force && typeof cur.baseVersion === "number") body.baseVersion = cur.baseVersion;
103
+ fetch(apiBase + "/write", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) })
104
+ .then((r) => r.json().then((j) => ({ s: r.status, j: j })))
105
+ .then((res) => {
106
+ if (res.s === 200 && res.j && res.j.ok) { cur!.baseVersion = res.j.mtimeMs; showConflict(false); setStatus("Saved ✓", "ok"); return; }
107
+ if (res.s === 409) { showConflict(true); setStatus("Changed on disk since you opened it", "warn"); return; }
108
+ if (res.s === 403) { setStatus("This file isn't editable.", "warn"); return; }
109
+ setStatus((res.j && res.j.message) || "Save failed", "warn");
110
+ })
111
+ .catch(() => { setStatus(isDev ? "Save failed — dev server unreachable" : offlineMsg, "warn"); });
112
+ }
113
+
114
+ viewEl.addEventListener("input", () => {
115
+ if (!cur || !cur.writable) return;
116
+ setStatus("Editing…");
117
+ if (saveTimer) clearTimeout(saveTimer);
118
+ saveTimer = setTimeout(() => { doSave(false); }, 600);
119
+ });
120
+ viewEl.addEventListener("keydown", (e: KeyboardEvent) => {
121
+ if ((e.metaKey || e.ctrlKey) && (e.key === "s" || e.key === "S")) {
122
+ e.preventDefault();
123
+ if (saveTimer) clearTimeout(saveTimer);
124
+ doSave(false);
125
+ }
126
+ });
127
+ if (reloadBtn) reloadBtn.addEventListener("click", () => { if (cur && selected) openFile(cur.path, selected); });
128
+ if (forceBtn) forceBtn.addEventListener("click", () => { showConflict(false); doSave(true); });
129
+
130
+ function setDiffMode(on: boolean) {
131
+ diffOn = on;
132
+ if (diffEl) diffEl.hidden = !on;
133
+ viewEl.hidden = on;
134
+ if (diffBtn) diffBtn.textContent = on ? "Edit" : "Diff";
135
+ }
136
+ function renderDiffText(t: string) { if (diffEl) diffEl.textContent = t; }
137
+ function lineDiff(before: string, after: string): [string, string][] | null {
138
+ const a = before.split("\n"), b = after.split("\n");
139
+ const m = a.length, n = b.length;
140
+ if (m * n > 4000000) return null;
141
+ const dp: number[][] = []; for (let i = 0; i <= m; i++) { dp.push(new Array(n + 1).fill(0)); }
142
+ for (let i = m - 1; i >= 0; i--) for (let j = n - 1; j >= 0; j--) dp[i]![j] = a[i] === b[j] ? dp[i + 1]![j + 1]! + 1 : (dp[i + 1]![j]! >= dp[i]![j + 1]! ? dp[i + 1]![j]! : dp[i]![j + 1]!);
143
+ const out: [string, string][] = []; let x = 0, y = 0;
144
+ while (x < m && y < n) {
145
+ if (a[x] === b[y]) { out.push([" ", a[x]!]); x++; y++; }
146
+ else if (dp[x + 1]![y]! >= dp[x]![y + 1]!) { out.push(["-", a[x]!]); x++; }
147
+ else { out.push(["+", b[y]!]); y++; }
148
+ }
149
+ while (x < m) { out.push(["-", a[x]!]); x++; }
150
+ while (y < n) { out.push(["+", b[y]!]); y++; }
151
+ return out;
152
+ }
153
+ function renderDiff(before: string, after: string) {
154
+ if (!diffEl) return;
155
+ diffEl.textContent = "";
156
+ const rows = lineDiff(before, after);
157
+ if (!rows) { renderDiffText("(file too large to diff)"); return; }
158
+ const frag = document.createDocumentFragment();
159
+ rows.forEach((row) => {
160
+ const ln = document.createElement("span");
161
+ ln.className = "dl " + (row[0] === "+" ? "add" : row[0] === "-" ? "del" : "ctx");
162
+ ln.textContent = row[0] + " " + row[1];
163
+ frag.appendChild(ln);
164
+ });
165
+ diffEl.appendChild(frag);
166
+ }
167
+ function doDiff() {
168
+ if (!cur) return;
169
+ if (diffOn) { setDiffMode(false); setStatus(cur.writable ? "Editable" : "Read-only"); return; }
170
+ setStatus("Loading diff…");
171
+ fetch(apiBase + "/diff?path=" + encodeURIComponent(cur.path))
172
+ .then((r) => r.json())
173
+ .then((d) => {
174
+ if (!d || !d.ok) { setStatus((d && d.message) || "Could not diff.", "warn"); return; }
175
+ if (!d.shown) { renderDiffText("(diff not shown — " + (d.reason || "") + ")"); setDiffMode(true); setStatus(d.status); return; }
176
+ renderDiff(d.before || "", d.after || "");
177
+ setDiffMode(true);
178
+ setStatus(d.status === "unchanged" ? "No changes vs your last commit" : (d.status + " vs HEAD"));
179
+ })
180
+ .catch(() => { setStatus(offlineMsg, "warn"); });
181
+ }
182
+ if (diffBtn) diffBtn.addEventListener("click", doDiff);
183
+
184
+ // cp-publish: draft -> PR-backed candidate for review — never straight to
185
+ // live, and no longer straight to the test channel either; it opens/updates
186
+ // a pull request an owner reviews and accepts. Confirm-before-submit.
187
+ function doPublish() {
188
+ if (!cur || !cur.writable || !publishBtn) return;
189
+ if (!window.confirm("Submit your saved edit for review? (Opens/updates a pull request — not your live site.)")) return;
190
+ const prevLabel = publishBtn.textContent;
191
+ publishBtn.disabled = true;
192
+ setStatus("Submitting…");
193
+ fetch(apiBase + "/publish", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ path: cur.path }) })
194
+ .then((r) => r.json().then((j) => ({ s: r.status, j: j })))
195
+ .then((res) => {
196
+ if (res.s === 200 && res.j && res.j.ok) { setStatus("Submitted for review ✓" + (res.j.prNumber ? " (PR #" + res.j.prNumber + ")" : ""), "ok"); return; }
197
+ if (res.s === 409 && res.j && res.j.status === "no_draft") { setStatus("No unpublished edit to submit.", "warn"); return; }
198
+ setStatus((res.j && res.j.message) || "Submit failed", "warn");
199
+ })
200
+ .catch(() => { setStatus(offlineMsg, "warn"); })
201
+ .then(() => { publishBtn.disabled = false; publishBtn.textContent = prevLabel; });
202
+ }
203
+ if (publishBtn) publishBtn.addEventListener("click", doPublish);
204
+
205
+ function renderNodes(nodes: any[], parentUl: any, depth: number) {
206
+ nodes.forEach((n) => {
207
+ const li = document.createElement("li");
208
+ li.className = "ft-" + n.type;
209
+ const row: any = document.createElement("div");
210
+ row.className = "ft-row";
211
+ row.style.paddingLeft = (depth * 12 + 10) + "px";
212
+ const icon = document.createElement("span");
213
+ icon.className = "ft-ic";
214
+ icon.textContent = n.type === "dir" ? "📁" : "📄";
215
+ const label = document.createElement("span");
216
+ label.className = "ft-name";
217
+ label.textContent = n.name;
218
+ row.appendChild(icon); row.appendChild(label); li.appendChild(row);
219
+ if (n.type === "dir") {
220
+ const childUl = document.createElement("ul");
221
+ childUl.className = "ft-children";
222
+ renderNodes(n.children || [], childUl, depth + 1);
223
+ li.appendChild(childUl);
224
+ } else {
225
+ row.tabIndex = 0;
226
+ rowByPath[n.path] = row; // for the programmatic jump
227
+ row.addEventListener("click", () => { openFile(n.path, row); });
228
+ row.addEventListener("keydown", (e: KeyboardEvent) => { if (e.key === "Enter") { e.preventDefault(); openFile(n.path, row); } });
229
+ }
230
+ parentUl.appendChild(li);
231
+ });
232
+ }
233
+
234
+ function load() {
235
+ fetch(apiBase + "/tree")
236
+ .then((r) => r.json())
237
+ .then((d) => {
238
+ treeEl.textContent = "";
239
+ rowByPath = {}; // rebuild the path→row index for this fresh tree
240
+ if (!d || !d.ok) { treeEl.textContent = (d && d.message) || "Could not load your files."; return; }
241
+ const ul = document.createElement("ul");
242
+ ul.className = "ft-root";
243
+ renderNodes(d.tree || [], ul, 0);
244
+ treeEl.appendChild(ul);
245
+ })
246
+ .catch(() => { treeEl.textContent = offlineMsg; });
247
+ }
248
+ load();
249
+ }