@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,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Certified provider-checkout-extension contract.
|
|
3
|
+
*
|
|
4
|
+
* The managed checkout is PROVIDER-HOSTED (Foxy): the payment form, card fields,
|
|
5
|
+
* and the money-bearing hosted checkout page live on the provider's origin, never
|
|
6
|
+
* on the storefront. The storefront's only reach into checkout is a small set of
|
|
7
|
+
* BRANDING/PRESENTATION seams — a themed in-page cart drawer and CSS/asset tokens
|
|
8
|
+
* pushed to the hosted checkout template. This module declares the CLOSED set of
|
|
9
|
+
* those seams and the fail-closed validator a CERTIFIED extension is bound by.
|
|
10
|
+
*
|
|
11
|
+
* It is a SPECIALIZATION of the integration capability model
|
|
12
|
+
* (`../integration-capabilities.ts`), not a competing one:
|
|
13
|
+
* - The surface is PINNED to `checkout-payment` — the strictly-most-protected
|
|
14
|
+
* sub-surface (sandbox-only, elevated-parent prohibited). A caller cannot pick
|
|
15
|
+
* another surface; there is no surface field on the request.
|
|
16
|
+
* - Attachment is the closed {@link CHECKOUT_EXTENSION_SEAMS} registry. Every
|
|
17
|
+
* seam is a presentation seam (style tokens, scoped CSS, an asset ref, a
|
|
18
|
+
* curated template region, a non-payment custom field). NONE reads or writes
|
|
19
|
+
* card data, the signed cart, checkout totals, or the payment DOM — those live
|
|
20
|
+
* only in `FORBIDDEN_CAPABILITIES` and are structurally absent here.
|
|
21
|
+
* - Any registry capability a checkout extension additionally requests must be in
|
|
22
|
+
* the tight, read-mostly {@link CHECKOUT_ELIGIBLE_CAPABILITIES} allowlist; the
|
|
23
|
+
* request is then delegated to `validateIntegrationCapabilities`, so the
|
|
24
|
+
* tenant-tier matrix, forbidden set, binding, and origin grammar are the ONE
|
|
25
|
+
* source of truth. Two gates (checkout-eligibility + the capability model) both
|
|
26
|
+
* have to pass.
|
|
27
|
+
* - Certification is server-resolved and defaults OFF: an uncertified request is
|
|
28
|
+
* denied. "Certified" here is the checkout-extension vetting gate — distinct
|
|
29
|
+
* from the capability model's `certifiedImmutable` (which governs regulated
|
|
30
|
+
* elevated-parent code, a tier that is prohibited on this surface anyway).
|
|
31
|
+
*
|
|
32
|
+
* Compliance obligations (policy-04, `../compliance-obligations.ts`) are unchanged
|
|
33
|
+
* by anything here: they are server-derived from tenant config and no seam is an
|
|
34
|
+
* input to their resolution. The platform-owned `checkout-controls` / `cart-preflight`
|
|
35
|
+
* anchors are `PROTECTED_SURFACES` there; this contract exposes no seam that reaches
|
|
36
|
+
* them.
|
|
37
|
+
*
|
|
38
|
+
* Provenance discipline: each seam is tagged `repo-confirmed` (backed by the
|
|
39
|
+
* storefront's existing Foxy integration) or `foxy-doc-assumption` (plausible from
|
|
40
|
+
* Foxy's model but NOT evidenced in this repo — needs external Foxy-doc verification
|
|
41
|
+
* before it is treated as delivered). Assumptions are in the contract as declared,
|
|
42
|
+
* validator-gated placeholders, not as confirmed capabilities.
|
|
43
|
+
*
|
|
44
|
+
* Pure and edge-safe (no node, no I/O): validators, CLI, docs, and admin review all
|
|
45
|
+
* read this one source of truth.
|
|
46
|
+
*/
|
|
47
|
+
import {
|
|
48
|
+
FORBIDDEN_CAPABILITIES,
|
|
49
|
+
isGrantableCapability,
|
|
50
|
+
validateIntegrationCapabilities,
|
|
51
|
+
type CapabilityDenial,
|
|
52
|
+
type CodeForm,
|
|
53
|
+
type ConsentPurpose,
|
|
54
|
+
type Enforcement,
|
|
55
|
+
type GrantedCapability,
|
|
56
|
+
type IntegrationBinding,
|
|
57
|
+
type Surface,
|
|
58
|
+
type TenantTier,
|
|
59
|
+
} from "../integration-capabilities.js";
|
|
60
|
+
import type { ExecutionTier } from "./phases.js";
|
|
61
|
+
|
|
62
|
+
/** Contract token — bump the minor for additive seams, the major for a break (ADR 0006 semver). */
|
|
63
|
+
export const PROVIDER_CHECKOUT_EXTENSION_CONTRACT = "provider-checkout-extension@1" as const;
|
|
64
|
+
export type ProviderCheckoutExtensionContract = typeof PROVIDER_CHECKOUT_EXTENSION_CONTRACT;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The surface is PINNED. Every certified checkout extension resolves against the
|
|
68
|
+
* strictly-most-protected `checkout-payment` cell — sandbox-only, elevated-parent
|
|
69
|
+
* prohibited (see the D-R2 matrix). It is not caller-selectable.
|
|
70
|
+
*/
|
|
71
|
+
export const CHECKOUT_EXTENSION_SURFACE: Surface = "checkout-payment";
|
|
72
|
+
|
|
73
|
+
// ── Seam vocabulary ──────────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
/** Where a seam attaches. Both are presentation-only surfaces the storefront controls. */
|
|
76
|
+
export const CHECKOUT_SEAM_LOCATIONS = ["in-page-cart-drawer", "hosted-checkout-page"] as const;
|
|
77
|
+
export type CheckoutSeamLocation = (typeof CHECKOUT_SEAM_LOCATIONS)[number];
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* How a seam contributes. Every kind is presentation/data-collection that stays on
|
|
81
|
+
* the storefront's side of the PCI boundary — none is executable parent code on the
|
|
82
|
+
* payment DOM (that is the elevated-parent tier, prohibited on this surface).
|
|
83
|
+
*/
|
|
84
|
+
export const CHECKOUT_ATTACHMENT_KINDS = [
|
|
85
|
+
"style-tokens", // CSS custom properties (`--tot-*`) the drawer/template references.
|
|
86
|
+
"scoped-css", // Bespoke CSS, scoped to the storefront's own drawer root.
|
|
87
|
+
"raw-css", // ASCII-safe raw CSS appended to the hosted checkout content.
|
|
88
|
+
"asset-ref", // An absolute-https asset URL (e.g. a logo) referenced by the template.
|
|
89
|
+
"template-content", // Curated content injected into a NAMED hosted-checkout region.
|
|
90
|
+
"custom-field", // A non-payment field collected at checkout, posted only to our server.
|
|
91
|
+
] as const;
|
|
92
|
+
export type CheckoutAttachmentKind = (typeof CHECKOUT_ATTACHMENT_KINDS)[number];
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Whether a seam is grounded in this repo's existing Foxy integration
|
|
96
|
+
* (`repo-confirmed`) or is a plausible Foxy mechanism NOT yet evidenced here
|
|
97
|
+
* (`foxy-doc-assumption`) and gated behind external Foxy-doc verification.
|
|
98
|
+
*/
|
|
99
|
+
export const SEAM_EVIDENCE = ["repo-confirmed", "foxy-doc-assumption"] as const;
|
|
100
|
+
export type SeamEvidence = (typeof SEAM_EVIDENCE)[number];
|
|
101
|
+
|
|
102
|
+
export interface CheckoutSeamDef {
|
|
103
|
+
/** Stable, wire-serialized seam id. */
|
|
104
|
+
id: string;
|
|
105
|
+
/** Operator-facing label. */
|
|
106
|
+
label: string;
|
|
107
|
+
location: CheckoutSeamLocation;
|
|
108
|
+
attachment: CheckoutAttachmentKind;
|
|
109
|
+
evidence: SeamEvidence;
|
|
110
|
+
/**
|
|
111
|
+
* For `repo-confirmed`: the code path that proves the seam exists.
|
|
112
|
+
* For `foxy-doc-assumption`: the exact external verification still owed.
|
|
113
|
+
*/
|
|
114
|
+
provenance: string;
|
|
115
|
+
/** Consent purpose the seam's runtime effect depends on, when any (broker-enforced). */
|
|
116
|
+
requiresConsent?: ConsentPurpose;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function seam(def: CheckoutSeamDef): CheckoutSeamDef {
|
|
120
|
+
return def;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The CLOSED set of checkout UI seams a certified extension may attach to. Anything
|
|
125
|
+
* not here is unknown and fails closed. Every entry is presentation-only and, by
|
|
126
|
+
* construction, card-data-free: there is deliberately NO seam for the payment form,
|
|
127
|
+
* the card fields, the signed cart, or checkout totals.
|
|
128
|
+
*/
|
|
129
|
+
export const CHECKOUT_EXTENSION_SEAMS: Readonly<Record<string, CheckoutSeamDef>> = Object.freeze(
|
|
130
|
+
Object.fromEntries(
|
|
131
|
+
[
|
|
132
|
+
// ── repo-confirmed: backed by the existing Foxy integration ──────────────
|
|
133
|
+
seam({
|
|
134
|
+
id: "cart-drawer.style-tokens",
|
|
135
|
+
label: "Theme the in-page cart drawer via CSS custom properties",
|
|
136
|
+
location: "in-page-cart-drawer",
|
|
137
|
+
attachment: "style-tokens",
|
|
138
|
+
evidence: "repo-confirmed",
|
|
139
|
+
provenance:
|
|
140
|
+
"checkout.ts — the Foxy loader renders the cart into the storefront's own light DOM (root `#fc`), so it inherits the theme's CSS custom properties; `<CartDrawerStyles>` emits the brand baseline.",
|
|
141
|
+
}),
|
|
142
|
+
seam({
|
|
143
|
+
id: "cart-drawer.scoped-css",
|
|
144
|
+
label: "Bespoke CSS overrides for the in-page cart drawer",
|
|
145
|
+
location: "in-page-cart-drawer",
|
|
146
|
+
attachment: "scoped-css",
|
|
147
|
+
evidence: "repo-confirmed",
|
|
148
|
+
provenance:
|
|
149
|
+
"checkout.ts `ManagedCheckoutConfig.cartDrawerCss` — per-tenant CSS appended after the brand baseline; rules scope under `#fc`.",
|
|
150
|
+
}),
|
|
151
|
+
seam({
|
|
152
|
+
id: "hosted-checkout.style-tokens",
|
|
153
|
+
label: "Theme the hosted checkout page via CSS custom-property tokens",
|
|
154
|
+
location: "hosted-checkout-page",
|
|
155
|
+
attachment: "style-tokens",
|
|
156
|
+
evidence: "repo-confirmed",
|
|
157
|
+
provenance:
|
|
158
|
+
"checkout-style.ts `checkoutStyleToCss` — emits `--tot-checkout-*` tokens served at the storefront URL Foxy pulls as its theme `content_url` (`/theme/foxy`).",
|
|
159
|
+
}),
|
|
160
|
+
seam({
|
|
161
|
+
id: "hosted-checkout.raw-css",
|
|
162
|
+
label: "ASCII-safe raw-CSS override appended to the hosted checkout content",
|
|
163
|
+
location: "hosted-checkout-page",
|
|
164
|
+
attachment: "raw-css",
|
|
165
|
+
evidence: "repo-confirmed",
|
|
166
|
+
provenance:
|
|
167
|
+
"checkout-style.ts `buildCheckoutStyleCss` / `checkout.css` artifact — appended only when `isAsciiSafe` (the checkout cache pass is not Unicode-safe).",
|
|
168
|
+
}),
|
|
169
|
+
seam({
|
|
170
|
+
id: "hosted-checkout.logo",
|
|
171
|
+
label: "Brand logo shown on the hosted checkout header",
|
|
172
|
+
location: "hosted-checkout-page",
|
|
173
|
+
attachment: "asset-ref",
|
|
174
|
+
evidence: "repo-confirmed",
|
|
175
|
+
provenance:
|
|
176
|
+
"checkout-style.ts `CheckoutStyle.logoUrl` → `--tot-checkout-logo` — accepted only as an absolute https URL.",
|
|
177
|
+
}),
|
|
178
|
+
|
|
179
|
+
// ── foxy-doc-assumption: NOT evidenced in this repo; gated on verification ─
|
|
180
|
+
seam({
|
|
181
|
+
id: "hosted-checkout.template-region",
|
|
182
|
+
label: "Curated content injected into a named hosted-checkout template region",
|
|
183
|
+
location: "hosted-checkout-page",
|
|
184
|
+
attachment: "template-content",
|
|
185
|
+
evidence: "foxy-doc-assumption",
|
|
186
|
+
provenance:
|
|
187
|
+
"ASSUMPTION — Foxy's checkout template is customizable, but the named content regions, whether arbitrary HTML is permitted under our ASCII/CSP discipline, and how tokens are substituted are NOT evidenced in this repo. Verify against Foxy's checkout-template docs before treating as delivered.",
|
|
188
|
+
}),
|
|
189
|
+
seam({
|
|
190
|
+
id: "hosted-checkout.custom-field",
|
|
191
|
+
label: "A non-payment custom field collected at checkout",
|
|
192
|
+
location: "hosted-checkout-page",
|
|
193
|
+
attachment: "custom-field",
|
|
194
|
+
evidence: "foxy-doc-assumption",
|
|
195
|
+
provenance:
|
|
196
|
+
"ASSUMPTION — Foxy supports custom checkout fields, but this repo has no such integration. Verify the field never sits in the card-data/PCI path and posts back only to our own order webhook (not a third party) before treating as delivered.",
|
|
197
|
+
}),
|
|
198
|
+
].map((s) => [s.id, s]),
|
|
199
|
+
),
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
const SEAM_IDS: ReadonlySet<string> = new Set(Object.keys(CHECKOUT_EXTENSION_SEAMS));
|
|
203
|
+
|
|
204
|
+
/** True when an id is in the closed checkout-seam registry. */
|
|
205
|
+
export function isCheckoutExtensionSeam(id: string): boolean {
|
|
206
|
+
return SEAM_IDS.has(id);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/** All checkout-seam ids, in declaration order. */
|
|
210
|
+
export function checkoutExtensionSeamIds(): string[] {
|
|
211
|
+
return Object.keys(CHECKOUT_EXTENSION_SEAMS);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** Seam ids whose delivery is still gated on external Foxy-doc verification. */
|
|
215
|
+
export function assumptionSeamIds(): string[] {
|
|
216
|
+
return checkoutExtensionSeamIds().filter(
|
|
217
|
+
(id) => CHECKOUT_EXTENSION_SEAMS[id]!.evidence === "foxy-doc-assumption",
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ── Checkout-eligible capability allowlist ───────────────────────────────────
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* The ONLY registry capabilities a certified checkout extension may additionally
|
|
225
|
+
* request on the `checkout-payment` surface. Deliberately tight and read-mostly:
|
|
226
|
+
* anonymous reads, consent-gated checkout analytics, and the app's own public
|
|
227
|
+
* config. A capability outside this allowlist is denied `capability-not-checkout-
|
|
228
|
+
* eligible` even if the general capability model would otherwise grant it — so a
|
|
229
|
+
* future registry addition can never become silently checkout-reachable.
|
|
230
|
+
*
|
|
231
|
+
* Excluded on purpose: `broker:cart.add-line` (mutation on the payment surface),
|
|
232
|
+
* `broker:navigate`, any `lifecycle:*` (checkout is provider-hosted — no phase
|
|
233
|
+
* attach on the hosted page), and every `assurance:*` / `consent:*` declaration.
|
|
234
|
+
*/
|
|
235
|
+
export const CHECKOUT_ELIGIBLE_CAPABILITIES: readonly string[] = Object.freeze([
|
|
236
|
+
"broker:cart.read",
|
|
237
|
+
"broker:consent.read",
|
|
238
|
+
"broker:page-context.read",
|
|
239
|
+
"broker:analytics.emit",
|
|
240
|
+
"event:cart.viewed",
|
|
241
|
+
"event:checkout.started",
|
|
242
|
+
"event:order.completed",
|
|
243
|
+
"config:public.read",
|
|
244
|
+
"config:public.write",
|
|
245
|
+
]);
|
|
246
|
+
|
|
247
|
+
const ELIGIBLE_CAPABILITY_IDS: ReadonlySet<string> = new Set(CHECKOUT_ELIGIBLE_CAPABILITIES);
|
|
248
|
+
|
|
249
|
+
/** True when a capability id may be requested by a checkout extension. */
|
|
250
|
+
export function isCheckoutEligibleCapability(id: string): boolean {
|
|
251
|
+
return ELIGIBLE_CAPABILITY_IDS.has(id);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// ── Request / result contract ────────────────────────────────────────────────
|
|
255
|
+
|
|
256
|
+
export interface CheckoutExtensionRequest {
|
|
257
|
+
binding: IntegrationBinding;
|
|
258
|
+
/** Execution tier. checkout-payment caps at sandbox; server/elevated-parent are denied. */
|
|
259
|
+
tier: ExecutionTier;
|
|
260
|
+
codeForm: CodeForm;
|
|
261
|
+
/** Requested seam ids from {@link CHECKOUT_EXTENSION_SEAMS}. */
|
|
262
|
+
seams: readonly string[];
|
|
263
|
+
/** Optional registry capabilities; each must be in {@link CHECKOUT_ELIGIBLE_CAPABILITIES}. */
|
|
264
|
+
capabilities?: readonly string[];
|
|
265
|
+
/** Requested exact-HTTPS CSP origins (shape-validated by the capability model). */
|
|
266
|
+
origins?: readonly string[];
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Server-resolved evaluation context. Certification defaults OFF (fail-closed). */
|
|
270
|
+
export interface CheckoutExtensionContext {
|
|
271
|
+
tenantTier: TenantTier;
|
|
272
|
+
/**
|
|
273
|
+
* A green, current checkout-extension certification for THIS binding. Server-
|
|
274
|
+
* resolved from authoritative state; never taken from the request. Absent → denied.
|
|
275
|
+
*/
|
|
276
|
+
certified?: boolean;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export type CheckoutExtensionDenialReason =
|
|
280
|
+
| "uncertified"
|
|
281
|
+
| "unknown-seam"
|
|
282
|
+
| "capability-not-checkout-eligible"
|
|
283
|
+
| "capability"; // a passthrough denial from the underlying capability model.
|
|
284
|
+
|
|
285
|
+
export interface CheckoutExtensionDenial {
|
|
286
|
+
reason: CheckoutExtensionDenialReason;
|
|
287
|
+
/** The offending seam or capability id, when one applies. */
|
|
288
|
+
subject?: string;
|
|
289
|
+
/** The underlying capability-model denial, when `reason` is `capability`. */
|
|
290
|
+
capabilityDenial?: CapabilityDenial;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export interface GrantedCheckoutSeam {
|
|
294
|
+
id: string;
|
|
295
|
+
location: CheckoutSeamLocation;
|
|
296
|
+
attachment: CheckoutAttachmentKind;
|
|
297
|
+
evidence: SeamEvidence;
|
|
298
|
+
requiresConsent?: ConsentPurpose;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export type CheckoutExtensionResult =
|
|
302
|
+
| {
|
|
303
|
+
ok: true;
|
|
304
|
+
contract: ProviderCheckoutExtensionContract;
|
|
305
|
+
binding: IntegrationBinding;
|
|
306
|
+
surface: Surface;
|
|
307
|
+
tier: ExecutionTier;
|
|
308
|
+
/** Honest enforcement for the granted tier (sandbox/adapter → enforced). */
|
|
309
|
+
enforcement: Enforcement;
|
|
310
|
+
seams: GrantedCheckoutSeam[];
|
|
311
|
+
capabilities: GrantedCapability[];
|
|
312
|
+
origins: string[];
|
|
313
|
+
}
|
|
314
|
+
| { ok: false; code: "checkout_extension_denied"; denials: CheckoutExtensionDenial[] };
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Validate a certified provider-checkout-extension request. Fail-closed and
|
|
318
|
+
* all-or-nothing: an uncertified binding, an unknown seam, a non-eligible
|
|
319
|
+
* capability, or any denial from the underlying capability model (tier above
|
|
320
|
+
* sandbox, forbidden/card-data scope, unbound binding, out-of-matrix surface,
|
|
321
|
+
* malformed origin) denies the WHOLE request — never a partial grant.
|
|
322
|
+
*/
|
|
323
|
+
export function validateCheckoutExtension(
|
|
324
|
+
request: CheckoutExtensionRequest,
|
|
325
|
+
context: CheckoutExtensionContext,
|
|
326
|
+
): CheckoutExtensionResult {
|
|
327
|
+
const denials: CheckoutExtensionDenial[] = [];
|
|
328
|
+
|
|
329
|
+
// 1. Certification is mandatory and server-resolved.
|
|
330
|
+
if (!context.certified) {
|
|
331
|
+
denials.push({ reason: "uncertified" });
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// 2. Every seam must be in the closed registry.
|
|
335
|
+
const grantedSeams: GrantedCheckoutSeam[] = [];
|
|
336
|
+
for (const id of request.seams) {
|
|
337
|
+
const def = CHECKOUT_EXTENSION_SEAMS[id];
|
|
338
|
+
if (!def) {
|
|
339
|
+
denials.push({ reason: "unknown-seam", subject: id });
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
grantedSeams.push({
|
|
343
|
+
id: def.id,
|
|
344
|
+
location: def.location,
|
|
345
|
+
attachment: def.attachment,
|
|
346
|
+
evidence: def.evidence,
|
|
347
|
+
requiresConsent: def.requiresConsent,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// 3. Partition requested capabilities into checkout-eligible (delegated) and
|
|
352
|
+
// ineligible (denied here). A forbidden/card-data capability is never in the
|
|
353
|
+
// allowlist, so it is caught here AND, defensively, by the delegated model.
|
|
354
|
+
const eligible: string[] = [];
|
|
355
|
+
for (const id of request.capabilities ?? []) {
|
|
356
|
+
if (isCheckoutEligibleCapability(id)) {
|
|
357
|
+
eligible.push(id);
|
|
358
|
+
} else {
|
|
359
|
+
denials.push({ reason: "capability-not-checkout-eligible", subject: id });
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// 4. Delegate binding / tier / surface / capability / origin validation to the
|
|
364
|
+
// ONE capability model, with the surface pinned to checkout-payment.
|
|
365
|
+
const capResult = validateIntegrationCapabilities(
|
|
366
|
+
{
|
|
367
|
+
binding: request.binding,
|
|
368
|
+
tier: request.tier,
|
|
369
|
+
surface: CHECKOUT_EXTENSION_SURFACE,
|
|
370
|
+
codeForm: request.codeForm,
|
|
371
|
+
capabilities: eligible,
|
|
372
|
+
origins: request.origins,
|
|
373
|
+
},
|
|
374
|
+
{ tenantTier: context.tenantTier },
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
if (!capResult.ok) {
|
|
378
|
+
for (const d of capResult.denials) {
|
|
379
|
+
denials.push({ reason: "capability", subject: d.subject, capabilityDenial: d });
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (denials.length > 0 || !capResult.ok) {
|
|
384
|
+
return { ok: false, code: "checkout_extension_denied", denials };
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return {
|
|
388
|
+
ok: true,
|
|
389
|
+
contract: PROVIDER_CHECKOUT_EXTENSION_CONTRACT,
|
|
390
|
+
binding: request.binding,
|
|
391
|
+
surface: CHECKOUT_EXTENSION_SURFACE,
|
|
392
|
+
tier: capResult.tier,
|
|
393
|
+
enforcement: capResult.enforcement,
|
|
394
|
+
seams: grantedSeams,
|
|
395
|
+
capabilities: capResult.capabilities,
|
|
396
|
+
origins: capResult.origins,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// ── Structural boundary invariant ────────────────────────────────────────────
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Assert (at module-load and in tests) that the checkout-extension vocabulary can
|
|
404
|
+
* never reach card data. Structurally: no eligible capability is a forbidden scope,
|
|
405
|
+
* and every eligible capability is a real, grantable registry id. This is the
|
|
406
|
+
* belt-and-suspenders check behind the "an extension cannot request card data"
|
|
407
|
+
* invariant — the primary enforcement is the allowlist + the capability model.
|
|
408
|
+
*/
|
|
409
|
+
export function assertCheckoutExtensionCardDataFree(): void {
|
|
410
|
+
const forbidden = new Set<string>(FORBIDDEN_CAPABILITIES as readonly string[]);
|
|
411
|
+
for (const id of CHECKOUT_ELIGIBLE_CAPABILITIES) {
|
|
412
|
+
if (forbidden.has(id)) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`checkout-eligible capability "${id}" is a forbidden scope — the card-data boundary is broken`,
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
if (!isGrantableCapability(id)) {
|
|
418
|
+
throw new Error(
|
|
419
|
+
`checkout-eligible capability "${id}" is not a grantable registry capability`,
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
assertCheckoutExtensionCardDataFree();
|