@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.
- package/apps/storefront/astro.config.mjs +3 -3
- package/apps/storefront/env.d.ts +54 -5
- package/apps/storefront/integrations/materialize-guard.mjs +12 -14
- package/apps/storefront/migrations-apps/0004_deep_morph.sql +36 -0
- package/apps/storefront/migrations-apps/0005_common_mystique.sql +23 -0
- package/apps/storefront/migrations-apps/0006_broad_microchip.sql +16 -0
- package/apps/storefront/migrations-apps/0007_brave_outlaw_kid.sql +15 -0
- package/apps/storefront/migrations-apps/0008_blue_dazzler.sql +11 -0
- package/apps/storefront/migrations-apps/0009_bored_shinobi_shaw.sql +15 -0
- package/apps/storefront/migrations-apps/0010_ws4_verified_provider_measurement.sql +35 -0
- package/apps/storefront/migrations-apps/meta/0004_snapshot.json +1474 -0
- package/apps/storefront/migrations-apps/meta/0005_snapshot.json +1617 -0
- package/apps/storefront/migrations-apps/meta/0006_snapshot.json +1716 -0
- package/apps/storefront/migrations-apps/meta/0007_snapshot.json +1812 -0
- package/apps/storefront/migrations-apps/meta/0008_snapshot.json +1881 -0
- package/apps/storefront/migrations-apps/meta/0009_snapshot.json +1979 -0
- package/apps/storefront/migrations-apps/meta/_journal.json +42 -0
- package/apps/storefront/public/apps/tot.demo.analytics/0.1.0/entry.js +42 -0
- package/apps/storefront/public/platform/amplitude-http/v1/entry.mjs +19 -0
- package/apps/storefront/public/platform/google-measurement/v1/entry.mjs +19 -0
- package/apps/storefront/public/shared/commerce-chrome.css +20 -2
- package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +68 -0
- package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +111 -0
- package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +2 -0
- package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +247 -0
- package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +73 -0
- package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +79 -0
- package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +10982 -0
- package/apps/storefront/scripts/import-v84-through-ws2.ts +38 -0
- package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +2 -0
- package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +4 -0
- package/apps/storefront/scripts/install-v84-native-through-ws1.ts +185 -0
- package/apps/storefront/scripts/prove-clone-isolation.ts +506 -0
- package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +148 -0
- package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +35 -0
- package/apps/storefront/scripts/replay-v84-clean-clone.ts +214 -0
- package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +18 -0
- package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +18 -0
- package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +18 -0
- package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +17 -0
- package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +15 -0
- package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +21 -0
- package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +42 -0
- package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +145 -0
- package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +18 -0
- package/apps/storefront/src/components/Img.astro +1 -1
- package/apps/storefront/src/components/admin/AdminBlogTab.astro +19 -16
- package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +105 -0
- package/apps/storefront/src/components/admin/AdminPublishTab.astro +1057 -412
- package/apps/storefront/src/components/admin/AdminSettingsTab.astro +2 -2
- package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +5 -5
- package/apps/storefront/src/components/chrome/NavDropdown.astro +12 -0
- package/apps/storefront/src/components/chrome/SiteFooter.astro +7 -2
- package/apps/storefront/src/components/chrome/SiteHeader.astro +46 -10
- package/apps/storefront/src/components/compliance/AdultSignatureNotice.astro +1 -1
- package/apps/storefront/src/components/compliance/ComplianceNotice.astro +1 -2
- package/apps/storefront/src/components/compliance/ExciseTaxNotice.astro +1 -2
- package/apps/storefront/src/components/compliance/PactActNotice.astro +1 -1
- package/apps/storefront/src/components/compliance/Prop65Warning.astro +1 -2
- package/apps/storefront/src/components/compliance/PurchaseLimitNotice.astro +2 -3
- package/apps/storefront/src/components/compliance/ShippingRestrictionNotice.astro +2 -2
- package/apps/storefront/src/components/compliance/StateEligibilityNotice.astro +2 -3
- package/apps/storefront/src/components/content/TrustStrip.astro +4 -4
- package/apps/storefront/src/components/islands/MobileNav.tsx +26 -1
- package/apps/storefront/src/components/islands/VariantSelector.tsx +27 -2
- package/apps/storefront/src/components/islands/useCheckoutHandoffCorrelation.ts +75 -0
- package/apps/storefront/src/components/membership/IllustrativeLabel.astro +1 -2
- package/apps/storefront/src/components/membership/TierCards.astro +2 -2
- package/apps/storefront/src/components/membership/TierComparisonTable.astro +2 -2
- package/apps/storefront/src/components/subscription/SavingsExplainer.astro +2 -2
- package/apps/storefront/src/config/adminTenantLookup.ts +35 -0
- package/apps/storefront/src/config/devTenantSeed.ts +9 -9
- package/apps/storefront/src/config/resolver.ts +4 -4
- package/apps/storefront/src/layouts/Layout.astro +100 -20
- package/apps/storefront/src/lib/activity/candidateSubmitLease.ts +87 -0
- package/apps/storefront/src/lib/activity/changeActorAttribution.ts +86 -6
- package/apps/storefront/src/lib/activity/deployVersion.ts +1 -1
- package/apps/storefront/src/lib/admin/adminShell.ts +2 -0
- package/apps/storefront/src/lib/admin/envelope.ts +1 -2
- package/apps/storefront/src/lib/apps/adminService.ts +10 -0
- package/apps/storefront/src/lib/apps/adminSession.ts +1 -1
- package/apps/storefront/src/lib/apps/appVersionStore.ts +281 -0
- package/apps/storefront/src/lib/apps/consentConfigStore.ts +228 -0
- package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +447 -0
- package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +367 -0
- package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +315 -0
- package/apps/storefront/src/lib/apps/integrationLifecycle.ts +614 -0
- package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +125 -0
- package/apps/storefront/src/lib/apps/integrationReadModel.ts +563 -0
- package/apps/storefront/src/lib/apps/integrationsTab.ts +547 -0
- package/apps/storefront/src/lib/apps/integrationsView.ts +106 -0
- package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +599 -0
- package/apps/storefront/src/lib/apps/orders/orderConversionD1.ts +150 -0
- package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +8 -0
- package/apps/storefront/src/lib/apps/orders/ordersStore.ts +1 -1
- package/apps/storefront/src/lib/apps/orders/verifiedProviderMeasurement.ts +117 -0
- package/apps/storefront/src/lib/apps/registryService.ts +264 -10
- package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +170 -0
- package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +16 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +105 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +177 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +251 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +241 -0
- package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +211 -0
- package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +409 -0
- package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +368 -0
- package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +188 -0
- package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +291 -0
- package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +95 -0
- package/apps/storefront/src/lib/auth/adminApiGuard.ts +66 -0
- package/apps/storefront/src/lib/auth/adminEntry.ts +2 -2
- package/apps/storefront/src/lib/auth/adminLanding.ts +88 -0
- package/apps/storefront/src/lib/blog/collection.ts +97 -10
- package/apps/storefront/src/lib/blog/markdown.ts +1 -1
- package/apps/storefront/src/lib/blog/provider.ts +57 -3
- package/apps/storefront/src/lib/blog/types.ts +9 -9
- package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome-assignments.example.json +6 -0
- package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome.example.json +79 -0
- package/apps/storefront/src/lib/chrome/model.ts +48 -253
- package/apps/storefront/src/lib/chrome/navCurrent.ts +29 -0
- package/apps/storefront/src/lib/chrome/parseConfig.ts +18 -32
- package/apps/storefront/src/lib/chrome/variant.ts +39 -0
- package/apps/storefront/src/lib/commerce/checkoutHandoffCorrelation.ts +105 -0
- package/apps/storefront/src/lib/compliance/tamper-sentinel-boot.ts +152 -0
- package/apps/storefront/src/lib/compliance/tamper-sentinel.ts +327 -0
- package/apps/storefront/src/lib/content/index.ts +5 -5
- package/apps/storefront/src/lib/content-edit/applyDiff.ts +1 -1
- package/apps/storefront/src/lib/content-edit/route.ts +1 -1
- package/apps/storefront/src/lib/d1/catalog.ts +12 -0
- package/apps/storefront/src/lib/d1/schema-apps.ts +276 -0
- package/apps/storefront/src/lib/dev/cockpit/ask.ts +49 -0
- package/apps/storefront/src/lib/dev/cockpit/clickToSource.ts +71 -0
- package/apps/storefront/src/lib/dev/cockpit/copyCommand.ts +227 -0
- package/apps/storefront/src/lib/dev/cockpit/files.ts +249 -0
- package/apps/storefront/src/lib/dev/cockpit/hostedActivity.ts +500 -0
- package/apps/storefront/src/lib/dev/cockpit/infoPopover.ts +12 -0
- package/apps/storefront/src/lib/dev/cockpit/mcpCopy.ts +34 -0
- package/apps/storefront/src/lib/dev/cockpit/monitor.ts +107 -0
- package/apps/storefront/src/lib/dev/cockpit/stepper.ts +116 -0
- package/apps/storefront/src/lib/dev/cockpit/themeToggle.ts +23 -0
- package/apps/storefront/src/lib/dev/runtimeStore.ts +1 -1
- package/apps/storefront/src/lib/edgeCache.ts +18 -6
- package/apps/storefront/src/lib/email/candidateConflictEmail.ts +80 -0
- package/apps/storefront/src/lib/integration/browserEnvironment.ts +137 -0
- package/apps/storefront/src/lib/integration/managedInstallDeclarations.ts +72 -0
- package/apps/storefront/src/lib/integration/nonceStamp.ts +49 -0
- package/apps/storefront/src/lib/integration/tenantDeclarations.ts +116 -0
- package/apps/storefront/src/lib/membership/eligibility.ts +1 -1
- package/apps/storefront/src/lib/membership/model.ts +1 -2
- package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +2 -2
- package/apps/storefront/src/lib/newsletter/consent.ts +2 -2
- package/apps/storefront/src/lib/newsletter/send.ts +3 -3
- package/apps/storefront/src/lib/previewReload.ts +57 -1
- package/apps/storefront/src/lib/publish/adminPublishTab.ts +1775 -669
- package/apps/storefront/src/lib/publish/buildStream.ts +269 -0
- package/apps/storefront/src/lib/publish/collapsePersistence.ts +72 -0
- package/apps/storefront/src/lib/publish/lifecycleState.ts +369 -0
- package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +29 -0
- package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +78 -0
- package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +62 -0
- package/apps/storefront/src/lib/publish/mergeRowFindings.ts +124 -0
- package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +75 -0
- package/apps/storefront/src/lib/publish/publish-guard.ts +88 -0
- package/apps/storefront/src/lib/publish/publishFormat.ts +165 -0
- package/apps/storefront/src/lib/publish/publishHero.ts +177 -0
- package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +66 -0
- package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +141 -0
- package/apps/storefront/src/lib/publish/reviewRelease/index.ts +41 -0
- package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +47 -0
- package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +42 -0
- package/apps/storefront/src/lib/publish/reviewRelease/types.ts +59 -0
- package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +440 -0
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +161 -0
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +325 -0
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +241 -0
- package/apps/storefront/src/lib/publish/shipWorkspace.ts +22 -3
- package/apps/storefront/src/lib/publish/sseRoute.ts +119 -0
- package/apps/storefront/src/lib/publish/streamLogConsole.ts +142 -0
- package/apps/storefront/src/lib/publish/versionNumber.ts +52 -0
- package/apps/storefront/src/lib/rawChrome.ts +125 -47
- package/apps/storefront/src/lib/rawMarketingHtml.ts +74 -3
- package/apps/storefront/src/lib/seo/alternates.ts +1 -1
- package/apps/storefront/src/lib/social/notify.ts +4 -4
- package/apps/storefront/src/lib/storyblok/content-model.ts +7 -33
- package/apps/storefront/src/lib/storyblok/provider.ts +168 -60
- package/apps/storefront/src/lib/subscription/model.ts +4 -4
- package/apps/storefront/src/lib/the-build/provider.ts +9 -4
- package/apps/storefront/src/middleware/index.ts +273 -51
- package/apps/storefront/src/pages/[...slug].astro +9 -4
- package/apps/storefront/src/pages/admin/review-release.astro +265 -0
- package/apps/storefront/src/pages/admin/select.astro +96 -0
- package/apps/storefront/src/pages/admin.astro +16 -2
- package/apps/storefront/src/pages/api/activity.ts +8 -8
- package/apps/storefront/src/pages/api/admin/activity-alerts.ts +5 -20
- package/apps/storefront/src/pages/api/admin/orders/[id].ts +7 -2
- package/apps/storefront/src/pages/api/admin/orders.ts +8 -2
- package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +174 -0
- package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +96 -0
- package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +118 -0
- package/apps/storefront/src/pages/api/apps/admin/integrations.ts +89 -0
- package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +85 -0
- package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +74 -2
- package/apps/storefront/src/pages/api/commerce/checkout-handoff.ts +77 -0
- package/apps/storefront/src/pages/api/compliance/tamper.ts +88 -0
- package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +108 -0
- package/apps/storefront/src/pages/api/rum/vitals.ts +1 -2
- package/apps/storefront/src/pages/blog/[slug].astro +5 -5
- package/apps/storefront/src/pages/blog/author/[author].astro +3 -3
- package/apps/storefront/src/pages/blog/category/[category].astro +2 -2
- package/apps/storefront/src/pages/blog/index.astro +2 -2
- package/apps/storefront/src/pages/blog/tag/[tag].astro +2 -2
- package/apps/storefront/src/pages/cockpit.astro +61 -1362
- package/apps/storefront/src/pages/index.astro +10 -5
- package/apps/storefront/src/pages/llms.txt.ts +1 -1
- package/apps/storefront/src/pages/products/[handle].astro +7 -6
- package/apps/storefront/src/pages/sitemap.xml.ts +2 -2
- package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +31 -27
- package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +1 -1
- package/apps/storefront/src/pages/tenants/[id]/[...path].ts +38 -2
- package/apps/storefront/src/pages/the-build/[slug].astro +4 -4
- package/apps/storefront/src/pages/the-build/index.astro +2 -2
- package/apps/storefront/src/pages/the-build/rss.xml.ts +2 -2
- package/apps/storefront/src/styles/admin.css +27 -1
- package/apps/storefront/tsconfig.json +1 -1
- package/package.json +1 -1
- package/packages/public-runtime/package.json +2 -1
- package/packages/public-runtime/schemas/managed-analytics/v1/adapter-definition.schema.json +427 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/create-integration-install-request.schema.json +161 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/create-migration-draft-request.schema.json +157 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/delete-integration-install-request.schema.json +84 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/delete-migration-draft-request.schema.json +84 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/error-envelope.schema.json +180 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-adapter-definition-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-install-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-revision-request.schema.json +79 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-migration-draft-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/integration-install.schema.json +167 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/integration-revision.schema.json +208 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/list-adapter-definitions-request.schema.json +53 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-installs-request.schema.json +53 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-revisions-request.schema.json +82 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/migration-draft.schema.json +218 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/mutation-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/mutation-success-envelope.schema.json +49 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/read-request.schema.json +20 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/read-success-envelope.schema.json +45 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/revise-integration-install-request.schema.json +156 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/set-integration-install-status-request.schema.json +92 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/update-migration-draft-request.schema.json +184 -0
- package/packages/public-runtime/scripts/generate-managed-analytics-api-v1-schemas.mjs +13 -0
- package/packages/public-runtime/src/activity/catalog.ts +41 -37
- package/packages/public-runtime/src/activity/event.ts +6 -6
- package/packages/public-runtime/src/activity/index.ts +2 -2
- package/packages/public-runtime/src/activity/redaction.ts +4 -4
- package/packages/public-runtime/src/candidate-index.ts +42 -8
- package/packages/public-runtime/src/checkout-orders.ts +2 -2
- package/packages/public-runtime/src/checkout-style-publish.ts +2 -2
- package/packages/public-runtime/src/checkout-style.ts +7 -7
- package/packages/public-runtime/src/checkout.ts +3 -3
- package/packages/public-runtime/src/chrome.ts +777 -0
- package/packages/public-runtime/src/compliance-obligations.ts +310 -0
- package/packages/public-runtime/src/csp.ts +99 -0
- package/packages/public-runtime/src/customization-runtime.ts +32 -1
- package/packages/public-runtime/src/destination-webhook/contract.ts +353 -0
- package/packages/public-runtime/src/embed-catalog.d.mts +9 -0
- package/packages/public-runtime/src/embed-catalog.mjs +40 -0
- package/packages/public-runtime/src/evidence.ts +288 -0
- package/packages/public-runtime/src/gtm-migration/bounds.ts +138 -0
- package/packages/public-runtime/src/gtm-migration/disposition-rules.ts +361 -0
- package/packages/public-runtime/src/gtm-migration/dispositions.ts +181 -0
- package/packages/public-runtime/src/gtm-migration/draft-generator.ts +400 -0
- package/packages/public-runtime/src/gtm-migration/graph.ts +468 -0
- package/packages/public-runtime/src/gtm-migration/index.ts +95 -0
- package/packages/public-runtime/src/gtm-migration/parse.ts +410 -0
- package/packages/public-runtime/src/gtm-migration/references.ts +266 -0
- package/packages/public-runtime/src/gtm-migration/types.ts +86 -0
- package/packages/public-runtime/src/index.ts +16 -1
- package/packages/public-runtime/src/integration/assurance-decision.ts +259 -0
- package/packages/public-runtime/src/integration/assurance.ts +228 -0
- package/packages/public-runtime/src/integration/candidate-evidence.ts +377 -0
- package/packages/public-runtime/src/integration/commerce-broker.ts +497 -0
- package/packages/public-runtime/src/integration/consent-broker.ts +337 -0
- package/packages/public-runtime/src/integration/consent-cmp-demand.ts +115 -0
- package/packages/public-runtime/src/integration/consent-config.ts +260 -0
- package/packages/public-runtime/src/integration/consent-preview.ts +125 -0
- package/packages/public-runtime/src/integration/correlation-token.ts +444 -0
- package/packages/public-runtime/src/integration/csp-compiler.ts +267 -0
- package/packages/public-runtime/src/integration/csp.ts +105 -0
- package/packages/public-runtime/src/integration/digest.ts +43 -0
- package/packages/public-runtime/src/integration/environment.ts +228 -0
- package/packages/public-runtime/src/integration/events-catalog.ts +186 -0
- package/packages/public-runtime/src/integration/events.ts +701 -0
- package/packages/public-runtime/src/integration/g2-action-boundary.ts +106 -0
- package/packages/public-runtime/src/integration/index.ts +90 -0
- package/packages/public-runtime/src/integration/interim-bridge.ts +138 -0
- package/packages/public-runtime/src/integration/lifecycle-boot.ts +317 -0
- package/packages/public-runtime/src/integration/lifecycle-runtime.ts +393 -0
- package/packages/public-runtime/src/integration/lifecycle.ts +94 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.d.mts +2 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.mjs +10 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +382 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +684 -0
- package/packages/public-runtime/src/integration/managed-analytics-bridge.ts +383 -0
- package/packages/public-runtime/src/integration/managed-analytics-value-safety.ts +14 -0
- package/packages/public-runtime/src/integration/managed-analytics.ts +277 -0
- package/packages/public-runtime/src/integration/manifest.ts +470 -0
- package/packages/public-runtime/src/integration/native-amplitude.ts +362 -0
- package/packages/public-runtime/src/integration/native-ga4.ts +352 -0
- package/packages/public-runtime/src/integration/observability.ts +451 -0
- package/packages/public-runtime/src/integration/order-conversion.ts +0 -0
- package/packages/public-runtime/src/integration/phases.ts +182 -0
- package/packages/public-runtime/src/integration/plan.ts +112 -0
- package/packages/public-runtime/src/integration/platform-adapter-runtime.ts +146 -0
- package/packages/public-runtime/src/integration/platform-adapters.ts +671 -0
- package/packages/public-runtime/src/integration/promotion-gate.ts +451 -0
- package/packages/public-runtime/src/integration/provider-checkout-extension.ts +425 -0
- package/packages/public-runtime/src/integration/receipt-measurement.ts +370 -0
- package/packages/public-runtime/src/integration/regulated-parent-cert.ts +311 -0
- package/packages/public-runtime/src/integration/render-phases.ts +267 -0
- package/packages/public-runtime/src/integration/resolve.ts +465 -0
- package/packages/public-runtime/src/integration/result.ts +239 -0
- package/packages/public-runtime/src/integration/secrets.ts +92 -0
- package/packages/public-runtime/src/integration/tamper-evidence.ts +205 -0
- package/packages/public-runtime/src/integration/tamper-recovery.ts +127 -0
- package/packages/public-runtime/src/integration/version.ts +92 -0
- package/packages/public-runtime/src/integration-capabilities.ts +520 -0
- package/packages/public-runtime/src/membership.ts +2 -2
- package/packages/public-runtime/src/raw-html-policy.ts +2 -4
- package/packages/public-runtime/src/regulated-commerce/broker/consent-dedupe.ts +144 -0
- package/packages/public-runtime/src/regulated-commerce/correlation/contract.ts +177 -0
- package/packages/public-runtime/src/regulated-commerce/diagnostics/local-dispatch.ts +24 -0
- package/packages/public-runtime/src/regulated-commerce/diagnostics/read-model.ts +69 -0
- package/packages/public-runtime/src/regulated-commerce/dispatch/core.ts +134 -0
- package/packages/public-runtime/src/regulated-commerce/events/contract.ts +113 -0
- package/packages/public-runtime/src/regulated-commerce/ledger/core.ts +81 -0
- package/packages/public-runtime/src/regulated-commerce/mappings/ga4-ads.ts +87 -0
- package/packages/public-runtime/src/regulated-commerce/provider-order/bridge.ts +52 -0
- package/packages/public-runtime/src/regulated-commerce/purchase-truth/contract.ts +252 -0
- package/packages/public-runtime/src/regulated-commerce/sources/accepted-browser-operation.ts +67 -0
- package/packages/public-runtime/src/regulated-commerce/testing/fake-destination.ts +93 -0
- package/packages/public-runtime/src/static-bundle.ts +5 -5
- package/packages/public-runtime/src/tenant-assets.ts +143 -4
- package/packages/public-runtime/src/tenant.ts +45 -9
- package/packages/public-runtime/tests/fixtures/integration/browser-environment.example.json +8 -0
- package/packages/public-runtime/tests/fixtures/integration/commerce-event.example.json +44 -0
- package/packages/public-runtime/tests/fixtures/integration/commerce-order-event.example.json +44 -0
- package/packages/public-runtime/tests/fixtures/integration/compliance-assurance-record.example.json +50 -0
- package/packages/public-runtime/tests/fixtures/integration/integration-manifest-v2.example.json +120 -0
- package/packages/public-runtime/tests/fixtures/integration/managed-analytics-v1/fake-adapter-catalog.json +35 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-action-registry.example.json +11 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/README.md +22 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/entry.js +30 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/manifest.json +75 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/public-config.json +3 -0
- package/packages/public-runtime/tests/fixtures/regulated-commerce/fake-destinations.ts +38 -0
- package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.provenance.json +29 -0
- package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.redacted.json +3397 -0
- package/scripts/dev/file-browser.mjs +2 -2
- package/scripts/dev/file-writer.mjs +2 -2
- package/scripts/dev/integration-guardrails.mjs +498 -0
- package/scripts/dev/safe-path.mjs +2 -2
- package/scripts/dev/tenant-source-root.mjs +1 -1
- package/scripts/tot-dev.mjs +2 -2
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import type { ApprovedMarketingActionName, UnresolvedInventoryItem } from "@tot/public-runtime";
|
|
2
|
+
|
|
3
|
+
export const V84_NONPORTABLE_REFUSAL_CRITERIA = [
|
|
4
|
+
"obfuscated-or-dynamic-code",
|
|
5
|
+
"secret-bearing-payload",
|
|
6
|
+
"dom-scrape-or-mutation",
|
|
7
|
+
"protected-surface-replay",
|
|
8
|
+
"regulated-data-outside-typed-schema",
|
|
9
|
+
"consent-bypass",
|
|
10
|
+
"unbounded-storage-or-cross-tenant",
|
|
11
|
+
"mutable-supply-chain-or-licensing",
|
|
12
|
+
"checkout-or-compliance-mutation",
|
|
13
|
+
"not-deterministic-testable-reversible",
|
|
14
|
+
"not-fail-closed",
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
export type V84NonportableRefusalCriterion = (typeof V84_NONPORTABLE_REFUSAL_CRITERIA)[number];
|
|
18
|
+
|
|
19
|
+
export const V84_NATIVE_REPLACEMENT_PRIORITY = [
|
|
20
|
+
"reviewed-ws1-adapter-and-actions",
|
|
21
|
+
"reviewed-first-party-storefront-code",
|
|
22
|
+
"declarative-typed-mapping",
|
|
23
|
+
"constrained-server-workflow",
|
|
24
|
+
"pinned-vendor-sdk",
|
|
25
|
+
"redesign",
|
|
26
|
+
"retire",
|
|
27
|
+
] as const;
|
|
28
|
+
|
|
29
|
+
type SourceKind = "tag" | "variable" | "customTemplate";
|
|
30
|
+
type CoachingDecision = "do-not-port";
|
|
31
|
+
type NativeHook = "storefront.action.activated.v1" | "storefront.page.viewed.v2";
|
|
32
|
+
type ActionSelection = "not-applicable" | "fixed" | "owner-selection-required";
|
|
33
|
+
|
|
34
|
+
export interface V84NonportableCodeIntentDossier {
|
|
35
|
+
readonly schemaVersion: 1;
|
|
36
|
+
readonly dossierId: string;
|
|
37
|
+
readonly sourceObject: {
|
|
38
|
+
readonly nodeKey: string;
|
|
39
|
+
readonly kind: SourceKind;
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly type: string | null;
|
|
42
|
+
readonly importedArtifact: "redacted-inert-evidence-only";
|
|
43
|
+
};
|
|
44
|
+
readonly recoveredBusinessIntent: string;
|
|
45
|
+
readonly requiredContract: {
|
|
46
|
+
readonly events: readonly NativeHook[];
|
|
47
|
+
readonly typedData: readonly string[];
|
|
48
|
+
readonly destination: string;
|
|
49
|
+
readonly consent: readonly string[];
|
|
50
|
+
readonly allowedSurfaces: readonly string[];
|
|
51
|
+
readonly excludedSurfaces: readonly string[];
|
|
52
|
+
readonly actionSelection: ActionSelection;
|
|
53
|
+
readonly approvedActionNames: readonly ApprovedMarketingActionName[];
|
|
54
|
+
};
|
|
55
|
+
readonly portabilityReview: {
|
|
56
|
+
readonly decision: CoachingDecision;
|
|
57
|
+
readonly whyOriginalSnippetIsNotPortable: string;
|
|
58
|
+
readonly security: string;
|
|
59
|
+
readonly privacy: string;
|
|
60
|
+
readonly compliance: string;
|
|
61
|
+
readonly refusalCriteria: readonly V84NonportableRefusalCriterion[];
|
|
62
|
+
};
|
|
63
|
+
readonly recommendedTotPort: {
|
|
64
|
+
readonly route: (typeof V84_NATIVE_REPLACEMENT_PRIORITY)[number];
|
|
65
|
+
readonly nativeHook: NativeHook | null;
|
|
66
|
+
readonly owningProductGap: string | null;
|
|
67
|
+
readonly saferAlternative: string;
|
|
68
|
+
readonly migrationPlan: readonly string[];
|
|
69
|
+
readonly status: "not-installed";
|
|
70
|
+
};
|
|
71
|
+
readonly verification: {
|
|
72
|
+
readonly syntheticTests: readonly string[];
|
|
73
|
+
readonly cloneQa: readonly string[];
|
|
74
|
+
readonly rollback: string;
|
|
75
|
+
readonly residualRisk: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface DossierPlan {
|
|
80
|
+
readonly nodeKey: string;
|
|
81
|
+
readonly kind: SourceKind;
|
|
82
|
+
readonly id: string;
|
|
83
|
+
readonly type: string | null;
|
|
84
|
+
readonly dossierId: string;
|
|
85
|
+
readonly intent: string;
|
|
86
|
+
readonly events: readonly NativeHook[];
|
|
87
|
+
readonly data: readonly string[];
|
|
88
|
+
readonly destination: string;
|
|
89
|
+
readonly consent: readonly string[];
|
|
90
|
+
readonly allowed: readonly string[];
|
|
91
|
+
readonly excluded: readonly string[];
|
|
92
|
+
readonly actionSelection: ActionSelection;
|
|
93
|
+
readonly actionNames: readonly ApprovedMarketingActionName[];
|
|
94
|
+
readonly why: string;
|
|
95
|
+
readonly security: string;
|
|
96
|
+
readonly privacy: string;
|
|
97
|
+
readonly compliance: string;
|
|
98
|
+
readonly criteria: readonly V84NonportableRefusalCriterion[];
|
|
99
|
+
readonly route: (typeof V84_NATIVE_REPLACEMENT_PRIORITY)[number];
|
|
100
|
+
readonly hook: NativeHook | null;
|
|
101
|
+
readonly gap: string | null;
|
|
102
|
+
readonly alternative: string;
|
|
103
|
+
readonly plan: readonly string[];
|
|
104
|
+
readonly tests: readonly string[];
|
|
105
|
+
readonly qa: readonly string[];
|
|
106
|
+
readonly rollback: string;
|
|
107
|
+
readonly risk: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const PUBLIC_ONLY = ["public-marketing-pages"] as const;
|
|
111
|
+
const PROTECTED = ["admin", "account", "identity", "age-assurance", "checkout", "payment"] as const;
|
|
112
|
+
const ACTION_HOOK = "storefront.action.activated.v1" as const;
|
|
113
|
+
const PAGE_VIEW_HOOK = "storefront.page.viewed.v2" as const;
|
|
114
|
+
const ALL_APPROVED_ACTION_NAMES = [
|
|
115
|
+
"user_clicked_contact_sales_mktg",
|
|
116
|
+
"user_clicked_create_account_mktg",
|
|
117
|
+
"user_clicked_login_mktg",
|
|
118
|
+
"user_clicked_contact_support_consumer_mktg",
|
|
119
|
+
"user_clicked_contact_support_partner_mktg",
|
|
120
|
+
] as const satisfies readonly ApprovedMarketingActionName[];
|
|
121
|
+
|
|
122
|
+
const PLANS: readonly DossierPlan[] = [
|
|
123
|
+
{
|
|
124
|
+
nodeKey: "tag:4", kind: "tag", id: "4", type: "cvt_88888888_3", dossierId: "v84-hubspot-lead-tag",
|
|
125
|
+
intent: "Send a consented contact-sales or account-creation signal to HubSpot.",
|
|
126
|
+
events: [ACTION_HOOK], data: ["name"],
|
|
127
|
+
destination: "future managed HubSpot destination", consent: ["analytics"], allowed: PUBLIC_ONLY, excluded: PROTECTED,
|
|
128
|
+
actionSelection: "fixed", actionNames: ["user_clicked_contact_sales_mktg", "user_clicked_create_account_mktg"],
|
|
129
|
+
why: "The custom-template tag delegates behavior to imported template code and carries an unresolved destination reference.",
|
|
130
|
+
security: "A template runner would create mutable code and destination authority outside the reviewed adapter catalog.",
|
|
131
|
+
privacy: "Lead identity must not be inferred from page state or forwarded outside a typed, consented server contract.",
|
|
132
|
+
compliance: "Contact and account actions may be forwarded only after purpose-specific consent and destination review.",
|
|
133
|
+
criteria: ["secret-bearing-payload", "dom-scrape-or-mutation", "consent-bypass", "mutable-supply-chain-or-licensing", "not-fail-closed"],
|
|
134
|
+
route: "constrained-server-workflow", hook: ACTION_HOOK, gap: "managed-hubspot-action-destination",
|
|
135
|
+
alternative: "Hold delivery until an owned HubSpot server destination accepts only approved action names and typed fields.",
|
|
136
|
+
plan: ["Map only approved contact-sales and create-account actions.", "Resolve the destination from reviewed server configuration.", "Ship the owned destination with consent, dedupe, timeout, and fail-closed tests."],
|
|
137
|
+
tests: ["Reject non-allowlisted actions and unknown fields.", "Prove missing consent or destination produces zero delivery effects."],
|
|
138
|
+
qa: ["Use an in-memory destination in the diagnostic clone.", "Verify no request, listener, markup, or storage effect occurs from this dossier."],
|
|
139
|
+
rollback: "Remove the owned destination revision; the imported template remains inert and cannot resume.",
|
|
140
|
+
risk: "HubSpot delivery remains intentionally unavailable until the owning product gap is reviewed and shipped.",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
nodeKey: "customTemplate:3", kind: "customTemplate", id: "3", type: null, dossierId: "v84-hubspot-template-definition-primary",
|
|
144
|
+
intent: "Provide the reusable code definition behind the HubSpot lead tag.",
|
|
145
|
+
events: [], data: [], destination: "none", consent: [], allowed: [], excluded: PROTECTED,
|
|
146
|
+
actionSelection: "not-applicable", actionNames: [],
|
|
147
|
+
why: "A custom-template definition is executable supply-chain material, not a portable business configuration.",
|
|
148
|
+
security: "The gallery reference is modified and cannot establish immutable, reviewed behavior.",
|
|
149
|
+
privacy: "The redacted definition cannot prove data minimization or consent enforcement.",
|
|
150
|
+
compliance: "Unknown code cannot be certified for identity, age, checkout, payment, or account surfaces.",
|
|
151
|
+
criteria: ["obfuscated-or-dynamic-code", "regulated-data-outside-typed-schema", "mutable-supply-chain-or-licensing", "not-deterministic-testable-reversible"],
|
|
152
|
+
route: "retire", hook: null, gap: null,
|
|
153
|
+
alternative: "Retire the definition and use the owned HubSpot action destination described by dossier v84-hubspot-lead-tag.",
|
|
154
|
+
plan: ["Preserve only this redacted inventory record for audit.", "Do not copy the definition into any runtime or tenant configuration."],
|
|
155
|
+
tests: ["Assert the definition is represented once and has no payload field."],
|
|
156
|
+
qa: ["Confirm the clone adds no markup, origin, listener, storage, or runtime asset."],
|
|
157
|
+
rollback: "No runtime rollback is needed; retiring inert evidence has no delivery effect.",
|
|
158
|
+
risk: "No vendor behavior is retained from the unverifiable template definition.",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
nodeKey: "customTemplate:8", kind: "customTemplate", id: "8", type: null, dossierId: "v84-hubspot-template-definition-secondary",
|
|
162
|
+
intent: "Provide a second reusable code definition associated with the HubSpot experiment.",
|
|
163
|
+
events: [], data: [], destination: "none", consent: [], allowed: [], excluded: PROTECTED,
|
|
164
|
+
actionSelection: "not-applicable", actionNames: [],
|
|
165
|
+
why: "The second custom-template definition is executable material with no independently verified native contract.",
|
|
166
|
+
security: "Its mutable gallery provenance cannot meet pinned supply-chain review requirements.",
|
|
167
|
+
privacy: "Its redacted implementation cannot demonstrate a closed data schema or bounded retention.",
|
|
168
|
+
compliance: "Unverifiable template behavior cannot operate on regulated storefront surfaces.",
|
|
169
|
+
criteria: ["obfuscated-or-dynamic-code", "unbounded-storage-or-cross-tenant", "mutable-supply-chain-or-licensing", "not-fail-closed"],
|
|
170
|
+
route: "retire", hook: null, gap: null,
|
|
171
|
+
alternative: "Retire the duplicate definition and consolidate the recovered intent into the owned HubSpot destination gap.",
|
|
172
|
+
plan: ["Keep the redacted node identity for accounting.", "Do not install, render, sandbox, or translate the definition."],
|
|
173
|
+
tests: ["Assert this definition has a distinct dossier and no runtime authority."],
|
|
174
|
+
qa: ["Confirm the diagnostic clone remains unchanged outside inert evidence output."],
|
|
175
|
+
rollback: "No runtime rollback is needed because nothing is installed.",
|
|
176
|
+
risk: "Any behavior unique to this definition is deliberately not reproduced.",
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
nodeKey: "tag:18", kind: "tag", id: "18", type: "html", dossierId: "v84-capterra-conversion-pixel",
|
|
180
|
+
intent: "Attribute an approved sign-in marketing action to Capterra.",
|
|
181
|
+
events: [ACTION_HOOK], data: ["name"],
|
|
182
|
+
destination: "future managed Capterra destination", consent: ["analytics"], allowed: PUBLIC_ONLY, excluded: PROTECTED,
|
|
183
|
+
actionSelection: "fixed", actionNames: ["user_clicked_login_mktg"],
|
|
184
|
+
why: "The HTML pixel hides its transport, destination, and field selection inside redacted markup.",
|
|
185
|
+
security: "Re-hosting it could load mutable third-party code or bypass exact-origin controls.",
|
|
186
|
+
privacy: "A sign-in signal must contain no identity, credential, or DOM-derived value.",
|
|
187
|
+
compliance: "Authentication and age-assurance surfaces are excluded even when a marketing action shares a label.",
|
|
188
|
+
criteria: ["dom-scrape-or-mutation", "regulated-data-outside-typed-schema", "consent-bypass", "mutable-supply-chain-or-licensing"],
|
|
189
|
+
route: "constrained-server-workflow", hook: ACTION_HOOK, gap: "managed-capterra-action-destination",
|
|
190
|
+
alternative: "Hold the pixel until an owned server destination can accept the allowlisted login action without user identity.",
|
|
191
|
+
plan: ["Bind only the canonical login marketing action.", "Send a deduplicated anonymous event to an exact reviewed destination."],
|
|
192
|
+
tests: ["Reject identity and credential fields.", "Prove protected surfaces and absent analytics consent produce zero effects."],
|
|
193
|
+
qa: ["Exercise a fake in-memory Capterra receiver only.", "Assert the imported HTML is never rendered or interpreted."],
|
|
194
|
+
rollback: "Disable and remove the owned destination revision without restoring the HTML tag.",
|
|
195
|
+
risk: "Attribution is paused until Capterra support exists in owning product code.",
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
nodeKey: "tag:29", kind: "tag", id: "29", type: "html", dossierId: "v84-linkedin-pageview-loader",
|
|
199
|
+
intent: "Measure consented public marketing page views for LinkedIn attribution.",
|
|
200
|
+
events: [PAGE_VIEW_HOOK], data: ["path"],
|
|
201
|
+
destination: "future managed LinkedIn destination", consent: ["analytics"], allowed: PUBLIC_ONLY, excluded: PROTECTED,
|
|
202
|
+
actionSelection: "not-applicable", actionNames: [],
|
|
203
|
+
why: "A page-load HTML loader grants opaque third-party runtime authority rather than declaring a bounded event mapping.",
|
|
204
|
+
security: "A mutable loader cannot satisfy pinned asset, exact-origin, and deterministic failure requirements.",
|
|
205
|
+
privacy: "Only a canonical public path may be shared; query strings, identity, and page content are excluded.",
|
|
206
|
+
compliance: "The destination must remain off on protected, checkout, payment, identity, and age-assurance surfaces.",
|
|
207
|
+
criteria: ["dom-scrape-or-mutation", "protected-surface-replay", "unbounded-storage-or-cross-tenant", "mutable-supply-chain-or-licensing", "not-deterministic-testable-reversible"],
|
|
208
|
+
route: "reviewed-first-party-storefront-code", hook: PAGE_VIEW_HOOK, gap: "managed-linkedin-pageview-destination",
|
|
209
|
+
alternative: "Hold collection until a reviewed LinkedIn destination subscribes to minimized public page-view events.",
|
|
210
|
+
plan: ["Use the canonical page-view event, not a document observer.", "Allow only data.path on public marketing surfaces after consent."],
|
|
211
|
+
tests: ["Reject queries, fragments, DOM content, and protected routes.", "Prove exact destination origin and dedupe."],
|
|
212
|
+
qa: ["Use an in-memory receiver with a synthetic public path.", "Assert zero loader, CSP, markup, and listener effects."],
|
|
213
|
+
rollback: "Remove the reviewed destination revision; do not restore the loader.",
|
|
214
|
+
risk: "LinkedIn page-view attribution remains unavailable until the owned gap ships.",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
nodeKey: "tag:31", kind: "tag", id: "31", type: "html", dossierId: "v84-g2-action-pixel",
|
|
218
|
+
intent: "Record a consented account-interest action for G2 attribution.",
|
|
219
|
+
events: [ACTION_HOOK], data: ["name"],
|
|
220
|
+
destination: "future managed G2 destination", consent: ["analytics"], allowed: PUBLIC_ONLY, excluded: PROTECTED,
|
|
221
|
+
actionSelection: "owner-selection-required", actionNames: ALL_APPROVED_ACTION_NAMES,
|
|
222
|
+
why: "The HTML pixel cannot prove that it sends only a canonical action or that it avoids protected account context.",
|
|
223
|
+
security: "Opaque markup can mutate the document or initiate unreviewed transport.",
|
|
224
|
+
privacy: "Account identity, age signals, and authentication state must never be derived for attribution.",
|
|
225
|
+
compliance: "Only approved action names on public marketing surfaces may cross the destination boundary.",
|
|
226
|
+
criteria: ["dom-scrape-or-mutation", "regulated-data-outside-typed-schema", "consent-bypass", "checkout-or-compliance-mutation"],
|
|
227
|
+
route: "constrained-server-workflow", hook: ACTION_HOOK, gap: "managed-g2-action-destination",
|
|
228
|
+
alternative: "Hold delivery until a reviewed G2 destination accepts a closed, anonymous action payload.",
|
|
229
|
+
plan: ["Choose one of the five approved marketing action names.", "Deliver only after consent with an opaque event dedupe key."],
|
|
230
|
+
tests: ["Reject unknown actions and protected-surface context.", "Prove retries are bounded and idempotent."],
|
|
231
|
+
qa: ["Use an in-memory receiver and synthetic action.", "Assert no imported markup or destination is activated."],
|
|
232
|
+
rollback: "Disable the owned destination revision and preserve only redacted audit evidence.",
|
|
233
|
+
risk: "G2 action attribution remains intentionally paused pending managed support.",
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
nodeKey: "tag:48", kind: "tag", id: "48", type: "html", dossierId: "v84-g2-sitewide-loader",
|
|
237
|
+
intent: "Load a sitewide G2 attribution capability outside embedded and non-live hosts.",
|
|
238
|
+
events: [PAGE_VIEW_HOOK], data: ["path"],
|
|
239
|
+
destination: "none", consent: ["analytics"], allowed: PUBLIC_ONLY, excluded: PROTECTED,
|
|
240
|
+
actionSelection: "not-applicable", actionNames: [],
|
|
241
|
+
why: "A sitewide HTML loader has broad runtime reach and its exclusions cannot substitute for an allowlisted native surface contract.",
|
|
242
|
+
security: "The loader is mutable supply-chain code with unbounded document and network authority.",
|
|
243
|
+
privacy: "Sitewide observation risks collecting page content, account state, and cross-surface browsing behavior.",
|
|
244
|
+
compliance: "Negative host/path rules do not fail closed and cannot prove checkout, payment, identity, or age-surface exclusion.",
|
|
245
|
+
criteria: ["dom-scrape-or-mutation", "protected-surface-replay", "unbounded-storage-or-cross-tenant", "mutable-supply-chain-or-licensing", "not-fail-closed"],
|
|
246
|
+
route: "retire", hook: null, gap: null,
|
|
247
|
+
alternative: "Retire the sitewide loader; evaluate a future event-scoped G2 adapter only if the narrower action dossier has approved demand.",
|
|
248
|
+
plan: ["Do not recreate negative hostname or path gates.", "Preserve no loader behavior or generic sitewide observer."],
|
|
249
|
+
tests: ["Assert the dossier recommends no runtime hook.", "Assert all protected surfaces remain excluded."],
|
|
250
|
+
qa: ["Confirm clone markup, CSP, listeners, storage, and network counters stay zero."],
|
|
251
|
+
rollback: "No runtime rollback is needed because the loader is never installed.",
|
|
252
|
+
risk: "Broad sitewide attribution is intentionally discontinued.",
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
nodeKey: "variable:38", kind: "variable", id: "38", type: "jsm", dossierId: "v84-page-context-custom-js",
|
|
256
|
+
intent: "Derive a stable page-load context value for downstream marketing rules.",
|
|
257
|
+
events: [PAGE_VIEW_HOOK], data: ["path"], destination: "none", consent: ["analytics"],
|
|
258
|
+
allowed: PUBLIC_ONLY, excluded: PROTECTED,
|
|
259
|
+
actionSelection: "not-applicable", actionNames: [],
|
|
260
|
+
why: "A Custom JavaScript variable is an arbitrary computation with no declared inputs, output schema, or failure behavior.",
|
|
261
|
+
security: "The hidden computation could read globals, storage, DOM state, or secrets.",
|
|
262
|
+
privacy: "Only the platform-owned canonical path is an acceptable input; page content and identity are excluded.",
|
|
263
|
+
compliance: "Derived values must use a closed schema and cannot inspect checkout, payment, identity, or age-assurance state.",
|
|
264
|
+
criteria: ["secret-bearing-payload", "dom-scrape-or-mutation", "regulated-data-outside-typed-schema", "not-deterministic-testable-reversible"],
|
|
265
|
+
route: "declarative-typed-mapping", hook: PAGE_VIEW_HOOK, gap: null,
|
|
266
|
+
alternative: "Replace the computation with a reviewed declarative mapping over data.path if a named consumer still needs it.",
|
|
267
|
+
plan: ["Document the required output enum with the consumer owner.", "Implement a pure total mapping from data.path with an explicit unknown value.", "Delete the mapping if no named consumer remains."],
|
|
268
|
+
tests: ["Table-test every path class and the unknown fallback.", "Prove no DOM, global, storage, query, fragment, or identity input is available."],
|
|
269
|
+
qa: ["Run the mapping against synthetic clone paths only.", "Assert no destination or runtime effect is created by the dossier."],
|
|
270
|
+
rollback: "Remove the declarative mapping and let consumers receive the explicit unknown value.",
|
|
271
|
+
risk: "The recovered fixture cannot establish the original output semantics; consumer confirmation is required before implementing the mapping.",
|
|
272
|
+
},
|
|
273
|
+
] as const;
|
|
274
|
+
|
|
275
|
+
export interface V84NonportableCoachingInput {
|
|
276
|
+
readonly scope: {
|
|
277
|
+
readonly sourceTenant: string;
|
|
278
|
+
readonly sourceMode: string;
|
|
279
|
+
readonly cloneTenant: string;
|
|
280
|
+
readonly destinationMode: string;
|
|
281
|
+
};
|
|
282
|
+
readonly codeExecutionUnsupported: readonly UnresolvedInventoryItem[];
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface V84NonportableCodeCoaching {
|
|
286
|
+
readonly schemaVersion: 1;
|
|
287
|
+
readonly policy: {
|
|
288
|
+
readonly sourceReadOnly: true;
|
|
289
|
+
readonly importedArtifactsInert: true;
|
|
290
|
+
readonly installsOrPublishes: false;
|
|
291
|
+
readonly refusalCriteria: typeof V84_NONPORTABLE_REFUSAL_CRITERIA;
|
|
292
|
+
readonly replacementPriority: typeof V84_NATIVE_REPLACEMENT_PRIORITY;
|
|
293
|
+
};
|
|
294
|
+
readonly dossiers: readonly V84NonportableCodeIntentDossier[];
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function assertExactScope(input: V84NonportableCoachingInput): void {
|
|
298
|
+
if (
|
|
299
|
+
input.scope.sourceTenant !== "tokenoftrust.com" ||
|
|
300
|
+
input.scope.sourceMode !== "read-only-fixture" ||
|
|
301
|
+
input.scope.cloneTenant !== "tokenoftrust.com~clone~gtm-migration-v84" ||
|
|
302
|
+
input.scope.destinationMode !== "offline-in-memory-only"
|
|
303
|
+
) throw new Error("Nonportable coaching is restricted to the exact read-only diagnostic clone proof.");
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function itemByNodeKey(items: readonly UnresolvedInventoryItem[]): Map<string, UnresolvedInventoryItem> {
|
|
307
|
+
const result = new Map<string, UnresolvedInventoryItem>();
|
|
308
|
+
for (const item of items) {
|
|
309
|
+
if (result.has(item.nodeKey)) throw new Error("The nonportable coaching inventory contains a duplicate object.");
|
|
310
|
+
result.set(item.nodeKey, item);
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function buildDossier(plan: DossierPlan, item: UnresolvedInventoryItem): V84NonportableCodeIntentDossier {
|
|
316
|
+
if (
|
|
317
|
+
item.kind !== plan.kind || item.id !== plan.id || item.type !== plan.type ||
|
|
318
|
+
item.disposition !== "unsupported-by-design" || item.reasonCode !== "code-execution-unsupported"
|
|
319
|
+
) throw new Error("The nonportable coaching inventory no longer matches the reviewed v84 object contract.");
|
|
320
|
+
return {
|
|
321
|
+
schemaVersion: 1,
|
|
322
|
+
dossierId: plan.dossierId,
|
|
323
|
+
sourceObject: { nodeKey: item.nodeKey, kind: plan.kind, id: plan.id, type: plan.type, importedArtifact: "redacted-inert-evidence-only" },
|
|
324
|
+
recoveredBusinessIntent: plan.intent,
|
|
325
|
+
requiredContract: {
|
|
326
|
+
events: plan.events,
|
|
327
|
+
typedData: plan.data,
|
|
328
|
+
destination: plan.destination,
|
|
329
|
+
consent: plan.consent,
|
|
330
|
+
allowedSurfaces: plan.allowed,
|
|
331
|
+
excludedSurfaces: plan.excluded,
|
|
332
|
+
actionSelection: plan.actionSelection,
|
|
333
|
+
approvedActionNames: plan.actionNames,
|
|
334
|
+
},
|
|
335
|
+
portabilityReview: { decision: "do-not-port", whyOriginalSnippetIsNotPortable: plan.why, security: plan.security, privacy: plan.privacy, compliance: plan.compliance, refusalCriteria: plan.criteria },
|
|
336
|
+
recommendedTotPort: { route: plan.route, nativeHook: plan.hook, owningProductGap: plan.gap, saferAlternative: plan.alternative, migrationPlan: plan.plan, status: "not-installed" },
|
|
337
|
+
verification: { syntheticTests: plan.tests, cloneQa: plan.qa, rollback: plan.rollback, residualRisk: plan.risk },
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Convert the exact eight inert unsupported v84 records into reviewed coaching.
|
|
343
|
+
* Only stable object identity is read from the import; no source name,
|
|
344
|
+
* explanation, raw field, markup, template body, or script text is propagated.
|
|
345
|
+
*/
|
|
346
|
+
export function buildV84NonportableCodeCoaching(input: V84NonportableCoachingInput): V84NonportableCodeCoaching {
|
|
347
|
+
assertExactScope(input);
|
|
348
|
+
if (input.codeExecutionUnsupported.length !== PLANS.length) {
|
|
349
|
+
throw new Error("The nonportable coaching inventory must contain exactly eight objects.");
|
|
350
|
+
}
|
|
351
|
+
const byNodeKey = itemByNodeKey(input.codeExecutionUnsupported);
|
|
352
|
+
const dossiers = PLANS.map((plan) => {
|
|
353
|
+
const item = byNodeKey.get(plan.nodeKey);
|
|
354
|
+
if (!item) throw new Error("The nonportable coaching inventory is missing a reviewed v84 object.");
|
|
355
|
+
return buildDossier(plan, item);
|
|
356
|
+
});
|
|
357
|
+
return {
|
|
358
|
+
schemaVersion: 1,
|
|
359
|
+
policy: {
|
|
360
|
+
sourceReadOnly: true,
|
|
361
|
+
importedArtifactsInert: true,
|
|
362
|
+
installsOrPublishes: false,
|
|
363
|
+
refusalCriteria: V84_NONPORTABLE_REFUSAL_CRITERIA,
|
|
364
|
+
replacementPriority: V84_NATIVE_REPLACEMENT_PRIORITY,
|
|
365
|
+
},
|
|
366
|
+
dossiers,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/** Exact reviewed input boundary for the v84 eight-route dogfood gate. */
|
|
2
|
+
import type { V84CloneMigrationEvidence } from "./v84CloneMigrationEvidence.js";
|
|
3
|
+
import type { V84NonportableCodeIntentDossier } from "./v84NonportableCodeCoaching.js";
|
|
4
|
+
|
|
5
|
+
const SOURCE = "tokenoftrust.com";
|
|
6
|
+
const CLONE = "tokenoftrust.com~clone~gtm-migration-v84";
|
|
7
|
+
const FINGERPRINT_REFUSAL = "The reviewed eight-dossier identity and contract fingerprint changed.";
|
|
8
|
+
|
|
9
|
+
function snapshotPlainData(value: unknown, ancestors = new Set<object>()): unknown {
|
|
10
|
+
const invalid = (): never => { throw new Error(FINGERPRINT_REFUSAL); };
|
|
11
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
12
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
13
|
+
if (typeof value !== "object") return invalid();
|
|
14
|
+
if (ancestors.has(value)) return invalid();
|
|
15
|
+
ancestors.add(value);
|
|
16
|
+
try {
|
|
17
|
+
const array = Array.isArray(value);
|
|
18
|
+
if (Object.getPrototypeOf(value) !== (array ? Array.prototype : Object.prototype)) {
|
|
19
|
+
return invalid();
|
|
20
|
+
}
|
|
21
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
22
|
+
const keys = Reflect.ownKeys(descriptors);
|
|
23
|
+
if (keys.some((key) => typeof key !== "string" || key === "toJSON")) {
|
|
24
|
+
return invalid();
|
|
25
|
+
}
|
|
26
|
+
if (array) {
|
|
27
|
+
const length = descriptors.length;
|
|
28
|
+
if (!length || !("value" in length) || !Number.isSafeInteger(length.value) || length.value < 0) {
|
|
29
|
+
return invalid();
|
|
30
|
+
}
|
|
31
|
+
const expectedKeys = [...Array.from({ length: length.value }, (_, index) => String(index)), "length"];
|
|
32
|
+
if (JSON.stringify(keys.sort()) !== JSON.stringify(expectedKeys.sort())) return invalid();
|
|
33
|
+
return Object.freeze(Array.from({ length: length.value }, (_, index) => {
|
|
34
|
+
const descriptor = descriptors[String(index)];
|
|
35
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) return invalid();
|
|
36
|
+
return snapshotPlainData(descriptor.value, ancestors);
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
const copy: Record<string, unknown> = {};
|
|
40
|
+
for (const key of keys) {
|
|
41
|
+
const descriptor = descriptors[key as string];
|
|
42
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) return invalid();
|
|
43
|
+
Object.defineProperty(copy, key, {
|
|
44
|
+
enumerable: true, configurable: false, writable: false,
|
|
45
|
+
value: snapshotPlainData(descriptor.value, ancestors),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return Object.freeze(copy);
|
|
49
|
+
} finally {
|
|
50
|
+
ancestors.delete(value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ownPlainData(value: unknown, key: string): unknown {
|
|
55
|
+
if (value === null || typeof value !== "object" || Object.getPrototypeOf(value) !== Object.prototype) {
|
|
56
|
+
throw new Error(FINGERPRINT_REFUSAL);
|
|
57
|
+
}
|
|
58
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
59
|
+
for (const ownKey of Reflect.ownKeys(descriptors)) {
|
|
60
|
+
const descriptor = descriptors[ownKey as string];
|
|
61
|
+
if (typeof ownKey !== "string" || ownKey === "toJSON" ||
|
|
62
|
+
!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
63
|
+
throw new Error(FINGERPRINT_REFUSAL);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const selected = descriptors[key];
|
|
67
|
+
if (!selected || !("value" in selected)) throw new Error(FINGERPRINT_REFUSAL);
|
|
68
|
+
return selected.value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function safeBoundary(evidence: unknown, catalogAdapterIds: unknown) {
|
|
72
|
+
try {
|
|
73
|
+
const scope = snapshotPlainData(ownPlainData(evidence, "scope"));
|
|
74
|
+
const nonportableCodeCoaching = snapshotPlainData(ownPlainData(evidence, "nonportableCodeCoaching"));
|
|
75
|
+
const analysis = ownPlainData(evidence, "analysis");
|
|
76
|
+
const graph = ownPlainData(analysis, "graph");
|
|
77
|
+
const edges = snapshotPlainData(ownPlainData(graph, "edges"));
|
|
78
|
+
return {
|
|
79
|
+
evidence: { scope, nonportableCodeCoaching, analysis: { graph: { edges } } } as V84CloneMigrationEvidence,
|
|
80
|
+
catalogAdapterIds: snapshotPlainData(catalogAdapterIds) as readonly string[],
|
|
81
|
+
};
|
|
82
|
+
} catch {
|
|
83
|
+
throw new Error(FINGERPRINT_REFUSAL);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function fingerprint(item: V84NonportableCodeIntentDossier): string {
|
|
88
|
+
return JSON.stringify([
|
|
89
|
+
item.schemaVersion, item.sourceObject.nodeKey, item.sourceObject.kind, item.sourceObject.id,
|
|
90
|
+
item.sourceObject.type, item.sourceObject.importedArtifact, item.dossierId,
|
|
91
|
+
item.recoveredBusinessIntent, item.requiredContract.events,
|
|
92
|
+
item.requiredContract.typedData, item.requiredContract.destination,
|
|
93
|
+
item.requiredContract.consent, item.requiredContract.allowedSurfaces,
|
|
94
|
+
item.requiredContract.excludedSurfaces, item.requiredContract.actionSelection,
|
|
95
|
+
item.requiredContract.approvedActionNames, item.recommendedTotPort.route,
|
|
96
|
+
item.recommendedTotPort.nativeHook, item.recommendedTotPort.owningProductGap,
|
|
97
|
+
item.recommendedTotPort.saferAlternative, item.recommendedTotPort.status,
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const PROTECTED = ["admin", "account", "identity", "age-assurance", "checkout", "payment"];
|
|
102
|
+
const ACTIONS = [
|
|
103
|
+
"user_clicked_contact_sales_mktg", "user_clicked_create_account_mktg",
|
|
104
|
+
"user_clicked_login_mktg", "user_clicked_contact_support_consumer_mktg",
|
|
105
|
+
"user_clicked_contact_support_partner_mktg",
|
|
106
|
+
];
|
|
107
|
+
const row = (...value: unknown[]) => JSON.stringify(value);
|
|
108
|
+
const EXPECTED_FINGERPRINTS = [
|
|
109
|
+
row(1, "tag:4", "tag", "4", "cvt_88888888_3", "redacted-inert-evidence-only", "v84-hubspot-lead-tag",
|
|
110
|
+
"Send a consented contact-sales or account-creation signal to HubSpot.", ["storefront.action.activated.v1"], ["name"],
|
|
111
|
+
"future managed HubSpot destination", ["analytics"], ["public-marketing-pages"], PROTECTED, "fixed", ACTIONS.slice(0, 2),
|
|
112
|
+
"constrained-server-workflow", "storefront.action.activated.v1", "managed-hubspot-action-destination",
|
|
113
|
+
"Hold delivery until an owned HubSpot server destination accepts only approved action names and typed fields.", "not-installed"),
|
|
114
|
+
row(1, "customTemplate:3", "customTemplate", "3", null, "redacted-inert-evidence-only", "v84-hubspot-template-definition-primary",
|
|
115
|
+
"Provide the reusable code definition behind the HubSpot lead tag.", [], [], "none", [], [], PROTECTED, "not-applicable", [],
|
|
116
|
+
"retire", null, null,
|
|
117
|
+
"Retire the definition and use the owned HubSpot action destination described by dossier v84-hubspot-lead-tag.", "not-installed"),
|
|
118
|
+
row(1, "customTemplate:8", "customTemplate", "8", null, "redacted-inert-evidence-only", "v84-hubspot-template-definition-secondary",
|
|
119
|
+
"Provide a second reusable code definition associated with the HubSpot experiment.", [], [], "none", [], [], PROTECTED, "not-applicable", [],
|
|
120
|
+
"retire", null, null,
|
|
121
|
+
"Retire the duplicate definition and consolidate the recovered intent into the owned HubSpot destination gap.", "not-installed"),
|
|
122
|
+
row(1, "tag:18", "tag", "18", "html", "redacted-inert-evidence-only", "v84-capterra-conversion-pixel",
|
|
123
|
+
"Attribute an approved sign-in marketing action to Capterra.", ["storefront.action.activated.v1"], ["name"],
|
|
124
|
+
"future managed Capterra destination", ["analytics"], ["public-marketing-pages"], PROTECTED, "fixed", [ACTIONS[2]],
|
|
125
|
+
"constrained-server-workflow", "storefront.action.activated.v1", "managed-capterra-action-destination",
|
|
126
|
+
"Hold the pixel until an owned server destination can accept the allowlisted login action without user identity.", "not-installed"),
|
|
127
|
+
row(1, "tag:29", "tag", "29", "html", "redacted-inert-evidence-only", "v84-linkedin-pageview-loader",
|
|
128
|
+
"Measure consented public marketing page views for LinkedIn attribution.", ["storefront.page.viewed.v2"], ["path"],
|
|
129
|
+
"future managed LinkedIn destination", ["analytics"], ["public-marketing-pages"], PROTECTED, "not-applicable", [],
|
|
130
|
+
"reviewed-first-party-storefront-code", "storefront.page.viewed.v2", "managed-linkedin-pageview-destination",
|
|
131
|
+
"Hold collection until a reviewed LinkedIn destination subscribes to minimized public page-view events.", "not-installed"),
|
|
132
|
+
row(1, "tag:31", "tag", "31", "html", "redacted-inert-evidence-only", "v84-g2-action-pixel",
|
|
133
|
+
"Record a consented account-interest action for G2 attribution.", ["storefront.action.activated.v1"], ["name"],
|
|
134
|
+
"future managed G2 destination", ["analytics"], ["public-marketing-pages"], PROTECTED, "owner-selection-required", ACTIONS,
|
|
135
|
+
"constrained-server-workflow", "storefront.action.activated.v1", "managed-g2-action-destination",
|
|
136
|
+
"Hold delivery until a reviewed G2 destination accepts a closed, anonymous action payload.", "not-installed"),
|
|
137
|
+
row(1, "tag:48", "tag", "48", "html", "redacted-inert-evidence-only", "v84-g2-sitewide-loader",
|
|
138
|
+
"Load a sitewide G2 attribution capability outside embedded and non-live hosts.", ["storefront.page.viewed.v2"], ["path"],
|
|
139
|
+
"none", ["analytics"], ["public-marketing-pages"], PROTECTED, "not-applicable", [], "retire", null, null,
|
|
140
|
+
"Retire the sitewide loader; evaluate a future event-scoped G2 adapter only if the narrower action dossier has approved demand.", "not-installed"),
|
|
141
|
+
row(1, "variable:38", "variable", "38", "jsm", "redacted-inert-evidence-only", "v84-page-context-custom-js",
|
|
142
|
+
"Derive a stable page-load context value for downstream marketing rules.", ["storefront.page.viewed.v2"], ["path"],
|
|
143
|
+
"none", ["analytics"], ["public-marketing-pages"], PROTECTED, "not-applicable", [],
|
|
144
|
+
"declarative-typed-mapping", "storefront.page.viewed.v2", null,
|
|
145
|
+
"Replace the computation with a reviewed declarative mapping over data.path if a named consumer still needs it.", "not-installed"),
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
function assertGraph(evidence: V84CloneMigrationEvidence): void {
|
|
149
|
+
const edges = evidence.analysis.graph.edges;
|
|
150
|
+
const has = (from: string, to: string, kind: string) => edges.some((edge) =>
|
|
151
|
+
edge.from === from && edge.to === to && edge.kind === kind);
|
|
152
|
+
if (!has("tag:4", "customTemplate:3", "usesTemplate") ||
|
|
153
|
+
edges.some((edge) => edge.to === "customTemplate:8")) {
|
|
154
|
+
throw new Error("The reviewed template dependency graph changed.");
|
|
155
|
+
}
|
|
156
|
+
if (!has("trigger:39", "variable:38", "references") ||
|
|
157
|
+
edges.some((edge) => edge.from.startsWith("tag:") && edge.to === "trigger:39")) {
|
|
158
|
+
throw new Error("The Custom JS consumer graph changed.");
|
|
159
|
+
}
|
|
160
|
+
const tag48 = edges.filter((edge) => edge.from === "tag:48")
|
|
161
|
+
.map((edge) => `${edge.kind}:${edge.to}`).sort();
|
|
162
|
+
const expected = ["blocks:trigger:10", "blocks:trigger:11", "blocks:trigger:42", "blocks:trigger:9", "fires:builtInTrigger:2147479553"];
|
|
163
|
+
if (JSON.stringify(tag48) !== JSON.stringify(expected)) throw new Error("The tag:48 retirement graph changed.");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Refuse any type-shaped dossier, scope, graph, or catalog substitution. */
|
|
167
|
+
export function assertExactV84DogfoodContract(
|
|
168
|
+
evidence: V84CloneMigrationEvidence,
|
|
169
|
+
catalogAdapterIds: readonly string[],
|
|
170
|
+
): { readonly evidence: V84CloneMigrationEvidence; readonly catalogAdapterIds: readonly string[] } {
|
|
171
|
+
const safe = safeBoundary(evidence, catalogAdapterIds);
|
|
172
|
+
if (safe.evidence.scope.sourceTenant !== SOURCE || safe.evidence.scope.sourceMode !== "read-only-fixture" ||
|
|
173
|
+
safe.evidence.scope.cloneTenant !== CLONE || safe.evidence.scope.destinationMode !== "offline-in-memory-only") {
|
|
174
|
+
throw new Error("The dogfood evidence is outside the exact diagnostic clone.");
|
|
175
|
+
}
|
|
176
|
+
const expectedCatalog = ["platform.amplitude", "platform.google-measurement", "platform.meta-pixel"];
|
|
177
|
+
if (JSON.stringify([...safe.catalogAdapterIds].sort()) !== JSON.stringify(expectedCatalog)) {
|
|
178
|
+
throw new Error("The reviewed native adapter catalog changed.");
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const actual = safe.evidence.nonportableCodeCoaching.dossiers.map(fingerprint);
|
|
182
|
+
if (JSON.stringify(actual) !== JSON.stringify(EXPECTED_FINGERPRINTS)) throw new Error(FINGERPRINT_REFUSAL);
|
|
183
|
+
} catch {
|
|
184
|
+
throw new Error(FINGERPRINT_REFUSAL);
|
|
185
|
+
}
|
|
186
|
+
assertGraph(safe.evidence);
|
|
187
|
+
return safe;
|
|
188
|
+
}
|