@tokenoftrust/storefront-runner 1.4.2-rc.0 → 2.0.1
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/dev-plugins/tenant-hot-reload.mjs +8 -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 +18 -10
- 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 +114 -17
- package/apps/storefront/src/lib/blog/markdown.ts +1 -1
- package/apps/storefront/src/lib/blog/provider.ts +76 -9
- 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 +203 -69
- 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 +42 -31
- package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +8 -3
- package/apps/storefront/src/pages/style-guide/[tenant]/guide/[theme].astro +6 -2
- package/apps/storefront/src/pages/style-guide/[tenant]/index.astro +6 -2
- package/apps/storefront/src/pages/style-guide/index.astro +19 -5
- 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/src/themes/tenants/index.ts +19 -7
- 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 +136 -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/build/copy-tenant-assets.mjs +12 -5
- package/scripts/dev/ai-edit.mjs +2 -1
- 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 +3 -2
- package/scripts/tot-dev.mjs +5 -4
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The merchant consent configuration — the tenant-approval surface that FEEDS the
|
|
3
|
+
* neutral consent broker (ext-policy-03 `consent-broker.ts`). A merchant declares which
|
|
4
|
+
* consent purposes exist, each one's legal basis and default state, and (optionally) a
|
|
5
|
+
* CMP adapter; this module validates that declaration FAIL-CLOSED and materializes it
|
|
6
|
+
* into the {@link TenantConsentPolicy} the broker is constructed from, plus the
|
|
7
|
+
* default-state seed the broker starts at.
|
|
8
|
+
*
|
|
9
|
+
* The broker is the single source of truth for what a shopper is eligible for at
|
|
10
|
+
* runtime; this is where a tenant's decisions about that broker are made, validated,
|
|
11
|
+
* and turned into broker inputs. Nothing here grants anything at runtime — it only
|
|
12
|
+
* approves which purposes may EVER become eligible and what their pre-interaction
|
|
13
|
+
* default is.
|
|
14
|
+
*
|
|
15
|
+
* Fail-closed contract (each clause is a release gate):
|
|
16
|
+
* - An unknown/unlisted purpose is rejected — an invalid purpose mapping blocks.
|
|
17
|
+
* - `essential` is implicit and platform-owned; a config may not redeclare it.
|
|
18
|
+
* - A `consent` legal-basis purpose may NOT default to granted — a shopper must
|
|
19
|
+
* opt in; only `legitimate-interest` may default granted (opt-out).
|
|
20
|
+
* - A CMP adapter may be selected only from DEMONSTRATED demand
|
|
21
|
+
* (`consent-cmp-demand.ts`); with no demand evidence every CMP choice is rejected.
|
|
22
|
+
*/
|
|
23
|
+
import {
|
|
24
|
+
CONSENT_PURPOSES,
|
|
25
|
+
type ConsentPurpose,
|
|
26
|
+
} from "../integration-capabilities.js";
|
|
27
|
+
import { CONSENT_CONFIG_SCHEMA_VERSION } from "./version.js";
|
|
28
|
+
import {
|
|
29
|
+
ConsentBroker,
|
|
30
|
+
type ConsentDecision,
|
|
31
|
+
type ConsentLegalBasis,
|
|
32
|
+
type TenantConsentPolicy,
|
|
33
|
+
} from "./consent-broker.js";
|
|
34
|
+
import {
|
|
35
|
+
Violations,
|
|
36
|
+
reqObject,
|
|
37
|
+
reqEnum,
|
|
38
|
+
reqLiteral,
|
|
39
|
+
reqArray,
|
|
40
|
+
optString,
|
|
41
|
+
rejectUnknownKeys,
|
|
42
|
+
isPlainObject,
|
|
43
|
+
type ContractResult,
|
|
44
|
+
} from "./result.js";
|
|
45
|
+
import {
|
|
46
|
+
DEFAULT_CMP_DEMAND_THRESHOLD,
|
|
47
|
+
isCmpSelectable,
|
|
48
|
+
type CmpDemandLedger,
|
|
49
|
+
} from "./consent-cmp-demand.js";
|
|
50
|
+
|
|
51
|
+
/** `essential` is always on and platform-owned; it is never a merchant-configurable purpose. */
|
|
52
|
+
const ESSENTIAL: ConsentPurpose = "essential";
|
|
53
|
+
|
|
54
|
+
const LEGAL_BASES: readonly ConsentLegalBasis[] = ["consent", "legitimate-interest"];
|
|
55
|
+
const DECISIONS: readonly ConsentDecision[] = ["granted", "denied"];
|
|
56
|
+
|
|
57
|
+
/** One merchant-configured purpose: whether it exists, its basis, and its default state. */
|
|
58
|
+
export interface ConsentPurposeConfig {
|
|
59
|
+
purpose: ConsentPurpose;
|
|
60
|
+
legalBasis: ConsentLegalBasis;
|
|
61
|
+
/** What a fresh shopper sees before any CMP/banner interaction. */
|
|
62
|
+
defaultState: ConsentDecision;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The merchant's CMP choice. `none` uses the native banner only; `cmp` names an adapter. */
|
|
66
|
+
export type ConsentCmpChoice =
|
|
67
|
+
| { mode: "none" }
|
|
68
|
+
| { mode: "cmp"; adapterId: string };
|
|
69
|
+
|
|
70
|
+
/** The whole tenant consent configuration — a closed, versioned record. */
|
|
71
|
+
export interface TenantConsentConfig {
|
|
72
|
+
schemaVersion: typeof CONSENT_CONFIG_SCHEMA_VERSION;
|
|
73
|
+
purposes: readonly ConsentPurposeConfig[];
|
|
74
|
+
cmp: ConsentCmpChoice;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Options that decide whether a CMP choice is admissible. */
|
|
78
|
+
export interface ConsentConfigValidationOptions {
|
|
79
|
+
/** The demand ledger a CMP choice is checked against — no ledger means no CMP is selectable. */
|
|
80
|
+
demand?: CmpDemandLedger;
|
|
81
|
+
/** Distinct-tenant demand a CMP must have demonstrated to be selectable. */
|
|
82
|
+
cmpDemandThreshold?: number;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const PURPOSE_KEYS = ["purpose", "legalBasis", "defaultState"];
|
|
86
|
+
const CONFIG_KEYS = ["schemaVersion", "purposes", "cmp"];
|
|
87
|
+
const CMP_KEYS = ["mode", "adapterId"];
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Validate a raw consent configuration fail-closed. Any unknown field, unknown purpose,
|
|
91
|
+
* a redeclared `essential`, a `consent`-basis purpose that defaults to granted, a
|
|
92
|
+
* duplicate purpose, or a CMP adapter without demonstrated demand yields structured
|
|
93
|
+
* violations and NO config — a caller can never persist or publish an invalid mapping.
|
|
94
|
+
*/
|
|
95
|
+
export function validateConsentConfig(
|
|
96
|
+
raw: unknown,
|
|
97
|
+
options: ConsentConfigValidationOptions = {},
|
|
98
|
+
): ContractResult<TenantConsentConfig> {
|
|
99
|
+
const v = new Violations();
|
|
100
|
+
const root = reqObject(raw, v, "");
|
|
101
|
+
if (!root) return { ok: false, violations: v.items };
|
|
102
|
+
rejectUnknownKeys(root, CONFIG_KEYS, v, "");
|
|
103
|
+
|
|
104
|
+
reqLiteral(root, "schemaVersion", CONSENT_CONFIG_SCHEMA_VERSION, v, "");
|
|
105
|
+
|
|
106
|
+
const purposes = validatePurposes(root, v);
|
|
107
|
+
const cmp = validateCmp(root, v, options);
|
|
108
|
+
|
|
109
|
+
if (!v.ok) return { ok: false, violations: v.items };
|
|
110
|
+
return {
|
|
111
|
+
ok: true,
|
|
112
|
+
value: {
|
|
113
|
+
schemaVersion: CONSENT_CONFIG_SCHEMA_VERSION,
|
|
114
|
+
purposes: purposes!,
|
|
115
|
+
cmp: cmp!,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function validatePurposes(
|
|
121
|
+
root: Record<string, unknown>,
|
|
122
|
+
v: Violations,
|
|
123
|
+
): ConsentPurposeConfig[] | undefined {
|
|
124
|
+
const arr = reqArray(root, "purposes", v, "");
|
|
125
|
+
if (!arr) return undefined;
|
|
126
|
+
const out: ConsentPurposeConfig[] = [];
|
|
127
|
+
const seen = new Set<ConsentPurpose>();
|
|
128
|
+
|
|
129
|
+
arr.forEach((entry, i) => {
|
|
130
|
+
const path = `purposes[${i}]`;
|
|
131
|
+
if (!isPlainObject(entry)) {
|
|
132
|
+
v.add(path, "type", "Expected a purpose object.");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
rejectUnknownKeys(entry, PURPOSE_KEYS, v, path);
|
|
136
|
+
|
|
137
|
+
const purpose = reqEnum<ConsentPurpose>(entry, "purpose", CONSENT_PURPOSES, v, path);
|
|
138
|
+
const legalBasis = reqEnum<ConsentLegalBasis>(entry, "legalBasis", LEGAL_BASES, v, path);
|
|
139
|
+
const defaultState = reqEnum<ConsentDecision>(entry, "defaultState", DECISIONS, v, path);
|
|
140
|
+
if (!purpose || !legalBasis || !defaultState) return;
|
|
141
|
+
|
|
142
|
+
if (purpose === ESSENTIAL) {
|
|
143
|
+
// `essential` is always granted and platform-owned; it is never a merchant decision.
|
|
144
|
+
v.add(`${path}.purpose`, "essential_is_implicit", "`essential` is always on and cannot be configured.");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (seen.has(purpose)) {
|
|
148
|
+
v.add(`${path}.purpose`, "duplicate", `Duplicate purpose "${purpose}"; duplicates are rejected.`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
seen.add(purpose);
|
|
152
|
+
|
|
153
|
+
if (legalBasis === "consent" && defaultState === "granted") {
|
|
154
|
+
// A consent-basis purpose must default to denied — a shopper opts in, never pre-granted.
|
|
155
|
+
v.add(
|
|
156
|
+
`${path}.defaultState`,
|
|
157
|
+
"consent_default_grant_forbidden",
|
|
158
|
+
`Purpose "${purpose}" has legal basis "consent"; its default state must be "denied" (opt-in), not "granted".`,
|
|
159
|
+
);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
out.push({ purpose, legalBasis, defaultState });
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function validateCmp(
|
|
170
|
+
root: Record<string, unknown>,
|
|
171
|
+
v: Violations,
|
|
172
|
+
options: ConsentConfigValidationOptions,
|
|
173
|
+
): ConsentCmpChoice | undefined {
|
|
174
|
+
const cmp = reqObject(root["cmp"], v, "cmp");
|
|
175
|
+
if (!cmp) return undefined;
|
|
176
|
+
rejectUnknownKeys(cmp, CMP_KEYS, v, "cmp");
|
|
177
|
+
const mode = reqEnum<"none" | "cmp">(cmp, "mode", ["none", "cmp"], v, "cmp");
|
|
178
|
+
if (!mode) return undefined;
|
|
179
|
+
|
|
180
|
+
if (mode === "none") return { mode: "none" };
|
|
181
|
+
|
|
182
|
+
const adapterId = optString(cmp, "adapterId", v, "cmp");
|
|
183
|
+
if (!adapterId) {
|
|
184
|
+
v.add("cmp.adapterId", "type", 'A CMP choice ("cmp") requires a non-empty "adapterId".');
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
const ledger = options.demand ?? { signals: [] };
|
|
188
|
+
const threshold = options.cmpDemandThreshold ?? DEFAULT_CMP_DEMAND_THRESHOLD;
|
|
189
|
+
if (!isCmpSelectable(ledger, adapterId, threshold)) {
|
|
190
|
+
v.add(
|
|
191
|
+
"cmp.adapterId",
|
|
192
|
+
"cmp_no_demand",
|
|
193
|
+
`CMP adapter "${adapterId}" has not demonstrated the demand required to be selectable; a CMP is chosen from demonstrated demand, not a hardcoded list.`,
|
|
194
|
+
);
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
return { mode: "cmp", adapterId };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Project a validated config onto the {@link TenantConsentPolicy} the broker is
|
|
202
|
+
* constructed from: every configured purpose with its legal basis. `essential` is left
|
|
203
|
+
* implicit (the broker adds it). This is the tenant-approval half of what feeds the broker.
|
|
204
|
+
*/
|
|
205
|
+
export function toTenantConsentPolicy(config: TenantConsentConfig): TenantConsentPolicy {
|
|
206
|
+
return {
|
|
207
|
+
purposes: config.purposes.map((p) => ({ purpose: p.purpose, legalBasis: p.legalBasis })),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* The default-state seed applied to a fresh broker — the decisions a shopper starts at
|
|
213
|
+
* before any interaction. Only purposes configured to default `granted` (which the
|
|
214
|
+
* validator restricts to `legitimate-interest`) contribute; `consent`-basis purposes
|
|
215
|
+
* contribute nothing and stay denied until an affirmative decision grants them.
|
|
216
|
+
*/
|
|
217
|
+
export function defaultDecisionSeed(
|
|
218
|
+
config: TenantConsentConfig,
|
|
219
|
+
): Partial<Record<ConsentPurpose, ConsentDecision>> {
|
|
220
|
+
const seed: Partial<Record<ConsentPurpose, ConsentDecision>> = {};
|
|
221
|
+
for (const p of config.purposes) {
|
|
222
|
+
if (p.defaultState === "granted") seed[p.purpose] = "granted";
|
|
223
|
+
}
|
|
224
|
+
return seed;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Build the neutral consent broker a validated config describes: constructed from the
|
|
229
|
+
* tenant policy and advanced to the configured default state. This is the concrete seam
|
|
230
|
+
* by which a merchant's consent configuration feeds the ext-policy-03 broker — the same
|
|
231
|
+
* broker instance the browser loader and server destination filter then read.
|
|
232
|
+
*/
|
|
233
|
+
export function buildTenantConsentBroker(config: TenantConsentConfig): ConsentBroker {
|
|
234
|
+
const broker = new ConsentBroker(toTenantConsentPolicy(config));
|
|
235
|
+
const seed = defaultDecisionSeed(config);
|
|
236
|
+
if (Object.keys(seed).length > 0) broker.setDecisions(seed);
|
|
237
|
+
return broker;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The purposes a destination requires that the tenant has NOT approved to exist — the
|
|
242
|
+
* unmet consent dependencies the admin surface displays before publish. `essential` is
|
|
243
|
+
* always satisfied; an unknown purpose is treated as unmet (fail closed).
|
|
244
|
+
*/
|
|
245
|
+
export function unmetConsentDependencies(
|
|
246
|
+
config: TenantConsentConfig,
|
|
247
|
+
required: readonly ConsentPurpose[],
|
|
248
|
+
): ConsentPurpose[] {
|
|
249
|
+
const approved = new Set<ConsentPurpose>([ESSENTIAL, ...config.purposes.map((p) => p.purpose)]);
|
|
250
|
+
const unmet: ConsentPurpose[] = [];
|
|
251
|
+
for (const purpose of required) {
|
|
252
|
+
if (!approved.has(purpose) && !unmet.includes(purpose)) unmet.push(purpose);
|
|
253
|
+
}
|
|
254
|
+
return unmet;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** An empty, valid configuration: no purpose approved beyond the implicit essential floor, no CMP. */
|
|
258
|
+
export function emptyConsentConfig(): TenantConsentConfig {
|
|
259
|
+
return { schemaVersion: CONSENT_CONFIG_SCHEMA_VERSION, purposes: [], cmp: { mode: "none" } };
|
|
260
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consent preview — proves the exact defaults and updates a shopper would see under a
|
|
3
|
+
* given merchant consent configuration, by driving the real ext-policy-03 broker
|
|
4
|
+
* (`consent-broker.ts`) the config feeds. Preview is not a mock: it constructs the same
|
|
5
|
+
* broker `buildTenantConsentBroker` produces, then replays a sequence of shopper/CMP
|
|
6
|
+
* updates, recording the resulting eligibility at each step.
|
|
7
|
+
*
|
|
8
|
+
* Two acceptance guarantees fall out of running the real broker:
|
|
9
|
+
* - The FIRST step is what a fresh shopper sees before interacting — the configured
|
|
10
|
+
* defaults, demonstrably.
|
|
11
|
+
* - A `cmp-removed` step can only NARROW eligibility versus the step before it —
|
|
12
|
+
* disabling a CMP never grants a purpose. {@link cmpDisableNarrows} is the witness;
|
|
13
|
+
* preview records it per removal step, and a broadening removal is an invariant
|
|
14
|
+
* violation surfaced on the step.
|
|
15
|
+
*
|
|
16
|
+
* Pure and edge-safe: config + actions in, snapshots out. No I/O, no wall clock.
|
|
17
|
+
*/
|
|
18
|
+
import type { ConsentPurpose } from "../integration-capabilities.js";
|
|
19
|
+
import type {
|
|
20
|
+
CmpConsentReport,
|
|
21
|
+
ConsentDecision,
|
|
22
|
+
ConsentSnapshot,
|
|
23
|
+
} from "./consent-broker.js";
|
|
24
|
+
import { buildTenantConsentBroker, type TenantConsentConfig } from "./consent-config.js";
|
|
25
|
+
|
|
26
|
+
/** A shopper/CMP interaction to replay against the previewed broker. */
|
|
27
|
+
export type ConsentPreviewAction =
|
|
28
|
+
| { kind: "cmp"; label?: string; report: CmpConsentReport }
|
|
29
|
+
| { kind: "cmp-removed"; label?: string }
|
|
30
|
+
| { kind: "banner"; label?: string; decisions: Partial<Record<ConsentPurpose, ConsentDecision>> };
|
|
31
|
+
|
|
32
|
+
/** One preview step: the eligibility a shopper would see after an action. */
|
|
33
|
+
export interface ConsentPreviewStep {
|
|
34
|
+
label: string;
|
|
35
|
+
action: ConsentPreviewAction["kind"] | "default";
|
|
36
|
+
eligiblePurposes: ConsentPurpose[];
|
|
37
|
+
snapshotId: string;
|
|
38
|
+
/**
|
|
39
|
+
* For a `cmp-removed` step: whether eligibility only narrowed versus the prior step
|
|
40
|
+
* (always true from a correct broker). `false` is an invariant violation — a CMP
|
|
41
|
+
* removal that granted a purpose.
|
|
42
|
+
*/
|
|
43
|
+
narrowedOnly?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ConsentPreviewResult {
|
|
47
|
+
/** What a fresh shopper sees before any interaction — the configured defaults. */
|
|
48
|
+
defaultStep: ConsentPreviewStep;
|
|
49
|
+
/** Each replayed update, in order — the updates a shopper would see. */
|
|
50
|
+
steps: ConsentPreviewStep[];
|
|
51
|
+
/** True when no `cmp-removed` step broadened eligibility (a CMP disable never granted). */
|
|
52
|
+
cmpDisableSafe: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** True when `after` grants no purpose `before` did not — i.e. eligibility only narrowed or held. */
|
|
56
|
+
export function cmpDisableNarrows(before: ConsentSnapshot, after: ConsentSnapshot): boolean {
|
|
57
|
+
return after.eligiblePurposes.every((p) => before.eligiblePurposes.includes(p));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function stepFrom(
|
|
61
|
+
label: string,
|
|
62
|
+
action: ConsentPreviewStep["action"],
|
|
63
|
+
snapshot: ConsentSnapshot,
|
|
64
|
+
): ConsentPreviewStep {
|
|
65
|
+
return {
|
|
66
|
+
label,
|
|
67
|
+
action,
|
|
68
|
+
eligiblePurposes: [...snapshot.eligiblePurposes],
|
|
69
|
+
snapshotId: snapshot.snapshotId,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Replay a merchant consent configuration through the real broker and return the
|
|
75
|
+
* default a shopper sees plus each subsequent update. The default step reflects the
|
|
76
|
+
* configured default state; each action step reflects what the same shopper would then
|
|
77
|
+
* see. A CMP removal is annotated with whether it only narrowed eligibility.
|
|
78
|
+
*/
|
|
79
|
+
export function previewConsentConfig(
|
|
80
|
+
config: TenantConsentConfig,
|
|
81
|
+
actions: readonly ConsentPreviewAction[] = [],
|
|
82
|
+
): ConsentPreviewResult {
|
|
83
|
+
const broker = buildTenantConsentBroker(config);
|
|
84
|
+
const defaultStep = stepFrom("Default (fresh shopper)", "default", broker.getSnapshot());
|
|
85
|
+
|
|
86
|
+
const steps: ConsentPreviewStep[] = [];
|
|
87
|
+
let previous = broker.getSnapshot();
|
|
88
|
+
let cmpDisableSafe = true;
|
|
89
|
+
|
|
90
|
+
for (const action of actions) {
|
|
91
|
+
let snapshot: ConsentSnapshot;
|
|
92
|
+
switch (action.kind) {
|
|
93
|
+
case "cmp":
|
|
94
|
+
snapshot = broker.applyCmp(action.report);
|
|
95
|
+
break;
|
|
96
|
+
case "cmp-removed":
|
|
97
|
+
snapshot = broker.applyCmp(null);
|
|
98
|
+
break;
|
|
99
|
+
case "banner":
|
|
100
|
+
snapshot = broker.setDecisions(action.decisions);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
const step = stepFrom(action.label ?? defaultLabel(action.kind), action.kind, snapshot);
|
|
104
|
+
if (action.kind === "cmp-removed") {
|
|
105
|
+
const narrowed = cmpDisableNarrows(previous, snapshot);
|
|
106
|
+
step.narrowedOnly = narrowed;
|
|
107
|
+
if (!narrowed) cmpDisableSafe = false;
|
|
108
|
+
}
|
|
109
|
+
steps.push(step);
|
|
110
|
+
previous = snapshot;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { defaultStep, steps, cmpDisableSafe };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function defaultLabel(kind: ConsentPreviewAction["kind"]): string {
|
|
117
|
+
switch (kind) {
|
|
118
|
+
case "cmp":
|
|
119
|
+
return "CMP consent applied";
|
|
120
|
+
case "cmp-removed":
|
|
121
|
+
return "CMP removed";
|
|
122
|
+
case "banner":
|
|
123
|
+
return "Shopper banner choice";
|
|
124
|
+
}
|
|
125
|
+
}
|