@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,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progressive stepper + staged flow. Drives Run → Edit → What's next with
|
|
3
|
+
* progressive disclosure: only the current stage shows, completed stages
|
|
4
|
+
* collapse to a done-bar, and the flow AUTO-ADVANCES on monitor.ts's REAL loop
|
|
5
|
+
* signal (never a timer) — Step 1 completes when the local server is live,
|
|
6
|
+
* Step 2 when a real save→reload is observed since the edit step began.
|
|
7
|
+
* Consumes the shared tot:loop-state event from monitor.ts (one poll for the
|
|
8
|
+
* whole page). Imported from a processed `<script>` in cockpit.astro (ADR
|
|
9
|
+
* 0013), rendered only when isLocalDevLoop.
|
|
10
|
+
*
|
|
11
|
+
* Progress is persisted in sessionStorage. This is REQUIRED, not a nicety:
|
|
12
|
+
* saving a watched file triggers Vite's global full-reload, which reloads
|
|
13
|
+
* THIS /dev tab too — resetting in-memory state and re-baselining the very
|
|
14
|
+
* save that should advance Edit→Next. Persisting done-flags + current stage +
|
|
15
|
+
* the edit baseline (the lastSaveAt watermark captured when the edit step
|
|
16
|
+
* began, BEFORE the qualifying save) lets the flow survive that reload and
|
|
17
|
+
* credit the save.
|
|
18
|
+
*/
|
|
19
|
+
export function initStepper(): void {
|
|
20
|
+
const stepper: any = document.getElementById("stepper");
|
|
21
|
+
if (!stepper) return;
|
|
22
|
+
const stages: any = { run: document.getElementById("stage-run"), edit: document.getElementById("stage-edit"), next: document.getElementById("stage-next") };
|
|
23
|
+
const bars: any = { run: document.getElementById("bar-run"), edit: document.getElementById("bar-edit") };
|
|
24
|
+
const celRun = document.getElementById("cel-run");
|
|
25
|
+
const celEdit = document.getElementById("cel-edit");
|
|
26
|
+
const toNext: any = document.getElementById("toNext");
|
|
27
|
+
const detect = document.getElementById("detect");
|
|
28
|
+
const detectTxt = document.getElementById("detectTxt");
|
|
29
|
+
const detectEdit = document.getElementById("detect-edit");
|
|
30
|
+
const detectEditTxt = document.getElementById("detectEditTxt");
|
|
31
|
+
const barRunMeta = document.getElementById("bar-run-meta");
|
|
32
|
+
const barEditMeta = document.getElementById("bar-edit-meta");
|
|
33
|
+
const toast = document.getElementById("toast");
|
|
34
|
+
const toastMsg = document.getElementById("toastMsg");
|
|
35
|
+
let tT: ReturnType<typeof setTimeout>;
|
|
36
|
+
const reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
37
|
+
|
|
38
|
+
const SS = window.sessionStorage;
|
|
39
|
+
function load(k: string, d: any) { try { const v = SS.getItem(k); return v === null ? d : JSON.parse(v); } catch (e) { return d; } }
|
|
40
|
+
function put(k: string, v: any) { try { SS.setItem(k, JSON.stringify(v)); } catch (e) {} }
|
|
41
|
+
|
|
42
|
+
function ping(m: string, once?: string) {
|
|
43
|
+
if (once && load(once, false)) return;
|
|
44
|
+
if (once) put(once, true);
|
|
45
|
+
if (!toast || !toastMsg) return;
|
|
46
|
+
toastMsg.textContent = m; toast.classList.add("show");
|
|
47
|
+
clearTimeout(tT); tT = setTimeout(() => { toast.classList.remove("show"); }, 1900);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const state = {
|
|
51
|
+
unlocked: load("tot.unlocked", { run: true, edit: false, next: false }),
|
|
52
|
+
done: load("tot.done", { run: false, edit: false }),
|
|
53
|
+
current: load("tot.current", "run"),
|
|
54
|
+
};
|
|
55
|
+
let editBase = load("tot.editBase", null);
|
|
56
|
+
function persist() { put("tot.unlocked", state.unlocked); put("tot.done", state.done); put("tot.current", state.current); }
|
|
57
|
+
|
|
58
|
+
function render() {
|
|
59
|
+
Array.prototype.forEach.call(stepper.querySelectorAll(".snode"), (n: any) => {
|
|
60
|
+
const s = n.getAttribute("data-go");
|
|
61
|
+
n.setAttribute("data-st", state.current === s ? "active" : state.done[s] ? "done" : state.unlocked[s] ? "done" : "locked");
|
|
62
|
+
});
|
|
63
|
+
Object.keys(stages).forEach((s) => { if (stages[s]) stages[s].hidden = state.current !== s; });
|
|
64
|
+
if (bars.run) bars.run.hidden = !(state.done.run && state.current !== "run");
|
|
65
|
+
if (bars.edit) bars.edit.hidden = !(state.done.edit && state.current !== "edit");
|
|
66
|
+
// Contextual celebrate banners reflect achieved state (survive reloads).
|
|
67
|
+
if (celRun && state.done.run) celRun.hidden = false;
|
|
68
|
+
if (celEdit && state.done.edit) celEdit.hidden = false;
|
|
69
|
+
if (toNext) toNext.disabled = !state.unlocked.next;
|
|
70
|
+
}
|
|
71
|
+
function goTo(s: string) {
|
|
72
|
+
if (!state.unlocked[s]) return;
|
|
73
|
+
state.current = s; persist(); render();
|
|
74
|
+
window.scrollTo({ top: 0, behavior: reduce ? "auto" : "smooth" });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function onSignal(s: any) {
|
|
78
|
+
if (!s || s.offline) return;
|
|
79
|
+
|
|
80
|
+
// Step 1 — local server is live.
|
|
81
|
+
if (s.server && !state.done.run) {
|
|
82
|
+
state.done.run = true; state.unlocked.edit = true;
|
|
83
|
+
if (editBase === null) { editBase = s.lastSaveAt || 0; put("tot.editBase", editBase); }
|
|
84
|
+
persist();
|
|
85
|
+
if (barRunMeta && s.port) barRunMeta.textContent = "localhost:" + s.port + (s.tenant ? "/" + s.tenant + "/" : "/");
|
|
86
|
+
if (detect) detect.setAttribute("data-listening", "false");
|
|
87
|
+
if (detectTxt) detectTxt.textContent = "Your store is live on this machine.";
|
|
88
|
+
if (state.current === "run") { goTo("edit"); } else { render(); }
|
|
89
|
+
ping("Your store is live", "tot.pinged.run");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Step 2 — a NEW save (since the edit step began) has been reflected by a reload.
|
|
93
|
+
if (state.done.run && !state.done.edit && editBase !== null) {
|
|
94
|
+
const newSave = (s.lastSaveAt || 0) > editBase;
|
|
95
|
+
const reflected = (s.lastSaveAt || 0) > 0 && (s.lastReloadAt || 0) >= (s.lastSaveAt || 0);
|
|
96
|
+
if (newSave && !reflected && detectEditTxt) {
|
|
97
|
+
detectEditTxt.textContent = "Change detected — reloading your store…";
|
|
98
|
+
}
|
|
99
|
+
if (newSave && reflected) {
|
|
100
|
+
state.done.edit = true; state.unlocked.next = true; persist();
|
|
101
|
+
if (barEditMeta && s.watchedFile) barEditMeta.textContent = s.watchedFile;
|
|
102
|
+
if (detectEdit) detectEdit.setAttribute("data-listening", "false");
|
|
103
|
+
if (detectEditTxt) detectEditTxt.textContent = "Saved — your store reloaded. That's the loop.";
|
|
104
|
+
if (state.current === "edit") { goTo("next"); } else { render(); }
|
|
105
|
+
ping("Saved — your page reloaded", "tot.pinged.edit");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
render();
|
|
111
|
+
Array.prototype.forEach.call(document.querySelectorAll("[data-go]"), (el: any) => {
|
|
112
|
+
el.addEventListener("click", () => { goTo(el.getAttribute("data-go")); });
|
|
113
|
+
});
|
|
114
|
+
window.addEventListener("tot:loop-state", (e: any) => { onSignal(e.detail); });
|
|
115
|
+
if (window.__totLoop) onSignal(window.__totLoop);
|
|
116
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme toggle: flip data-theme on <html>, seeded from the OS preference on
|
|
3
|
+
* first click, and PERSISTED to localStorage so a reload stays on the manual
|
|
4
|
+
* choice (the is:inline head seed script reads this same key before first
|
|
5
|
+
* paint — that one stays is:inline because it must run synchronously before
|
|
6
|
+
* CSS paints, the one legitimate is:inline case per ADR 0013). Clearing
|
|
7
|
+
* storage falls back to prefers-color-scheme again, same as a first-ever
|
|
8
|
+
* visit. Imported from a processed `<script>` in cockpit.astro.
|
|
9
|
+
*/
|
|
10
|
+
export function initThemeToggle(): void {
|
|
11
|
+
const root = document.documentElement;
|
|
12
|
+
const btn = document.getElementById("themeBtn");
|
|
13
|
+
if (!btn) return;
|
|
14
|
+
const KEY = "tot.theme";
|
|
15
|
+
function store(v: string) { try { localStorage.setItem(KEY, v); } catch (e) {} }
|
|
16
|
+
btn.addEventListener("click", () => {
|
|
17
|
+
const cur = root.getAttribute("data-theme");
|
|
18
|
+
const next = cur === "dark" ? "light" : cur === "light" ? "dark"
|
|
19
|
+
: (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? "light" : "dark");
|
|
20
|
+
root.setAttribute("data-theme", next);
|
|
21
|
+
store(next);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Per-DEVELOPER "local dev runtime" latest-state — the LIVE half of the
|
|
3
|
-
* local→hosted activity bridge
|
|
3
|
+
* local→hosted activity bridge. Where activityStore.ts holds a ring buffer
|
|
4
4
|
* of file-SAVE events, this holds the most recent heartbeat a developer's LOCAL
|
|
5
5
|
* `tot dev`/`tot start` sent (see the CLI's dev-heartbeat.mjs). The hosted cockpit
|
|
6
6
|
* reads it to show a LIVE, clickable local-dev link + the running CLI version.
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
* response with Set-Cookie, and anything non-200/non-HTML. In `astro dev` there
|
|
16
16
|
* is no `caches` global, so every helper is a clean no-op.
|
|
17
17
|
*
|
|
18
|
-
* Note on the CSP nonce: a stored page
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
18
|
+
* Note on the CSP nonce (ADR 0018): a stored page is NONCE-FREE — its inline tags
|
|
19
|
+
* and CSP header carry the nonce placeholder, not a live nonce. A fresh per-response
|
|
20
|
+
* nonce is stamped in at serve time (stampResponseNonce), on both the cold render and
|
|
21
|
+
* the warm cache hit, so no cached artifact ever holds a reusable nonce and every
|
|
22
|
+
* response gets its own matching nonce/CSP pair.
|
|
22
23
|
*/
|
|
23
24
|
|
|
24
25
|
/** Synthetic internal origin for cache keys — never hits the network. */
|
|
@@ -62,12 +63,23 @@ export function pageCacheKey(
|
|
|
62
63
|
pathname: string,
|
|
63
64
|
search: string,
|
|
64
65
|
version: number,
|
|
66
|
+
planRevision?: string,
|
|
65
67
|
): Request {
|
|
66
|
-
|
|
68
|
+
// A stored page carries the CSP header it was rendered with, INCLUDING any
|
|
69
|
+
// version-scoped integration origins. Folding the resolved `planRevision` into
|
|
70
|
+
// the key makes a warm entry plan-scoped: a rollback/uninstall resolves a new
|
|
71
|
+
// revision, so the old entry is unreachable (a clean miss that re-renders
|
|
72
|
+
// without the removed origins) instead of surviving to TTL. Absent (no
|
|
73
|
+
// integration plane resolved) the key is byte-identical to the non-integration
|
|
74
|
+
// form, so a plain tenant pays nothing and its cache is never busted.
|
|
75
|
+
const planSegment = planRevision ? `/pr:${planRevision}` : "";
|
|
76
|
+
return new Request(
|
|
77
|
+
`${CACHE_ORIGIN}/${tenantId}/v${version}${planSegment}${pathname}${search}`,
|
|
78
|
+
);
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
/**
|
|
70
|
-
* Cache key for a digest-addressed static-bundle response (
|
|
82
|
+
* Cache key for a digest-addressed static-bundle response (ADR 0012).
|
|
71
83
|
* Keyed by `treeDigest` instead of the integer `cachever` `pageCacheKey` uses —
|
|
72
84
|
* a pointer flip to a NEW digest is a different key, so it is a clean cache
|
|
73
85
|
* miss (never a stale serve of the old digest); an unchanged digest keeps
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The storefront's OWN branded "your open change now conflicts" email. When the shared
|
|
3
|
+
* preview base advances (another change was accepted/integrated), every OTHER open
|
|
4
|
+
* candidate is auto-rebased onto the new base; a clean rebuild is silent, but a genuine
|
|
5
|
+
* same-line overlap can't be auto-combined and needs the author's call. This is the push
|
|
6
|
+
* notification for that case — the author is pinged the MOMENT their change actually
|
|
7
|
+
* conflicts with someone else's merge, not at their own accept attempt.
|
|
8
|
+
*
|
|
9
|
+
* Rendered here (our brand), transmitted by tot20 (see lib/messaging/messagesClient.ts).
|
|
10
|
+
* Email HTML rules: inline styles only, table-free simple layout, a visible fallback URL
|
|
11
|
+
* under the button.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Minimal HTML escape for untrusted interpolation (file paths, store name). */
|
|
15
|
+
function esc(s: string): string {
|
|
16
|
+
return s
|
|
17
|
+
.replace(/&/g, "&")
|
|
18
|
+
.replace(/</g, "<")
|
|
19
|
+
.replace(/>/g, ">")
|
|
20
|
+
.replace(/"/g, """);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CandidateConflictEmailInput {
|
|
24
|
+
/** Display name of the store/experience. Default "Regulated Storefront". */
|
|
25
|
+
storeName?: string;
|
|
26
|
+
/** The author's open change PR number, when known. */
|
|
27
|
+
prNumber?: number | null;
|
|
28
|
+
/** Repo-relative paths that changed on both sides and need the author's pick. */
|
|
29
|
+
unresolved: string[];
|
|
30
|
+
/** Absolute deep-link to the resolve UI (admin#publish), or null when no origin is known. */
|
|
31
|
+
resolveUrl?: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const FILE_LIMIT = 12;
|
|
35
|
+
|
|
36
|
+
export function renderCandidateConflictEmail(input: CandidateConflictEmailInput): {
|
|
37
|
+
subject: string;
|
|
38
|
+
html: string;
|
|
39
|
+
} {
|
|
40
|
+
const store = input.storeName?.trim() || "Regulated Storefront";
|
|
41
|
+
const label = input.prNumber != null ? `PR #${input.prNumber}` : "your change";
|
|
42
|
+
const subject = `Action needed: ${label} now conflicts with ${store}`;
|
|
43
|
+
const url = input.resolveUrl || null;
|
|
44
|
+
|
|
45
|
+
const files = input.unresolved.slice(0, FILE_LIMIT);
|
|
46
|
+
const overflow = input.unresolved.length - files.length;
|
|
47
|
+
const fileList = files.length
|
|
48
|
+
? `<ul style="margin:8px 0 0;padding-left:20px;color:#33415b;font-size:14px;">${files
|
|
49
|
+
.map((f) => `<li style="margin:2px 0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;">${esc(f)}</li>`)
|
|
50
|
+
.join("")}${overflow > 0 ? `<li style="margin:2px 0;color:#8593a8;">…and ${overflow} more file(s)</li>` : ""}</ul>`
|
|
51
|
+
: "";
|
|
52
|
+
|
|
53
|
+
const cta = url
|
|
54
|
+
? `<div style="margin:28px 0;">
|
|
55
|
+
<a href="${esc(url)}" style="display:inline-block;background:#0b7a6d;color:#ffffff;text-decoration:none;font-weight:600;font-size:16px;padding:14px 28px;border-radius:999px;">Resolve it now</a>
|
|
56
|
+
</div>
|
|
57
|
+
<p style="margin:0 0 4px;font-size:13px;color:#55637a;">Or paste this link into your browser:</p>
|
|
58
|
+
<p style="margin:0 0 24px;font-size:13px;word-break:break-all;"><a href="${esc(url)}" style="color:#0b7a6d;">${esc(url)}</a></p>`
|
|
59
|
+
: "";
|
|
60
|
+
|
|
61
|
+
const html = `<!doctype html>
|
|
62
|
+
<html lang="en">
|
|
63
|
+
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /></head>
|
|
64
|
+
<body style="margin:0;padding:0;background:#f7f9fc;">
|
|
65
|
+
<div style="max-width:520px;margin:0 auto;padding:32px 20px;font:16px/1.6 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;color:#33415b;">
|
|
66
|
+
<div style="font:600 12px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.12em;text-transform:uppercase;color:#0b7a6d;margin:0 0 24px;">
|
|
67
|
+
Token of Trust© · ${esc(store)}
|
|
68
|
+
</div>
|
|
69
|
+
<h1 style="font-size:22px;line-height:1.3;letter-spacing:-.02em;margin:0 0 12px;color:#0a2540;">${esc(label)} needs your input</h1>
|
|
70
|
+
<p style="margin:0 0 8px;color:#33415b;">The store moved on — another change was just accepted into <strong>${esc(store)}</strong>, and we tried to rebuild ${esc(label)} on top of it automatically. Most of it merged cleanly, but these files were edited on both sides and need you to pick which version wins:</p>
|
|
71
|
+
${fileList}
|
|
72
|
+
${cta}
|
|
73
|
+
<p style="margin:16px 0 0;font-size:14px;color:#33415b;">You can also resolve it from the command line — <code style="font-family:ui-monospace,SFMono-Regular,Menlo,monospace;">tot preview --strategy=ours</code> keeps your version, <code style="font-family:ui-monospace,SFMono-Regular,Menlo,monospace;">tot preview --strategy=theirs</code> takes the store's.</p>
|
|
74
|
+
<p style="margin:24px 0 0;font-size:12px;color:#8593a8;border-top:1px solid #e3e8ef;padding-top:16px;">Your change is safe and still open — it just stays not-mergeable until you resolve these files. Nothing was overwritten.</p>
|
|
75
|
+
</div>
|
|
76
|
+
</body>
|
|
77
|
+
</html>`;
|
|
78
|
+
|
|
79
|
+
return { subject, html };
|
|
80
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storefront-side resolution of the renderer-owned four-stage browser
|
|
3
|
+
* environment (`@tot/public-runtime` `resolveBrowserEnvironment`). This is the ONE
|
|
4
|
+
* place request state is turned into the authoritative environment object; both
|
|
5
|
+
* document mounts (Layout.astro and `rawHtmlResponse`) serialize the result, so
|
|
6
|
+
* the object is identical in both by construction.
|
|
7
|
+
*
|
|
8
|
+
* The stage is derived from server facts only — `import.meta.env.DEV`, the request
|
|
9
|
+
* host, the resolved customization environment, and whether this is a per-change
|
|
10
|
+
* candidate render — never a client-supplied value. A candidate render is always
|
|
11
|
+
* `candidate` and never `live`; anything unresolved stays non-live.
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
resolveBrowserEnvironment,
|
|
15
|
+
resolveEnvironmentOnlyPlan,
|
|
16
|
+
type BrowserEnvironment,
|
|
17
|
+
type EffectivePlan,
|
|
18
|
+
type IntegrationSiteSurface,
|
|
19
|
+
} from "@tot/public-runtime";
|
|
20
|
+
import { isAdminPath } from "@/lib/auth/loginGate";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The non-secret render revision: the commit SHA this build was cut from (baked at
|
|
24
|
+
* build time, the same value GET /health reports), or `"local"` when there is no
|
|
25
|
+
* git context (dev, vitest). Never a token or signed URL.
|
|
26
|
+
*/
|
|
27
|
+
function platformRevision(): string {
|
|
28
|
+
return typeof __GIT_SHA__ !== "undefined" && __GIT_SHA__ ? __GIT_SHA__ : "local";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** A request host is local when it is served on loopback (`astro dev` or a local built Worker). */
|
|
32
|
+
function isLocalHost(host: string): boolean {
|
|
33
|
+
return host.startsWith("localhost") || host.startsWith("127.0.0.1");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Map the resolved tenant + request path to a document surface. Admin/cockpit
|
|
38
|
+
* paths are `admin`; cart/checkout paths are `checkout`; a catalog tenant is
|
|
39
|
+
* `storefront`; a marketing tenant (no catalog) is `marketing`.
|
|
40
|
+
*/
|
|
41
|
+
export function deriveSiteSurface(input: {
|
|
42
|
+
catalog: boolean;
|
|
43
|
+
pathname: string;
|
|
44
|
+
}): IntegrationSiteSurface {
|
|
45
|
+
// Admin + the cockpit control-plane panel (host-routed `/cockpit` or tenant-first
|
|
46
|
+
// `/<tenant>/cockpit`) are the `admin` surface.
|
|
47
|
+
if (isAdminPath(input.pathname) || /^\/(?:[^/]+\/)?cockpit(?:\/|$)/.test(input.pathname)) {
|
|
48
|
+
return "admin";
|
|
49
|
+
}
|
|
50
|
+
if (/^\/(checkout|cart)(\/|$)/.test(input.pathname)) return "checkout";
|
|
51
|
+
return input.catalog ? "storefront" : "marketing";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The normal (non-candidate) per-request environment object, computed once by the
|
|
56
|
+
* middleware. `astro dev` and a Worker served on localhost both resolve to `local`
|
|
57
|
+
* (their CSP-enforcement mode differs — report-only vs enforced — but that is a
|
|
58
|
+
* response-header concern, not part of this object).
|
|
59
|
+
*/
|
|
60
|
+
export function requestBrowserEnvironment(input: {
|
|
61
|
+
host: string;
|
|
62
|
+
isPreviewHost: boolean;
|
|
63
|
+
customizationEnv: "live" | "test";
|
|
64
|
+
canonicalHost: string;
|
|
65
|
+
siteSurface: IntegrationSiteSurface;
|
|
66
|
+
}): BrowserEnvironment {
|
|
67
|
+
return resolveBrowserEnvironment({
|
|
68
|
+
dev: import.meta.env.DEV,
|
|
69
|
+
localHost: isLocalHost(input.host),
|
|
70
|
+
candidate: false,
|
|
71
|
+
previewHost: input.isPreviewHost,
|
|
72
|
+
customizationEnv: input.customizationEnv,
|
|
73
|
+
siteSurface: input.siteSurface,
|
|
74
|
+
canonicalHost: input.canonicalHost,
|
|
75
|
+
revision: platformRevision(),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* CSP enforcement mode for this runtime — the axis that stays DISTINCT from the
|
|
81
|
+
* `local` stage. `astro dev` (Node) serves un-nonced Vite `<style>`/`<script>`, so a
|
|
82
|
+
* strict nonce policy would blank the site: it is REPORT-ONLY there (violations
|
|
83
|
+
* still surface). The built Worker is CSP-clean, so the strict policy is ENFORCED —
|
|
84
|
+
* including the built Worker run locally, which is how enforced CSP is proven.
|
|
85
|
+
* Report-only-dev and enforced-built-Worker are both correct; only the mode differs,
|
|
86
|
+
* never the four-stage environment object.
|
|
87
|
+
*/
|
|
88
|
+
export type CspEnforcementMode = "report-only" | "enforced";
|
|
89
|
+
|
|
90
|
+
export function cspEnforcementMode(dev: boolean): CspEnforcementMode {
|
|
91
|
+
return dev ? "report-only" : "enforced";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** The response header name that carries the mode: report-only in dev, enforced otherwise. */
|
|
95
|
+
export function cspHeaderName(
|
|
96
|
+
dev: boolean,
|
|
97
|
+
): "Content-Security-Policy-Report-Only" | "Content-Security-Policy" {
|
|
98
|
+
return dev ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The environment object for a per-change candidate render (the cockpit candidate
|
|
103
|
+
* renderer, the revision renderer, and the not-yet-built PR page). The stage is
|
|
104
|
+
* always `candidate` — never `live`, even when the underlying tenant is live — and
|
|
105
|
+
* `revision` is the candidate's own version identity (a versionId / head sha), a
|
|
106
|
+
* public, non-secret value.
|
|
107
|
+
*/
|
|
108
|
+
export function candidateBrowserEnvironment(input: {
|
|
109
|
+
canonicalHost: string;
|
|
110
|
+
revision: string;
|
|
111
|
+
siteSurface?: IntegrationSiteSurface;
|
|
112
|
+
}): BrowserEnvironment {
|
|
113
|
+
return resolveBrowserEnvironment({
|
|
114
|
+
dev: import.meta.env.DEV,
|
|
115
|
+
localHost: false,
|
|
116
|
+
candidate: true,
|
|
117
|
+
previewHost: true,
|
|
118
|
+
customizationEnv: "test",
|
|
119
|
+
siteSurface: input.siteSurface ?? "marketing",
|
|
120
|
+
canonicalHost: input.canonicalHost,
|
|
121
|
+
revision: input.revision,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The resolved effective plan for a candidate render — the `candidate`-stage
|
|
127
|
+
* environment wrapped in an environment-only plan so `rawHtmlResponse` (the raw
|
|
128
|
+
* mount of the fixed-phase engine) renders the same renderer-owned phases a live
|
|
129
|
+
* page gets. No integration declarations are materialized on the candidate hot
|
|
130
|
+
* path, so this is environment-only until that wiring lands.
|
|
131
|
+
*/
|
|
132
|
+
export function candidateIntegrationPlan(
|
|
133
|
+
input: { canonicalHost: string; revision: string; siteSurface?: IntegrationSiteSurface },
|
|
134
|
+
tenantPublicId: string,
|
|
135
|
+
): EffectivePlan {
|
|
136
|
+
return resolveEnvironmentOnlyPlan(candidateBrowserEnvironment(input), tenantPublicId);
|
|
137
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Materialize active managed-analytics installs into the render plane's existing
|
|
3
|
+
* declaration seam. `app_installs` owns status/manifest and MAX(seq) owns the
|
|
4
|
+
* active public config; candidates and drafts are never read here.
|
|
5
|
+
*/
|
|
6
|
+
import {
|
|
7
|
+
ENVIRONMENT_SCHEMA_VERSION,
|
|
8
|
+
buildPlatformAdapterDeclaration,
|
|
9
|
+
validateIntegrationManifest,
|
|
10
|
+
type IntegrationDeclarationInput,
|
|
11
|
+
} from "@tot/public-runtime";
|
|
12
|
+
import { AppVersionStore } from "../apps/appVersionStore.js";
|
|
13
|
+
import type { Queryable } from "../d1/catalog.js";
|
|
14
|
+
|
|
15
|
+
const MANAGED_KIND = "managed-analytics-v1";
|
|
16
|
+
|
|
17
|
+
interface ActiveManagedRow {
|
|
18
|
+
install_id: string;
|
|
19
|
+
app_id: string;
|
|
20
|
+
app_version: string;
|
|
21
|
+
manifest: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Return only declarations whose canonical row, current immutable activation,
|
|
26
|
+
* and reviewed platform-adapter rebuild agree. Malformed/stale rows fail closed
|
|
27
|
+
* individually; an unavailable database is handled by the caller as no effects.
|
|
28
|
+
*/
|
|
29
|
+
export async function loadActiveManagedInstallDeclarations(
|
|
30
|
+
db: Queryable,
|
|
31
|
+
tenantPublicId: string,
|
|
32
|
+
): Promise<IntegrationDeclarationInput[]> {
|
|
33
|
+
const rows = await db.all<ActiveManagedRow>(
|
|
34
|
+
`SELECT install_id, app_id, app_version, manifest
|
|
35
|
+
FROM app_installs
|
|
36
|
+
WHERE tenant_id = ? AND managed_kind = ? AND status = 'active'
|
|
37
|
+
ORDER BY install_id`,
|
|
38
|
+
tenantPublicId,
|
|
39
|
+
MANAGED_KIND,
|
|
40
|
+
);
|
|
41
|
+
const versions = new AppVersionStore(db);
|
|
42
|
+
const declarations: IntegrationDeclarationInput[] = [];
|
|
43
|
+
for (const row of rows) {
|
|
44
|
+
try {
|
|
45
|
+
const manifest = validateIntegrationManifest(JSON.parse(row.manifest) as unknown);
|
|
46
|
+
const current = await versions.currentVersion(row.install_id);
|
|
47
|
+
if (!manifest.ok || !current || current.tenantId !== tenantPublicId) continue;
|
|
48
|
+
if (current.appVersion !== row.app_version || current.facets.appVersion !== row.app_version) continue;
|
|
49
|
+
if (current.facets.digest !== manifest.value.app.digest || manifest.value.app.id !== row.app_id) continue;
|
|
50
|
+
const destinationId = current.facets.publicConfig["destinationId"];
|
|
51
|
+
if (typeof destinationId !== "string") continue;
|
|
52
|
+
const built = buildPlatformAdapterDeclaration({
|
|
53
|
+
adapterId: row.app_id,
|
|
54
|
+
ids: { live: destinationId },
|
|
55
|
+
tenantPublicId,
|
|
56
|
+
environment: {
|
|
57
|
+
schemaVersion: ENVIRONMENT_SCHEMA_VERSION,
|
|
58
|
+
siteSurface: "storefront",
|
|
59
|
+
environment: "live",
|
|
60
|
+
canonicalHost: tenantPublicId,
|
|
61
|
+
revision: `managed-live:${current.seq}`,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
if (!built.ok || built.declaration.manifest.app.digest !== manifest.value.app.digest) continue;
|
|
65
|
+
declarations.push({ ...built.declaration, ref: `managed-install:${row.install_id}` });
|
|
66
|
+
} catch {
|
|
67
|
+
// Persisted JSON/version corruption must disable this install, never widen
|
|
68
|
+
// CSP or partially materialize a subscription.
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return declarations;
|
|
72
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-response CSP-nonce stamping (ADR 0018 nonce non-serialization; ext-kernel-04).
|
|
3
|
+
*
|
|
4
|
+
* The renderer emits a nonce-free template: every platform inline tag and the CSP
|
|
5
|
+
* header carry {@link INTEGRATION_NONCE_PLACEHOLDER}, never a live nonce. This is
|
|
6
|
+
* what the edge cache stores — a nonce-free artifact. At serve time (a cold render
|
|
7
|
+
* OR a warm cache hit) this stamps ONE fresh per-response nonce into both the HTML
|
|
8
|
+
* body and the CSP header, so every response gets a fresh, matching nonce/CSP pair
|
|
9
|
+
* and no nonce is ever reused across responses.
|
|
10
|
+
*/
|
|
11
|
+
import { INTEGRATION_NONCE_PLACEHOLDER, stampNonce } from "@tot/public-runtime";
|
|
12
|
+
|
|
13
|
+
const CSP_HEADERS = [
|
|
14
|
+
"content-security-policy",
|
|
15
|
+
"content-security-policy-report-only",
|
|
16
|
+
] as const;
|
|
17
|
+
|
|
18
|
+
/** A fresh, non-guessable per-response nonce. */
|
|
19
|
+
export function freshNonce(): string {
|
|
20
|
+
return crypto.randomUUID();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Replace the nonce placeholder with a fresh `nonce` in a response's CSP header(s)
|
|
25
|
+
* and — for an HTML response — its body. Non-HTML responses keep their (streamed)
|
|
26
|
+
* body untouched; their CSP header is still stamped. A response with no placeholder
|
|
27
|
+
* (a static-bundle body, an API JSON) is returned effectively unchanged.
|
|
28
|
+
*/
|
|
29
|
+
export async function stampResponseNonce(
|
|
30
|
+
response: Response,
|
|
31
|
+
nonce: string,
|
|
32
|
+
): Promise<Response> {
|
|
33
|
+
for (const header of CSP_HEADERS) {
|
|
34
|
+
const value = response.headers.get(header);
|
|
35
|
+
if (value && value.includes(INTEGRATION_NONCE_PLACEHOLDER)) {
|
|
36
|
+
response.headers.set(header, stampNonce(value, nonce));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
41
|
+
if (!contentType.includes("text/html")) return response;
|
|
42
|
+
|
|
43
|
+
const body = await response.text();
|
|
44
|
+
return new Response(stampNonce(body, nonce), {
|
|
45
|
+
status: response.status,
|
|
46
|
+
statusText: response.statusText,
|
|
47
|
+
headers: response.headers,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant-local integration declaration materialization (ext-kernel-09).
|
|
3
|
+
*
|
|
4
|
+
* This is the ONE production seam that turns a tenant's OWN declared, exact-version
|
|
5
|
+
* integrations into the already-materialized {@link IntegrationDeclarationInput} set
|
|
6
|
+
* the render hot path consumes. The interim marketing bridge
|
|
7
|
+
* ({@link resolveInterimBridgePlan}) resolves that set into the effective plan the
|
|
8
|
+
* fixed-phase engine serves — refusing a regulated tenant, resolving an eligible
|
|
9
|
+
* unregulated one — so a declared tenant boots its integration on-by-default
|
|
10
|
+
* (consent-gated) with no page edit and no vendor branch.
|
|
11
|
+
*
|
|
12
|
+
* A tenant with no declaration returns the empty set, so the bridge resolves an
|
|
13
|
+
* environment-only plan and the request is byte-identical to non-integration
|
|
14
|
+
* behavior (zero cost). The declarations are already materialized in tenant config
|
|
15
|
+
* (the manifest, the resolved public config, the set of asset paths present for the
|
|
16
|
+
* version); this loader only reads them, fail-closed — resolution is the bridge's
|
|
17
|
+
* job, materialization is config's, and the two never blur.
|
|
18
|
+
*/
|
|
19
|
+
import type { IntegrationDeclarationInput, IntegrationManifest, TenantConfig } from "@tot/public-runtime";
|
|
20
|
+
|
|
21
|
+
const NO_DECLARATIONS: readonly IntegrationDeclarationInput[] = Object.freeze([]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Read a tenant's already-materialized tenant-local declarations. Returns the empty
|
|
25
|
+
* set (never throws) when the tenant declares none or the field is malformed — an
|
|
26
|
+
* undeclared tenant must resolve to the environment-only plan, never an error.
|
|
27
|
+
*/
|
|
28
|
+
export function loadTenantIntegrationDeclarations(
|
|
29
|
+
tenant: Pick<TenantConfig, "integrations">,
|
|
30
|
+
): readonly IntegrationDeclarationInput[] {
|
|
31
|
+
const declared = tenant.integrations;
|
|
32
|
+
if (!Array.isArray(declared) || declared.length === 0) return NO_DECLARATIONS;
|
|
33
|
+
return declared;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Demo tenant-local declaration — a same-origin sandbox analytics adapter.
|
|
38
|
+
//
|
|
39
|
+
// Seeded on the unregulated marketing demo/home tenants so a preview deploy
|
|
40
|
+
// DEMONSTRABLY materializes a real integration on-by-default: its exact-version
|
|
41
|
+
// entry module (committed under `public/apps/…`, so always materialized and served
|
|
42
|
+
// same-origin) flows the declaration → interim bridge → effective plan → boot
|
|
43
|
+
// descriptor → lifecycle import. Loading is consent-gated (purpose `analytics`,
|
|
44
|
+
// held back under the default-deny snapshot until granted), and the declared
|
|
45
|
+
// beacon origin reaches the strict CSP via `cspNeeds`. A regulated tenant carrying
|
|
46
|
+
// the same declaration is still REFUSED by the bridge.
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
/** The demo adapter's app id — a same-origin, sandbox-tier marketing analytics adapter. */
|
|
50
|
+
export const DEMO_ANALYTICS_APP_ID = "tot.demo.analytics";
|
|
51
|
+
/** The demo adapter's exact pinned version. */
|
|
52
|
+
export const DEMO_ANALYTICS_VERSION = "0.1.0";
|
|
53
|
+
/**
|
|
54
|
+
* The same-origin, exact-version entry module the lifecycle runtime dynamically
|
|
55
|
+
* imports. Committed under `apps/storefront/public/apps/…` so it is served verbatim
|
|
56
|
+
* at this root-absolute URL and is ALWAYS materialized (no R2 pointer needed).
|
|
57
|
+
*/
|
|
58
|
+
export const DEMO_ANALYTICS_ENTRY_URL = `/apps/${DEMO_ANALYTICS_APP_ID}/${DEMO_ANALYTICS_VERSION}/entry.js`;
|
|
59
|
+
/** The beacon endpoint the demo declaration reserves in CSP (`connect-src`). */
|
|
60
|
+
export const DEMO_ANALYTICS_BEACON_ORIGIN = "https://demo-analytics.tokenoftrust.com";
|
|
61
|
+
|
|
62
|
+
/** The demo adapter's shared browser manifest (ext-kernel-01 v2). */
|
|
63
|
+
const DEMO_ANALYTICS_MANIFEST: IntegrationManifest = {
|
|
64
|
+
schemaVersion: 2,
|
|
65
|
+
app: {
|
|
66
|
+
id: DEMO_ANALYTICS_APP_ID,
|
|
67
|
+
name: "ToT Demo Analytics",
|
|
68
|
+
version: DEMO_ANALYTICS_VERSION,
|
|
69
|
+
digest: `sha256:${DEMO_ANALYTICS_APP_ID}-${DEMO_ANALYTICS_VERSION}`,
|
|
70
|
+
publisher: "Token of Trust",
|
|
71
|
+
},
|
|
72
|
+
compatibility: { storefrontBrowserContract: ">=2.0.0 <3.0.0", configurationSchemaVersion: 1 },
|
|
73
|
+
browser: {
|
|
74
|
+
executionTier: "sandbox",
|
|
75
|
+
entry: { asset: DEMO_ANALYTICS_ENTRY_URL, format: "module", phase: "document.deferred" },
|
|
76
|
+
contributions: [],
|
|
77
|
+
dependencies: [],
|
|
78
|
+
publicConfigSchema: {
|
|
79
|
+
type: "object",
|
|
80
|
+
additionalProperties: false,
|
|
81
|
+
required: ["siteId"],
|
|
82
|
+
properties: { siteId: { type: "string" } },
|
|
83
|
+
},
|
|
84
|
+
consent: {
|
|
85
|
+
purposes: ["analytics"],
|
|
86
|
+
loadWhen: "all-declared-purposes-eligible",
|
|
87
|
+
unknownState: "block",
|
|
88
|
+
},
|
|
89
|
+
// Same-origin entry loads under the strict base `'self'`; the declared beacon
|
|
90
|
+
// origin is the advanced exact source the compiler folds into `connect-src`.
|
|
91
|
+
csp: { profiles: [], sources: { "connect-src": [DEMO_ANALYTICS_BEACON_ORIGIN] } },
|
|
92
|
+
permissions: { events: ["storefront.page.viewed.v1"], data: [], actions: [], domIntent: "none" },
|
|
93
|
+
performanceBudget: {
|
|
94
|
+
maxTransferredBytes: 20000,
|
|
95
|
+
maxAdditionalRequests: 1,
|
|
96
|
+
maxMainThreadMilliseconds: 20,
|
|
97
|
+
mustBeAsyncOrDeferred: true,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
server: { topics: [], secretRequirements: [] },
|
|
101
|
+
assurance: { requestedClassification: "baseline", regulatedTenantDefault: "disabled-until-certified" },
|
|
102
|
+
configurationMigrations: [],
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The demo tenant-local declaration seeded on the unregulated marketing demo tenants.
|
|
107
|
+
* `materializedAssets` names the committed same-origin entry module, so the resolver's
|
|
108
|
+
* fail-closed materialized-asset check passes without any R2/publish step.
|
|
109
|
+
*/
|
|
110
|
+
export const DEMO_ANALYTICS_DECLARATION: IntegrationDeclarationInput = {
|
|
111
|
+
origin: "tenant-local",
|
|
112
|
+
ref: "config/tenants:demo-analytics",
|
|
113
|
+
manifest: DEMO_ANALYTICS_MANIFEST,
|
|
114
|
+
publicConfig: { siteId: "tot-demo" },
|
|
115
|
+
materializedAssets: [DEMO_ANALYTICS_ENTRY_URL],
|
|
116
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shopper membership eligibility — the request-scoped seam that resolves whether
|
|
3
|
-
* the current shopper is a member, and which tier
|
|
3
|
+
* the current shopper is a member, and which tier.
|
|
4
4
|
*
|
|
5
5
|
* Phase 1 storefronts have NO shopper-login/account source (member accounts are
|
|
6
6
|
* a Phase-2 managed-checkout capability), so this resolves anonymous
|