@tokenoftrust/storefront-runner 1.4.1 → 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 +17 -1
- package/apps/storefront/env.d.ts +54 -5
- package/apps/storefront/integrations/materialize-guard.mjs +54 -0
- package/apps/storefront/migrations-apps/0002_good_switch.sql +26 -0
- package/apps/storefront/migrations-apps/0003_mute_marauders.sql +12 -0
- 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/0002_snapshot.json +1160 -0
- package/apps/storefront/migrations-apps/meta/0003_snapshot.json +1235 -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 +56 -0
- package/apps/storefront/public/apps/tot.demo.analytics/0.1.0/entry.js +42 -0
- package/apps/storefront/public/js/dashboard-team.js +38 -2
- 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/Seo.astro +65 -1
- package/apps/storefront/src/components/admin/AdminBlogDetailRail.astro +878 -0
- package/apps/storefront/src/components/admin/AdminBlogTab.astro +1435 -0
- package/apps/storefront/src/components/admin/AdminCustomersTab.astro +3 -7
- package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +105 -0
- package/apps/storefront/src/components/admin/AdminPublishTab.astro +1980 -2564
- package/apps/storefront/src/components/admin/AdminSettingsTab.astro +2 -2
- package/apps/storefront/src/components/admin/AdminSubscriptionsTab.astro +1 -3
- package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +5 -5
- package/apps/storefront/src/components/blog/BlogPaywall.astro +87 -0
- package/apps/storefront/src/components/blog/PostAccessBadge.astro +43 -0
- package/apps/storefront/src/components/blog/PostGrid.astro +57 -0
- package/apps/storefront/src/components/blog/ReactionBar.astro +214 -0
- 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 +146 -21
- package/apps/storefront/src/lib/activity/alerts.ts +17 -19
- package/apps/storefront/src/lib/activity/candidateSubmitLease.ts +87 -0
- package/apps/storefront/src/lib/activity/changeActorAttribution.ts +89 -9
- package/apps/storefront/src/lib/activity/deployVersion.ts +20 -27
- package/apps/storefront/src/lib/activity/ingest.ts +8 -8
- package/apps/storefront/src/lib/activity/ingestAuth.ts +1 -1
- package/apps/storefront/src/lib/activity/killSwitch.ts +6 -6
- package/apps/storefront/src/lib/activity/query.ts +9 -9
- package/apps/storefront/src/lib/activity/recordActivity.ts +11 -15
- package/apps/storefront/src/lib/activity/store.ts +4 -6
- package/apps/storefront/src/lib/activity/uiActor.ts +12 -12
- package/apps/storefront/src/lib/activity/workerCommit.ts +6 -6
- package/apps/storefront/src/lib/admin/adminShell.ts +292 -0
- package/apps/storefront/src/lib/admin/ai/approvalMode.ts +2 -3
- package/apps/storefront/src/lib/admin/ai/audit.ts +3 -5
- package/apps/storefront/src/lib/admin/checkoutStyleInput.ts +7 -7
- package/apps/storefront/src/lib/admin/checkoutStyleTarget.ts +3 -3
- package/apps/storefront/src/lib/admin/envelope.ts +1 -2
- package/apps/storefront/src/lib/admin/orderClient.ts +3 -5
- package/apps/storefront/src/lib/admin/services/orders.ts +17 -19
- package/apps/storefront/src/lib/admin/viewmodels/aiWorkflows.ts +4 -6
- package/apps/storefront/src/lib/admin/viewmodels/settings.ts +1 -1
- package/apps/storefront/src/lib/apps/adminService.ts +14 -4
- package/apps/storefront/src/lib/apps/adminSession.ts +54 -45
- package/apps/storefront/src/lib/apps/apiAuth.ts +2 -2
- package/apps/storefront/src/lib/apps/apiRoute.ts +2 -2
- package/apps/storefront/src/lib/apps/appVersionStore.ts +281 -0
- package/apps/storefront/src/lib/apps/catalogMapper.ts +1 -1
- package/apps/storefront/src/lib/apps/consentConfigStore.ts +228 -0
- package/apps/storefront/src/lib/apps/credentials.ts +2 -2
- package/apps/storefront/src/lib/apps/gatewayKeys.ts +4 -4
- 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/healthAggregate.ts +5 -5
- 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/attributionService.ts +2 -2
- package/apps/storefront/src/lib/apps/orders/customerHash.ts +1 -1
- package/apps/storefront/src/lib/apps/orders/foxyOrderClient.ts +12 -12
- package/apps/storefront/src/lib/apps/orders/idempotency.ts +7 -7
- package/apps/storefront/src/lib/apps/orders/orderConversionD1.ts +150 -0
- package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +9 -1
- package/apps/storefront/src/lib/apps/orders/orderMapper.ts +2 -2
- package/apps/storefront/src/lib/apps/orders/ordersStore.ts +7 -7
- package/apps/storefront/src/lib/apps/orders/verifiedProviderMeasurement.ts +117 -0
- package/apps/storefront/src/lib/apps/registryService.ts +270 -16
- package/apps/storefront/src/lib/apps/scopes.ts +2 -2
- package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +170 -0
- package/apps/storefront/src/lib/apps/tokenIssuer.ts +4 -4
- package/apps/storefront/src/lib/apps/tokenVerifier.ts +6 -6
- 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/widgets/eligibility.ts +2 -2
- package/apps/storefront/src/lib/apps/widgets/frameProps.ts +3 -3
- package/apps/storefront/src/lib/apps/widgets/launchToken.ts +4 -4
- package/apps/storefront/src/lib/apps/widgets/placements.ts +2 -2
- package/apps/storefront/src/lib/apps/widgets/renderSlot.ts +1 -1
- 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 +11 -11
- package/apps/storefront/src/lib/auth/adminLanding.ts +88 -0
- package/apps/storefront/src/lib/auth/identityToken.ts +6 -14
- package/apps/storefront/src/lib/auth/loginGate.ts +75 -13
- package/apps/storefront/src/lib/auth/mcpClientAssertion.ts +2 -4
- package/apps/storefront/src/lib/auth/operatorSession.ts +113 -0
- package/apps/storefront/src/lib/auth/session.ts +7 -8
- package/apps/storefront/src/lib/auth/totAccessClient.ts +8 -18
- package/apps/storefront/src/lib/basePath.ts +9 -2
- package/apps/storefront/src/lib/blog/access.ts +29 -0
- package/apps/storefront/src/lib/blog/collection.ts +400 -0
- package/apps/storefront/src/lib/blog/markdown.ts +174 -0
- package/apps/storefront/src/lib/blog/provider.ts +62 -3
- package/apps/storefront/src/lib/blog/reactions.ts +87 -0
- package/apps/storefront/src/lib/blog/rss.ts +92 -0
- package/apps/storefront/src/lib/blog/teaser.ts +83 -0
- package/apps/storefront/src/lib/blog/types.ts +34 -0
- package/apps/storefront/src/lib/blog/viewCounts.ts +243 -0
- 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 +14 -2
- package/apps/storefront/src/lib/d1/schema-apps.ts +372 -17
- package/apps/storefront/src/lib/dev/activityIngestToken.ts +2 -4
- package/apps/storefront/src/lib/dev/activityStore.ts +3 -5
- package/apps/storefront/src/lib/dev/apiBase.ts +1 -4
- 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/cockpitStore.ts +1 -9
- package/apps/storefront/src/lib/dev/devDraft.ts +1 -1
- package/apps/storefront/src/lib/dev/previewStatus.ts +9 -21
- package/apps/storefront/src/lib/dev/rendezvousBroker.ts +9 -24
- package/apps/storefront/src/lib/dev/runtimeStore.ts +1 -1
- package/apps/storefront/src/lib/edgeCache.ts +34 -5
- package/apps/storefront/src/lib/email/candidateConflictEmail.ts +80 -0
- package/apps/storefront/src/lib/http/fetchTransport.ts +63 -0
- package/apps/storefront/src/lib/i18n.ts +25 -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/jsonld.ts +118 -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/monitoring/manifest.ts +11 -11
- package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +30 -0
- package/apps/storefront/src/lib/newsletter/consent.ts +23 -0
- package/apps/storefront/src/lib/newsletter/digest.ts +117 -0
- package/apps/storefront/src/lib/newsletter/resendClient.ts +79 -0
- package/apps/storefront/src/lib/newsletter/send.ts +265 -0
- package/apps/storefront/src/lib/newsletter/subscribers.ts +156 -0
- package/apps/storefront/src/lib/previewReload.ts +57 -1
- package/apps/storefront/src/lib/publish/adminPublishTab.ts +4625 -0
- package/apps/storefront/src/lib/publish/apex-readiness.ts +41 -18
- 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/dispatchHealth.ts +5 -7
- package/apps/storefront/src/lib/publish/domainState.ts +22 -13
- 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/panelPolling.ts +78 -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 +121 -51
- package/apps/storefront/src/lib/publish/sseRoute.ts +119 -0
- package/apps/storefront/src/lib/publish/stageBundleUpload.ts +215 -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/rate/kvWindow.ts +53 -0
- package/apps/storefront/src/lib/rawChrome.ts +125 -47
- package/apps/storefront/src/lib/rawMarketingHtml.ts +74 -3
- package/apps/storefront/src/lib/search/index.ts +2 -2
- package/apps/storefront/src/lib/seo/alternates.ts +42 -0
- package/apps/storefront/src/lib/seo/meta.ts +65 -0
- package/apps/storefront/src/lib/social/golive.ts +212 -0
- package/apps/storefront/src/lib/social/notify.ts +32 -0
- package/apps/storefront/src/lib/social/tokenStore.ts +171 -0
- 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 +32 -0
- package/apps/storefront/src/lib/the-build/readingTime.ts +35 -0
- package/apps/storefront/src/lib/the-build/toc.ts +95 -0
- package/apps/storefront/src/lib/tot/ToTClient.ts +1 -1
- package/apps/storefront/src/lib/tot/d1Client.ts +2 -2
- package/apps/storefront/src/lib/tot/totClientInterface.ts +3 -4
- package/apps/storefront/src/lib/webhooks/deliveryStore.ts +16 -17
- package/apps/storefront/src/middleware/index.ts +385 -52
- 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 +25 -1313
- 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/blog/[collection]/[slug]/react.ts +104 -0
- 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/newsletter/[collection]/subscribe.ts +146 -0
- package/apps/storefront/src/pages/api/newsletter/confirm.ts +75 -0
- package/apps/storefront/src/pages/api/newsletter/unsubscribe.ts +90 -0
- package/apps/storefront/src/pages/api/publish/stage-bundle.ts +70 -0
- package/apps/storefront/src/pages/api/rum/vitals.ts +20 -2
- package/apps/storefront/src/pages/blog/[slug].astro +99 -19
- package/apps/storefront/src/pages/blog/author/[author].astro +140 -0
- package/apps/storefront/src/pages/blog/category/[category].astro +67 -0
- package/apps/storefront/src/pages/blog/index.astro +4 -2
- package/apps/storefront/src/pages/blog/tag/[tag].astro +65 -0
- package/apps/storefront/src/pages/cockpit.astro +77 -1353
- package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +15 -11
- 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/search.astro +1 -1
- package/apps/storefront/src/pages/sitemap.xml.ts +21 -1
- 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 +129 -0
- package/apps/storefront/src/pages/the-build/index.astro +146 -0
- package/apps/storefront/src/pages/the-build/rss.xml.ts +33 -0
- package/apps/storefront/src/styles/admin.css +1106 -0
- package/apps/storefront/tsconfig.json +6 -1
- package/package.json +1 -1
- package/packages/public-runtime/package.json +3 -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 +89 -33
- 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/catalog-d1.ts +1 -1
- 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-preview.ts +25 -2
- package/packages/public-runtime/src/customization-runtime.ts +156 -3
- package/packages/public-runtime/src/customization-versioning.ts +10 -0
- 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 +17 -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 +357 -0
- package/packages/public-runtime/src/tenant-assets.ts +143 -4
- package/packages/public-runtime/src/tenant.ts +81 -17
- package/packages/public-runtime/tests/fixtures/integration/browser-environment.example.json +8 -0
- package/packages/public-runtime/tests/fixtures/integration/commerce-event.example.json +44 -0
- package/packages/public-runtime/tests/fixtures/integration/commerce-order-event.example.json +44 -0
- package/packages/public-runtime/tests/fixtures/integration/compliance-assurance-record.example.json +50 -0
- package/packages/public-runtime/tests/fixtures/integration/integration-manifest-v2.example.json +120 -0
- package/packages/public-runtime/tests/fixtures/integration/managed-analytics-v1/fake-adapter-catalog.json +35 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-action-registry.example.json +11 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/README.md +22 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/entry.js +30 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/manifest.json +75 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/public-config.json +3 -0
- package/packages/public-runtime/tests/fixtures/regulated-commerce/fake-destinations.ts +38 -0
- package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.provenance.json +29 -0
- package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.redacted.json +3397 -0
- package/scripts/build/copy-tenant-assets.mjs +14 -4
- package/scripts/dev/ai-edit.mjs +1 -1
- package/scripts/dev/checkout-watch.mjs +2 -2
- package/scripts/dev/file-browser.mjs +4 -6
- package/scripts/dev/file-writer.mjs +3 -3
- package/scripts/dev/git-status.mjs +2 -2
- package/scripts/dev/integration-guardrails.mjs +498 -0
- package/scripts/dev/locate-handler.mjs +3 -3
- package/scripts/dev/port-check.mjs +3 -3
- package/scripts/dev/publish.mjs +5 -9
- package/scripts/dev/safe-path.mjs +2 -2
- package/scripts/dev/shot.mjs +1 -1
- package/scripts/dev/tenant-source-root.mjs +1 -1
- package/scripts/dev/unified-diff.mjs +8 -3
- package/scripts/tot-dev.mjs +8 -11
- package/apps/storefront/src/lib/dev/vcBinding.ts +0 -80
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Machine-verifiable apex-cutover READINESS gate
|
|
2
|
+
* Machine-verifiable apex-cutover READINESS gate — the green
|
|
3
3
|
* preconditions that MUST all pass before an owner apex (DNS) cutover is
|
|
4
|
-
* permitted.
|
|
4
|
+
* permitted. It consumes the go-live apex machinery:
|
|
5
5
|
* go-live owns the admin Domain Connect/Rollback button, the DNS cutover/rollback
|
|
6
6
|
* CI (`www-domain.yml` → `cutover-dns.mjs`, prior-records persisted to
|
|
7
|
-
* `s3://.../meta/`), and the HMAC completion callback;
|
|
7
|
+
* `s3://.../meta/`), and the HMAC completion callback; this gate CONSUMES those and
|
|
8
8
|
* GATES them. Nothing here mutates DNS — it decides whether a cutover is ALLOWED.
|
|
9
9
|
*
|
|
10
10
|
* The gate is a PURE function over a signals bundle so the exact policy is
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* `change/ship`'s CLI and the `acceptGate`/`apexCutoverGate` pure decisions). The
|
|
13
13
|
* server endpoint (`GET /api/domain/readiness`) assembles the signals from the
|
|
14
14
|
* live sources via {@link assembleApexReadinessSignals} — the owner capability
|
|
15
|
-
* (
|
|
15
|
+
* (`resolveShipCapabilities`), the per-tenant `DomainState` (in-flight run +
|
|
16
16
|
* the CAPTURED revert target), and the consumed dual-run parity / target-health /
|
|
17
17
|
* live-digest evidence record — and the admin Domain display + the `tot go-live`
|
|
18
18
|
* CLI both read the SAME endpoint, so the enforcement gate and the surfaces never
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
*
|
|
21
21
|
* EVIDENCE CONTRACT (the seam the go-live dual-run/health CI feeds): the parity,
|
|
22
22
|
* target-health and live-digest signals are CONSUMED from a per-tenant evidence
|
|
23
|
-
* record persisted at {@link readinessEvidenceKey} (KV).
|
|
23
|
+
* record persisted at {@link readinessEvidenceKey} (KV). The gate does not RE-RUN
|
|
24
24
|
* dual-run — it reads the record `scripts/publish/dual-run.mjs` + the health
|
|
25
25
|
* probe produce. An absent/garbage record normalises fail-closed (no parity, no
|
|
26
26
|
* digest, unhealthy), so readiness BLOCKS until the go-live CI writes real
|
|
27
27
|
* evidence — never a false "ready" from a missing feed.
|
|
28
28
|
*
|
|
29
|
-
* FAIL-CLOSED throughout
|
|
29
|
+
* FAIL-CLOSED throughout:
|
|
30
30
|
* a missing, stale, or failed signal BLOCKS the cutover with an honest,
|
|
31
31
|
* itemized reason — never a false "ready". Absence denies. The gate is
|
|
32
32
|
* ADVISORY-vs-authoritative honest: it reports readiness, but the actual cutover
|
|
33
|
-
* is still owner-gated at `apexCutoverGate`/`guardApexCutover`
|
|
33
|
+
* is still owner-gated at `apexCutoverGate`/`guardApexCutover` and executed
|
|
34
34
|
* only by the go-live CI — a green readiness verdict never bypasses those.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* The consumed dual-run parity evidence (produced by `scripts/publish/dual-run.mjs`
|
|
39
|
-
* — the
|
|
40
|
-
* wants).
|
|
39
|
+
* — the CloudFront-vs-baseline structural diff the pending-dns-cutover gate
|
|
40
|
+
* wants). This shape is consumed here; dual-run is not re-run. Green = the hard
|
|
41
41
|
* gate dual-run itself enforces: zero CloudFront route failures. `statusMismatches`
|
|
42
42
|
* are surfaced for review (content legitimately differs during a migration) but do
|
|
43
43
|
* NOT block, exactly as `dual-run.mjs` treats them. `digest` ties the evidence to
|
|
@@ -73,7 +73,7 @@ export interface RevertTarget {
|
|
|
73
73
|
export interface ApexReadinessSignals {
|
|
74
74
|
/**
|
|
75
75
|
* The acting principal holds the OWNER-ONLY apex-cutover capability
|
|
76
|
-
* (`resolveShipCapabilities(principal).apexCutover
|
|
76
|
+
* (`resolveShipCapabilities(principal).apexCutover`). A `ship-on-behalf`
|
|
77
77
|
* developer or an unauthenticated caller is false → denied.
|
|
78
78
|
*/
|
|
79
79
|
ownerCapable: boolean;
|
|
@@ -96,8 +96,8 @@ export interface ApexReadinessSignals {
|
|
|
96
96
|
targetHealthy: boolean;
|
|
97
97
|
/**
|
|
98
98
|
* The digest currently published live (the reviewed tree the cutover would
|
|
99
|
-
* point traffic at). Evidence must be tied to THIS digest to count as fresh
|
|
100
|
-
*
|
|
99
|
+
* point traffic at). Evidence must be tied to THIS digest to count as fresh.
|
|
100
|
+
* Null ⇒ freshness fails closed.
|
|
101
101
|
*/
|
|
102
102
|
liveDigest: string | null;
|
|
103
103
|
/** The captured revert target — a rollback must have somewhere to restore FROM. */
|
|
@@ -122,6 +122,14 @@ export interface ApexReadinessCheck {
|
|
|
122
122
|
ok: boolean;
|
|
123
123
|
/** Why it passed or, more importantly, why it's blocking — always actionable. */
|
|
124
124
|
detail: string;
|
|
125
|
+
/**
|
|
126
|
+
* The concrete action that clears this precondition when it's blocking — the
|
|
127
|
+
* "how to get ready" guide, carried on the gate itself so the admin panel and
|
|
128
|
+
* `tot go-live` surface identical remediation (never a divergent side doc). Only
|
|
129
|
+
* meaningful/shown when `ok` is false; the full operator walkthrough (secret
|
|
130
|
+
* provisioning, IAM) lives in `docs/runbooks/apex-cutover-readiness.md`.
|
|
131
|
+
*/
|
|
132
|
+
remedy: string;
|
|
125
133
|
}
|
|
126
134
|
|
|
127
135
|
/** The full readiness verdict: ready iff EVERY check passed; itemized either way. */
|
|
@@ -146,7 +154,7 @@ export interface ApexReadiness {
|
|
|
146
154
|
export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadiness {
|
|
147
155
|
const checks: ApexReadinessCheck[] = [];
|
|
148
156
|
|
|
149
|
-
// 1. Owner-only capability
|
|
157
|
+
// 1. Owner-only capability. A non-owner is denied outright — this is the
|
|
150
158
|
// same floor `apexCutoverGate` enforces, surfaced as a readiness item.
|
|
151
159
|
checks.push({
|
|
152
160
|
id: "owner-capability",
|
|
@@ -155,6 +163,7 @@ export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadine
|
|
|
155
163
|
detail: signals.ownerCapable
|
|
156
164
|
? "you hold the owner-only apex-cutover capability"
|
|
157
165
|
: "apex cutover is owner-only — a ship-on-behalf developer cannot cut over the apex",
|
|
166
|
+
remedy: "Sign in as the store owner — apex cutover cannot be delegated to a ship-on-behalf developer.",
|
|
158
167
|
});
|
|
159
168
|
|
|
160
169
|
// 2. No run in flight — two concurrent DNS mutations is the race DomainState guards.
|
|
@@ -165,6 +174,7 @@ export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadine
|
|
|
165
174
|
detail: signals.runInFlight
|
|
166
175
|
? "a domain connect/rollback run is already in flight — wait for it to complete"
|
|
167
176
|
: "no domain run is in flight",
|
|
177
|
+
remedy: "Wait for the in-flight connect/rollback run to finish (watch the run log), then re-check.",
|
|
168
178
|
});
|
|
169
179
|
|
|
170
180
|
// 3. Dual-run parity — zero CloudFront route failures (the hard gate dual-run.mjs
|
|
@@ -186,6 +196,10 @@ export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadine
|
|
|
186
196
|
(dr.statusMismatches > 0
|
|
187
197
|
? ` (${dr.statusMismatches} status mismatch(es) surfaced for review — non-blocking)`
|
|
188
198
|
: ""),
|
|
199
|
+
remedy:
|
|
200
|
+
"Publish tokenoftrust.com (a www-publish run) so the dual-run records fresh evidence. " +
|
|
201
|
+
"First time only: provision the WWW_READINESS_EVIDENCE_URL variable + WWW_READINESS_EVIDENCE_SECRET " +
|
|
202
|
+
"secret (see the apex-cutover-readiness runbook).",
|
|
189
203
|
});
|
|
190
204
|
|
|
191
205
|
// 4. Target health — the apex target (CloudFront/static origin) is serving.
|
|
@@ -196,11 +210,14 @@ export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadine
|
|
|
196
210
|
detail: signals.targetHealthy
|
|
197
211
|
? "apex target health check passed"
|
|
198
212
|
: "apex target health check failing or unestablished",
|
|
213
|
+
remedy:
|
|
214
|
+
"Cleared by the same www-publish evidence run as Dual-run parity — every route serving " +
|
|
215
|
+
"correctly on CloudFront is what proves the target healthy.",
|
|
199
216
|
});
|
|
200
217
|
|
|
201
|
-
// 5. Evidence freshness — the parity evidence is tied to the CURRENT live digest
|
|
202
|
-
//
|
|
203
|
-
//
|
|
218
|
+
// 5. Evidence freshness — the parity evidence is tied to the CURRENT live digest.
|
|
219
|
+
// Stale evidence (a different digest) or a missing digest on either side fails
|
|
220
|
+
// closed.
|
|
204
221
|
const evidenceDigest = dr?.digest ?? null;
|
|
205
222
|
const freshOk =
|
|
206
223
|
!!evidenceDigest && !!signals.liveDigest && evidenceDigest === signals.liveDigest;
|
|
@@ -216,6 +233,8 @@ export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadine
|
|
|
216
233
|
? "parity evidence carries no digest — cannot confirm it matches the live tree"
|
|
217
234
|
: `parity evidence is stale: it was produced against ${short(evidenceDigest)}, ` +
|
|
218
235
|
`not the live digest ${short(signals.liveDigest)}`,
|
|
236
|
+
remedy:
|
|
237
|
+
"Re-publish tokenoftrust.com so the dual-run evidence is re-tied to the current live digest.",
|
|
219
238
|
});
|
|
220
239
|
|
|
221
240
|
// 6. Captured revert target — a rollback must have persisted prior DNS records to
|
|
@@ -230,6 +249,9 @@ export function computeApexReadiness(signals: ApexReadinessSignals): ApexReadine
|
|
|
230
249
|
signals.revert.capturedAt ? ` @ ${signals.revert.capturedAt}` : ""
|
|
231
250
|
})`
|
|
232
251
|
: "no captured revert target — prior DNS records are not persisted, so there is no tested rollback",
|
|
252
|
+
remedy:
|
|
253
|
+
"Run a rehearsal (dry-run connect) from the Domain section — it captures the current DNS " +
|
|
254
|
+
"records as the rollback target without changing live DNS.",
|
|
233
255
|
});
|
|
234
256
|
|
|
235
257
|
const blockedReasons = checks.filter((c) => !c.ok).map((c) => c.detail);
|
|
@@ -267,9 +289,10 @@ function num(v: unknown): number | null {
|
|
|
267
289
|
|
|
268
290
|
/**
|
|
269
291
|
* The consumed readiness-evidence record the go-live dual-run/health CI persists
|
|
270
|
-
* per tenant.
|
|
292
|
+
* per tenant. Bundles the three signals the gate
|
|
271
293
|
* cannot derive from `DomainState` alone: the dual-run parity result, the apex
|
|
272
294
|
* target's health, and the digest currently live (so freshness can be checked).
|
|
295
|
+
* The gate READS it; it does not produce it.
|
|
273
296
|
*/
|
|
274
297
|
export interface ReadinessEvidence {
|
|
275
298
|
dualRun: DualRunEvidence | null;
|
|
@@ -311,7 +334,7 @@ export interface ReadinessDomainState {
|
|
|
311
334
|
|
|
312
335
|
/**
|
|
313
336
|
* Assemble the {@link ApexReadinessSignals} the gate decides over from the three
|
|
314
|
-
* live sources — the owner capability
|
|
337
|
+
* live sources — the owner capability, the per-tenant domain state (revert +
|
|
315
338
|
* in-flight), and the consumed evidence record — PURE so the endpoint's mapping is
|
|
316
339
|
* unit-testable without KV/session I/O. The endpoint does the reads; this does the
|
|
317
340
|
* mapping.
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure logic for the admin Publish tab's real-time build/check streaming (SSE).
|
|
3
|
+
*
|
|
4
|
+
* The build endpoint (`POST /api/preview/build` with `Accept: text/event-stream`)
|
|
5
|
+
* streams coarse lifecycle PHASES as it materializes a candidate — resolve head →
|
|
6
|
+
* read+validate tenant files → publish the immutable version → run evidence checks —
|
|
7
|
+
* then a terminal `result` event carrying the full outcome. This module is the tested
|
|
8
|
+
* source of truth for:
|
|
9
|
+
* - parsing the raw SSE byte-frames into events (partial-chunk safe);
|
|
10
|
+
* - mapping a phase to its human label + rail position;
|
|
11
|
+
* - reducing the event sequence into a render-ready progress state;
|
|
12
|
+
* - assembling the "Copy for your AI agent" prompt from a build FAILURE.
|
|
13
|
+
* The DOM wiring that drives the dialog from these is verified on a live preview, per
|
|
14
|
+
* this codebase's client-island convention (see reviewReleaseWorkspace/controller.ts).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** One decoded SSE event: its `event:` name and the concatenated `data:` payload. */
|
|
18
|
+
export interface SseEvent {
|
|
19
|
+
event: string;
|
|
20
|
+
data: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Parse an accumulated SSE text buffer into complete events, returning any trailing
|
|
25
|
+
* INCOMPLETE frame as `rest` for the next chunk to prepend. Partial-chunk safe: a
|
|
26
|
+
* frame is complete only once its blank-line terminator (`\n\n`) has arrived.
|
|
27
|
+
* Lines with no field (`:` comments, stray blanks) are ignored; multiple `data:`
|
|
28
|
+
* lines in one frame join with `\n` (the SSE spec). A frame with no fields yields
|
|
29
|
+
* nothing.
|
|
30
|
+
*/
|
|
31
|
+
export function parseSseChunk(buffer: string): { events: SseEvent[]; rest: string } {
|
|
32
|
+
const normalized = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
33
|
+
const events: SseEvent[] = [];
|
|
34
|
+
const lastSep = normalized.lastIndexOf("\n\n");
|
|
35
|
+
if (lastSep === -1) return { events, rest: normalized };
|
|
36
|
+
|
|
37
|
+
const complete = normalized.slice(0, lastSep);
|
|
38
|
+
const rest = normalized.slice(lastSep + 2);
|
|
39
|
+
|
|
40
|
+
for (const frame of complete.split("\n\n")) {
|
|
41
|
+
let eventName = "message";
|
|
42
|
+
const dataLines: string[] = [];
|
|
43
|
+
let sawField = false;
|
|
44
|
+
for (const rawLine of frame.split("\n")) {
|
|
45
|
+
if (!rawLine || rawLine.startsWith(":")) continue;
|
|
46
|
+
const colon = rawLine.indexOf(":");
|
|
47
|
+
const field = colon === -1 ? rawLine : rawLine.slice(0, colon);
|
|
48
|
+
// Per spec a single leading space after the colon is stripped.
|
|
49
|
+
let value = colon === -1 ? "" : rawLine.slice(colon + 1);
|
|
50
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
51
|
+
if (field === "event") {
|
|
52
|
+
eventName = value;
|
|
53
|
+
sawField = true;
|
|
54
|
+
} else if (field === "data") {
|
|
55
|
+
dataLines.push(value);
|
|
56
|
+
sawField = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (sawField) events.push({ event: eventName, data: dataLines.join("\n") });
|
|
60
|
+
}
|
|
61
|
+
return { events, rest };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The ordered build lifecycle stages the flight rail renders (mirrors the dialog). */
|
|
65
|
+
export const BUILD_STAGES = ["resolve", "read", "publish", "check"] as const;
|
|
66
|
+
export type BuildStage = (typeof BUILD_STAGES)[number];
|
|
67
|
+
|
|
68
|
+
/** The `phase` values the server emits, in lifecycle order. */
|
|
69
|
+
export type BuildPhase = "resolving" | "reading" | "publishing" | "checking";
|
|
70
|
+
|
|
71
|
+
const PHASE_TO_STAGE: Record<BuildPhase, BuildStage> = {
|
|
72
|
+
resolving: "resolve",
|
|
73
|
+
reading: "read",
|
|
74
|
+
publishing: "publish",
|
|
75
|
+
checking: "check",
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const PHASE_LABEL: Record<BuildPhase, string> = {
|
|
79
|
+
resolving: "Locating the pull request's latest commit…",
|
|
80
|
+
reading: "Reading and validating your store's files…",
|
|
81
|
+
publishing: "Publishing this version's preview…",
|
|
82
|
+
checking: "Running the checks on this version…",
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const STAGE_LABEL: Record<BuildStage, string> = {
|
|
86
|
+
resolve: "Locate commit",
|
|
87
|
+
read: "Read & validate",
|
|
88
|
+
publish: "Publish version",
|
|
89
|
+
check: "Run checks",
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export function buildPhaseLabel(phase: BuildPhase): string {
|
|
93
|
+
return PHASE_LABEL[phase];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function buildStageLabel(stage: BuildStage): string {
|
|
97
|
+
return STAGE_LABEL[stage];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function isBuildPhase(value: unknown): value is BuildPhase {
|
|
101
|
+
return value === "resolving" || value === "reading" || value === "publishing" || value === "checking";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The terminal outcome the server reports on its `result` event. */
|
|
105
|
+
export type BuildOutcome = "ok" | "blocked" | "failed";
|
|
106
|
+
|
|
107
|
+
/** The full terminal payload of a build (mirrors the endpoint's JSON body). */
|
|
108
|
+
export interface BuildResult {
|
|
109
|
+
ok: boolean;
|
|
110
|
+
outcome: BuildOutcome;
|
|
111
|
+
tenantId?: string | null;
|
|
112
|
+
changeId?: string | null;
|
|
113
|
+
headSha?: string | null;
|
|
114
|
+
prNumber?: number | null;
|
|
115
|
+
previewUrl?: string | null;
|
|
116
|
+
errors?: string[];
|
|
117
|
+
error?: string | null;
|
|
118
|
+
findings?: BuildFinding[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface BuildFinding {
|
|
122
|
+
id?: string;
|
|
123
|
+
label?: string;
|
|
124
|
+
detail?: string;
|
|
125
|
+
disposition?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Render-ready progress the dialog reads. `stageState` is a per-stage rail map. */
|
|
129
|
+
export interface BuildProgress {
|
|
130
|
+
phase: BuildPhase | null;
|
|
131
|
+
liveLabel: string;
|
|
132
|
+
stageState: Record<BuildStage, "pending" | "active" | "done" | "fail">;
|
|
133
|
+
terminal: boolean;
|
|
134
|
+
result: BuildResult | null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function initialBuildProgress(): BuildProgress {
|
|
138
|
+
return {
|
|
139
|
+
phase: null,
|
|
140
|
+
liveLabel: "Starting…",
|
|
141
|
+
stageState: { resolve: "pending", read: "pending", publish: "pending", check: "pending" },
|
|
142
|
+
terminal: false,
|
|
143
|
+
result: null,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Advance the flight rail to `stage`: everything before it is `done`, it is `active`,
|
|
149
|
+
* everything after stays `pending`. A `fail` mark is never un-done. Pure.
|
|
150
|
+
*/
|
|
151
|
+
function railTo(
|
|
152
|
+
prev: Record<BuildStage, "pending" | "active" | "done" | "fail">,
|
|
153
|
+
stage: BuildStage,
|
|
154
|
+
): Record<BuildStage, "pending" | "active" | "done" | "fail"> {
|
|
155
|
+
const idx = BUILD_STAGES.indexOf(stage);
|
|
156
|
+
const next = { ...prev };
|
|
157
|
+
BUILD_STAGES.forEach((s, i) => {
|
|
158
|
+
if (next[s] === "fail") return;
|
|
159
|
+
next[s] = i < idx ? "done" : i === idx ? "active" : "pending";
|
|
160
|
+
});
|
|
161
|
+
return next;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Fold one SSE event into the progress state. A `phase` event advances the rail + live
|
|
166
|
+
* label; a `result` event is terminal (all reached stages `done` on success, the active
|
|
167
|
+
* stage `fail` on a blocked/failed outcome). Unknown events are ignored (state
|
|
168
|
+
* unchanged). Pure — the dialog calls this per event and re-renders from the result.
|
|
169
|
+
*/
|
|
170
|
+
export function reduceBuildProgress(prev: BuildProgress, ev: SseEvent): BuildProgress {
|
|
171
|
+
if (ev.event === "phase") {
|
|
172
|
+
const parsed = safeParse(ev.data);
|
|
173
|
+
const phase = parsed && (parsed as { phase?: unknown }).phase;
|
|
174
|
+
if (!isBuildPhase(phase)) return prev;
|
|
175
|
+
const stage = PHASE_TO_STAGE[phase];
|
|
176
|
+
const label =
|
|
177
|
+
(parsed && typeof (parsed as { label?: unknown }).label === "string"
|
|
178
|
+
? (parsed as { label: string }).label
|
|
179
|
+
: "") || buildPhaseLabel(phase);
|
|
180
|
+
return {
|
|
181
|
+
...prev,
|
|
182
|
+
phase,
|
|
183
|
+
liveLabel: label,
|
|
184
|
+
stageState: railTo(prev.stageState, stage),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (ev.event === "result") {
|
|
189
|
+
const parsed = (safeParse(ev.data) as BuildResult | null) ?? {
|
|
190
|
+
ok: false,
|
|
191
|
+
outcome: "failed",
|
|
192
|
+
errors: ["build ended without a result"],
|
|
193
|
+
};
|
|
194
|
+
const result: BuildResult = {
|
|
195
|
+
...parsed,
|
|
196
|
+
outcome: parsed.outcome ?? (parsed.ok ? "ok" : "failed"),
|
|
197
|
+
};
|
|
198
|
+
let stageState = prev.stageState;
|
|
199
|
+
if (result.ok) {
|
|
200
|
+
stageState = { resolve: "done", read: "done", publish: "done", check: "done" };
|
|
201
|
+
} else {
|
|
202
|
+
// Fail the stage that was active (the phase we got furthest into); if none was
|
|
203
|
+
// active yet, fail the first stage so the rail shows an honest stop point.
|
|
204
|
+
const active = BUILD_STAGES.find((s) => prev.stageState[s] === "active") ?? BUILD_STAGES[0];
|
|
205
|
+
stageState = { ...prev.stageState, [active]: "fail" };
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
...prev,
|
|
209
|
+
liveLabel: result.ok ? "Done." : "Stopped.",
|
|
210
|
+
stageState,
|
|
211
|
+
terminal: true,
|
|
212
|
+
result,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return prev;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** The human-readable failure detail (the honest reason), joined from errors/findings. */
|
|
220
|
+
export function buildFailureDetail(result: BuildResult): string {
|
|
221
|
+
const parts: string[] = [];
|
|
222
|
+
for (const e of result.errors ?? []) if (e && e.trim()) parts.push(e.trim());
|
|
223
|
+
if (result.error && result.error.trim()) parts.push(result.error.trim());
|
|
224
|
+
for (const f of result.findings ?? []) {
|
|
225
|
+
const line = [f.label || f.id, f.detail].filter(Boolean).join(": ");
|
|
226
|
+
if (line) parts.push((f.disposition === "blocking-safety" ? "[blocking] " : "") + line);
|
|
227
|
+
}
|
|
228
|
+
return parts.join("\n");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Assemble the "Copy for your AI agent" prompt from a build FAILURE — the honest,
|
|
233
|
+
* paste-ready brief an operator hands to a coding agent to diagnose why the preview
|
|
234
|
+
* build/checks failed. Mirrors the merge-conflict copy pattern (a framed ask + the
|
|
235
|
+
* system's own words), never a bare error dump.
|
|
236
|
+
*/
|
|
237
|
+
export function assembleBuildFailureCopy(input: {
|
|
238
|
+
tenant: string;
|
|
239
|
+
prNumber?: number | null;
|
|
240
|
+
changeId?: string | null;
|
|
241
|
+
result: BuildResult;
|
|
242
|
+
}): string {
|
|
243
|
+
const { tenant, prNumber, changeId, result } = input;
|
|
244
|
+
const pr = prNumber != null ? `PR #${prNumber}` : changeId ? `change ${changeId}` : "my open candidate PR";
|
|
245
|
+
const stage = result.outcome === "blocked" ? "was blocked by a check" : "failed to build";
|
|
246
|
+
const detail = buildFailureDetail(result) || "(no detail was reported)";
|
|
247
|
+
return [
|
|
248
|
+
`In my ${tenant} store, the preview build for ${pr} ${stage}. ` +
|
|
249
|
+
`Diagnose why from the detail below, then tell me the exact file(s) to change and the fix.`,
|
|
250
|
+
"",
|
|
251
|
+
"What the build reported:",
|
|
252
|
+
detail,
|
|
253
|
+
"",
|
|
254
|
+
result.headSha ? `Head commit: ${result.headSha}` : "",
|
|
255
|
+
"Context: this is a Token of Trust storefront tenant repo — customization files are " +
|
|
256
|
+
"mapped to artifacts and validated against the tenant-editable manifest before the " +
|
|
257
|
+
"version is published. A blocking finding or a validation error stops the build.",
|
|
258
|
+
]
|
|
259
|
+
.filter((l) => l !== "")
|
|
260
|
+
.join("\n");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function safeParse(text: string): unknown {
|
|
264
|
+
try {
|
|
265
|
+
return JSON.parse(text);
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* r05 — persist each Publish-tab collapsible section's open/closed state per user,
|
|
3
|
+
* scoped per store so a power user's layout survives reloads without bleeding across
|
|
4
|
+
* stores. Pure key/read/write logic, extracted from the DOM wiring in
|
|
5
|
+
* `adminPublishTab.ts` so it is unit-testable and storage-agnostic.
|
|
6
|
+
*
|
|
7
|
+
* The persisted value is the human-legible "open"/"closed" (not a boolean string).
|
|
8
|
+
* `readPersistedOpen` returns `null` when nothing is stored (or storage is
|
|
9
|
+
* unreadable) — the caller then leaves the section at its SSR default, so the
|
|
10
|
+
* default open/closed state is preserved when a user has never toggled a section.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** The slice of the Web Storage API this helper needs (localStorage satisfies it). */
|
|
14
|
+
export interface CollapseStorage {
|
|
15
|
+
getItem(key: string): string | null;
|
|
16
|
+
setItem(key: string, value: string): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Stable identifiers for the collapsible sections on the Publish tab. */
|
|
20
|
+
export type CollapseSectionId =
|
|
21
|
+
| "review-queue"
|
|
22
|
+
| "closed-changes"
|
|
23
|
+
| "next-release"
|
|
24
|
+
| "live-site"
|
|
25
|
+
| "rollback";
|
|
26
|
+
|
|
27
|
+
const KEY_PREFIX = "tot.publish.collapse";
|
|
28
|
+
const OPEN = "open";
|
|
29
|
+
const CLOSED = "closed";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Per-store, per-section storage key. The store scope (appDomain) keeps one store's
|
|
33
|
+
* layout from bleeding into another; an empty tenant collapses to a shared "_" scope
|
|
34
|
+
* rather than producing a dangling key.
|
|
35
|
+
*/
|
|
36
|
+
export function collapseStorageKey(tenant: string, sectionId: CollapseSectionId): string {
|
|
37
|
+
return `${KEY_PREFIX}.${tenant || "_"}.${sectionId}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The stored open/closed state, or `null` when nothing is stored, the value is
|
|
42
|
+
* unrecognized, or storage throws (private mode / disabled). Never throws.
|
|
43
|
+
*/
|
|
44
|
+
export function readPersistedOpen(
|
|
45
|
+
storage: CollapseStorage,
|
|
46
|
+
tenant: string,
|
|
47
|
+
sectionId: CollapseSectionId,
|
|
48
|
+
): boolean | null {
|
|
49
|
+
let raw: string | null;
|
|
50
|
+
try {
|
|
51
|
+
raw = storage.getItem(collapseStorageKey(tenant, sectionId));
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
if (raw === OPEN) return true;
|
|
56
|
+
if (raw === CLOSED) return false;
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Persist a section's open/closed state. Swallows storage errors (never throws). */
|
|
61
|
+
export function writePersistedOpen(
|
|
62
|
+
storage: CollapseStorage,
|
|
63
|
+
tenant: string,
|
|
64
|
+
sectionId: CollapseSectionId,
|
|
65
|
+
open: boolean,
|
|
66
|
+
): void {
|
|
67
|
+
try {
|
|
68
|
+
storage.setItem(collapseStorageKey(tenant, sectionId), open ? OPEN : CLOSED);
|
|
69
|
+
} catch {
|
|
70
|
+
/* storage unavailable (private mode / disabled) — persistence is best-effort */
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dispatch-health assessment
|
|
2
|
+
* Dispatch-health assessment — is the static-publish `repository_dispatch`
|
|
3
3
|
* path actually WIRED and HEALTHY, or would a "go-live" silently hand the publish
|
|
4
4
|
* to a dead-end? The Worker fires a `repository_dispatch` and gets a 204 back
|
|
5
5
|
* having verified NOTHING about the target (see `createRepositoryDispatchSink` —
|
|
6
6
|
* it is fire-and-forget by construction). This module is the HONEST pre-flight
|
|
7
|
-
* surface that answers
|
|
8
|
-
* reviewed-sha`, whether that path can carry a publish at all — reporting each
|
|
7
|
+
* surface that answers whether that path can carry a publish at all — reporting each
|
|
9
8
|
* concrete signal pass/fail/unknown with a reason, never a silent assumption.
|
|
10
9
|
*
|
|
11
10
|
* FOUR SIGNALS:
|
|
@@ -19,14 +18,13 @@
|
|
|
19
18
|
* that lives only on the deploy branch is
|
|
20
19
|
* NOT yet reachable. A 404 here is the
|
|
21
20
|
* honest "not yet promoted to main" state
|
|
22
|
-
* (the HELD main-promotion gate
|
|
23
|
-
*
|
|
24
|
-
* publish-activation`) — surfaced, not papered.
|
|
21
|
+
* (the HELD main-promotion gate) —
|
|
22
|
+
* surfaced, not papered.
|
|
25
23
|
* - `target-reachable` — does the published `live/manifest.json`
|
|
26
24
|
* answer? DIAGNOSTIC ONLY: a pre-first-
|
|
27
25
|
* publish target legitimately has none, so
|
|
28
26
|
* this never blocks a ship (the post-merge
|
|
29
|
-
* VERIFY in
|
|
27
|
+
* VERIFY in the orchestrator is the real
|
|
30
28
|
* no-false-live gate).
|
|
31
29
|
*
|
|
32
30
|
* FAIL-CLOSED SEMANTICS:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Apex domain-connect state + dispatch
|
|
2
|
+
* Apex domain-connect state + dispatch.
|
|
3
3
|
*
|
|
4
4
|
* The admin Publish tab's "Domain" section drives the apex DNS cutover
|
|
5
5
|
* (tokenoftrust.com → CloudFront) and its rollback as PRODUCT actions, not a
|
|
@@ -212,8 +212,11 @@ export interface DomainRunCallback {
|
|
|
212
212
|
* overwrite an existing pointer with null — the FIRST capture is
|
|
213
213
|
* the true pre-platform state)
|
|
214
214
|
* rollback → `pantheon`
|
|
215
|
-
* Rehearsal (wire: dryRun) runs never move state —
|
|
216
|
-
*
|
|
215
|
+
* Rehearsal (wire: dryRun) runs never move `state` — but a rehearsal CONNECT
|
|
216
|
+
* that reports a `priorKey` DOES record the revert target (prior-records pointer),
|
|
217
|
+
* because persisting a metadata capture mutates no live DNS, and it's what lets
|
|
218
|
+
* the apex-cutover readiness gate's "revert captured" precondition go green BEFORE
|
|
219
|
+
* the real cutover. Capturing the revert target is decoupled from moving state.
|
|
217
220
|
*/
|
|
218
221
|
export function completeDomainRun(
|
|
219
222
|
state: DomainState,
|
|
@@ -245,19 +248,25 @@ export function completeDomainRun(
|
|
|
245
248
|
};
|
|
246
249
|
|
|
247
250
|
let next: DomainState = { ...state, lastRun: updatedRun };
|
|
248
|
-
if (cb.status === "succeeded"
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
if (cb.status === "succeeded") {
|
|
252
|
+
// Platform state flips only on a REAL (non-rehearsal) run — a rehearsal
|
|
253
|
+
// changes no DNS, so it must never claim the apex moved.
|
|
254
|
+
if (!run.rehearsal) {
|
|
255
|
+
const reported =
|
|
256
|
+
cb.state === "cloudfront" || cb.state === "pantheon" ? cb.state : null;
|
|
257
|
+
next = {
|
|
258
|
+
...next,
|
|
259
|
+
state: reported ?? (run.action === "connect" ? "cloudfront" : "pantheon"),
|
|
260
|
+
since: updatedRun.finishedAt,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
// Capturing the revert target is DECOUPLED from moving state: any successful
|
|
264
|
+
// connect that carries a priorKey records it — a rehearsal included — so the
|
|
265
|
+
// readiness gate can confirm a tested rollback before the real cutover. Never
|
|
266
|
+
// regress an existing pointer to null (the FIRST capture is the true origin).
|
|
256
267
|
if (run.action === "connect") {
|
|
257
268
|
next = {
|
|
258
269
|
...next,
|
|
259
|
-
// Keep the FIRST capture if the callback carries none — never regress
|
|
260
|
-
// the pointer to null once a real capture exists.
|
|
261
270
|
priorRecordsKey: cb.priorKey ?? state.priorRecordsKey,
|
|
262
271
|
priorCapturedAt: cb.priorKey
|
|
263
272
|
? (cb.completedAt ?? at)
|