@tokenoftrust/storefront-runner 1.4.2-rc.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. package/apps/storefront/astro.config.mjs +3 -3
  2. package/apps/storefront/env.d.ts +54 -5
  3. package/apps/storefront/integrations/materialize-guard.mjs +12 -14
  4. package/apps/storefront/migrations-apps/0004_deep_morph.sql +36 -0
  5. package/apps/storefront/migrations-apps/0005_common_mystique.sql +23 -0
  6. package/apps/storefront/migrations-apps/0006_broad_microchip.sql +16 -0
  7. package/apps/storefront/migrations-apps/0007_brave_outlaw_kid.sql +15 -0
  8. package/apps/storefront/migrations-apps/0008_blue_dazzler.sql +11 -0
  9. package/apps/storefront/migrations-apps/0009_bored_shinobi_shaw.sql +15 -0
  10. package/apps/storefront/migrations-apps/0010_ws4_verified_provider_measurement.sql +35 -0
  11. package/apps/storefront/migrations-apps/meta/0004_snapshot.json +1474 -0
  12. package/apps/storefront/migrations-apps/meta/0005_snapshot.json +1617 -0
  13. package/apps/storefront/migrations-apps/meta/0006_snapshot.json +1716 -0
  14. package/apps/storefront/migrations-apps/meta/0007_snapshot.json +1812 -0
  15. package/apps/storefront/migrations-apps/meta/0008_snapshot.json +1881 -0
  16. package/apps/storefront/migrations-apps/meta/0009_snapshot.json +1979 -0
  17. package/apps/storefront/migrations-apps/meta/_journal.json +42 -0
  18. package/apps/storefront/public/apps/tot.demo.analytics/0.1.0/entry.js +42 -0
  19. package/apps/storefront/public/platform/amplitude-http/v1/entry.mjs +19 -0
  20. package/apps/storefront/public/platform/google-measurement/v1/entry.mjs +19 -0
  21. package/apps/storefront/public/shared/commerce-chrome.css +20 -2
  22. package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +68 -0
  23. package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +111 -0
  24. package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +2 -0
  25. package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +247 -0
  26. package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +73 -0
  27. package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +79 -0
  28. package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +10982 -0
  29. package/apps/storefront/scripts/import-v84-through-ws2.ts +38 -0
  30. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +2 -0
  31. package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +4 -0
  32. package/apps/storefront/scripts/install-v84-native-through-ws1.ts +185 -0
  33. package/apps/storefront/scripts/prove-clone-isolation.ts +506 -0
  34. package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +148 -0
  35. package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +35 -0
  36. package/apps/storefront/scripts/replay-v84-clean-clone.ts +214 -0
  37. package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +18 -0
  38. package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +18 -0
  39. package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +18 -0
  40. package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +17 -0
  41. package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +15 -0
  42. package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +21 -0
  43. package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +42 -0
  44. package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +145 -0
  45. package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +18 -0
  46. package/apps/storefront/src/components/Img.astro +1 -1
  47. package/apps/storefront/src/components/admin/AdminBlogTab.astro +19 -16
  48. package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +105 -0
  49. package/apps/storefront/src/components/admin/AdminPublishTab.astro +1057 -412
  50. package/apps/storefront/src/components/admin/AdminSettingsTab.astro +2 -2
  51. package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +5 -5
  52. package/apps/storefront/src/components/chrome/NavDropdown.astro +12 -0
  53. package/apps/storefront/src/components/chrome/SiteFooter.astro +7 -2
  54. package/apps/storefront/src/components/chrome/SiteHeader.astro +46 -10
  55. package/apps/storefront/src/components/compliance/AdultSignatureNotice.astro +1 -1
  56. package/apps/storefront/src/components/compliance/ComplianceNotice.astro +1 -2
  57. package/apps/storefront/src/components/compliance/ExciseTaxNotice.astro +1 -2
  58. package/apps/storefront/src/components/compliance/PactActNotice.astro +1 -1
  59. package/apps/storefront/src/components/compliance/Prop65Warning.astro +1 -2
  60. package/apps/storefront/src/components/compliance/PurchaseLimitNotice.astro +2 -3
  61. package/apps/storefront/src/components/compliance/ShippingRestrictionNotice.astro +2 -2
  62. package/apps/storefront/src/components/compliance/StateEligibilityNotice.astro +2 -3
  63. package/apps/storefront/src/components/content/TrustStrip.astro +4 -4
  64. package/apps/storefront/src/components/islands/MobileNav.tsx +26 -1
  65. package/apps/storefront/src/components/islands/VariantSelector.tsx +27 -2
  66. package/apps/storefront/src/components/islands/useCheckoutHandoffCorrelation.ts +75 -0
  67. package/apps/storefront/src/components/membership/IllustrativeLabel.astro +1 -2
  68. package/apps/storefront/src/components/membership/TierCards.astro +2 -2
  69. package/apps/storefront/src/components/membership/TierComparisonTable.astro +2 -2
  70. package/apps/storefront/src/components/subscription/SavingsExplainer.astro +2 -2
  71. package/apps/storefront/src/config/adminTenantLookup.ts +35 -0
  72. package/apps/storefront/src/config/devTenantSeed.ts +9 -9
  73. package/apps/storefront/src/config/resolver.ts +4 -4
  74. package/apps/storefront/src/layouts/Layout.astro +100 -20
  75. package/apps/storefront/src/lib/activity/candidateSubmitLease.ts +87 -0
  76. package/apps/storefront/src/lib/activity/changeActorAttribution.ts +86 -6
  77. package/apps/storefront/src/lib/activity/deployVersion.ts +1 -1
  78. package/apps/storefront/src/lib/admin/adminShell.ts +2 -0
  79. package/apps/storefront/src/lib/admin/envelope.ts +1 -2
  80. package/apps/storefront/src/lib/apps/adminService.ts +10 -0
  81. package/apps/storefront/src/lib/apps/adminSession.ts +1 -1
  82. package/apps/storefront/src/lib/apps/appVersionStore.ts +281 -0
  83. package/apps/storefront/src/lib/apps/consentConfigStore.ts +228 -0
  84. package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +447 -0
  85. package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +367 -0
  86. package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +315 -0
  87. package/apps/storefront/src/lib/apps/integrationLifecycle.ts +614 -0
  88. package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +125 -0
  89. package/apps/storefront/src/lib/apps/integrationReadModel.ts +563 -0
  90. package/apps/storefront/src/lib/apps/integrationsTab.ts +547 -0
  91. package/apps/storefront/src/lib/apps/integrationsView.ts +106 -0
  92. package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +599 -0
  93. package/apps/storefront/src/lib/apps/orders/orderConversionD1.ts +150 -0
  94. package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +8 -0
  95. package/apps/storefront/src/lib/apps/orders/ordersStore.ts +1 -1
  96. package/apps/storefront/src/lib/apps/orders/verifiedProviderMeasurement.ts +117 -0
  97. package/apps/storefront/src/lib/apps/registryService.ts +264 -10
  98. package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +170 -0
  99. package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +16 -0
  100. package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +105 -0
  101. package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +177 -0
  102. package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +251 -0
  103. package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +241 -0
  104. package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +211 -0
  105. package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +409 -0
  106. package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +368 -0
  107. package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +188 -0
  108. package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +291 -0
  109. package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +95 -0
  110. package/apps/storefront/src/lib/auth/adminApiGuard.ts +66 -0
  111. package/apps/storefront/src/lib/auth/adminEntry.ts +2 -2
  112. package/apps/storefront/src/lib/auth/adminLanding.ts +88 -0
  113. package/apps/storefront/src/lib/blog/collection.ts +97 -10
  114. package/apps/storefront/src/lib/blog/markdown.ts +1 -1
  115. package/apps/storefront/src/lib/blog/provider.ts +57 -3
  116. package/apps/storefront/src/lib/blog/types.ts +9 -9
  117. package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome-assignments.example.json +6 -0
  118. package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome.example.json +79 -0
  119. package/apps/storefront/src/lib/chrome/model.ts +48 -253
  120. package/apps/storefront/src/lib/chrome/navCurrent.ts +29 -0
  121. package/apps/storefront/src/lib/chrome/parseConfig.ts +18 -32
  122. package/apps/storefront/src/lib/chrome/variant.ts +39 -0
  123. package/apps/storefront/src/lib/commerce/checkoutHandoffCorrelation.ts +105 -0
  124. package/apps/storefront/src/lib/compliance/tamper-sentinel-boot.ts +152 -0
  125. package/apps/storefront/src/lib/compliance/tamper-sentinel.ts +327 -0
  126. package/apps/storefront/src/lib/content/index.ts +5 -5
  127. package/apps/storefront/src/lib/content-edit/applyDiff.ts +1 -1
  128. package/apps/storefront/src/lib/content-edit/route.ts +1 -1
  129. package/apps/storefront/src/lib/d1/catalog.ts +12 -0
  130. package/apps/storefront/src/lib/d1/schema-apps.ts +276 -0
  131. package/apps/storefront/src/lib/dev/cockpit/ask.ts +49 -0
  132. package/apps/storefront/src/lib/dev/cockpit/clickToSource.ts +71 -0
  133. package/apps/storefront/src/lib/dev/cockpit/copyCommand.ts +227 -0
  134. package/apps/storefront/src/lib/dev/cockpit/files.ts +249 -0
  135. package/apps/storefront/src/lib/dev/cockpit/hostedActivity.ts +500 -0
  136. package/apps/storefront/src/lib/dev/cockpit/infoPopover.ts +12 -0
  137. package/apps/storefront/src/lib/dev/cockpit/mcpCopy.ts +34 -0
  138. package/apps/storefront/src/lib/dev/cockpit/monitor.ts +107 -0
  139. package/apps/storefront/src/lib/dev/cockpit/stepper.ts +116 -0
  140. package/apps/storefront/src/lib/dev/cockpit/themeToggle.ts +23 -0
  141. package/apps/storefront/src/lib/dev/runtimeStore.ts +1 -1
  142. package/apps/storefront/src/lib/edgeCache.ts +18 -6
  143. package/apps/storefront/src/lib/email/candidateConflictEmail.ts +80 -0
  144. package/apps/storefront/src/lib/integration/browserEnvironment.ts +137 -0
  145. package/apps/storefront/src/lib/integration/managedInstallDeclarations.ts +72 -0
  146. package/apps/storefront/src/lib/integration/nonceStamp.ts +49 -0
  147. package/apps/storefront/src/lib/integration/tenantDeclarations.ts +116 -0
  148. package/apps/storefront/src/lib/membership/eligibility.ts +1 -1
  149. package/apps/storefront/src/lib/membership/model.ts +1 -2
  150. package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +2 -2
  151. package/apps/storefront/src/lib/newsletter/consent.ts +2 -2
  152. package/apps/storefront/src/lib/newsletter/send.ts +3 -3
  153. package/apps/storefront/src/lib/previewReload.ts +57 -1
  154. package/apps/storefront/src/lib/publish/adminPublishTab.ts +1775 -669
  155. package/apps/storefront/src/lib/publish/buildStream.ts +269 -0
  156. package/apps/storefront/src/lib/publish/collapsePersistence.ts +72 -0
  157. package/apps/storefront/src/lib/publish/lifecycleState.ts +369 -0
  158. package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +29 -0
  159. package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +78 -0
  160. package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +62 -0
  161. package/apps/storefront/src/lib/publish/mergeRowFindings.ts +124 -0
  162. package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +75 -0
  163. package/apps/storefront/src/lib/publish/publish-guard.ts +88 -0
  164. package/apps/storefront/src/lib/publish/publishFormat.ts +165 -0
  165. package/apps/storefront/src/lib/publish/publishHero.ts +177 -0
  166. package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +66 -0
  167. package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +141 -0
  168. package/apps/storefront/src/lib/publish/reviewRelease/index.ts +41 -0
  169. package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +47 -0
  170. package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +42 -0
  171. package/apps/storefront/src/lib/publish/reviewRelease/types.ts +59 -0
  172. package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +440 -0
  173. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +161 -0
  174. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +325 -0
  175. package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +241 -0
  176. package/apps/storefront/src/lib/publish/shipWorkspace.ts +22 -3
  177. package/apps/storefront/src/lib/publish/sseRoute.ts +119 -0
  178. package/apps/storefront/src/lib/publish/streamLogConsole.ts +142 -0
  179. package/apps/storefront/src/lib/publish/versionNumber.ts +52 -0
  180. package/apps/storefront/src/lib/rawChrome.ts +125 -47
  181. package/apps/storefront/src/lib/rawMarketingHtml.ts +74 -3
  182. package/apps/storefront/src/lib/seo/alternates.ts +1 -1
  183. package/apps/storefront/src/lib/social/notify.ts +4 -4
  184. package/apps/storefront/src/lib/storyblok/content-model.ts +7 -33
  185. package/apps/storefront/src/lib/storyblok/provider.ts +168 -60
  186. package/apps/storefront/src/lib/subscription/model.ts +4 -4
  187. package/apps/storefront/src/lib/the-build/provider.ts +9 -4
  188. package/apps/storefront/src/middleware/index.ts +273 -51
  189. package/apps/storefront/src/pages/[...slug].astro +9 -4
  190. package/apps/storefront/src/pages/admin/review-release.astro +265 -0
  191. package/apps/storefront/src/pages/admin/select.astro +96 -0
  192. package/apps/storefront/src/pages/admin.astro +16 -2
  193. package/apps/storefront/src/pages/api/activity.ts +8 -8
  194. package/apps/storefront/src/pages/api/admin/activity-alerts.ts +5 -20
  195. package/apps/storefront/src/pages/api/admin/orders/[id].ts +7 -2
  196. package/apps/storefront/src/pages/api/admin/orders.ts +8 -2
  197. package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +174 -0
  198. package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +96 -0
  199. package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +118 -0
  200. package/apps/storefront/src/pages/api/apps/admin/integrations.ts +89 -0
  201. package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +85 -0
  202. package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +74 -2
  203. package/apps/storefront/src/pages/api/commerce/checkout-handoff.ts +77 -0
  204. package/apps/storefront/src/pages/api/compliance/tamper.ts +88 -0
  205. package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +108 -0
  206. package/apps/storefront/src/pages/api/rum/vitals.ts +1 -2
  207. package/apps/storefront/src/pages/blog/[slug].astro +5 -5
  208. package/apps/storefront/src/pages/blog/author/[author].astro +3 -3
  209. package/apps/storefront/src/pages/blog/category/[category].astro +2 -2
  210. package/apps/storefront/src/pages/blog/index.astro +2 -2
  211. package/apps/storefront/src/pages/blog/tag/[tag].astro +2 -2
  212. package/apps/storefront/src/pages/cockpit.astro +61 -1362
  213. package/apps/storefront/src/pages/index.astro +10 -5
  214. package/apps/storefront/src/pages/llms.txt.ts +1 -1
  215. package/apps/storefront/src/pages/products/[handle].astro +7 -6
  216. package/apps/storefront/src/pages/sitemap.xml.ts +2 -2
  217. package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +31 -27
  218. package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +1 -1
  219. package/apps/storefront/src/pages/tenants/[id]/[...path].ts +38 -2
  220. package/apps/storefront/src/pages/the-build/[slug].astro +4 -4
  221. package/apps/storefront/src/pages/the-build/index.astro +2 -2
  222. package/apps/storefront/src/pages/the-build/rss.xml.ts +2 -2
  223. package/apps/storefront/src/styles/admin.css +27 -1
  224. package/apps/storefront/tsconfig.json +1 -1
  225. package/package.json +1 -1
  226. package/packages/public-runtime/package.json +2 -1
  227. package/packages/public-runtime/schemas/managed-analytics/v1/adapter-definition.schema.json +427 -0
  228. package/packages/public-runtime/schemas/managed-analytics/v1/create-integration-install-request.schema.json +161 -0
  229. package/packages/public-runtime/schemas/managed-analytics/v1/create-migration-draft-request.schema.json +157 -0
  230. package/packages/public-runtime/schemas/managed-analytics/v1/delete-integration-install-request.schema.json +84 -0
  231. package/packages/public-runtime/schemas/managed-analytics/v1/delete-migration-draft-request.schema.json +84 -0
  232. package/packages/public-runtime/schemas/managed-analytics/v1/error-envelope.schema.json +180 -0
  233. package/packages/public-runtime/schemas/managed-analytics/v1/get-adapter-definition-request.schema.json +52 -0
  234. package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-install-request.schema.json +52 -0
  235. package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-revision-request.schema.json +79 -0
  236. package/packages/public-runtime/schemas/managed-analytics/v1/get-migration-draft-request.schema.json +52 -0
  237. package/packages/public-runtime/schemas/managed-analytics/v1/integration-install.schema.json +167 -0
  238. package/packages/public-runtime/schemas/managed-analytics/v1/integration-revision.schema.json +208 -0
  239. package/packages/public-runtime/schemas/managed-analytics/v1/list-adapter-definitions-request.schema.json +53 -0
  240. package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-installs-request.schema.json +53 -0
  241. package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-revisions-request.schema.json +82 -0
  242. package/packages/public-runtime/schemas/managed-analytics/v1/migration-draft.schema.json +218 -0
  243. package/packages/public-runtime/schemas/managed-analytics/v1/mutation-request.schema.json +52 -0
  244. package/packages/public-runtime/schemas/managed-analytics/v1/mutation-success-envelope.schema.json +49 -0
  245. package/packages/public-runtime/schemas/managed-analytics/v1/read-request.schema.json +20 -0
  246. package/packages/public-runtime/schemas/managed-analytics/v1/read-success-envelope.schema.json +45 -0
  247. package/packages/public-runtime/schemas/managed-analytics/v1/revise-integration-install-request.schema.json +156 -0
  248. package/packages/public-runtime/schemas/managed-analytics/v1/set-integration-install-status-request.schema.json +92 -0
  249. package/packages/public-runtime/schemas/managed-analytics/v1/update-migration-draft-request.schema.json +184 -0
  250. package/packages/public-runtime/scripts/generate-managed-analytics-api-v1-schemas.mjs +13 -0
  251. package/packages/public-runtime/src/activity/catalog.ts +41 -37
  252. package/packages/public-runtime/src/activity/event.ts +6 -6
  253. package/packages/public-runtime/src/activity/index.ts +2 -2
  254. package/packages/public-runtime/src/activity/redaction.ts +4 -4
  255. package/packages/public-runtime/src/candidate-index.ts +42 -8
  256. package/packages/public-runtime/src/checkout-orders.ts +2 -2
  257. package/packages/public-runtime/src/checkout-style-publish.ts +2 -2
  258. package/packages/public-runtime/src/checkout-style.ts +7 -7
  259. package/packages/public-runtime/src/checkout.ts +3 -3
  260. package/packages/public-runtime/src/chrome.ts +777 -0
  261. package/packages/public-runtime/src/compliance-obligations.ts +310 -0
  262. package/packages/public-runtime/src/csp.ts +99 -0
  263. package/packages/public-runtime/src/customization-runtime.ts +32 -1
  264. package/packages/public-runtime/src/destination-webhook/contract.ts +353 -0
  265. package/packages/public-runtime/src/embed-catalog.d.mts +9 -0
  266. package/packages/public-runtime/src/embed-catalog.mjs +40 -0
  267. package/packages/public-runtime/src/evidence.ts +288 -0
  268. package/packages/public-runtime/src/gtm-migration/bounds.ts +138 -0
  269. package/packages/public-runtime/src/gtm-migration/disposition-rules.ts +361 -0
  270. package/packages/public-runtime/src/gtm-migration/dispositions.ts +181 -0
  271. package/packages/public-runtime/src/gtm-migration/draft-generator.ts +400 -0
  272. package/packages/public-runtime/src/gtm-migration/graph.ts +468 -0
  273. package/packages/public-runtime/src/gtm-migration/index.ts +95 -0
  274. package/packages/public-runtime/src/gtm-migration/parse.ts +410 -0
  275. package/packages/public-runtime/src/gtm-migration/references.ts +266 -0
  276. package/packages/public-runtime/src/gtm-migration/types.ts +86 -0
  277. package/packages/public-runtime/src/index.ts +16 -1
  278. package/packages/public-runtime/src/integration/assurance-decision.ts +259 -0
  279. package/packages/public-runtime/src/integration/assurance.ts +228 -0
  280. package/packages/public-runtime/src/integration/candidate-evidence.ts +377 -0
  281. package/packages/public-runtime/src/integration/commerce-broker.ts +497 -0
  282. package/packages/public-runtime/src/integration/consent-broker.ts +337 -0
  283. package/packages/public-runtime/src/integration/consent-cmp-demand.ts +115 -0
  284. package/packages/public-runtime/src/integration/consent-config.ts +260 -0
  285. package/packages/public-runtime/src/integration/consent-preview.ts +125 -0
  286. package/packages/public-runtime/src/integration/correlation-token.ts +444 -0
  287. package/packages/public-runtime/src/integration/csp-compiler.ts +267 -0
  288. package/packages/public-runtime/src/integration/csp.ts +105 -0
  289. package/packages/public-runtime/src/integration/digest.ts +43 -0
  290. package/packages/public-runtime/src/integration/environment.ts +228 -0
  291. package/packages/public-runtime/src/integration/events-catalog.ts +186 -0
  292. package/packages/public-runtime/src/integration/events.ts +701 -0
  293. package/packages/public-runtime/src/integration/g2-action-boundary.ts +106 -0
  294. package/packages/public-runtime/src/integration/index.ts +90 -0
  295. package/packages/public-runtime/src/integration/interim-bridge.ts +138 -0
  296. package/packages/public-runtime/src/integration/lifecycle-boot.ts +317 -0
  297. package/packages/public-runtime/src/integration/lifecycle-runtime.ts +393 -0
  298. package/packages/public-runtime/src/integration/lifecycle.ts +94 -0
  299. package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.d.mts +2 -0
  300. package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.mjs +10 -0
  301. package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +382 -0
  302. package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +684 -0
  303. package/packages/public-runtime/src/integration/managed-analytics-bridge.ts +383 -0
  304. package/packages/public-runtime/src/integration/managed-analytics-value-safety.ts +14 -0
  305. package/packages/public-runtime/src/integration/managed-analytics.ts +277 -0
  306. package/packages/public-runtime/src/integration/manifest.ts +470 -0
  307. package/packages/public-runtime/src/integration/native-amplitude.ts +362 -0
  308. package/packages/public-runtime/src/integration/native-ga4.ts +352 -0
  309. package/packages/public-runtime/src/integration/observability.ts +451 -0
  310. package/packages/public-runtime/src/integration/order-conversion.ts +0 -0
  311. package/packages/public-runtime/src/integration/phases.ts +182 -0
  312. package/packages/public-runtime/src/integration/plan.ts +112 -0
  313. package/packages/public-runtime/src/integration/platform-adapter-runtime.ts +146 -0
  314. package/packages/public-runtime/src/integration/platform-adapters.ts +671 -0
  315. package/packages/public-runtime/src/integration/promotion-gate.ts +451 -0
  316. package/packages/public-runtime/src/integration/provider-checkout-extension.ts +425 -0
  317. package/packages/public-runtime/src/integration/receipt-measurement.ts +370 -0
  318. package/packages/public-runtime/src/integration/regulated-parent-cert.ts +311 -0
  319. package/packages/public-runtime/src/integration/render-phases.ts +267 -0
  320. package/packages/public-runtime/src/integration/resolve.ts +465 -0
  321. package/packages/public-runtime/src/integration/result.ts +239 -0
  322. package/packages/public-runtime/src/integration/secrets.ts +92 -0
  323. package/packages/public-runtime/src/integration/tamper-evidence.ts +205 -0
  324. package/packages/public-runtime/src/integration/tamper-recovery.ts +127 -0
  325. package/packages/public-runtime/src/integration/version.ts +92 -0
  326. package/packages/public-runtime/src/integration-capabilities.ts +520 -0
  327. package/packages/public-runtime/src/membership.ts +2 -2
  328. package/packages/public-runtime/src/raw-html-policy.ts +2 -4
  329. package/packages/public-runtime/src/regulated-commerce/broker/consent-dedupe.ts +144 -0
  330. package/packages/public-runtime/src/regulated-commerce/correlation/contract.ts +177 -0
  331. package/packages/public-runtime/src/regulated-commerce/diagnostics/local-dispatch.ts +24 -0
  332. package/packages/public-runtime/src/regulated-commerce/diagnostics/read-model.ts +69 -0
  333. package/packages/public-runtime/src/regulated-commerce/dispatch/core.ts +134 -0
  334. package/packages/public-runtime/src/regulated-commerce/events/contract.ts +113 -0
  335. package/packages/public-runtime/src/regulated-commerce/ledger/core.ts +81 -0
  336. package/packages/public-runtime/src/regulated-commerce/mappings/ga4-ads.ts +87 -0
  337. package/packages/public-runtime/src/regulated-commerce/provider-order/bridge.ts +52 -0
  338. package/packages/public-runtime/src/regulated-commerce/purchase-truth/contract.ts +252 -0
  339. package/packages/public-runtime/src/regulated-commerce/sources/accepted-browser-operation.ts +67 -0
  340. package/packages/public-runtime/src/regulated-commerce/testing/fake-destination.ts +93 -0
  341. package/packages/public-runtime/src/static-bundle.ts +5 -5
  342. package/packages/public-runtime/src/tenant-assets.ts +143 -4
  343. package/packages/public-runtime/src/tenant.ts +45 -9
  344. package/packages/public-runtime/tests/fixtures/integration/browser-environment.example.json +8 -0
  345. package/packages/public-runtime/tests/fixtures/integration/commerce-event.example.json +44 -0
  346. package/packages/public-runtime/tests/fixtures/integration/commerce-order-event.example.json +44 -0
  347. package/packages/public-runtime/tests/fixtures/integration/compliance-assurance-record.example.json +50 -0
  348. package/packages/public-runtime/tests/fixtures/integration/integration-manifest-v2.example.json +120 -0
  349. package/packages/public-runtime/tests/fixtures/integration/managed-analytics-v1/fake-adapter-catalog.json +35 -0
  350. package/packages/public-runtime/tests/fixtures/integration/tenant-action-registry.example.json +11 -0
  351. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/README.md +22 -0
  352. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/entry.js +30 -0
  353. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/manifest.json +75 -0
  354. package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/public-config.json +3 -0
  355. package/packages/public-runtime/tests/fixtures/regulated-commerce/fake-destinations.ts +38 -0
  356. package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.provenance.json +29 -0
  357. package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.redacted.json +3397 -0
  358. package/scripts/dev/file-browser.mjs +2 -2
  359. package/scripts/dev/file-writer.mjs +2 -2
  360. package/scripts/dev/integration-guardrails.mjs +498 -0
  361. package/scripts/dev/safe-path.mjs +2 -2
  362. package/scripts/dev/tenant-source-root.mjs +1 -1
  363. package/scripts/tot-dev.mjs +2 -2
