@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
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import type { AuthorBio, BlogPost, BlogPostSummary, PostStatus } from "./types.js";
|
|
2
|
+
import type { ContentProvider } from "../storyblok/provider.js";
|
|
3
|
+
|
|
4
|
+
type ArtifactSource = Pick<ContentProvider, "readArtifact" | "listArtifactPaths">;
|
|
5
|
+
function canReadArtifacts(value: ArtifactSource | undefined): value is ArtifactSource {
|
|
6
|
+
return typeof value?.listArtifactPaths === "function" && typeof value.readArtifact === "function";
|
|
7
|
+
}
|
|
8
|
+
export interface CollectionReadOptions {
|
|
9
|
+
includeUnpublished?: boolean;
|
|
10
|
+
now?: string;
|
|
11
|
+
content?: ArtifactSource;
|
|
12
|
+
}
|
|
2
13
|
|
|
3
14
|
/** A blog collection = a route base + a per-tenant content dir. */
|
|
4
15
|
export interface Collection {
|
|
@@ -147,9 +158,22 @@ function toSummary(p: BlogPost): BlogPostSummary {
|
|
|
147
158
|
* the same glob the index is built from (no per-tenant config needed). Sorted for
|
|
148
159
|
* a stable admin ordering. A tenant with no blog content returns `[]`.
|
|
149
160
|
*/
|
|
150
|
-
export function listCollections(
|
|
161
|
+
export async function listCollections(
|
|
162
|
+
tenantId: string,
|
|
163
|
+
content?: ArtifactSource,
|
|
164
|
+
): Promise<string[]> {
|
|
151
165
|
const marker = `/tenants/${tenantId}/content/`;
|
|
152
166
|
const collections = new Set<string>();
|
|
167
|
+
const runtimePaths = canReadArtifacts(content)
|
|
168
|
+
? await content.listArtifactPaths("")
|
|
169
|
+
: null;
|
|
170
|
+
if (runtimePaths !== null) {
|
|
171
|
+
for (const path of runtimePaths) {
|
|
172
|
+
const match = /^([^/]+)\/posts\/[^/]+\.json$/.exec(path);
|
|
173
|
+
if (match?.[1] && SEGMENT_RE.test(match[1])) collections.add(match[1]);
|
|
174
|
+
}
|
|
175
|
+
return [...collections].sort();
|
|
176
|
+
}
|
|
153
177
|
for (const key of Object.keys(postGlobs)) {
|
|
154
178
|
const at = key.indexOf(marker);
|
|
155
179
|
if (at < 0) continue;
|
|
@@ -168,12 +192,33 @@ export function listCollections(tenantId: string): string[] {
|
|
|
168
192
|
export async function listPosts(
|
|
169
193
|
tenantId: string,
|
|
170
194
|
collection: string,
|
|
171
|
-
opts?:
|
|
195
|
+
opts?: CollectionReadOptions,
|
|
172
196
|
): Promise<BlogPostSummary[]> {
|
|
173
197
|
if (!SEGMENT_RE.test(collection)) return [];
|
|
174
198
|
const prefix = postsPrefix(tenantId, collection);
|
|
175
|
-
const
|
|
176
|
-
const
|
|
199
|
+
const runtimeContent = canReadArtifacts(opts?.content) ? opts.content : null;
|
|
200
|
+
const runtimePaths = runtimeContent
|
|
201
|
+
? await runtimeContent.listArtifactPaths(`${collection}/posts/`)
|
|
202
|
+
: null;
|
|
203
|
+
const posts = runtimePaths !== null
|
|
204
|
+
? (await Promise.all(
|
|
205
|
+
runtimePaths
|
|
206
|
+
.filter((path) => path.endsWith(".json"))
|
|
207
|
+
.map(async (path) => {
|
|
208
|
+
const raw = await runtimeContent?.readArtifact(path);
|
|
209
|
+
if (!raw) return null;
|
|
210
|
+
try {
|
|
211
|
+
return normalize(JSON.parse(raw) as BlogPost);
|
|
212
|
+
} catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
}),
|
|
216
|
+
)).filter((post): post is BlogPost => post !== null)
|
|
217
|
+
: (await Promise.all(
|
|
218
|
+
Object.keys(postGlobs)
|
|
219
|
+
.filter((key) => key.includes(prefix))
|
|
220
|
+
.map((key) => postGlobs[key]!()),
|
|
221
|
+
)).map(normalize);
|
|
177
222
|
const includeUnpublished = opts?.includeUnpublished ?? false;
|
|
178
223
|
const now = opts?.now ?? new Date().toISOString();
|
|
179
224
|
return posts
|
|
@@ -191,9 +236,23 @@ export async function getPost(
|
|
|
191
236
|
tenantId: string,
|
|
192
237
|
collection: string,
|
|
193
238
|
slug: string,
|
|
194
|
-
opts?:
|
|
239
|
+
opts?: CollectionReadOptions,
|
|
195
240
|
): Promise<BlogPost | null> {
|
|
196
241
|
if (!SEGMENT_RE.test(collection) || !SLUG_RE.test(slug)) return null;
|
|
242
|
+
if (canReadArtifacts(opts?.content)) {
|
|
243
|
+
const paths = await opts.content.listArtifactPaths(`${collection}/posts/`);
|
|
244
|
+
const raw = await opts.content.readArtifact(`${collection}/posts/${slug}.json`);
|
|
245
|
+
if (raw) {
|
|
246
|
+
try {
|
|
247
|
+
const post = normalize(JSON.parse(raw) as BlogPost);
|
|
248
|
+
if (!(opts.includeUnpublished ?? false) && !isVisibleOnLive(post, opts.now)) return null;
|
|
249
|
+
return post;
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (paths !== null) return null;
|
|
255
|
+
}
|
|
197
256
|
const key = Object.keys(postGlobs).find(
|
|
198
257
|
(candidate) =>
|
|
199
258
|
candidate.includes(postsPrefix(tenantId, collection)) && candidate.endsWith(`/${slug}.json`),
|
|
@@ -215,7 +274,7 @@ export async function listTranslations(
|
|
|
215
274
|
tenantId: string,
|
|
216
275
|
collection: string,
|
|
217
276
|
translationGroupId: string,
|
|
218
|
-
opts?:
|
|
277
|
+
opts?: CollectionReadOptions,
|
|
219
278
|
): Promise<BlogPostSummary[]> {
|
|
220
279
|
if (!translationGroupId) return [];
|
|
221
280
|
const posts = await listPosts(tenantId, collection, opts);
|
|
@@ -233,7 +292,7 @@ export async function getTranslations(
|
|
|
233
292
|
tenantId: string,
|
|
234
293
|
collection: string,
|
|
235
294
|
slug: string,
|
|
236
|
-
opts?:
|
|
295
|
+
opts?: CollectionReadOptions,
|
|
237
296
|
): Promise<BlogPostSummary[]> {
|
|
238
297
|
const post = await getPost(tenantId, collection, slug, opts);
|
|
239
298
|
if (!post) return [];
|
|
@@ -252,9 +311,10 @@ export async function relatedPosts(
|
|
|
252
311
|
collection: string,
|
|
253
312
|
slug: string,
|
|
254
313
|
n = 3,
|
|
314
|
+
content?: ArtifactSource,
|
|
255
315
|
): Promise<BlogPostSummary[]> {
|
|
256
|
-
const pool = (await listPosts(tenantId, collection)).filter((p) => p.slug !== slug);
|
|
257
|
-
const current = await getPost(tenantId, collection, slug);
|
|
316
|
+
const pool = (await listPosts(tenantId, collection, { content })).filter((p) => p.slug !== slug);
|
|
317
|
+
const current = await getPost(tenantId, collection, slug, { content });
|
|
258
318
|
const category = current?.categories[0];
|
|
259
319
|
const result = category ? pool.filter((p) => p.categories.includes(category)) : [];
|
|
260
320
|
for (const p of pool) {
|
|
@@ -268,9 +328,10 @@ export async function resolveRedirect(
|
|
|
268
328
|
tenantId: string,
|
|
269
329
|
collection: string,
|
|
270
330
|
slug: string,
|
|
331
|
+
content?: ArtifactSource,
|
|
271
332
|
): Promise<string | null> {
|
|
272
333
|
if (!SEGMENT_RE.test(collection)) return null;
|
|
273
|
-
const redirects = await getRedirects(tenantId, collection);
|
|
334
|
+
const redirects = await getRedirects(tenantId, collection, content);
|
|
274
335
|
return redirects[slug] ?? null;
|
|
275
336
|
}
|
|
276
337
|
|
|
@@ -282,8 +343,21 @@ export async function resolveRedirect(
|
|
|
282
343
|
export async function getRedirects(
|
|
283
344
|
tenantId: string,
|
|
284
345
|
collection: string,
|
|
346
|
+
content?: ArtifactSource,
|
|
285
347
|
): Promise<Record<string, string>> {
|
|
286
348
|
if (!SEGMENT_RE.test(collection)) return {};
|
|
349
|
+
if (canReadArtifacts(content)) {
|
|
350
|
+
const paths = await content.listArtifactPaths(`${collection}/`);
|
|
351
|
+
const raw = await content.readArtifact(`${collection}/redirects.json`);
|
|
352
|
+
if (raw) {
|
|
353
|
+
try {
|
|
354
|
+
return JSON.parse(raw) as Record<string, string>;
|
|
355
|
+
} catch {
|
|
356
|
+
return {};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
if (paths !== null) return {};
|
|
360
|
+
}
|
|
287
361
|
const key = Object.keys(redirectGlobs).find(
|
|
288
362
|
(candidate) =>
|
|
289
363
|
candidate.includes(`/tenants/${tenantId}/content/${collection}/`) &&
|
|
@@ -301,8 +375,21 @@ export async function getRedirects(
|
|
|
301
375
|
export async function getAuthors(
|
|
302
376
|
tenantId: string,
|
|
303
377
|
collection: string,
|
|
378
|
+
content?: ArtifactSource,
|
|
304
379
|
): Promise<Record<string, AuthorBio>> {
|
|
305
380
|
if (!SEGMENT_RE.test(collection)) return {};
|
|
381
|
+
if (canReadArtifacts(content)) {
|
|
382
|
+
const paths = await content.listArtifactPaths(`${collection}/`);
|
|
383
|
+
const raw = await content.readArtifact(`${collection}/authors.json`);
|
|
384
|
+
if (raw) {
|
|
385
|
+
try {
|
|
386
|
+
return JSON.parse(raw) as Record<string, AuthorBio>;
|
|
387
|
+
} catch {
|
|
388
|
+
return {};
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (paths !== null) return {};
|
|
392
|
+
}
|
|
306
393
|
const key = Object.keys(authorsGlobs).find(
|
|
307
394
|
(candidate) =>
|
|
308
395
|
candidate.includes(`/tenants/${tenantId}/content/${collection}/`) &&
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal, dependency-free Markdown -> sanitized HTML for the admin blog editor
|
|
3
|
-
* (
|
|
3
|
+
* (see docs/plans/2026-08-21-blog-platform-workstream.md). The storefront
|
|
4
4
|
* ships no markdown library (see the "No new deps" convention in §1), and the
|
|
5
5
|
* migration package's `sanitize-html` is a node-only devtool — so authoring from
|
|
6
6
|
* the admin gets this small hand-rolled renderer instead.
|
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
// collection; switching `/blog` onto it is a later migration once order is
|
|
5
5
|
// encoded as data (see B0.1 §"/blog migration caution").
|
|
6
6
|
import type { BlogPost, BlogPostSummary } from "./types.js";
|
|
7
|
+
import type { ContentProvider } from "../storyblok/provider.js";
|
|
8
|
+
|
|
9
|
+
type ArtifactSource = Pick<ContentProvider, "readArtifact" | "listArtifactPaths">;
|
|
10
|
+
|
|
11
|
+
function canReadArtifacts(value: ArtifactSource | undefined): value is ArtifactSource {
|
|
12
|
+
return typeof value?.listArtifactPaths === "function" && typeof value.readArtifact === "function";
|
|
13
|
+
}
|
|
7
14
|
|
|
8
15
|
const indexGlobs = import.meta.glob<BlogPostSummary[]>(
|
|
9
16
|
"../../../../../tenants/*/content/blog/index.json",
|
|
@@ -23,19 +30,66 @@ function tenantKey(keys: string[], tenantId: string, suffix: string): string | u
|
|
|
23
30
|
return keys.find((key) => key.includes(segment) && key.endsWith(suffix));
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
export async function listBlogPosts(
|
|
33
|
+
export async function listBlogPosts(
|
|
34
|
+
tenantId: string,
|
|
35
|
+
source?: ArtifactSource,
|
|
36
|
+
): Promise<BlogPostSummary[]> {
|
|
37
|
+
if (canReadArtifacts(source)) {
|
|
38
|
+
const paths = await source.listArtifactPaths("blog/");
|
|
39
|
+
const raw = await source.readArtifact("blog/index.json");
|
|
40
|
+
if (raw) {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(raw) as BlogPostSummary[];
|
|
43
|
+
} catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (paths !== null) return [];
|
|
48
|
+
}
|
|
27
49
|
const key = tenantKey(Object.keys(indexGlobs), tenantId, "/index.json")
|
|
28
50
|
?? Object.keys(indexGlobs).find((candidate) => candidate.includes(`/tenants/${tenantId}/content/blog/index.json`));
|
|
29
51
|
return key ? indexGlobs[key]!() : [];
|
|
30
52
|
}
|
|
31
53
|
|
|
32
|
-
export async function getBlogPost(
|
|
54
|
+
export async function getBlogPost(
|
|
55
|
+
tenantId: string,
|
|
56
|
+
slug: string,
|
|
57
|
+
source?: ArtifactSource,
|
|
58
|
+
): Promise<BlogPost | null> {
|
|
33
59
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) return null;
|
|
60
|
+
if (canReadArtifacts(source)) {
|
|
61
|
+
const paths = await source.listArtifactPaths("blog/posts/");
|
|
62
|
+
const raw = await source.readArtifact(`blog/posts/${slug}.json`);
|
|
63
|
+
if (raw) {
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(raw) as BlogPost;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (paths !== null) return null;
|
|
71
|
+
}
|
|
34
72
|
const key = tenantKey(Object.keys(postGlobs), tenantId, `/posts/${slug}.json`);
|
|
35
73
|
return key ? postGlobs[key]!() : null;
|
|
36
74
|
}
|
|
37
75
|
|
|
38
|
-
export async function resolveBlogRedirect(
|
|
76
|
+
export async function resolveBlogRedirect(
|
|
77
|
+
tenantId: string,
|
|
78
|
+
slug: string,
|
|
79
|
+
source?: ArtifactSource,
|
|
80
|
+
): Promise<string | null> {
|
|
81
|
+
if (canReadArtifacts(source)) {
|
|
82
|
+
const paths = await source.listArtifactPaths("blog/");
|
|
83
|
+
const raw = await source.readArtifact("blog/redirects.json");
|
|
84
|
+
if (raw) {
|
|
85
|
+
try {
|
|
86
|
+
return (JSON.parse(raw) as Record<string, string>)[slug] ?? null;
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (paths !== null) return null;
|
|
92
|
+
}
|
|
39
93
|
const key = tenantKey(Object.keys(redirectGlobs), tenantId, "/redirects.json")
|
|
40
94
|
?? Object.keys(redirectGlobs).find((candidate) => candidate.includes(`/tenants/${tenantId}/content/blog/redirects.json`));
|
|
41
95
|
if (!key) return null;
|
|
@@ -5,7 +5,7 @@ export interface BlogImage {
|
|
|
5
5
|
height?: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export type PostStatus = "draft" | "published" | "unlisted" | "scheduled";
|
|
8
|
+
export type PostStatus = "draft" | "published" | "unlisted" | "scheduled";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Per-post entitlement gate — who may read the body. Orthogonal to `PostStatus`
|
|
@@ -29,17 +29,17 @@ export interface BlogPostSummary {
|
|
|
29
29
|
tags: string[];
|
|
30
30
|
featuredImage?: BlogImage;
|
|
31
31
|
status: PostStatus; // seeded/legacy posts without this field default to "published"
|
|
32
|
-
scheduledAt?: string; // ISO date; when status === "scheduled", the post goes live once this instant has passed
|
|
33
|
-
canonicalUrl?: string; // syndication override
|
|
34
|
-
inLanguage?: string; // default "en"
|
|
35
|
-
access?: BlogAccess; // entitlement gate; default "public". Orthogonal to `status`
|
|
36
|
-
translationGroupId?: string; // stable id shared by every language variant of one article; absent = singleton
|
|
32
|
+
scheduledAt?: string; // ISO date; when status === "scheduled", the post goes live once this instant has passed
|
|
33
|
+
canonicalUrl?: string; // syndication override
|
|
34
|
+
inLanguage?: string; // default "en"
|
|
35
|
+
access?: BlogAccess; // entitlement gate; default "public". Orthogonal to `status`
|
|
36
|
+
translationGroupId?: string; // stable id shared by every language variant of one article; absent = singleton
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export interface BlogPost extends BlogPostSummary {
|
|
40
40
|
oldSlugs: string[];
|
|
41
41
|
contentHtml: string;
|
|
42
|
-
// Markdown source for the admin editor
|
|
42
|
+
// Markdown source for the admin editor. When present, `contentHtml` is
|
|
43
43
|
// its rendered output; migrated/legacy posts may carry only `contentHtml`.
|
|
44
44
|
bodyMarkdown?: string;
|
|
45
45
|
}
|
|
@@ -55,6 +55,6 @@ export interface AuthorBio {
|
|
|
55
55
|
title?: string; // role/title, e.g. "Founder"
|
|
56
56
|
avatar?: string; // image path (site-relative or absolute)
|
|
57
57
|
url?: string; // personal/site URL
|
|
58
|
-
sameAs?: string[]; // social profile URLs — E-E-A-T signal (feeds Person.sameAs
|
|
59
|
-
twitter?: string; // handle, e.g. "@ada" (feeds twitter:creator
|
|
58
|
+
sameAs?: string[]; // social profile URLs — E-E-A-T signal (feeds Person.sameAs)
|
|
59
|
+
twitter?: string; // handle, e.g. "@ada" (feeds twitter:creator)
|
|
60
60
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lang": "en",
|
|
3
|
+
"head": {
|
|
4
|
+
"favicon": "/tenants/tokenoftrust.com/favicon.png",
|
|
5
|
+
"themeStylesheets": ["/tenants/tokenoftrust.com/themes/tot-navy.css"]
|
|
6
|
+
},
|
|
7
|
+
"sharedMarketingCss": true,
|
|
8
|
+
"header": {
|
|
9
|
+
"variant": "primary",
|
|
10
|
+
"brand": {
|
|
11
|
+
"href": "/",
|
|
12
|
+
"label": "Token of Trust",
|
|
13
|
+
"logo": {
|
|
14
|
+
"src": "/tenants/tokenoftrust.com/logo-wordmark.png",
|
|
15
|
+
"alt": "Token of Trust",
|
|
16
|
+
"width": 180,
|
|
17
|
+
"height": 32
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"nav": [
|
|
21
|
+
{ "id": "nav-platform", "label": "Platform", "href": "/#platform" },
|
|
22
|
+
{ "id": "nav-industries", "label": "Industries", "href": "/#industries" },
|
|
23
|
+
{ "id": "nav-resources", "label": "Resources", "href": "https://help.tokenoftrust.com", "external": true },
|
|
24
|
+
{ "id": "nav-pricing", "label": "Pricing", "href": "https://tokenoftrust.com/pricing/", "external": true },
|
|
25
|
+
{ "id": "nav-login", "label": "Login", "href": "https://app.tokenoftrust.com", "external": true }
|
|
26
|
+
],
|
|
27
|
+
"ctas": [
|
|
28
|
+
{ "id": "cta-book-demo", "label": "Book Demo", "href": "https://tokenoftrust.com/contact/", "variant": "secondary" },
|
|
29
|
+
{ "id": "cta-start-free", "label": "Start For Free", "href": "https://app.tokenoftrust.com", "variant": "primary" }
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"footer": {
|
|
33
|
+
"variant": "default",
|
|
34
|
+
"brand": {
|
|
35
|
+
"text": "Customer verification and compliance for regulated ecommerce. 200+ countries. We will never sell your data."
|
|
36
|
+
},
|
|
37
|
+
"columns": [
|
|
38
|
+
{
|
|
39
|
+
"title": "Platform",
|
|
40
|
+
"links": [
|
|
41
|
+
{ "id": "ftr-platform-idv", "label": "Identity Verification", "href": "/#platform" },
|
|
42
|
+
{ "id": "ftr-platform-age", "label": "Age Assurance", "href": "/#platform" },
|
|
43
|
+
{ "id": "ftr-platform-fraud", "label": "Fraud Prevention", "href": "/#platform" },
|
|
44
|
+
{ "id": "ftr-platform-evidence", "label": "Compliance Evidence", "href": "/#platform" },
|
|
45
|
+
{ "id": "ftr-platform-aml", "label": "AML · PACT Act · Tax", "href": "/#platform" }
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"title": "Industries",
|
|
50
|
+
"links": [
|
|
51
|
+
{ "id": "ftr-industries-alcohol", "label": "Alcohol", "href": "/#industries" },
|
|
52
|
+
{ "id": "ftr-industries-vape", "label": "Tobacco & Vape", "href": "/#industries" },
|
|
53
|
+
{ "id": "ftr-industries-age-restricted", "label": "Age-Restricted Goods", "href": "/#industries" },
|
|
54
|
+
{ "id": "ftr-industries-marketplaces", "label": "Marketplaces", "href": "/#industries" }
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"title": "Company",
|
|
59
|
+
"links": [
|
|
60
|
+
{ "id": "ftr-company-pricing", "label": "Pricing", "href": "https://tokenoftrust.com/pricing/", "external": true },
|
|
61
|
+
{ "id": "ftr-company-contact", "label": "Contact Sales", "href": "https://tokenoftrust.com/contact/", "external": true },
|
|
62
|
+
{ "id": "ftr-company-resources", "label": "Resources", "href": "https://help.tokenoftrust.com", "external": true },
|
|
63
|
+
{ "id": "ftr-company-login", "label": "Login", "href": "https://app.tokenoftrust.com", "external": true }
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"title": "Legal",
|
|
68
|
+
"links": [
|
|
69
|
+
{ "id": "ftr-legal-privacy", "label": "Privacy Policy", "href": "https://tokenoftrust.com/privacy/", "external": true },
|
|
70
|
+
{ "id": "ftr-legal-terms", "label": "Terms", "href": "https://tokenoftrust.com/terms/", "external": true }
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"social": [],
|
|
75
|
+
"bottom": {
|
|
76
|
+
"note": "GDPR · CCPA · PIPEDA compliant. 256-bit SSL. We will never sell your data."
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|