@tokenoftrust/storefront-runner 2.0.2 → 2.0.4

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 (254) hide show
  1. package/apps/storefront/.astro/content.d.ts +159 -0
  2. package/apps/storefront/.astro/integrations/_astrojs_cloudflare/cloudflare.d.ts +1 -0
  3. package/apps/storefront/.astro/types.d.ts +3 -0
  4. package/apps/storefront/node_modules/.bin/acorn +43 -0
  5. package/apps/storefront/node_modules/.bin/astro +43 -0
  6. package/apps/storefront/node_modules/.bin/astro-check +43 -0
  7. package/apps/storefront/node_modules/.bin/browserslist +43 -0
  8. package/apps/storefront/node_modules/.bin/cf-wrangler +43 -0
  9. package/apps/storefront/node_modules/.bin/depcruise +43 -0
  10. package/apps/storefront/node_modules/.bin/depcruise-baseline +43 -0
  11. package/apps/storefront/node_modules/.bin/depcruise-fmt +43 -0
  12. package/apps/storefront/node_modules/.bin/depcruise-wrap-stream-in-html +43 -0
  13. package/apps/storefront/node_modules/.bin/dependency-cruise +43 -0
  14. package/apps/storefront/node_modules/.bin/dependency-cruiser +43 -0
  15. package/apps/storefront/node_modules/.bin/drizzle-kit +43 -0
  16. package/apps/storefront/node_modules/.bin/esbuild +43 -0
  17. package/apps/storefront/node_modules/.bin/jiti +43 -0
  18. package/apps/storefront/node_modules/.bin/playwright +43 -0
  19. package/apps/storefront/node_modules/.bin/playwright-core +43 -0
  20. package/apps/storefront/node_modules/.bin/prettier +43 -0
  21. package/apps/storefront/node_modules/.bin/rollup +43 -0
  22. package/apps/storefront/node_modules/.bin/tsc +43 -0
  23. package/apps/storefront/node_modules/.bin/tsserver +43 -0
  24. package/apps/storefront/node_modules/.bin/tsx +43 -0
  25. package/apps/storefront/node_modules/.bin/vite +43 -0
  26. package/apps/storefront/node_modules/.bin/vitest +43 -0
  27. package/apps/storefront/node_modules/.bin/workerd +43 -0
  28. package/apps/storefront/node_modules/.bin/wrangler +43 -0
  29. package/apps/storefront/node_modules/.bin/wrangler2 +43 -0
  30. package/apps/storefront/node_modules/.bin/yaml +43 -0
  31. package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_client__js.js +58 -0
  32. package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_client__js.js.map +1 -0
  33. package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_n_@preact_signals.js +741 -0
  34. package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_n_@preact_signals.js.map +1 -0
  35. package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_server__js.js +2549 -0
  36. package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_server__js.js.map +1 -0
  37. package/apps/storefront/node_modules/.vite/deps/_metadata.json +150 -0
  38. package/apps/storefront/node_modules/.vite/deps/astro-BIHuWFxm.js +434 -0
  39. package/apps/storefront/node_modules/.vite/deps/astro-BIHuWFxm.js.map +1 -0
  40. package/apps/storefront/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
  41. package/apps/storefront/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
  42. package/apps/storefront/node_modules/.vite/deps/astro_n_axobject-query.js +2705 -0
  43. package/apps/storefront/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
  44. package/apps/storefront/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
  45. package/apps/storefront/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
  46. package/apps/storefront/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
  47. package/apps/storefront/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
  48. package/apps/storefront/node_modules/.vite/deps/audit-DKDpcdEI.js +1535 -0
  49. package/apps/storefront/node_modules/.vite/deps/audit-DKDpcdEI.js.map +1 -0
  50. package/apps/storefront/node_modules/.vite/deps/highlight-B9UoX1wa.js +48 -0
  51. package/apps/storefront/node_modules/.vite/deps/highlight-B9UoX1wa.js.map +1 -0
  52. package/apps/storefront/node_modules/.vite/deps/icons-BWi2wI9n.js +42 -0
  53. package/apps/storefront/node_modules/.vite/deps/icons-BWi2wI9n.js.map +1 -0
  54. package/apps/storefront/node_modules/.vite/deps/package.json +3 -0
  55. package/apps/storefront/node_modules/.vite/deps/preact.js +310 -0
  56. package/apps/storefront/node_modules/.vite/deps/preact.js.map +1 -0
  57. package/apps/storefront/node_modules/.vite/deps/preact_compat.js +420 -0
  58. package/apps/storefront/node_modules/.vite/deps/preact_compat.js.map +1 -0
  59. package/apps/storefront/node_modules/.vite/deps/preact_compat_jsx-runtime.js +4 -0
  60. package/apps/storefront/node_modules/.vite/deps/preact_debug.js +236 -0
  61. package/apps/storefront/node_modules/.vite/deps/preact_debug.js.map +1 -0
  62. package/apps/storefront/node_modules/.vite/deps/preact_devtools.js +12 -0
  63. package/apps/storefront/node_modules/.vite/deps/preact_devtools.js.map +1 -0
  64. package/apps/storefront/node_modules/.vite/deps/preact_hooks.js +192 -0
  65. package/apps/storefront/node_modules/.vite/deps/preact_hooks.js.map +1 -0
  66. package/apps/storefront/node_modules/.vite/deps/preact_jsx-dev-runtime.js +3 -0
  67. package/apps/storefront/node_modules/.vite/deps/preact_jsx-runtime.js +92 -0
  68. package/apps/storefront/node_modules/.vite/deps/preact_jsx-runtime.js.map +1 -0
  69. package/apps/storefront/node_modules/.vite/deps/preact_test-utils.js +59 -0
  70. package/apps/storefront/node_modules/.vite/deps/preact_test-utils.js.map +1 -0
  71. package/apps/storefront/node_modules/.vite/deps/rolldown-runtime-BPOCksWG.js +24 -0
  72. package/apps/storefront/node_modules/.vite/deps/settings-BVDV0Roj.js +189 -0
  73. package/apps/storefront/node_modules/.vite/deps/settings-BVDV0Roj.js.map +1 -0
  74. package/apps/storefront/node_modules/.vite/deps/static-html-DveYqwMo.js +13 -0
  75. package/apps/storefront/node_modules/.vite/deps/static-html-DveYqwMo.js.map +1 -0
  76. package/apps/storefront/node_modules/.vite/deps/toolbar-B3VIHCXg.js +458 -0
  77. package/apps/storefront/node_modules/.vite/deps/toolbar-B3VIHCXg.js.map +1 -0
  78. package/apps/storefront/node_modules/.vite/deps/ui-library-BK6ricUd.js +1016 -0
  79. package/apps/storefront/node_modules/.vite/deps/ui-library-BK6ricUd.js.map +1 -0
  80. package/apps/storefront/node_modules/.vite/deps/window-BvxDenKN.js +32 -0
  81. package/apps/storefront/node_modules/.vite/deps/window-BvxDenKN.js.map +1 -0
  82. package/apps/storefront/node_modules/.vite/deps/xray-YFiRUU0Z.js +113 -0
  83. package/apps/storefront/node_modules/.vite/deps/xray-YFiRUU0Z.js.map +1 -0
  84. package/apps/storefront/node_modules/.vite/deps_ssr/_metadata.json +8 -0
  85. package/apps/storefront/node_modules/.vite/deps_ssr/package.json +3 -0
  86. package/apps/storefront/src/layouts/Layout.astro +1 -1
  87. package/apps/storefront/src/lib/apps/registryAccess.ts +45 -0
  88. package/apps/storefront/src/lib/auth/adminEntry.ts +4 -4
  89. package/apps/storefront/src/lib/shared/capability.ts +68 -0
  90. package/apps/storefront/src/lib/shared/developerInvites.ts +1250 -0
  91. package/apps/storefront/src/lib/shared/invitePreflight.ts +123 -0
  92. package/apps/storefront/src/lib/webhooks/deliveryEngine.ts +38 -4
  93. package/apps/storefront/src/lib/webhooks/emit.ts +1 -1
  94. package/apps/storefront/src/lib/webhooks/getDispatcher.ts +1 -1
  95. package/apps/storefront/src/pages/api/auth/magic-exchange.ts +1 -1
  96. package/apps/storefront/src/pages/index.astro +1 -1
  97. package/apps/storefront/src/pages/products/[handle].astro +1 -1
  98. package/package.json +1 -1
  99. package/packages/public-runtime/node_modules/.bin/tsc +43 -0
  100. package/packages/public-runtime/node_modules/.bin/tsserver +43 -0
  101. package/packages/public-runtime/node_modules/.bin/vitest +43 -0
  102. package/pnpm-workspace.yaml +3 -0
  103. package/scripts/lib/tenant-dirs.mjs +80 -0
  104. package/scripts/tenant/lint-embeds.mjs +180 -0
  105. package/scripts/tenant/materialize-tenant-content.mjs +533 -0
  106. package/scripts/tenant/validate.mjs +837 -0
  107. package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +0 -68
  108. package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +0 -111
  109. package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +0 -2
  110. package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +0 -247
  111. package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +0 -73
  112. package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +0 -79
  113. package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +0 -10982
  114. package/apps/storefront/scripts/import-v84-through-ws2.ts +0 -38
  115. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +0 -2
  116. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +0 -4
  117. package/apps/storefront/scripts/install-v84-native-through-ws1.ts +0 -185
  118. package/apps/storefront/scripts/prove-clone-isolation.ts +0 -506
  119. package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +0 -148
  120. package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +0 -35
  121. package/apps/storefront/scripts/replay-v84-clean-clone.ts +0 -214
  122. package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +0 -18
  123. package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +0 -18
  124. package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +0 -18
  125. package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +0 -17
  126. package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +0 -15
  127. package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +0 -21
  128. package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +0 -42
  129. package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +0 -145
  130. package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +0 -18
  131. package/apps/storefront/src/components/admin/AdminAIWorkflowsTab.astro +0 -531
  132. package/apps/storefront/src/components/admin/AdminBlogDetailRail.astro +0 -878
  133. package/apps/storefront/src/components/admin/AdminBlogTab.astro +0 -1435
  134. package/apps/storefront/src/components/admin/AdminCheckoutSettingsPanel.astro +0 -226
  135. package/apps/storefront/src/components/admin/AdminCustomersTab.astro +0 -593
  136. package/apps/storefront/src/components/admin/AdminFulfillmentTab.astro +0 -465
  137. package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +0 -105
  138. package/apps/storefront/src/components/admin/AdminProductsTab.astro +0 -901
  139. package/apps/storefront/src/components/admin/AdminPublishTab.astro +0 -2983
  140. package/apps/storefront/src/components/admin/AdminReportingTab.astro +0 -435
  141. package/apps/storefront/src/components/admin/AdminSettingsTab.astro +0 -782
  142. package/apps/storefront/src/components/admin/AdminSubscriptionsTab.astro +0 -611
  143. package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +0 -1223
  144. package/apps/storefront/src/lib/apps/adminService.ts +0 -116
  145. package/apps/storefront/src/lib/apps/adminSession.ts +0 -214
  146. package/apps/storefront/src/lib/apps/apiAuth.ts +0 -91
  147. package/apps/storefront/src/lib/apps/apiRoute.ts +0 -35
  148. package/apps/storefront/src/lib/apps/catalogMapper.ts +0 -39
  149. package/apps/storefront/src/lib/apps/consentConfigStore.ts +0 -228
  150. package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +0 -447
  151. package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +0 -367
  152. package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +0 -315
  153. package/apps/storefront/src/lib/apps/healthAggregate.ts +0 -66
  154. package/apps/storefront/src/lib/apps/integrationLifecycle.ts +0 -614
  155. package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +0 -125
  156. package/apps/storefront/src/lib/apps/integrationReadModel.ts +0 -563
  157. package/apps/storefront/src/lib/apps/integrationsTab.ts +0 -547
  158. package/apps/storefront/src/lib/apps/integrationsView.ts +0 -106
  159. package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +0 -599
  160. package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +0 -170
  161. package/apps/storefront/src/lib/apps/tokenIssuer.ts +0 -121
  162. package/apps/storefront/src/lib/apps/tokenVerifier.ts +0 -148
  163. package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +0 -16
  164. package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +0 -105
  165. package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +0 -177
  166. package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +0 -251
  167. package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +0 -241
  168. package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +0 -211
  169. package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +0 -409
  170. package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +0 -368
  171. package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +0 -188
  172. package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +0 -291
  173. package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +0 -95
  174. package/apps/storefront/src/lib/content-edit/applyDiff.ts +0 -91
  175. package/apps/storefront/src/lib/content-edit/client.ts +0 -286
  176. package/apps/storefront/src/lib/content-edit/index.ts +0 -14
  177. package/apps/storefront/src/lib/content-edit/route.ts +0 -25
  178. package/apps/storefront/src/lib/content-edit/types.ts +0 -19
  179. package/apps/storefront/src/lib/dev/cockpitStore.ts +0 -57
  180. package/apps/storefront/src/lib/publish/adminPublishTab.ts +0 -4625
  181. package/apps/storefront/src/lib/publish/apex-readiness.ts +0 -360
  182. package/apps/storefront/src/lib/publish/buildStream.ts +0 -269
  183. package/apps/storefront/src/lib/publish/collapsePersistence.ts +0 -72
  184. package/apps/storefront/src/lib/publish/dispatchHealth.ts +0 -267
  185. package/apps/storefront/src/lib/publish/domainState.ts +0 -360
  186. package/apps/storefront/src/lib/publish/lifecycleState.ts +0 -369
  187. package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +0 -29
  188. package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +0 -78
  189. package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +0 -62
  190. package/apps/storefront/src/lib/publish/mergeRowFindings.ts +0 -124
  191. package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +0 -75
  192. package/apps/storefront/src/lib/publish/panelPolling.ts +0 -78
  193. package/apps/storefront/src/lib/publish/publish-guard.ts +0 -88
  194. package/apps/storefront/src/lib/publish/publishFormat.ts +0 -165
  195. package/apps/storefront/src/lib/publish/publishHero.ts +0 -177
  196. package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +0 -66
  197. package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +0 -141
  198. package/apps/storefront/src/lib/publish/reviewRelease/index.ts +0 -41
  199. package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +0 -47
  200. package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +0 -42
  201. package/apps/storefront/src/lib/publish/reviewRelease/types.ts +0 -59
  202. package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +0 -440
  203. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +0 -161
  204. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +0 -325
  205. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +0 -241
  206. package/apps/storefront/src/lib/publish/shipWorkspace.ts +0 -439
  207. package/apps/storefront/src/lib/publish/sseRoute.ts +0 -119
  208. package/apps/storefront/src/lib/publish/stageBundleUpload.ts +0 -215
  209. package/apps/storefront/src/lib/publish/streamLogConsole.ts +0 -142
  210. package/apps/storefront/src/lib/publish/versionNumber.ts +0 -52
  211. package/apps/storefront/src/pages/admin/ops-timeline.astro +0 -420
  212. package/apps/storefront/src/pages/admin/review-release.astro +0 -265
  213. package/apps/storefront/src/pages/admin/select.astro +0 -96
  214. package/apps/storefront/src/pages/admin.astro +0 -570
  215. package/apps/storefront/src/pages/api/apps/admin/credentials/rotate.ts +0 -86
  216. package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +0 -174
  217. package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +0 -96
  218. package/apps/storefront/src/pages/api/apps/admin/health.ts +0 -44
  219. package/apps/storefront/src/pages/api/apps/admin/install.ts +0 -125
  220. package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +0 -118
  221. package/apps/storefront/src/pages/api/apps/admin/integrations.ts +0 -89
  222. package/apps/storefront/src/pages/api/apps/admin/list.ts +0 -26
  223. package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +0 -85
  224. package/apps/storefront/src/pages/api/apps/admin/resume.ts +0 -79
  225. package/apps/storefront/src/pages/api/apps/admin/suspend.ts +0 -80
  226. package/apps/storefront/src/pages/api/apps/admin/uninstall.ts +0 -98
  227. package/apps/storefront/src/pages/api/apps/admin/update.ts +0 -126
  228. package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries/[deliveryId]/replay.ts +0 -70
  229. package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries.ts +0 -51
  230. package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +0 -255
  231. package/apps/storefront/src/pages/api/apps/oauth/token.ts +0 -87
  232. package/apps/storefront/src/pages/api/apps/v1/attribution.ts +0 -162
  233. package/apps/storefront/src/pages/api/apps/v1/catalog/products/[handle].ts +0 -39
  234. package/apps/storefront/src/pages/api/apps/v1/catalog/products.ts +0 -49
  235. package/apps/storefront/src/pages/api/apps/v1/health.ts +0 -32
  236. package/apps/storefront/src/pages/api/apps/v1/inventory.ts +0 -59
  237. package/apps/storefront/src/pages/api/apps/v1/orders/[id].ts +0 -48
  238. package/apps/storefront/src/pages/api/apps/v1/orders.ts +0 -73
  239. package/apps/storefront/src/pages/api/apps/v1/reports.ts +0 -21
  240. package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries/[deliveryId]/replay.ts +0 -74
  241. package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries.ts +0 -47
  242. package/apps/storefront/src/pages/api/cache-purge.ts +0 -55
  243. package/apps/storefront/src/pages/api/compliance/tamper.ts +0 -88
  244. package/apps/storefront/src/pages/api/content-edit/ai-edit.ts +0 -164
  245. package/apps/storefront/src/pages/api/dashboard/enter-vendor.ts +0 -154
  246. package/apps/storefront/src/pages/api/dashboard/vendor-search.ts +0 -120
  247. package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +0 -108
  248. package/apps/storefront/src/pages/api/publish/stage-bundle.ts +0 -70
  249. package/apps/storefront/src/pages/api/test/dev-session.ts +0 -133
  250. package/apps/storefront/src/pages/cockpit.astro +0 -1548
  251. package/apps/storefront/src/pages/dashboard/[appDomain]/apps/index.astro +0 -119
  252. package/apps/storefront/src/pages/dashboard/[appDomain]/index.astro +0 -105
  253. package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +0 -177
  254. package/apps/storefront/src/pages/dashboard/index.astro +0 -160