@@ -0,0 +1,468 @@
1
+ /**
2
+ * Normalized GTM migration graph — a pure, NON-EXECUTING transformation of an
3
+ * already-parsed, inert GTM container into a node/edge graph with complete
4
+ * object accounting.
5
+ *
6
+ * SECURITY CONTRACT (inherited — a reviewer WILL reject violations):
7
+ * - Pure DATA transformation. Nothing here executes, evaluates, interprets, or
8
+ * compiles any part of the export. Variable references are recovered by STRING
9
+ * SCANNING `{{Name}}` tokens (see references.ts), never by evaluation.
10
+ * - Pure and deterministic: no I/O, no globals mutated, stable node/edge order.
11
+ * - Null-prototype safety: id/name lookup indexes are `Map`s (never object
12
+ * literals), so attacker-controlled ids/names cannot collide with prototype
13
+ * keys (`__proto__`, `constructor`, …).
14
+ * - Bounded: `{{...}}` token scanning is capped per-string and in total, and the
15
+ * edge count is capped — on breach the build STOPS WITH ACCOUNTING rather than
16
+ * growing unboundedly.
17
+ * - Nothing is silently dropped: a reference to a missing id/name is recorded in
18
+ * `danglingReferences`, and `nodeCount` is asserted to equal the sum of the 10
19
+ * input collections.
20
+ */
21
+
22
+ import type { GtmContainer, GtmContainerVersion, GtmInertRecord } from "./types.js";
23
+ import {
24
+ extractVariableTokensReport,
25
+ isBuiltInVariableRef,
26
+ readParentFolderId,
27
+ readTemplateId,
28
+ readTemplateTrailingId,
29
+ readTemplateTypeRef,
30
+ readTriggerIds,
31
+ resolveBuiltInTrigger,
32
+ type BuiltInTriggerInfo,
33
+ } from "./references.js";
34
+
35
+ /** The 10 GTM object collections, one graph-node kind each. */
36
+ export type GtmObjectKind =
37
+ | "tag"
38
+ | "trigger"
39
+ | "variable"
40
+ | "builtInVariable"
41
+ | "customTemplate"
42
+ | "folder"
43
+ | "zone"
44
+ | "client"
45
+ | "gtagConfig"
46
+ | "transformation";
47
+
48
+ /** The dependency-edge kinds resolved across the container. */
49
+ export type GtmEdgeKind = "fires" | "blocks" | "references" | "parentFolder" | "usesTemplate";
50
+
51
+ /**
52
+ * Marks a SYNTHETIC built-in node — a GTM reserved built-in that a container
53
+ * references but never materializes as a collection record (a reserved built-in
54
+ * trigger like "All Pages", or an underscore-prefixed built-in variable like
55
+ * `_event`). Absent on every record-backed node.
56
+ */
57
+ export interface GraphNodeBuiltIn {
58
+ /** Which built-in family this synthetic node stands in for. */
59
+ readonly of: "trigger" | "variable";
60
+ /** Human label (e.g. "All Pages", "Initialization", or the `_event` name). */
61
+ readonly label: string;
62
+ /** True when the exact built-in is recognized (vs a generic reserved-range id). */
63
+ readonly known: boolean;
64
+ }
65
+
66
+ /** One graph node — one per input record, or a synthetic built-in (see `builtIn`). */
67
+ export interface GraphNode {
68
+ /** Stable, unique key: `${kind}:${id ?? '#'+index}` (record) or `builtIn*:...` (synthetic). */
69
+ readonly key: string;
70
+ readonly kind: GtmObjectKind;
71
+ readonly id: string | null;
72
+ readonly name: string | null;
73
+ readonly type: string | null;
74
+ /** The complete inert record this node was built from (empty for synthetic built-ins). */
75
+ readonly record: GtmInertRecord;
76
+ /** Present only on synthetic built-in nodes; absent on record-backed nodes. */
77
+ readonly builtIn?: GraphNodeBuiltIn;
78
+ }
79
+
80
+ /** One resolved dependency edge between two node keys. */
81
+ export interface GraphEdge {
82
+ /** Source node key. */
83
+ readonly from: string;
84
+ /** Target node key. */
85
+ readonly to: string;
86
+ readonly kind: GtmEdgeKind;
87
+ /** The raw reference token that produced the edge (an id, or `{{Name}}`). */
88
+ readonly via?: string;
89
+ }
90
+
91
+ /** A reference whose target id/name has no node — recorded, never silently dropped. */
92
+ export interface DanglingReference {
93
+ /** Source node key that made the reference. */
94
+ readonly from: string;
95
+ readonly kind: GtmEdgeKind;
96
+ /** The unresolved id or variable name. */
97
+ readonly ref: string;
98
+ }
99
+
100
+ /** Complete object accounting — the reviewer checks nothing is dropped. */
101
+ export interface GraphAccounting {
102
+ readonly nodeCount: number;
103
+ readonly perKind: Record<GtmObjectKind, number>;
104
+ /**
105
+ * Number of SYNTHETIC built-in nodes (reserved built-in triggers +
106
+ * underscore-prefixed built-in variables) resolved on demand — included in
107
+ * `nodeCount` and `perKind`, but NOT backed by an input record. The record-node
108
+ * invariant (`nodeCount - syntheticNodeCount === sum of the 10 collections`)
109
+ * still holds.
110
+ */
111
+ readonly syntheticNodeCount: number;
112
+ readonly edgeCount: number;
113
+ readonly perEdgeKind: Record<GtmEdgeKind, number>;
114
+ readonly danglingCount: number;
115
+ /** Distinct built-in variable names that were referenced (deduped, stable order). */
116
+ readonly builtInVariablesReferenced: string[];
117
+ /** True when any bound engaged (distinct-token / total token cap, or the edge cap). */
118
+ readonly tokensCapped: boolean;
119
+ /**
120
+ * True when the PER-STRING `{{...}}` match cap engaged on at least one
121
+ * scanned string (a single string carried more matches than
122
+ * `maxTokensPerString` allows to be consumed). Additive to `tokensCapped`
123
+ * — a real cap can engage here even when `tokensCapped` stays false (e.g. a
124
+ * single string spamming one repeated token: distinct-token count stays
125
+ * low, but the per-string match cap still bounds the work).
126
+ */
127
+ readonly perStringTokensCapped: boolean;
128
+ }
129
+
130
+ /** The normalized migration graph. */
131
+ export interface MigrationGraph {
132
+ readonly nodes: GraphNode[];
133
+ readonly edges: GraphEdge[];
134
+ readonly danglingReferences: DanglingReference[];
135
+ readonly accounting: GraphAccounting;
136
+ }
137
+
138
+ /** Caps that keep graph construction bounded on adversarial input. */
139
+ export interface GraphBounds {
140
+ /** Max `{{...}}` tokens recovered from a single record's `raw` bag. */
141
+ maxTokensPerString: number;
142
+ /** Max `{{...}}` tokens recovered across the whole container. */
143
+ maxTotalTokens: number;
144
+ /** Max edges; on breach the build stops adding edges (flagged in accounting). */
145
+ maxEdges: number;
146
+ }
147
+
148
+ export const DEFAULT_GRAPH_BOUNDS: GraphBounds = {
149
+ maxTokensPerString: 500,
150
+ maxTotalTokens: 100_000,
151
+ maxEdges: 500_000,
152
+ };
153
+
154
+ /** Merge a partial override over the defaults, ignoring non-finite/non-positive caps. */
155
+ export function resolveGraphBounds(partial?: Partial<GraphBounds>): GraphBounds {
156
+ const out: GraphBounds = { ...DEFAULT_GRAPH_BOUNDS };
157
+ if (partial) {
158
+ for (const key of Object.keys(DEFAULT_GRAPH_BOUNDS) as (keyof GraphBounds)[]) {
159
+ const v = partial[key];
160
+ if (typeof v === "number" && Number.isFinite(v) && v > 0) out[key] = v;
161
+ }
162
+ }
163
+ return out;
164
+ }
165
+
166
+ /** Fixed kind order — drives deterministic node ordering and the `perKind` map. */
167
+ const KIND_ORDER: readonly GtmObjectKind[] = [
168
+ "tag",
169
+ "trigger",
170
+ "variable",
171
+ "builtInVariable",
172
+ "customTemplate",
173
+ "folder",
174
+ "zone",
175
+ "client",
176
+ "gtagConfig",
177
+ "transformation",
178
+ ];
179
+
180
+ /** Fixed edge-kind order — drives deterministic per-node edge emission. */
181
+ const EDGE_KIND_ORDER: readonly GtmEdgeKind[] = [
182
+ "fires",
183
+ "blocks",
184
+ "references",
185
+ "parentFolder",
186
+ "usesTemplate",
187
+ ];
188
+
189
+ function collectionFor(cv: GtmContainerVersion, kind: GtmObjectKind): readonly GtmInertRecord[] {
190
+ return cv[kind];
191
+ }
192
+
193
+ function nodeKey(kind: GtmObjectKind, id: string | null, index: number): string {
194
+ return `${kind}:${id ?? `#${index}`}`;
195
+ }
196
+
197
+ /**
198
+ * Build the normalized migration graph from an inert container.
199
+ *
200
+ * Pure and deterministic. NEVER executes any part of the input.
201
+ */
202
+ export function buildMigrationGraph(
203
+ container: GtmContainer,
204
+ bounds?: Partial<GraphBounds>,
205
+ ): MigrationGraph {
206
+ const b = resolveGraphBounds(bounds);
207
+ const cv = container.containerVersion;
208
+
209
+ // --- 1. Nodes: exactly one per record across all 10 collections. -----------
210
+ const nodes: GraphNode[] = [];
211
+ const perKind = Object.create(null) as Record<GtmObjectKind, number>;
212
+
213
+ // Per-kind indexes. Maps (NOT object literals) so attacker-controlled ids/names
214
+ // can never collide with prototype keys.
215
+ const idIndex = new Map<GtmObjectKind, Map<string, GraphNode>>();
216
+ const nameIndex = new Map<GtmObjectKind, Map<string, GraphNode>>();
217
+ // customTemplate resolves by its advertised templateId (== a tag/variable `cvt_*` type).
218
+ const templateIdIndex = new Map<string, GraphNode>();
219
+
220
+ for (const kind of KIND_ORDER) {
221
+ idIndex.set(kind, new Map<string, GraphNode>());
222
+ nameIndex.set(kind, new Map<string, GraphNode>());
223
+ const records = collectionFor(cv, kind);
224
+ perKind[kind] = records.length;
225
+ for (let i = 0; i < records.length; i += 1) {
226
+ const record = records[i];
227
+ if (record === undefined) continue; // defensive; arrays are dense
228
+ const node: GraphNode = {
229
+ key: nodeKey(kind, record.id, i),
230
+ kind,
231
+ id: record.id,
232
+ name: record.name,
233
+ type: record.type,
234
+ record,
235
+ };
236
+ nodes.push(node);
237
+ // First writer wins on duplicate id/name — deterministic and stable.
238
+ if (record.id !== null && !idIndex.get(kind)!.has(record.id)) {
239
+ idIndex.get(kind)!.set(record.id, node);
240
+ }
241
+ if (record.name !== null && !nameIndex.get(kind)!.has(record.name)) {
242
+ nameIndex.get(kind)!.set(record.name, node);
243
+ }
244
+ if (kind === "customTemplate") {
245
+ const tid = readTemplateId(record);
246
+ if (tid !== null && !templateIdIndex.has(tid)) templateIdIndex.set(tid, node);
247
+ }
248
+ }
249
+ }
250
+
251
+ // Assert-by-construction: one node per input record across the 10 collections.
252
+ const expectedNodeCount = KIND_ORDER.reduce((sum, kind) => sum + collectionFor(cv, kind).length, 0);
253
+ if (nodes.length !== expectedNodeCount) {
254
+ throw new Error(
255
+ `buildMigrationGraph invariant violated: nodeCount ${nodes.length} !== sum of collections ${expectedNodeCount}`,
256
+ );
257
+ }
258
+
259
+ // --- 2. Edges + dangling references, deterministically per node. -----------
260
+ const edges: GraphEdge[] = [];
261
+ const danglingReferences: DanglingReference[] = [];
262
+ const perEdgeKind = Object.create(null) as Record<GtmEdgeKind, number>;
263
+ for (const ek of EDGE_KIND_ORDER) perEdgeKind[ek] = 0;
264
+
265
+ const builtInSeen = new Set<string>();
266
+ const builtInVariablesReferenced: string[] = [];
267
+ let totalTokens = 0;
268
+ let tokensCapped = false;
269
+ let perStringTokensCapped = false;
270
+ let edgesFull = false;
271
+
272
+ const triggerIds = idIndex.get("trigger")!;
273
+ const folderIds = idIndex.get("folder")!;
274
+ const variableNames = nameIndex.get("variable")!;
275
+ const builtInNames = nameIndex.get("builtInVariable")!;
276
+
277
+ // --- Synthetic built-in nodes (reserved triggers + `_`-prefixed variables). --
278
+ // GTM references built-ins it never materializes as records; resolve each to a
279
+ // stable synthetic node (created once, on first reference) instead of dangling.
280
+ // Only RECORD nodes were built above, so iterate that fixed prefix — appended
281
+ // synthetic nodes must never be walked as edge SOURCES.
282
+ const recordNodeCount = nodes.length;
283
+ const EMPTY_RAW: Record<string, unknown> = Object.freeze(Object.create(null));
284
+ let syntheticNodeCount = 0;
285
+ const builtInTriggerNodes = new Map<string, GraphNode>();
286
+ const builtInVariableNodes = new Map<string, GraphNode>();
287
+
288
+ const getOrCreateBuiltInTrigger = (id: string, info: BuiltInTriggerInfo): GraphNode => {
289
+ const key = `builtInTrigger:${id}`;
290
+ const existing = builtInTriggerNodes.get(key);
291
+ if (existing) return existing;
292
+ const node: GraphNode = {
293
+ key,
294
+ kind: "trigger",
295
+ id,
296
+ name: info.label,
297
+ type: null,
298
+ record: { id, name: info.label, type: null, raw: EMPTY_RAW },
299
+ builtIn: { of: "trigger", label: info.label, known: info.known },
300
+ };
301
+ builtInTriggerNodes.set(key, node);
302
+ nodes.push(node);
303
+ perKind["trigger"] += 1;
304
+ syntheticNodeCount += 1;
305
+ return node;
306
+ };
307
+
308
+ const getOrCreateBuiltInVariable = (name: string): GraphNode => {
309
+ const key = `builtInVariable:${name}`;
310
+ const existing = builtInVariableNodes.get(key);
311
+ if (existing) return existing;
312
+ const node: GraphNode = {
313
+ key,
314
+ kind: "builtInVariable",
315
+ id: null,
316
+ name,
317
+ type: null,
318
+ record: { id: null, name, type: null, raw: EMPTY_RAW },
319
+ builtIn: { of: "variable", label: name, known: true },
320
+ };
321
+ builtInVariableNodes.set(key, node);
322
+ nodes.push(node);
323
+ perKind["builtInVariable"] += 1;
324
+ syntheticNodeCount += 1;
325
+ return node;
326
+ };
327
+
328
+ /** Resolve a firing/blocking trigger id to a real OR synthetic built-in node. */
329
+ const resolveTriggerTarget = (id: string): GraphNode | null => {
330
+ const real = triggerIds.get(id);
331
+ if (real) return real;
332
+ const info = resolveBuiltInTrigger(id);
333
+ return info ? getOrCreateBuiltInTrigger(id, info) : null;
334
+ };
335
+
336
+ /** Append an edge, respecting the edge cap. Returns false once the cap is hit. */
337
+ const pushEdge = (from: string, to: string, kind: GtmEdgeKind, via: string): boolean => {
338
+ if (edges.length >= b.maxEdges) {
339
+ if (!edgesFull) {
340
+ edgesFull = true;
341
+ tokensCapped = true; // a graph bound engaged — surfaced in accounting
342
+ }
343
+ return false;
344
+ }
345
+ edges.push({ from, to, kind, via });
346
+ perEdgeKind[kind] += 1;
347
+ return true;
348
+ };
349
+
350
+ const pushDangling = (from: string, kind: GtmEdgeKind, ref: string): void => {
351
+ danglingReferences.push({ from, kind, ref });
352
+ };
353
+
354
+ for (let ni = 0; ni < recordNodeCount; ni += 1) {
355
+ const node = nodes[ni]!;
356
+ if (edgesFull) break;
357
+ const raw = node.record.raw;
358
+
359
+ // 2a. fires: tag → trigger (raw.firingTriggerId[]) — reserved ids → built-in.
360
+ for (const tid of readTriggerIds(raw, "firingTriggerId")) {
361
+ const target = resolveTriggerTarget(tid);
362
+ if (target) {
363
+ if (!pushEdge(node.key, target.key, "fires", tid)) break;
364
+ } else {
365
+ pushDangling(node.key, "fires", tid);
366
+ }
367
+ }
368
+ if (edgesFull) break;
369
+
370
+ // 2b. blocks: tag → trigger (raw.blockingTriggerId[]) — reserved ids → built-in.
371
+ for (const tid of readTriggerIds(raw, "blockingTriggerId")) {
372
+ const target = resolveTriggerTarget(tid);
373
+ if (target) {
374
+ if (!pushEdge(node.key, target.key, "blocks", tid)) break;
375
+ } else {
376
+ pushDangling(node.key, "blocks", tid);
377
+ }
378
+ }
379
+ if (edgesFull) break;
380
+
381
+ // 2c. references: any object → variable / builtInVariable, from {{Name}} tokens.
382
+ // Per-record cap, plus a running total-token budget across the container.
383
+ let perRecordCap = b.maxTokensPerString;
384
+ if (totalTokens >= b.maxTotalTokens) {
385
+ tokensCapped = true;
386
+ perRecordCap = 0;
387
+ } else {
388
+ const remaining = b.maxTotalTokens - totalTokens;
389
+ if (remaining < perRecordCap) perRecordCap = remaining;
390
+ }
391
+ if (perRecordCap > 0) {
392
+ const { tokens, perStringCapped } = extractVariableTokensReport(raw, perRecordCap);
393
+ totalTokens += tokens.length;
394
+ if (tokens.length >= perRecordCap) tokensCapped = true;
395
+ if (perStringCapped) perStringTokensCapped = true;
396
+ // De-dupe reference edges per (from → target) within this record.
397
+ const linked = new Set<string>();
398
+ for (const name of tokens) {
399
+ const via = `{{${name}}}`;
400
+ const variableNode = variableNames.get(name);
401
+ const builtInNode = builtInNames.get(name);
402
+ // Underscore-prefixed names are GTM built-in variables the container never
403
+ // materializes (e.g. `_event`) — resolve to a synthetic node, not dangling.
404
+ const target =
405
+ variableNode ?? builtInNode ?? (isBuiltInVariableRef(name) ? getOrCreateBuiltInVariable(name) : undefined);
406
+ if (target) {
407
+ if (target !== variableNode && !builtInSeen.has(name)) {
408
+ builtInSeen.add(name);
409
+ builtInVariablesReferenced.push(name);
410
+ }
411
+ if (!linked.has(target.key)) {
412
+ linked.add(target.key);
413
+ if (!pushEdge(node.key, target.key, "references", via)) break;
414
+ }
415
+ } else {
416
+ pushDangling(node.key, "references", name);
417
+ }
418
+ }
419
+ }
420
+ if (edgesFull) break;
421
+
422
+ // 2d. parentFolder: any object → folder (raw.parentFolderId)
423
+ const parentFolderId = readParentFolderId(raw);
424
+ if (parentFolderId !== null) {
425
+ const target = folderIds.get(parentFolderId);
426
+ if (target) {
427
+ if (!pushEdge(node.key, target.key, "parentFolder", parentFolderId)) break;
428
+ } else {
429
+ pushDangling(node.key, "parentFolder", parentFolderId);
430
+ }
431
+ }
432
+ if (edgesFull) break;
433
+
434
+ // 2e. usesTemplate: tag / variable → customTemplate when its type is a cvt_* type.
435
+ // A real GTM tag/variable's `type` is the FULL `cvt_<containerId>_<n>` token, while
436
+ // the customTemplate it points at usually advertises just the bare `<n>` as its
437
+ // `templateId` — so resolve by the full token first, then by its trailing `<n>`
438
+ // segment (see `readTemplateTrailingId`). Either match is a valid, non-dangling link.
439
+ if (node.kind === "tag" || node.kind === "variable") {
440
+ const templateRef = readTemplateTypeRef(node.record);
441
+ if (templateRef !== null) {
442
+ const trailingId = readTemplateTrailingId(templateRef);
443
+ const target =
444
+ templateIdIndex.get(templateRef) ??
445
+ (trailingId !== null ? templateIdIndex.get(trailingId) : undefined);
446
+ if (target) {
447
+ if (!pushEdge(node.key, target.key, "usesTemplate", templateRef)) break;
448
+ } else {
449
+ pushDangling(node.key, "usesTemplate", templateRef);
450
+ }
451
+ }
452
+ }
453
+ }
454
+
455
+ const accounting: GraphAccounting = {
456
+ nodeCount: nodes.length,
457
+ perKind,
458
+ syntheticNodeCount,
459
+ edgeCount: edges.length,
460
+ perEdgeKind,
461
+ danglingCount: danglingReferences.length,
462
+ builtInVariablesReferenced,
463
+ tokensCapped,
464
+ perStringTokensCapped,
465
+ };
466
+
467
+ return { nodes, edges, danglingReferences, accounting };
468
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @tot/public-runtime — GTM container-export migration: the SAFE, non-executing
3
+ * parser + inert typed model + complete object accounting.
4
+ *
5
+ * This subtree turns an untrusted GTM (Google Tag Manager) container export into
6
+ * inert typed DATA and a normalized reference/dependency graph. It NEVER executes,
7
+ * evaluates, or interprets any part of the export (see `parse.ts` for the full
8
+ * security contract). It does NOT classify tags into dispositions or render any UI
9
+ * — those are separate downstream units that consume this module's output.
10
+ */
11
+
12
+ export { parseGtmExport, DEFAULT_BOUNDS } from "./parse.js";
13
+ export { enforceBounds, resolveBounds } from "./bounds.js";
14
+ export type { ParseBounds, GtmViolation } from "./bounds.js";
15
+ export type {
16
+ GtmContainer,
17
+ GtmContainerVersion,
18
+ GtmInertRecord,
19
+ GtmParseAccounting,
20
+ GtmParseResult,
21
+ } from "./types.js";
22
+
23
+ // Reference-extraction helpers (pure, non-executing, string-scanning only).
24
+ export {
25
+ extractVariableTokens,
26
+ extractVariableTokensReport,
27
+ readTriggerIds,
28
+ readParentFolderId,
29
+ isCustomTemplateType,
30
+ readTemplateTypeRef,
31
+ readTemplateTrailingId,
32
+ readTemplateId,
33
+ resolveBuiltInTrigger,
34
+ isBuiltInVariableRef,
35
+ GTM_RESERVED_TRIGGER_MIN,
36
+ GTM_RESERVED_TRIGGER_MAX,
37
+ } from "./references.js";
38
+ export type { ExtractVariableTokensResult, BuiltInTriggerInfo } from "./references.js";
39
+
40
+ // Normalized migration graph: nodes + resolved edges + complete accounting.
41
+ export { buildMigrationGraph, resolveGraphBounds, DEFAULT_GRAPH_BOUNDS } from "./graph.js";
42
+ export type {
43
+ GtmObjectKind,
44
+ GtmEdgeKind,
45
+ GraphNode,
46
+ GraphNodeBuiltIn,
47
+ GraphEdge,
48
+ DanglingReference,
49
+ GraphAccounting,
50
+ MigrationGraph,
51
+ GraphBounds,
52
+ } from "./graph.js";
53
+
54
+ // Migration disposition (classification) engine: one disposition per object +
55
+ // dangling reference, with complete accounting.
56
+ export { classifyMigration } from "./dispositions.js";
57
+ export type {
58
+ DispositionClass,
59
+ ObjectDisposition,
60
+ DanglingDisposition,
61
+ DispositionReport,
62
+ } from "./dispositions.js";
63
+
64
+ // The extensible disposition ruleset (GTM-type → disposition knowledge). Exported
65
+ // so the report UI can render the reason legend and the classification rubric.
66
+ export {
67
+ classifyNode,
68
+ isCodeBearing,
69
+ verdict,
70
+ dispositionForReason,
71
+ REASON_CATALOG,
72
+ TAG_TYPE_RULES,
73
+ VARIABLE_TYPE_RULES,
74
+ TRIGGER_TYPE_RULES,
75
+ KIND_RULES,
76
+ } from "./disposition-rules.js";
77
+ export type { ReasonCode, DispositionVerdict, NodeRuleContext } from "./disposition-rules.js";
78
+
79
+ // The disabled MigrationDraft v1 generator: map a classified migration into an
80
+ // inert, always-disabled managed-analytics draft + complete unresolved inventory.
81
+ export {
82
+ generateDisabledMigrationDraft,
83
+ WS1_GOOGLE_MEASUREMENT_ADAPTER_ID,
84
+ WS1_GOOGLE_MEASUREMENT_DESTINATION_KEY,
85
+ NO_ADAPTER_SELECTED_ID,
86
+ } from "./draft-generator.js";
87
+ export type {
88
+ GenerateDisabledMigrationDraftArgs,
89
+ DisabledDraftResult,
90
+ MappedConcept,
91
+ MappedConceptRole,
92
+ UnresolvedInventoryItem,
93
+ DraftProvenanceInput,
94
+ DraftProvenanceRecord,
95
+ } from "./draft-generator.js";