@@ -1,215 +0,0 @@
1
- /**
2
- * Authenticated static-bundle STAGING upload — the Worker-side write surface that
3
- * lets CI stage a materialized bundle's objects into the `STATIC_BUNDLES` R2
4
- * binding WITHOUT a static R2 S3-compatible key pair (`R2_ACCESS_KEY_ID`/
5
- * `R2_SECRET_ACCESS_KEY`). CI proves identity with the SAME OIDC→AWS→SSM→
6
- * `private_key_jwt` chain it already uses to authenticate to MCP
7
- * (`scripts/publish/ci-mcp-read-remote.mjs`): it mints a short-lived RS256
8
- * `client_assertion` under its dedicated confidential client
9
- * (`storefront-ci.tokenoftrust.com` / kid `storefront-ci-publish-1`, the key held
10
- * only in SSM), audience-bound to THIS upload endpoint, and the Worker verifies
11
- * the signature against that client's PUBLISHED public JWKS.
12
- *
13
- * This is a WRITE path to a production-serving bucket, so the auth boundary is
14
- * deliberately as strong as the MCP leg:
15
- * - RS256 signature over the CI client's JWKS (no shared static secret).
16
- * - `iss == sub == <expected CI client id>` (RFC 7523 §3).
17
- * - `aud == <this exact upload endpoint>` (RFC 8707 resource binding) — an
18
- * assertion minted for MCP's token endpoint can never be replayed here, and
19
- * vice versa.
20
- * - `exp`/`iat` freshness (jose enforces `exp`; assertions live ~60s).
21
- * - `jti` one-time-use replay rejection (KV-backed), mirroring MCP's replay
22
- * store — so a captured assertion can't be replayed inside its TTL window.
23
- * - Object key confined to `versions/<digest>/…`: a valid CI credential can
24
- * only write immutable version archives, never the `live/` pointer or any
25
- * other bucket key.
26
- *
27
- * The KEY SCHEME (`versions/<digest>/<rel>`) MUST byte-match the read side
28
- * (`@tot/public-runtime` `staticBundleObjectKey`/`staticBundleManifestKey`) and
29
- * the CI writer (`scripts/publish/lib/r2-publish.mjs` `r2ObjectKey`) — the same
30
- * lockstep those two already keep. MANIFEST-LAST ordering (the manifest is the
31
- * "fully staged" signal) is the CALLER's responsibility (CI writes it last, the
32
- * same as `writeBundleToR2`); this surface writes exactly the one object it is
33
- * handed per request.
34
- */
35
- import { createLocalJWKSet, jwtVerify, type JSONWebKeySet, type JWTPayload } from "jose";
36
-
37
- /** The only signature algorithm accepted (matches the CI minter). */
38
- export const STAGE_BUNDLE_UPLOAD_ALG = "RS256";
39
-
40
- /** The route this surface is mounted at — the canonical `aud`/resource identifier. */
41
- export const STAGE_BUNDLE_UPLOAD_PATH = "/api/publish/stage-bundle";
42
-
43
- /** Default CI confidential-client id (`iss == sub`), overridable per env. */
44
- export const DEFAULT_STAGE_BUNDLE_UPLOAD_ISSUER = "storefront-ci.tokenoftrust.com";
45
-
46
- /** How long a used `jti` is remembered — the assertion TTL (~60s) plus clock skew. */
47
- export const STAGE_BUNDLE_JTI_TTL_SECONDS = 120;
48
-
49
- /** Clock skew tolerated on `exp`/`iat`, in seconds. */
50
- const CLOCK_TOLERANCE_SECONDS = 5;
51
-
52
- /**
53
- * The `versions/<digest>/<rel>` keys a CI credential is allowed to write. The
54
- * digest is a lowercase hex tree digest; `rel` is a bundle-relative POSIX path
55
- * with no traversal. Anything else (a bare key, `live/…`, an absolute path, a
56
- * `..` segment) is refused with 400 — the write authority is bounded to
57
- * immutable version archives regardless of a valid signature.
58
- */
59
- const VERSION_KEY_RE = /^versions\/[a-f0-9]{8,}\/.+$/;
60
-
61
- /** Minimal R2 surface this module needs — structural, so tests pass a fake. */
62
- export interface StageBundleUploadBucket {
63
- head(key: string): Promise<{ key: string } | null>;
64
- put(
65
- key: string,
66
- value: ArrayBuffer | ArrayBufferView,
67
- options?: { httpMetadata?: { contentType?: string } },
68
- ): Promise<unknown>;
69
- }
70
-
71
- /**
72
- * One-time-use `jti` store. `checkAndRemember` returns `true` when the `jti` was
73
- * unseen (and records it), `false` when it was already used (a replay). Backed by
74
- * KV in the deployed Worker; omitted in dev/tests where no KV is bound (replay
75
- * protection then relies on the ~60s `aud`-bound `exp` window alone).
76
- */
77
- export interface JtiReplayStore {
78
- checkAndRemember(jti: string, ttlSeconds: number): Promise<boolean>;
79
- }
80
-
81
- export interface StageBundleUploadConfig {
82
- /** The CI client's published PUBLIC JWKS (verifies the assertion signature). */
83
- jwks: JSONWebKeySet;
84
- /** Expected `iss == sub` (the CI confidential-client id). */
85
- issuer: string;
86
- /** Expected `aud` — this exact upload endpoint URL (RFC 8707 resource). */
87
- audience: string;
88
- }
89
-
90
- /** A KV-namespace-shaped store (`get`/`put`) — the deployed jti replay backing. */
91
- export interface JtiKvLike {
92
- get(key: string): Promise<string | null>;
93
- put(key: string, value: string, options?: { expirationTtl?: number }): Promise<void>;
94
- }
95
-
96
- /** Build a KV-backed {@link JtiReplayStore}. Keyed under a dedicated prefix. */
97
- export function kvJtiReplayStore(kv: JtiKvLike): JtiReplayStore {
98
- return {
99
- async checkAndRemember(jti, ttlSeconds) {
100
- const key = `stage-bundle-jti:${jti}`;
101
- if (await kv.get(key)) return false;
102
- // KV's minimum expirationTtl is 60s; the TTL default already exceeds it.
103
- await kv.put(key, "1", { expirationTtl: Math.max(60, ttlSeconds) });
104
- return true;
105
- },
106
- };
107
- }
108
-
109
- function json(status: number, body: Record<string, unknown>): Response {
110
- return new Response(JSON.stringify(body), {
111
- status,
112
- headers: { "content-type": "application/json" },
113
- });
114
- }
115
-
116
- /** Extract the bearer assertion from the Authorization header, or null. */
117
- function bearer(request: Request): string | null {
118
- const h = request.headers.get("authorization");
119
- if (!h) return null;
120
- const m = /^Bearer (.+)$/.exec(h.trim());
121
- return m ? m[1]!.trim() : null;
122
- }
123
-
124
- /**
125
- * Verify the CI `client_assertion`: RS256 signature over the configured JWKS,
126
- * `iss`/`sub`/`aud` exact match, `exp` freshness, and one-time `jti`. Returns the
127
- * verified payload, or a `Response` (401) to return verbatim on any failure — no
128
- * failure detail beyond a stable machine reason is leaked.
129
- */
130
- export async function verifyUploadAssertion(
131
- token: string,
132
- config: StageBundleUploadConfig,
133
- jtiStore?: JtiReplayStore,
134
- ): Promise<{ payload: JWTPayload } | { reject: Response }> {
135
- let payload: JWTPayload;
136
- try {
137
- const keys = createLocalJWKSet(config.jwks);
138
- ({ payload } = await jwtVerify(token, keys, {
139
- algorithms: [STAGE_BUNDLE_UPLOAD_ALG],
140
- issuer: config.issuer,
141
- audience: config.audience,
142
- clockTolerance: CLOCK_TOLERANCE_SECONDS,
143
- }));
144
- } catch {
145
- // Signature, iss/aud mismatch, or expiry — one opaque 401 (never which).
146
- return { reject: json(401, { error: "invalid_assertion" }) };
147
- }
148
- // RFC 7523 §3: sub must equal the client id (iss). jose verifies iss but not
149
- // that sub matches it, so assert it explicitly.
150
- if (payload.sub !== config.issuer) {
151
- return { reject: json(401, { error: "invalid_assertion" }) };
152
- }
153
- const jti = typeof payload.jti === "string" ? payload.jti : "";
154
- if (!jti) {
155
- return { reject: json(401, { error: "invalid_assertion" }) };
156
- }
157
- if (jtiStore) {
158
- const fresh = await jtiStore.checkAndRemember(jti, STAGE_BUNDLE_JTI_TTL_SECONDS);
159
- if (!fresh) return { reject: json(401, { error: "assertion_replayed" }) };
160
- }
161
- return { payload };
162
- }
163
-
164
- /** True iff `key` is a well-formed, traversal-free `versions/<digest>/<rel>` key. */
165
- export function isSafeVersionKey(key: string): boolean {
166
- if (!VERSION_KEY_RE.test(key)) return false;
167
- return !key.split("/").some((seg) => seg === ".." || seg === "." || seg === "");
168
- }
169
-
170
- /**
171
- * Handle one authenticated staging request against `bucket`:
172
- * - `PUT ?key=versions/<digest>/<rel>` — write the request body as that object.
173
- * - `HEAD ?key=versions/<digest>/<rel>` — 200 if present, 404 if not (the CI
174
- * idempotency probe, mirroring `r2ObjectExists`).
175
- * Both require a valid CI assertion; the key is confined to `versions/<digest>/`.
176
- */
177
- export async function handleStageBundleUpload(opts: {
178
- request: Request;
179
- bucket: StageBundleUploadBucket;
180
- config: StageBundleUploadConfig;
181
- jtiStore?: JtiReplayStore;
182
- }): Promise<Response> {
183
- const { request, bucket, config, jtiStore } = opts;
184
- const method = request.method.toUpperCase();
185
- if (method !== "PUT" && method !== "HEAD") {
186
- return json(405, { error: "method_not_allowed" });
187
- }
188
-
189
- const token = bearer(request);
190
- if (!token) return json(401, { error: "missing_bearer" });
191
-
192
- // HEAD is a read/probe and must NOT consume the one-time jti (a PUT retry after
193
- // a probe would then falsely 401 as a replay). Only PUT records the jti.
194
- const verified = await verifyUploadAssertion(
195
- token,
196
- config,
197
- method === "PUT" ? jtiStore : undefined,
198
- );
199
- if ("reject" in verified) return verified.reject;
200
-
201
- const key = new URL(request.url).searchParams.get("key") ?? "";
202
- if (!isSafeVersionKey(key)) {
203
- return json(400, { error: "invalid_key" });
204
- }
205
-
206
- if (method === "HEAD") {
207
- const obj = await bucket.head(key);
208
- return new Response(null, { status: obj ? 200 : 404 });
209
- }
210
-
211
- const body = await request.arrayBuffer();
212
- const contentType = request.headers.get("content-type") ?? undefined;
213
- await bucket.put(key, body, contentType ? { httpMetadata: { contentType } } : undefined);
214
- return json(200, { key, staged: true });
215
- }
@@ -1,142 +0,0 @@
1
- /**
2
- * Pure formatting for the admin Publish tab's shared SCROLLING LIVE-LOG console —
3
- * the "CI build log" panel reused across ALL FOUR long-running flows (build /
4
- * integrate / rebuild / ship). Where `buildStream.ts` owns the build-flight
5
- * stage-RAIL (checkmarks), this owns the LOG: one human-readable, timestamped line
6
- * appended per server-pushed `phase` event, then a terminal ✓/✗ line.
7
- *
8
- * It is transport-agnostic (it consumes already-parsed {@link SseEvent}s from
9
- * `parseSseChunk`) and flow-agnostic: ONE phase→label map covers every phase any of
10
- * the four routes emits, so the SAME console renders an integrate merge, a ship
11
- * promote, or a build read with no per-flow branching. The terminal-line extractor
12
- * reads the union of the four routes' honest result shapes (build's
13
- * `ok`/`outcome`/`errors`, the queue's `ok`/`queueState`/`statusMessage`/`reason`,
14
- * ship's `ok`/`state`/`message`) without any one flow's assumptions leaking in.
15
- *
16
- * The DOM wiring that appends these to a scrollable `<div>` and auto-scrolls is
17
- * verified on a live preview, per this codebase's client-island convention (see
18
- * `reviewReleaseWorkspace/controller.ts`). Only this pure formatting is unit-tested.
19
- */
20
- import type { SseEvent } from "./buildStream.js";
21
-
22
- /**
23
- * The human label for every `phase` a streamed route emits, across all four flows.
24
- * Deliberately honest-but-neutral wording so the SAME line reads true whether the
25
- * phase came from a candidate build or an aggregate rebuild.
26
- */
27
- export const STREAM_PHASE_LABEL: Record<string, string> = {
28
- // Accept-to-preview (integrate) — the queue's merge boundary.
29
- merging: "Merging your change into the shared preview…",
30
- // Build (candidate) — head resolution.
31
- resolving: "Locating the pull request's latest commit…",
32
- // Shared reconcile boundaries (build candidate + aggregate integrate/rebuild).
33
- reading: "Reading and validating your store's files…",
34
- publishing: "Building and publishing this version…",
35
- checking: "Re-running the combined evidence checks…",
36
- // Publish-live (ship) — the orchestrator's post-gate boundaries.
37
- pinning: "Pinning the exact reviewed build…",
38
- promoting: "Promoting the reviewed build to your live channel…",
39
- verifying: "Verifying your live store serves the new build…",
40
- recording: "Recording the release in your ledger…",
41
- };
42
-
43
- /**
44
- * The label for one phase: a server-supplied `label` wins (a route may send a more
45
- * specific line, e.g. build's "Locating the latest commit for PR #12…"), else the
46
- * shared map, else `null` for an unknown phase (the caller ignores it — never
47
- * fabricates a line for a phase it doesn't understand).
48
- */
49
- export function phaseLogLabel(phase: string, serverLabel?: string | null): string | null {
50
- if (serverLabel && serverLabel.trim()) return serverLabel.trim();
51
- return STREAM_PHASE_LABEL[phase] ?? null;
52
- }
53
-
54
- /** `m:ss` elapsed, matching the dialog's own elapsed-clock format. Clamps negatives to 0. */
55
- export function formatElapsed(ms: number): string {
56
- const s = Math.max(0, Math.floor(ms / 1000));
57
- return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`;
58
- }
59
-
60
- /**
61
- * The log line for a `phase` event, or `null` to skip (unknown phase / not a phase
62
- * event). Shape: `[m:ss] <label>`. Pure — the console appends the returned string.
63
- */
64
- export function logLineForPhase(
65
- ev: SseEvent,
66
- elapsedMs: number,
67
- ): string | null {
68
- if (ev.event !== "phase") return null;
69
- let parsed: unknown = null;
70
- try {
71
- parsed = JSON.parse(ev.data);
72
- } catch {
73
- return null;
74
- }
75
- const phase = parsed && typeof (parsed as { phase?: unknown }).phase === "string"
76
- ? (parsed as { phase: string }).phase
77
- : null;
78
- if (!phase) return null;
79
- const serverLabel =
80
- parsed && typeof (parsed as { label?: unknown }).label === "string"
81
- ? (parsed as { label: string }).label
82
- : null;
83
- const label = phaseLogLabel(phase, serverLabel);
84
- if (!label) return null;
85
- return `[${formatElapsed(elapsedMs)}] ${label}`;
86
- }
87
-
88
- /** A terminal result across the four flows — the union of their honest shapes. */
89
- export interface StreamTerminalResult {
90
- ok?: boolean;
91
- /** build */
92
- outcome?: string | null;
93
- errors?: string[] | null;
94
- error?: string | null;
95
- /** integrate/rebuild */
96
- queueState?: string | null;
97
- statusMessage?: string | null;
98
- reason?: string | null;
99
- /** ship */
100
- state?: string | null;
101
- message?: string | null;
102
- }
103
-
104
- /** True iff the terminal result is a clean success, reading each flow's own success signal. */
105
- export function isStreamResultOk(result: StreamTerminalResult): boolean {
106
- if (result.state !== undefined && result.state !== null) return result.state === "shipped";
107
- if (result.ok === true) return true;
108
- return result.outcome === "ok";
109
- }
110
-
111
- /** A SHORT one-line reason for a non-ok terminal (the full detail lives in the outcome phase). */
112
- function streamResultReason(result: StreamTerminalResult): string {
113
- const first = (v: string[] | null | undefined) => (v && v.length ? v[0] : "");
114
- const candidate =
115
- result.statusMessage ||
116
- result.message ||
117
- first(result.errors) ||
118
- result.error ||
119
- (result.outcome === "blocked" ? "a check blocked this build" : "") ||
120
- result.reason ||
121
- result.queueState ||
122
- result.state ||
123
- "it did not complete";
124
- const line = String(candidate).replace(/\s+/g, " ").trim();
125
- return line.length > 160 ? line.slice(0, 157) + "…" : line;
126
- }
127
-
128
- /**
129
- * The terminal log line for a `result` event: `{ ok, line }`. `line` is
130
- * `[m:ss] ✓ Done.` on success, `[m:ss] ✗ Stopped — <short reason>` otherwise. Pure.
131
- */
132
- export function terminalLogLine(
133
- result: StreamTerminalResult,
134
- elapsedMs: number,
135
- ): { ok: boolean; line: string } {
136
- const ok = isStreamResultOk(result);
137
- const stamp = `[${formatElapsed(elapsedMs)}]`;
138
- return {
139
- ok,
140
- line: ok ? `${stamp} ✓ Done.` : `${stamp} ✗ Stopped — ${streamResultReason(result)}`,
141
- };
142
- }
@@ -1,52 +0,0 @@
1
- /**
2
- * The merchant-facing version counter — a monotonic, human "v1, v2, …" label for
3
- * the tenant's published versions, DERIVED from the live-promotion history so it is
4
- * never fabricated and never the raw SHA (which is meaningless to a merchant).
5
- *
6
- * A version's number is its rank by FIRST promotion to `live`: the earliest-ever
7
- * promoted sha is v1, the next distinct sha is v2, and so on. This has the two
8
- * properties merchants expect:
9
- * - monotonic increasing — a newer publish always gets a higher number; and
10
- * - stable for a given sha — a rollback re-points `live` at a prior version (per
11
- * `PromotionEvent`'s contract a plain rollback is not even recorded, and a
12
- * re-promote keeps the sha's ORIGINAL first-promotion rank), so "rolled back to
13
- * v3" reads honestly and a subsequent fresh publish becomes v(N+1), never
14
- * reusing a retired number.
15
- *
16
- * Pure (no I/O) so it unit-tests without a Worker/KV, and shared by both the
17
- * live-version resolver (the "Live version" metric) and the versions-panel view so
18
- * the two surfaces always agree on a version's number.
19
- */
20
- import type { PromotionEvent } from "@tot/public-runtime";
21
-
22
- /**
23
- * Map each promoted versionId → its 1-based version number, ranked by earliest
24
- * promotion time. Input order is irrelevant (the rank is computed from the `at`
25
- * timestamps), so it accepts the newest-first list `listPromotions` returns as-is.
26
- * A tie on `at` between two distinct shas is broken by versionId for determinism.
27
- */
28
- export function assignVersionNumbers(promotions: PromotionEvent[]): Map<string, number> {
29
- const earliest = new Map<string, string>();
30
- for (const p of promotions) {
31
- const seen = earliest.get(p.versionId);
32
- if (seen == null || p.at < seen) earliest.set(p.versionId, p.at);
33
- }
34
- const ordered = [...earliest.entries()].sort((a, b) =>
35
- a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0,
36
- );
37
- const numbers = new Map<string, number>();
38
- ordered.forEach(([versionId], i) => numbers.set(versionId, i + 1));
39
- return numbers;
40
- }
41
-
42
- /**
43
- * The version number for one versionId, or `null` when nothing in the promotion
44
- * history matches (an unpromoted/unknown sha — the label falls back to the raw SHA).
45
- */
46
- export function versionNumberFor(
47
- promotions: PromotionEvent[],
48
- versionId: string | null | undefined,
49
- ): number | null {
50
- if (!versionId) return null;
51
- return assignVersionNumbers(promotions).get(versionId) ?? null;
52
- }