@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
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* - OPEN CHANGE QUEUE from GET /api/changes ({ current, changes }) with
|
|
8
8
|
* per-change reconcile/compliance state, preview link, head sha, and age.
|
|
9
|
-
* - ACCEPT TO PREVIEW (POST /api/changes/integrate —
|
|
9
|
+
* - ACCEPT TO PREVIEW (POST /api/changes/integrate — the accept-to-preview
|
|
10
10
|
* split; advances the shared `preview` aggregate, does NOT go live) and
|
|
11
11
|
* REJECT (with a note) per change. Going live is the aggregate card's
|
|
12
12
|
* exact-digest PUBLISH (POST /api/changes/ship), never a per-change accept.
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* OWNER_CAPABILITIES) — others see the queue read-only with a sign-in note.
|
|
24
24
|
* - Non-premium tenants see the go-live control as a PAYWALL UPSELL — never
|
|
25
25
|
* hidden, never "coming soon" (recorded product direction). The
|
|
26
|
-
* entitlement signal is the existing premium model
|
|
26
|
+
* entitlement signal is the existing premium model: a custom-domain
|
|
27
27
|
* tenant is premium/pilot; a `<label>.tokenoftrust.store` self-serve store
|
|
28
28
|
* is not. TODO(paywall workstream): replace with the real billing
|
|
29
29
|
* entitlement when one exists.
|
|
@@ -32,9 +32,10 @@ import { readViewerSession } from "@/lib/auth/route";
|
|
|
32
32
|
import { withBase } from "@/lib/basePath";
|
|
33
33
|
import { readEnv } from "@/lib/env";
|
|
34
34
|
import { resolveViewerShipCapability } from "@/lib/change";
|
|
35
|
-
import { resolveLiveVersion } from "@/lib/change/
|
|
36
|
-
import { isPublicSiteCurrent } from "@/lib/change/
|
|
35
|
+
import { resolveLiveVersion } from "@/lib/change/views/live-version";
|
|
36
|
+
import { isPublicSiteCurrent, staticLiveManifestUrl } from "@/lib/change/views/live-digest";
|
|
37
37
|
import { isHostedStoreDomain, isInternalTestTenant } from "@tot/public-runtime";
|
|
38
|
+
import { mintPreviewShareToken } from "@/lib/preview/previewShareLink";
|
|
38
39
|
|
|
39
40
|
const { envelope } = Astro.props;
|
|
40
41
|
const { tenant, basePath } = Astro.locals;
|
|
@@ -51,7 +52,7 @@ const viewerCapability =
|
|
|
51
52
|
// A signed-in DEVELOPER (not owner/admin) may hold an explicit, owner-revocable
|
|
52
53
|
// ship-on-behalf grant. Resolve it LIVE from the MCP subject-capability store —
|
|
53
54
|
// NEVER the coarse role, NEVER a client header — so a ship-granted developer sees
|
|
54
|
-
// the queue + Go-live/Reject
|
|
55
|
+
// the queue + Go-live/Reject. This MIRRORS the server (resolveShipSession /
|
|
55
56
|
// effectiveShipCapability); the server re-authorizes every action. UX-only.
|
|
56
57
|
let viewerCanShip = viewerCapability === "owner" || viewerCapability === "admin";
|
|
57
58
|
if (!viewerCanShip && Astro.locals.viewer?.email) {
|
|
@@ -77,13 +78,13 @@ const internalTestTenant = isInternalTestTenant(tenant);
|
|
|
77
78
|
const staticPublishEnabled = Boolean(
|
|
78
79
|
tenant.staticPublish && tenant.staticPublish.enabled !== false,
|
|
79
80
|
);
|
|
80
|
-
// Presence-only signal for the
|
|
81
|
+
// Presence-only signal for the dispatch sink (never the value).
|
|
81
82
|
const dispatchConfigured = Boolean((await readEnv("WWW_PUBLISH_DISPATCH_TOKEN"))?.trim());
|
|
82
83
|
|
|
83
84
|
// "What does the public site actually serve right now?" — the read-back half of
|
|
84
85
|
// the static-publish seam (resolveLiveVersion's staticLiveDigest), computed here
|
|
85
86
|
// so it's ALWAYS visible rather than only living in GET /api/changes JSON. This is
|
|
86
|
-
// the exact gap that let tokenoftrust.com's public site
|
|
87
|
+
// the exact gap that can let tokenoftrust.com's published public site
|
|
87
88
|
// sit two days stale behind several accepted-but-unpublished changes with nothing
|
|
88
89
|
// in the console calling it out — going live and staying live for the PUBLIC
|
|
89
90
|
// static target are two different facts, and this card makes the second one
|
|
@@ -103,43 +104,37 @@ const liveVersion = staticPublishEnabled
|
|
|
103
104
|
: null;
|
|
104
105
|
const publicSiteDigest = liveVersion?.staticLiveDigest ?? null;
|
|
105
106
|
// The actual verdict: does the public target's manifest sha match what was last
|
|
106
|
-
// promoted to "live" here? Both are real tenant Gitea shas
|
|
107
|
+
// promoted to "live" here? Both are real tenant Gitea shas — a direct,
|
|
107
108
|
// honest comparison, not a heuristic. See liveDigest.ts's isPublicSiteCurrent.
|
|
108
109
|
const publicSiteVerdict = publicSiteDigest
|
|
109
110
|
? isPublicSiteCurrent(liveVersion?.versionId ?? null, publicSiteDigest)
|
|
110
111
|
: null;
|
|
111
112
|
|
|
112
113
|
const changesEndpoint = withBase(basePath || "", "/api/changes");
|
|
113
|
-
//
|
|
114
|
-
// - integrateEndpoint =
|
|
114
|
+
// The branch-integration lifecycle SPLIT of accept from publish:
|
|
115
|
+
// - integrateEndpoint = "accept = integrate into the protected preview
|
|
115
116
|
// aggregate" (POST /api/changes/integrate → TenantIntegrationQueue.enqueue).
|
|
116
117
|
// This is the candidate-queue "Accept to preview" action — it advances the
|
|
117
118
|
// shared aggregate, it does NOT go live. Returns an IntegrateOutcome
|
|
118
119
|
// (queueState/runState/statusMessage), never a bare merged:true.
|
|
119
|
-
// - shipEndpoint =
|
|
120
|
-
//
|
|
120
|
+
// - shipEndpoint = the exact-digest go-live (POST /api/changes/ship →
|
|
121
|
+
// AggregateShipOrchestrator.plan/ship). The aggregate card's "Publish"
|
|
121
122
|
// action: it ships the reviewed pinned SHA + digest, double-gated
|
|
122
123
|
// (paywall + human confirm). The read-only plan is served on GET /api/changes
|
|
123
124
|
// (`plan`), so the confirm surface never has to POST to preview it.
|
|
124
|
-
// If b08/b10's exact paths differ at fold, the integrator reconciles here —
|
|
125
|
-
// these are the agreed contract paths (see the unit brief).
|
|
126
125
|
const integrateEndpoint = withBase(basePath || "", "/api/changes/integrate");
|
|
127
126
|
const shipEndpoint = withBase(basePath || "", "/api/changes/ship");
|
|
128
|
-
//
|
|
129
|
-
// DISTINCT from reject (which closes the change). Gated server-side by retireGate.
|
|
130
|
-
const retireEndpoint = withBase(basePath || "", "/api/preview/retire");
|
|
131
|
-
// rux5 — build-on-demand for a synthetic not-built PR row: materialize the PR's
|
|
127
|
+
// Build-on-demand for a synthetic not-built PR row: materialize the PR's
|
|
132
128
|
// hosted preview (INERT — flips no live channel). Gated server-side by buildGate
|
|
133
129
|
// (the ship-on-behalf floor); the endpoint resolves the head sha via forge PR-read
|
|
134
130
|
// when the row supplies only the PR number.
|
|
135
131
|
const buildEndpoint = withBase(basePath || "", "/api/preview/build");
|
|
136
|
-
//
|
|
132
|
+
// The ship-operations workspace woven into this tab: versions/promotion
|
|
137
133
|
// history, per-candidate diff, and rollback (through the ONE rollback
|
|
138
134
|
// orchestrator). Read endpoints mirror the change-queue's auth/scope.
|
|
139
135
|
const versionsEndpoint = withBase(basePath || "", "/api/changes/versions");
|
|
140
136
|
const rollbackEndpoint = withBase(basePath || "", "/api/changes/rollback");
|
|
141
|
-
//
|
|
142
|
-
// DISTINCT endpoint from retireEndpoint above (branch delete vs artifact evict).
|
|
137
|
+
// Branch retention: GET dry-run classification / POST guarded delete.
|
|
143
138
|
const branchesEndpoint = withBase(basePath || "", "/api/changes/branches");
|
|
144
139
|
// The client builds `${diffEndpointBase}/<changeId>/diff` per candidate.
|
|
145
140
|
const diffEndpointBase = changesEndpoint;
|
|
@@ -147,9 +142,47 @@ const diffEndpointBase = changesEndpoint;
|
|
|
147
142
|
// digest actually serves. Rendered into "already live" copy + the publish
|
|
148
143
|
// ceremony's "View your live store" CTA.
|
|
149
144
|
const liveHref = withBase(basePath || "", "/");
|
|
145
|
+
|
|
146
|
+
// LIVE-SITE ENTRY POINTS — surfaced explicitly so "where does my store actually
|
|
147
|
+
// serve?" is never a mystery (it was). Two public URLs, always shown + clickable:
|
|
148
|
+
// 1. Hosted store — THIS worker at the request host + tenant base path
|
|
149
|
+
// (e.g. storefront.tokenoftrust.store/tokenoftrust.com/).
|
|
150
|
+
// 2. Public site — the static target's canonical URL, derived from the SAME
|
|
151
|
+
// manifest URL the freshness read-back probes (WWW_PUBLISH_VERIFY_URL or
|
|
152
|
+
// https://<canonicalDomain>/manifest.json), minus the /manifest.json tail
|
|
153
|
+
// (e.g. published.tokenoftrust.com). Only for static-publish tenants; a
|
|
154
|
+
// hosted-only tenant has no separate public site. Computed PURELY (no probe)
|
|
155
|
+
// so the URL shows even when the freshness probe above timed out.
|
|
156
|
+
const requestHost = Astro.request.headers.get("host") ?? Astro.url.host;
|
|
157
|
+
const liveStoreUrl = `${Astro.url.protocol}//${requestHost}${liveHref}`;
|
|
158
|
+
const publicManifestUrl = staticPublishEnabled
|
|
159
|
+
? staticLiveManifestUrl({
|
|
160
|
+
canonicalDomain: tenant.canonicalDomain,
|
|
161
|
+
// Per-tenant override first (never bleeds across stores), then the global env
|
|
162
|
+
// escape hatch, then the canonical-apex default — mirrors resolveLiveVersion.
|
|
163
|
+
explicitUrl: tenant.staticPublish?.verifyUrl ?? (await readEnv("WWW_PUBLISH_VERIFY_URL")) ?? null,
|
|
164
|
+
})
|
|
165
|
+
: null;
|
|
166
|
+
const publicSiteUrl = publicManifestUrl
|
|
167
|
+
? publicManifestUrl.replace(/\/manifest\.json$/, "/")
|
|
168
|
+
: null;
|
|
169
|
+
const stripScheme = (u: string): string => u.replace(/^https?:\/\//, "");
|
|
170
|
+
|
|
171
|
+
// r08 — a signed, tenant-scoped, expiring `?__preview` capability link an owner can
|
|
172
|
+
// copy and hand to a non-technical stakeholder (view-only, no sign-in required).
|
|
173
|
+
// Minted server-side so the signing secret never reaches the browser (mirrors
|
|
174
|
+
// preview/dashboard.astro). Signs the tenant_id claim: the shared-preview
|
|
175
|
+
// middleware verifies against `tenant.tenant_id` and the candidate renderer accepts
|
|
176
|
+
// tenant_id too, so ONE token authorizes BOTH the shared next-release preview AND
|
|
177
|
+
// per-candidate `preview/pr/<N>` links. Only minted for a ship-capable viewer, and
|
|
178
|
+
// absent when signing isn't configured — the copy buttons then stay hidden rather
|
|
179
|
+
// than offering a dead link. TTL 24h so a link copied late in a long session still
|
|
180
|
+
// works; a reload re-mints a fresh one.
|
|
181
|
+
const previewShareToken = viewerCanShip ? await mintPreviewShareToken(tenant.tenant_id) : null;
|
|
182
|
+
|
|
150
183
|
const domainStatusEndpoint = withBase(basePath || "", "/api/domain/status");
|
|
151
184
|
const domainDispatchEndpoint = withBase(basePath || "", "/api/domain/dispatch");
|
|
152
|
-
//
|
|
185
|
+
// The machine-verifiable apex-cutover readiness gate — the SAME server gate the
|
|
153
186
|
// `tot go-live` CLI reads, so the admin display and the CLI never diverge.
|
|
154
187
|
const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness");
|
|
155
188
|
---
|
|
@@ -165,7 +198,6 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
165
198
|
data-changes-endpoint={changesEndpoint}
|
|
166
199
|
data-integrate-endpoint={integrateEndpoint}
|
|
167
200
|
data-ship-endpoint={shipEndpoint}
|
|
168
|
-
data-retire-endpoint={retireEndpoint}
|
|
169
201
|
data-build-endpoint={buildEndpoint}
|
|
170
202
|
data-versions-endpoint={versionsEndpoint}
|
|
171
203
|
data-rollback-endpoint={rollbackEndpoint}
|
|
@@ -176,17 +208,20 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
176
208
|
data-domain-readiness-endpoint={domainReadinessEndpoint}
|
|
177
209
|
data-repo={tenant.appDomain}
|
|
178
210
|
data-app-domain={tenant.appDomain}
|
|
211
|
+
data-canonical-domain={tenant.canonicalDomain ?? ""}
|
|
212
|
+
data-preview-share-token={previewShareToken ?? ""}
|
|
179
213
|
data-live-href={liveHref}
|
|
180
214
|
data-can-ship={viewerCanShip ? "true" : "false"}
|
|
181
215
|
data-is-owner={viewerIsOwner ? "true" : "false"}
|
|
182
216
|
data-entitled={goLiveEntitled ? "true" : "false"}
|
|
183
217
|
data-static-publish={staticPublishEnabled ? "true" : "false"}
|
|
184
218
|
data-dispatch-configured={dispatchConfigured ? "true" : "false"}
|
|
219
|
+
data-public-site-host={publicSiteUrl ? stripScheme(publicSiteUrl).replace(/\/$/, "") : ""}
|
|
185
220
|
>
|
|
186
221
|
<div class="section-title">
|
|
187
222
|
<div>
|
|
188
223
|
<h2 id="publish-title">Publish</h2>
|
|
189
|
-
<p>
|
|
224
|
+
<p>Review what's changed, then publish your next release when you're ready.</p>
|
|
190
225
|
</div>
|
|
191
226
|
<div class="actions">
|
|
192
227
|
<button class="btn" type="button" data-publish-refresh>
|
|
@@ -237,11 +272,79 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
237
272
|
</div>
|
|
238
273
|
)}
|
|
239
274
|
|
|
275
|
+
<!-- State-driven "next action" hero (r01) — the SINGLE top-of-tab state
|
|
276
|
+
element. ONE sentence + ONE primary CTA, derived by lib/publish/publishHero.ts
|
|
277
|
+
from the SAME /api/changes read the queue + aggregate already fetch (no extra
|
|
278
|
+
read). It ABSORBS the two former standalone banners: the merge-doctor health
|
|
279
|
+
summary (B1) and the platform-fault "Report to support" escalation (B3) are
|
|
280
|
+
folded into the hero's state model, expressed through this one element — a
|
|
281
|
+
merge conflict/platform blocker turns the hero red/urgent instead of rendering
|
|
282
|
+
a separate banner. Rendered by renderHero() in adminPublishTab.ts; starts
|
|
283
|
+
hidden until the first /api/changes read resolves. The r03 stale-public-site
|
|
284
|
+
alarm sits alongside it in this region (a distinct top-level signal that
|
|
285
|
+
deep-links into Live Site), so there is ONE hero/alert region, not floating
|
|
286
|
+
banners. Urgency is never color-only: the tone drives the icon + an explicit
|
|
287
|
+
"Action needed" label. -->
|
|
288
|
+
<div class="publish-hero-region" data-publish-hero-region>
|
|
289
|
+
<div class="publish-hero" data-publish-hero data-tone="calm" hidden role="status" aria-live="polite">
|
|
290
|
+
<div class="publish-hero-main">
|
|
291
|
+
<span class="publish-hero-icon" data-publish-hero-icon aria-hidden="true">
|
|
292
|
+
<svg><use href="#i-check"></use></svg>
|
|
293
|
+
</span>
|
|
294
|
+
<div class="publish-hero-copy">
|
|
295
|
+
<span class="publish-hero-kicker" data-publish-hero-kicker hidden>Action needed</span>
|
|
296
|
+
<b class="publish-hero-headline" data-publish-hero-headline></b>
|
|
297
|
+
<span class="publish-hero-detail" data-publish-hero-detail></span>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
<div class="publish-hero-actions">
|
|
301
|
+
<button class="btn primary publish-hero-cta" type="button" data-publish-hero-cta hidden></button>
|
|
302
|
+
<a class="btn primary publish-hero-cta" data-publish-hero-cta-link hidden href="mailto:success@tokenoftrust.com"></a>
|
|
303
|
+
</div>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<!-- r03: stale-public-site alarm, LIFTED to top-level. The "public site is
|
|
307
|
+
behind the live pointer" verdict (resolveLiveVersion / isPublicSiteCurrent)
|
|
308
|
+
used to sit buried inside the collapsible Live Site section; when the public
|
|
309
|
+
target is behind, surface it here as a top-level amber alarm that deep-links
|
|
310
|
+
into Live Site (where the full breakdown stays nested). SSR-driven from the
|
|
311
|
+
same publicSiteVerdict the Live Site chip reads — shown only for a
|
|
312
|
+
static-publish tenant whose public target is confirmed behind. -->
|
|
313
|
+
{staticPublishEnabled && publicSiteVerdict && publicSiteVerdict.status === "behind" && (
|
|
314
|
+
<div class="risk-alert amber publish-stale-site" data-publish-stale-site role="status" aria-live="polite">
|
|
315
|
+
<div class="risk-alert-main">
|
|
316
|
+
<svg><use href="#i-alert"></use></svg>
|
|
317
|
+
<div>
|
|
318
|
+
<b>Public site is behind — re-publish to catch it up</b>
|
|
319
|
+
<span>
|
|
320
|
+
Your public site is still serving an older release
|
|
321
|
+
(<code class="publish-mono">{publicSiteVerdict.publishedSha.slice(0, 12)}</code>)
|
|
322
|
+
while your live pointer has moved on to
|
|
323
|
+
(<code class="publish-mono">{publicSiteVerdict.livePointerSha.slice(0, 12)}</code>).
|
|
324
|
+
Re-publish, or open the publishing details for the full breakdown.
|
|
325
|
+
</span>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
<a class="btn" href="#publish-live-site" data-publish-stale-site-link>Open publishing details</a>
|
|
329
|
+
</div>
|
|
330
|
+
)}
|
|
331
|
+
</div>
|
|
332
|
+
|
|
240
333
|
<div class="grid cols-3">
|
|
241
334
|
<div class="metric">
|
|
242
335
|
<span>Live version</span>
|
|
243
|
-
<strong
|
|
336
|
+
<strong>
|
|
337
|
+
<!-- The human version label ("v42") links straight to the live store; the
|
|
338
|
+
raw SHA is demoted to the Technical details disclosure below. -->
|
|
339
|
+
<a class="live-version-link" data-publish-live-version-link href={liveHref}
|
|
340
|
+
target="_blank" rel="noopener" hidden>—</a>
|
|
341
|
+
<span data-publish-live-version-none>—</span>
|
|
342
|
+
</strong>
|
|
244
343
|
<small data-publish-live-source>What shoppers see right now</small>
|
|
344
|
+
<details class="metric-tech" data-publish-live-tech hidden>
|
|
345
|
+
<summary>Technical details</summary>
|
|
346
|
+
<span class="publish-mono subtle" data-publish-live-sha>—</span>
|
|
347
|
+
</details>
|
|
245
348
|
</div>
|
|
246
349
|
<div class="metric">
|
|
247
350
|
<span>Published</span>
|
|
@@ -271,64 +374,12 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
271
374
|
</div>
|
|
272
375
|
)}
|
|
273
376
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
target (CloudFront/S3) is HONESTLY observed serving right now — the two
|
|
279
|
-
can diverge (a stale/failed republish job) with nothing else in this
|
|
280
|
-
console able to tell you. Answers "did going live actually reach the
|
|
281
|
-
public site?" without a manual curl. -->
|
|
282
|
-
{staticPublishEnabled && publicSiteDigest && publicSiteVerdict && (
|
|
283
|
-
<div
|
|
284
|
-
class={`risk-alert ${publicSiteVerdict.status === "current" ? "public-site-ok" : "amber"}`}
|
|
285
|
-
data-publish-public-site
|
|
286
|
-
>
|
|
287
|
-
<div class="risk-alert-main">
|
|
288
|
-
<svg><use href={publicSiteVerdict.status === "current" ? "#i-check" : "#i-alert"}></use></svg>
|
|
289
|
-
<div>
|
|
290
|
-
{publicSiteVerdict.status === "current" ? (
|
|
291
|
-
<>
|
|
292
|
-
<b>Public site is up to date</b>
|
|
293
|
-
<span>
|
|
294
|
-
<code>{tenant.appDomain}</code>'s public target is serving the same commit
|
|
295
|
-
(<code class="publish-mono">{liveVersion?.versionId?.slice(0, 12)}</code>)
|
|
296
|
-
as the hosted store's live pointer. Publishing live above
|
|
297
|
-
republishes it automatically — usually within a few minutes.
|
|
298
|
-
</span>
|
|
299
|
-
</>
|
|
300
|
-
) : publicSiteVerdict.status === "behind" ? (
|
|
301
|
-
<>
|
|
302
|
-
<b>Public site is behind the hosted store's live pointer</b>
|
|
303
|
-
<span>
|
|
304
|
-
<code>{tenant.appDomain}</code>'s public target is still serving{" "}
|
|
305
|
-
<code class="publish-mono">{publicSiteVerdict.publishedSha.slice(0, 12)}</code>, but
|
|
306
|
-
the hosted store's live pointer has since moved to{" "}
|
|
307
|
-
<code class="publish-mono">{publicSiteVerdict.livePointerSha.slice(0, 12)}</code>.
|
|
308
|
-
The republish job hasn't caught up yet (or a go-live happened before it was enabled) —
|
|
309
|
-
check the workflow run, or trigger a fresh go-live to re-dispatch it.
|
|
310
|
-
</span>
|
|
311
|
-
</>
|
|
312
|
-
) : (
|
|
313
|
-
<>
|
|
314
|
-
<b>Couldn't verify the public site is current</b>
|
|
315
|
-
<span>
|
|
316
|
-
Checked <code class="publish-mono">{publicSiteDigest.url}</code>: {publicSiteVerdict.reason}.
|
|
317
|
-
This does NOT mean the hosted store's own "Live version" above is wrong, only that the
|
|
318
|
-
separate public static target couldn't be confirmed current.
|
|
319
|
-
</span>
|
|
320
|
-
</>
|
|
321
|
-
)}
|
|
322
|
-
</div>
|
|
323
|
-
</div>
|
|
324
|
-
</div>
|
|
325
|
-
)}
|
|
326
|
-
|
|
327
|
-
<div class="panel">
|
|
328
|
-
<div class="panel-head">
|
|
329
|
-
<h3><svg><use href="#i-export"></use></svg>Candidate queue</h3>
|
|
377
|
+
<div class="panel" id="publish-queue">
|
|
378
|
+
<details class="publish-queue-details" open>
|
|
379
|
+
<summary class="panel-head">
|
|
380
|
+
<h3><svg><use href="#i-export"></use></svg>What needs your approval?</h3>
|
|
330
381
|
<span class="chip" data-publish-queue-chip>Loading</span>
|
|
331
|
-
</
|
|
382
|
+
</summary>
|
|
332
383
|
<div class="panel-body grid">
|
|
333
384
|
<p class="note publish-status" data-publish-status role="status" aria-live="polite"></p>
|
|
334
385
|
<!-- rux1: forge-listing degraded strip. Shown ONLY when GET /api/changes
|
|
@@ -375,20 +426,113 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
375
426
|
</p>
|
|
376
427
|
)}
|
|
377
428
|
</div>
|
|
429
|
+
</details>
|
|
430
|
+
</div>
|
|
431
|
+
|
|
432
|
+
<!-- "See all" history: changes that LEFT the queue by being rejected. Rejecting
|
|
433
|
+
is otherwise a black hole — this collapsed panel keeps them visible (and their
|
|
434
|
+
preview reachable) so a reject is recoverable-from-history. Collapsed by
|
|
435
|
+
default (a reference, not a work surface); the whole panel is hidden by the
|
|
436
|
+
client when there are none, so it never adds empty chrome. Excludes shipped
|
|
437
|
+
(merged) changes — those live in the Live Site / versions panel. -->
|
|
438
|
+
<div class="panel" id="publish-closed" data-publish-closed-panel hidden>
|
|
439
|
+
<details class="closed-changes-details">
|
|
440
|
+
<summary class="panel-head">
|
|
441
|
+
<h3><svg><use href="#i-undo"></use></svg>Closed & rejected changes</h3>
|
|
442
|
+
<span class="chip" data-publish-closed-chip>0</span>
|
|
443
|
+
</summary>
|
|
444
|
+
<div class="panel-body grid">
|
|
445
|
+
<p class="note subtle">
|
|
446
|
+
Changes you rejected. They're not in your next release and won't go live —
|
|
447
|
+
kept here so nothing you closed silently disappears. Open a preview to review
|
|
448
|
+
what it was.
|
|
449
|
+
</p>
|
|
450
|
+
<div class="table-wrap">
|
|
451
|
+
<table class="publish-table">
|
|
452
|
+
<thead>
|
|
453
|
+
<tr>
|
|
454
|
+
<th>Change</th>
|
|
455
|
+
<th>Closed</th>
|
|
456
|
+
<th>Head</th>
|
|
457
|
+
</tr>
|
|
458
|
+
</thead>
|
|
459
|
+
<tbody data-publish-closed-body></tbody>
|
|
460
|
+
</table>
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
</details>
|
|
378
464
|
</div>
|
|
379
465
|
|
|
380
466
|
<!-- b11: the AGGREGATE card — the protected `preview` aggregate the accepted
|
|
381
467
|
candidates integrate into, its combined evidence (the last integration
|
|
382
468
|
run's honest state), and the exact-digest Publish (b09/b10 ship the
|
|
383
469
|
reviewed pinned SHA + digest, never a rebuild). -->
|
|
384
|
-
<div class="panel agg-console" data-publish-aggregate>
|
|
385
|
-
<
|
|
386
|
-
|
|
470
|
+
<div class="panel agg-console" id="publish-next-release" data-publish-aggregate>
|
|
471
|
+
<details class="agg-console-details" open>
|
|
472
|
+
<summary class="panel-head">
|
|
473
|
+
<h3><svg><use href="#i-box"></use></svg>Next release</h3>
|
|
474
|
+
<!-- r11 — the human release name (aggregate.name), shown beside the heading.
|
|
475
|
+
Client-populated by renderAggregate; hidden (falls back to just "Next
|
|
476
|
+
release") when the release has no name. -->
|
|
477
|
+
<span class="agg-release-name" data-aggregate-name hidden></span>
|
|
478
|
+
<!-- One-click hop to the current preview build. Shown only when a
|
|
479
|
+
genuinely-built revision exists (renderAggregate toggles it via
|
|
480
|
+
classifyBuildLink), so it can never lead to a 404. The click is
|
|
481
|
+
stop-propagated in adminPublishTab.ts so opening the preview never
|
|
482
|
+
also toggles this collapsible. -->
|
|
483
|
+
<a class="btn btn-compact" data-aggregate-open-preview target="_blank" rel="noopener" hidden>Open preview</a>
|
|
484
|
+
<!-- r08 — copy a shareable, view-only preview link for the next release to hand
|
|
485
|
+
to a non-technical stakeholder (no sign-in). Unhidden by the client only
|
|
486
|
+
when a share token was minted; the click is stop-propagated so copying
|
|
487
|
+
never also toggles this collapsible. -->
|
|
488
|
+
<button class="btn btn-compact" type="button" data-aggregate-copy-preview hidden>
|
|
489
|
+
<svg><use href="#i-copy"></use></svg><span data-copy-preview-label>Copy preview link</span>
|
|
490
|
+
</button>
|
|
387
491
|
<span class="chip" data-aggregate-chip>Loading</span>
|
|
388
|
-
</
|
|
492
|
+
</summary>
|
|
389
493
|
<div class="panel-body grid">
|
|
390
494
|
<p class="note publish-status" data-aggregate-status role="status" aria-live="polite"></p>
|
|
391
495
|
|
|
496
|
+
<!-- Keep the primary action beside the release status. The detail table can
|
|
497
|
+
be long; publishing must never be buried beneath it. -->
|
|
498
|
+
<div class="check-row agg-launch">
|
|
499
|
+
<div>
|
|
500
|
+
<b>
|
|
501
|
+
{staticPublishEnabled
|
|
502
|
+
? "Publish this release to the hosted and public sites"
|
|
503
|
+
: "Publish this release to your live store"}
|
|
504
|
+
</b>
|
|
505
|
+
<p data-aggregate-publish-detail>
|
|
506
|
+
{publicSiteUrl ? (
|
|
507
|
+
<>
|
|
508
|
+
Publishes the exact build you reviewed to the hosted store, then
|
|
509
|
+
automatically republishes <code>{stripScheme(publicSiteUrl).replace(/\/$/, "")}</code>.
|
|
510
|
+
</>
|
|
511
|
+
) : (
|
|
512
|
+
<>Publishes the exact build you reviewed — no rebuild.</>
|
|
513
|
+
)}
|
|
514
|
+
</p>
|
|
515
|
+
</div>
|
|
516
|
+
<button class="btn primary agg-publish-btn" type="button" data-aggregate-publish disabled>
|
|
517
|
+
<svg><use href="#i-export"></use></svg>
|
|
518
|
+
{staticPublishEnabled ? "Publish to both live sites" : "Publish live"}
|
|
519
|
+
</button>
|
|
520
|
+
</div>
|
|
521
|
+
|
|
522
|
+
<!-- Only visible after an actually failed aggregate rebuild. -->
|
|
523
|
+
<div class="check-row" data-aggregate-retry-row hidden>
|
|
524
|
+
<div>
|
|
525
|
+
<b>Retry the build</b>
|
|
526
|
+
<p>
|
|
527
|
+
Your change was added, but rebuilding the preview failed. Retry rebuilds it
|
|
528
|
+
and re-runs your store's checks — nothing new is added.
|
|
529
|
+
</p>
|
|
530
|
+
</div>
|
|
531
|
+
<button class="btn" type="button" data-aggregate-retry-build>
|
|
532
|
+
<svg><use href="#i-refresh"></use></svg>Retry build
|
|
533
|
+
</button>
|
|
534
|
+
</div>
|
|
535
|
+
|
|
392
536
|
<!-- AI-assembled release summary — a plain-language "what am I about to
|
|
393
537
|
publish?" ahead of the technical trust chain. Rendered ONLY when the
|
|
394
538
|
server supplies data.releaseSummary; otherwise it stays hidden and the
|
|
@@ -409,34 +553,38 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
409
553
|
</div>
|
|
410
554
|
|
|
411
555
|
<!-- Chain of custody: the build that was verified → its combined evidence →
|
|
412
|
-
the digest that ships.
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
<
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
<
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
<
|
|
556
|
+
the digest that ships. Collapsed by default — this is verification
|
|
557
|
+
detail for a developer, not something a merchant needs to read to
|
|
558
|
+
decide whether to publish; the plain-language summary above and the
|
|
559
|
+
Publish button below are the actual decision surface. -->
|
|
560
|
+
<details class="agg-chain-details">
|
|
561
|
+
<summary>Technical details</summary>
|
|
562
|
+
<div class="agg-chain">
|
|
563
|
+
<div class="agg-stop">
|
|
564
|
+
<span class="agg-stop-label">Aggregate build</span>
|
|
565
|
+
<span class="agg-stop-val"><strong class="publish-mono" data-aggregate-sha>—</strong></span>
|
|
566
|
+
<p class="agg-stop-cap" data-aggregate-run-link>The current green preview build for this store.</p>
|
|
567
|
+
</div>
|
|
568
|
+
<div class="agg-link" aria-hidden="true">
|
|
569
|
+
<span class="agg-flowlabel">verified by</span>
|
|
570
|
+
<span class="agg-arrow"><svg viewBox="0 0 34 10" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M1 5h29m0 0-4-4m4 4-4 4"></path></svg></span>
|
|
571
|
+
</div>
|
|
572
|
+
<div class="agg-stop">
|
|
573
|
+
<span class="agg-stop-label">Combined evidence</span>
|
|
574
|
+
<span class="agg-stop-val"><strong data-aggregate-evidence>—</strong></span>
|
|
575
|
+
<p class="agg-stop-cap" data-aggregate-evidence-detail>The last integration run's verdict.</p>
|
|
576
|
+
</div>
|
|
577
|
+
<div class="agg-link" aria-hidden="true">
|
|
578
|
+
<span class="agg-flowlabel">produces</span>
|
|
579
|
+
<span class="agg-arrow"><svg viewBox="0 0 34 10" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M1 5h29m0 0-4-4m4 4-4 4"></path></svg></span>
|
|
580
|
+
</div>
|
|
581
|
+
<div class="agg-stop">
|
|
582
|
+
<span class="agg-stop-label">Reviewed digest</span>
|
|
583
|
+
<span class="agg-stop-val"><strong class="publish-mono agg-digest" data-aggregate-digest>—</strong></span>
|
|
584
|
+
<p class="agg-stop-cap">The content digest that will be published — exactly what you reviewed.</p>
|
|
585
|
+
</div>
|
|
438
586
|
</div>
|
|
439
|
-
</
|
|
587
|
+
</details>
|
|
440
588
|
|
|
441
589
|
<!-- Included PRs — the batch this aggregate composes (b01 includedPrs). u14:
|
|
442
590
|
the "missing middle" — this is the STAGED delta vs live. The title + note
|
|
@@ -467,255 +615,281 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
467
615
|
</span>
|
|
468
616
|
</div>
|
|
469
617
|
<p class="note" data-aggregate-delta-note hidden></p>
|
|
470
|
-
|
|
618
|
+
<!-- ONE table, one row per change — merges what used to be two separate
|
|
619
|
+
"Included changes" lists (this staged-delta section + the Publish
|
|
620
|
+
plan's own duplicate) into a single source of truth. Populated by
|
|
621
|
+
renderAggregate, enriched with the plan's per-change title/description/
|
|
622
|
+
file+line counts when available. -->
|
|
623
|
+
<div class="table-wrap">
|
|
624
|
+
<table class="publish-table agg-included-table">
|
|
625
|
+
<thead>
|
|
626
|
+
<tr>
|
|
627
|
+
<th>Change</th>
|
|
628
|
+
<th>Head</th>
|
|
629
|
+
<th>Files</th>
|
|
630
|
+
<th>Lines</th>
|
|
631
|
+
<th>Added</th>
|
|
632
|
+
<th class="action">Actions</th>
|
|
633
|
+
</tr>
|
|
634
|
+
</thead>
|
|
635
|
+
<tbody data-aggregate-prs></tbody>
|
|
636
|
+
</table>
|
|
637
|
+
</div>
|
|
471
638
|
</div>
|
|
472
639
|
|
|
473
640
|
<!-- The exact-digest Publish plan (b09 plan()): pinned SHA + digest +
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
641
|
+
rollback target + paywall verdict + run link. Shown inline (from
|
|
642
|
+
GET /api/changes `plan`) so the confirm never POSTs to preview.
|
|
643
|
+
Publish is refused until the plan is `ok`. Its own included-changes
|
|
644
|
+
list was merged into the single table above — see data-aggregate-prs. -->
|
|
477
645
|
<div class="aggregate-plan agg-manifest" data-aggregate-plan hidden>
|
|
478
646
|
<div class="aggregate-plan-head agg-manifest-head">
|
|
479
647
|
<b><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 11l3 3L22 4"></path><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path></svg>Publish plan</b>
|
|
480
648
|
<span class="chip" data-aggregate-plan-chip></span>
|
|
481
649
|
</div>
|
|
482
|
-
<
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
files / who + when). Populated by renderPlan; degrades to a bare count
|
|
487
|
-
when per-change titles/descriptions aren't available. The <details>
|
|
488
|
-
element is static so its open/closed state survives a poll re-render —
|
|
489
|
-
only the list contents are replaced. -->
|
|
490
|
-
<div class="agg-included" data-aggregate-plan-included hidden>
|
|
491
|
-
<details class="agg-included-details">
|
|
492
|
-
<summary>
|
|
493
|
-
<span class="agg-included-lead">Included changes</span>
|
|
494
|
-
<span class="agg-included-badge" data-aggregate-plan-included-count>0</span>
|
|
495
|
-
<span class="agg-included-hint" data-aggregate-plan-included-hint></span>
|
|
496
|
-
<span class="agg-chev" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 6l6 6-6 6"></path></svg></span>
|
|
497
|
-
</summary>
|
|
498
|
-
<ul class="agg-included-list" data-aggregate-plan-included-list></ul>
|
|
499
|
-
</details>
|
|
500
|
-
</div>
|
|
650
|
+
<details class="agg-chain-details">
|
|
651
|
+
<summary>Technical details</summary>
|
|
652
|
+
<dl class="aggregate-plan-grid" data-aggregate-plan-grid></dl>
|
|
653
|
+
</details>
|
|
501
654
|
|
|
502
655
|
<p class="note" data-aggregate-plan-note></p>
|
|
503
656
|
</div>
|
|
504
657
|
|
|
505
|
-
<!-- u15 — retry a DEAD rebuild (no new merge). Shown only while the aggregate
|
|
506
|
-
is red: a candidate's PR already merged into preview, but the
|
|
507
|
-
build/evidence step that follows died (e.g. a transient MCP error) — this
|
|
508
|
-
retries ONLY that step, against the sha the forge already carries. -->
|
|
509
|
-
<div class="check-row" data-aggregate-retry-row hidden>
|
|
510
|
-
<div>
|
|
511
|
-
<b>Retry the build</b>
|
|
512
|
-
<p>
|
|
513
|
-
The last merge landed on preview, but rebuilding it failed. Retry re-runs
|
|
514
|
-
the build + evidence check alone — no new merge, no membership change.
|
|
515
|
-
</p>
|
|
516
|
-
</div>
|
|
517
|
-
<button class="btn" type="button" data-aggregate-retry-build>
|
|
518
|
-
<svg><use href="#i-refresh"></use></svg>Retry build
|
|
519
|
-
</button>
|
|
520
|
-
</div>
|
|
521
|
-
|
|
522
|
-
<div class="check-row agg-launch">
|
|
523
|
-
<div>
|
|
524
|
-
<b>Publish the reviewed build to your live store</b>
|
|
525
|
-
<p data-aggregate-publish-detail>
|
|
526
|
-
Publishes the exact reviewed digest — no rebuild. Available once the
|
|
527
|
-
aggregate is green and its integration run passed.
|
|
528
|
-
</p>
|
|
529
|
-
</div>
|
|
530
|
-
<button class="btn primary agg-publish-btn" type="button" data-aggregate-publish disabled>
|
|
531
|
-
<svg><use href="#i-export"></use></svg>Publish live
|
|
532
|
-
</button>
|
|
533
|
-
</div>
|
|
534
|
-
</div>
|
|
535
|
-
</div>
|
|
536
|
-
|
|
537
|
-
<!-- dg7: published versions + promotion history + rollback (u2/u3 promotion_status,
|
|
538
|
-
u5 immutable /rev links, u8 rollback through the one orchestrator). -->
|
|
539
|
-
<div class="panel" data-publish-versions>
|
|
540
|
-
<div class="panel-head">
|
|
541
|
-
<h3><svg><use href="#i-refresh"></use></svg>Published versions</h3>
|
|
542
|
-
<span class="chip" data-versions-chip>Loading</span>
|
|
543
|
-
</div>
|
|
544
|
-
<div class="panel-body grid">
|
|
545
|
-
<p class="note publish-status" data-versions-status role="status" aria-live="polite"></p>
|
|
546
|
-
<p class="note" data-versions-rollback-note hidden></p>
|
|
547
|
-
<!-- u14: orients the owner between the staged aggregate above and live versions
|
|
548
|
-
below — "N staged change(s) not yet published; Publish live creates the next
|
|
549
|
-
version here." Owned by renderAggregate (its own element, so its timing never
|
|
550
|
-
races renderVersions). -->
|
|
551
|
-
<p class="note" data-versions-orientation hidden></p>
|
|
552
|
-
<div class="table-wrap">
|
|
553
|
-
<table class="publish-table versions-table">
|
|
554
|
-
<thead>
|
|
555
|
-
<tr>
|
|
556
|
-
<th>Version</th>
|
|
557
|
-
<th>Digest</th>
|
|
558
|
-
<th>Promoted</th>
|
|
559
|
-
<th>Preview</th>
|
|
560
|
-
<th>State</th>
|
|
561
|
-
<th class="action">Actions</th>
|
|
562
|
-
</tr>
|
|
563
|
-
</thead>
|
|
564
|
-
<tbody data-versions-body>
|
|
565
|
-
<tr data-versions-placeholder>
|
|
566
|
-
<td colspan="6"><span class="subtle">Loading published versions…</span></td>
|
|
567
|
-
</tr>
|
|
568
|
-
</tbody>
|
|
569
|
-
</table>
|
|
570
|
-
</div>
|
|
571
|
-
</div>
|
|
572
|
-
</div>
|
|
573
|
-
|
|
574
|
-
<!-- b17: branch retention — Admin visibility into the branch-lifecycle
|
|
575
|
-
contract's "Candidate branch retirement" table (P1 items 8/9/11). Reads
|
|
576
|
-
the guarded `candidate_list` classification (protected/active-open/
|
|
577
|
-
stale-open/integrated/closed-or-rejected/orphan) and, for a branch that
|
|
578
|
-
classifies as ready, runs the guarded `candidate_delete` — which
|
|
579
|
-
re-classifies fresh server-side and refuses anything not integrated or
|
|
580
|
-
closed-or-rejected, no matter what this panel last rendered. DISTINCT
|
|
581
|
-
from the "Retire" action in the candidate queue above: retire evicts a
|
|
582
|
-
hosted PREVIEW ARTIFACT (rebuildable); this panel deletes a Git BRANCH
|
|
583
|
-
(transport only, never the durable record — see the note below). An
|
|
584
|
-
orphan is always shown quarantined for review, never one-click deletable. -->
|
|
585
|
-
<div class="panel" data-publish-branches>
|
|
586
|
-
<div class="panel-head">
|
|
587
|
-
<h3><svg><use href="#i-workflows"></use></svg>Branch retention</h3>
|
|
588
|
-
<span class="chip" data-branches-chip>Loading</span>
|
|
589
|
-
</div>
|
|
590
|
-
<div class="panel-body grid">
|
|
591
|
-
<p class="note">
|
|
592
|
-
Cleans up candidate <b>branches</b> once their pull request is merged or
|
|
593
|
-
closed — a different action on a different object than <b>Retire</b> in
|
|
594
|
-
the queue above, which only evicts a hosted preview build (rebuildable
|
|
595
|
-
on demand, never a branch). Every classification below is a fresh
|
|
596
|
-
dry-run; <b>Sweep dead branches</b> lists exactly what it will delete and
|
|
597
|
-
asks once to confirm, then the server re-checks each ref fresh before
|
|
598
|
-
removing it.
|
|
599
|
-
</p>
|
|
600
|
-
<p class="note publish-status" data-branches-status role="status" aria-live="polite"></p>
|
|
601
|
-
<div class="toolbar" data-branches-actions hidden>
|
|
602
|
-
<button type="button" class="btn" data-branches-sweep>Sweep dead branches</button>
|
|
603
|
-
</div>
|
|
604
|
-
<div class="table-wrap">
|
|
605
|
-
<table class="publish-table">
|
|
606
|
-
<thead>
|
|
607
|
-
<tr>
|
|
608
|
-
<th>Branch</th>
|
|
609
|
-
<th>Classification</th>
|
|
610
|
-
<th>PR</th>
|
|
611
|
-
<th>Tip commit</th>
|
|
612
|
-
<th>Age</th>
|
|
613
|
-
<th>Evidence</th>
|
|
614
|
-
<th class="action">Actions</th>
|
|
615
|
-
</tr>
|
|
616
|
-
</thead>
|
|
617
|
-
<tbody data-branches-body>
|
|
618
|
-
<tr data-branches-placeholder>
|
|
619
|
-
<td colspan="7"><span class="subtle">Loading branch classification…</span></td>
|
|
620
|
-
</tr>
|
|
621
|
-
</tbody>
|
|
622
|
-
</table>
|
|
623
|
-
</div>
|
|
624
658
|
</div>
|
|
659
|
+
</details>
|
|
625
660
|
</div>
|
|
626
661
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
662
|
+
<!-- Branch retention panel removed entirely — old candidate branches now
|
|
663
|
+
clean themselves up automatically (auto-swept after each successful
|
|
664
|
+
accept/publish, see adminPublishTab.ts autoSweepBranches). There is
|
|
665
|
+
nothing here for anyone to look at or act on day-to-day, so there is no
|
|
666
|
+
panel at all, not even a collapsed one. -->
|
|
667
|
+
|
|
668
|
+
<!-- Publish next release — the collapsed destination/status panel below the
|
|
669
|
+
staged release. Its summary answers the operational question first: either
|
|
670
|
+
live already matches the staged release, or there is an action to advance it.
|
|
671
|
+
The disclosure contains destination links, freshness, rollback, and domain
|
|
672
|
+
controls for operators who need the detail. -->
|
|
673
|
+
<div class="panel" id="publish-live-site" data-publish-live-site>
|
|
674
|
+
<details class="live-site-details">
|
|
675
|
+
<summary class="panel-head">
|
|
676
|
+
<h3><svg><use href="#i-export"></use></svg>Publish next release</h3>
|
|
677
|
+
<span class="chip" data-live-release-state>Checking release…</span>
|
|
678
|
+
<button
|
|
679
|
+
class="btn primary btn-compact live-release-publish"
|
|
680
|
+
type="button"
|
|
681
|
+
data-live-release-publish
|
|
682
|
+
hidden
|
|
683
|
+
>Publish next release</button>
|
|
684
|
+
</summary>
|
|
633
685
|
<div class="panel-body grid">
|
|
634
|
-
<
|
|
635
|
-
<
|
|
636
|
-
<label>
|
|
637
|
-
<
|
|
638
|
-
<
|
|
639
|
-
</
|
|
640
|
-
|
|
641
|
-
<
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
<
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
disabled={!viewerCanApexCutover}
|
|
698
|
-
>
|
|
699
|
-
<svg><use href="#i-check"></use></svg>Connect domain
|
|
700
|
-
</button>
|
|
686
|
+
<ul class="live-site-links">
|
|
687
|
+
<li>
|
|
688
|
+
<span class="live-site-link-label">Hosted store</span>
|
|
689
|
+
<a class="live-site-link-url publish-mono" href={liveHref} target="_blank" rel="noopener">{stripScheme(liveStoreUrl)}</a>
|
|
690
|
+
<span class="live-site-link-note">Updates immediately when you publish the reviewed release above.</span>
|
|
691
|
+
</li>
|
|
692
|
+
{publicSiteUrl && (
|
|
693
|
+
<li>
|
|
694
|
+
<span class="live-site-link-label">Public site</span>
|
|
695
|
+
<a class="live-site-link-url publish-mono" href={publicSiteUrl} target="_blank" rel="noopener">{stripScheme(publicSiteUrl)}</a>
|
|
696
|
+
<span class="live-site-link-note">Republishes automatically after the hosted release is published.</span>
|
|
697
|
+
</li>
|
|
698
|
+
)}
|
|
699
|
+
</ul>
|
|
700
|
+
|
|
701
|
+
<!-- Public-site freshness read-back (static-publish seam's staticLiveDigest):
|
|
702
|
+
what the external target (CloudFront/S3) is HONESTLY observed serving
|
|
703
|
+
right now, vs the control-plane's live pointer — the two can diverge on a
|
|
704
|
+
stale/failed republish. Answers "did going live actually reach the public
|
|
705
|
+
site?" without a manual curl. -->
|
|
706
|
+
{staticPublishEnabled && publicSiteDigest && publicSiteVerdict && (
|
|
707
|
+
<div
|
|
708
|
+
class={`risk-alert ${publicSiteVerdict.status === "current" ? "public-site-ok" : "amber"}`}
|
|
709
|
+
data-publish-public-site
|
|
710
|
+
>
|
|
711
|
+
<div class="risk-alert-main">
|
|
712
|
+
<svg><use href={publicSiteVerdict.status === "current" ? "#i-check" : "#i-alert"}></use></svg>
|
|
713
|
+
<div>
|
|
714
|
+
{publicSiteVerdict.status === "current" ? (
|
|
715
|
+
<>
|
|
716
|
+
<b>Public site matches the currently published release</b>
|
|
717
|
+
<span>
|
|
718
|
+
<code>{stripScheme(publicSiteUrl ?? tenant.appDomain).replace(/\/$/, "")}</code> is serving
|
|
719
|
+
(<code class="publish-mono">{liveVersion?.versionId?.slice(0, 12)}</code>)
|
|
720
|
+
— the same release as the hosted store. Staged preview changes are
|
|
721
|
+
a separate next release: use <b>Publish to both live sites</b> above
|
|
722
|
+
to advance the hosted store and republish this public site.
|
|
723
|
+
</span>
|
|
724
|
+
</>
|
|
725
|
+
) : publicSiteVerdict.status === "behind" ? (
|
|
726
|
+
<>
|
|
727
|
+
<b>Public site is behind the hosted store's live pointer</b>
|
|
728
|
+
<span>
|
|
729
|
+
<code>{tenant.appDomain}</code>'s public target is still serving{" "}
|
|
730
|
+
<code class="publish-mono">{publicSiteVerdict.publishedSha.slice(0, 12)}</code>, but
|
|
731
|
+
the hosted store's live pointer has since moved to{" "}
|
|
732
|
+
<code class="publish-mono">{publicSiteVerdict.livePointerSha.slice(0, 12)}</code>.
|
|
733
|
+
The republish job hasn't caught up yet (or a go-live happened before it was enabled) —
|
|
734
|
+
check the workflow run, or trigger a fresh go-live to re-dispatch it.
|
|
735
|
+
</span>
|
|
736
|
+
</>
|
|
737
|
+
) : (
|
|
738
|
+
<>
|
|
739
|
+
<b>Couldn't verify the public site is current</b>
|
|
740
|
+
<span>
|
|
741
|
+
Checked <code class="publish-mono">{publicSiteDigest.url}</code>: {publicSiteVerdict.reason}.
|
|
742
|
+
This does NOT mean the hosted store's own "Live version" above is wrong, only that the
|
|
743
|
+
separate public static target couldn't be confirmed current.
|
|
744
|
+
</span>
|
|
745
|
+
</>
|
|
746
|
+
)}
|
|
747
|
+
</div>
|
|
748
|
+
</div>
|
|
701
749
|
</div>
|
|
750
|
+
)}
|
|
751
|
+
|
|
752
|
+
<!-- Rollback options — CONTAINED within Live Site as a subsection (was a sibling
|
|
753
|
+
panel). The full published-version history + one-click rollback through the
|
|
754
|
+
single rollback orchestrator; collapsed by default (most people never open
|
|
755
|
+
it — the live version is already the metric up top). Keeps its
|
|
756
|
+
data-publish-versions + data-versions-* hooks verbatim. -->
|
|
757
|
+
<div class="live-site-subsection" data-publish-versions>
|
|
758
|
+
<details class="versions-details">
|
|
759
|
+
<summary class="live-site-subhead">
|
|
760
|
+
<h4><svg><use href="#i-refresh"></use></svg>Rollback options</h4>
|
|
761
|
+
<span class="chip" data-versions-chip>Loading</span>
|
|
762
|
+
</summary>
|
|
763
|
+
<div class="grid">
|
|
764
|
+
<p class="note publish-status" data-versions-status role="status" aria-live="polite"></p>
|
|
765
|
+
<p class="note" data-versions-rollback-note hidden></p>
|
|
766
|
+
<!-- u14: orients the owner between the staged aggregate above and live versions
|
|
767
|
+
below — "N staged change(s) not yet published; Publish live creates the next
|
|
768
|
+
version here." Owned by renderAggregate (its own element, so its timing never
|
|
769
|
+
races renderVersions). -->
|
|
770
|
+
<p class="note" data-versions-orientation hidden></p>
|
|
771
|
+
<div class="table-wrap">
|
|
772
|
+
<table class="publish-table versions-table">
|
|
773
|
+
<thead>
|
|
774
|
+
<tr>
|
|
775
|
+
<th>Version</th>
|
|
776
|
+
<th>Digest</th>
|
|
777
|
+
<th>Promoted</th>
|
|
778
|
+
<th>Preview</th>
|
|
779
|
+
<th>State</th>
|
|
780
|
+
<th class="action">Actions</th>
|
|
781
|
+
</tr>
|
|
782
|
+
</thead>
|
|
783
|
+
<tbody data-versions-body>
|
|
784
|
+
<tr data-versions-placeholder>
|
|
785
|
+
<td colspan="6"><span class="subtle">Loading published versions…</span></td>
|
|
786
|
+
</tr>
|
|
787
|
+
</tbody>
|
|
788
|
+
</table>
|
|
789
|
+
</div>
|
|
790
|
+
</div>
|
|
791
|
+
</details>
|
|
702
792
|
</div>
|
|
703
793
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
794
|
+
<!-- Public domain (apex connect / rollback) — CONTAINED within Live Site as a
|
|
795
|
+
subsection. Keeps its data-publish-domain + data-domain-* hooks verbatim so
|
|
796
|
+
the client controller is unchanged; only the wrapper/heading are lighter to
|
|
797
|
+
read as a nested section rather than a sibling panel. -->
|
|
798
|
+
{staticPublishEnabled && (
|
|
799
|
+
<div class="live-site-subsection" data-publish-domain>
|
|
800
|
+
<div class="live-site-subhead">
|
|
801
|
+
<h4><svg><use href="#i-shield"></use></svg>Public domain</h4>
|
|
802
|
+
<span class="chip" data-domain-state-chip>Loading</span>
|
|
803
|
+
</div>
|
|
804
|
+
<div class="grid">
|
|
805
|
+
<div class="grid cols-3">
|
|
806
|
+
<div class="field">
|
|
807
|
+
<label>Serving from</label>
|
|
808
|
+
<strong data-domain-state>—</strong>
|
|
809
|
+
<p data-domain-since>Current host for {tenant.appDomain}</p>
|
|
810
|
+
</div>
|
|
811
|
+
<div class="field">
|
|
812
|
+
<label>Rollback records</label>
|
|
813
|
+
<strong data-domain-capture>None captured</strong>
|
|
814
|
+
<p>DNS records captured before connect — rollback restores these.</p>
|
|
815
|
+
</div>
|
|
816
|
+
<div class="field">
|
|
817
|
+
<label>Last run</label>
|
|
818
|
+
<strong data-domain-run>None</strong>
|
|
819
|
+
<p data-domain-run-detail>Connect and rollback runs appear here.</p>
|
|
820
|
+
</div>
|
|
821
|
+
</div>
|
|
822
|
+
|
|
823
|
+
<p class="note publish-status" data-domain-status role="status" aria-live="polite"></p>
|
|
824
|
+
|
|
825
|
+
<!-- u9: apex-cutover readiness — the itemized preconditions the server gate
|
|
826
|
+
requires before a connect is permitted. Populated from
|
|
827
|
+
/api/domain/readiness (the SAME gate `tot go-live` reads). -->
|
|
828
|
+
<div class="domain-readiness" data-domain-readiness hidden>
|
|
829
|
+
<div class="domain-readiness-head">
|
|
830
|
+
<b>Cutover readiness</b>
|
|
831
|
+
<span class="chip" data-domain-readiness-chip>Checking…</span>
|
|
832
|
+
</div>
|
|
833
|
+
<ul class="domain-readiness-list" data-domain-readiness-list></ul>
|
|
834
|
+
<p class="note" data-domain-readiness-note></p>
|
|
835
|
+
</div>
|
|
836
|
+
|
|
837
|
+
<div class="check-row">
|
|
838
|
+
<div>
|
|
839
|
+
<b>Connect {tenant.appDomain} to the storefront</b>
|
|
840
|
+
<p>
|
|
841
|
+
Updates two DNS names — <code>{tenant.appDomain}</code> and <code>www.{tenant.appDomain}</code> —
|
|
842
|
+
to serve the published site. Takes effect in about a minute. Type the
|
|
843
|
+
domain to confirm.
|
|
844
|
+
</p>
|
|
845
|
+
{!viewerCanApexCutover && (
|
|
846
|
+
<p><span class="chip amber">Owner/admin only</span> Connecting the domain requires an owner or admin sign-in.</p>
|
|
847
|
+
)}
|
|
848
|
+
</div>
|
|
849
|
+
<div class="domain-connect-controls">
|
|
850
|
+
<input
|
|
851
|
+
type="text"
|
|
852
|
+
placeholder={tenant.appDomain}
|
|
853
|
+
autocomplete="off"
|
|
854
|
+
spellcheck="false"
|
|
855
|
+
aria-label="Type the domain to confirm"
|
|
856
|
+
data-domain-confirm
|
|
857
|
+
disabled={!viewerCanApexCutover}
|
|
858
|
+
/>
|
|
859
|
+
<label class="domain-rehearsal">
|
|
860
|
+
<input type="checkbox" data-domain-rehearsal disabled={!viewerCanApexCutover} />
|
|
861
|
+
Rehearsal (dry run, no DNS change)
|
|
862
|
+
</label>
|
|
863
|
+
<button
|
|
864
|
+
class="btn primary"
|
|
865
|
+
type="button"
|
|
866
|
+
data-domain-connect
|
|
867
|
+
data-owner-locked={!viewerCanApexCutover ? "true" : undefined}
|
|
868
|
+
disabled={!viewerCanApexCutover}
|
|
869
|
+
>
|
|
870
|
+
<svg><use href="#i-check"></use></svg>Connect domain
|
|
871
|
+
</button>
|
|
872
|
+
</div>
|
|
873
|
+
</div>
|
|
874
|
+
|
|
875
|
+
<div class="check-row">
|
|
876
|
+
<div>
|
|
877
|
+
<b>Roll back to the previous host</b>
|
|
878
|
+
<p data-domain-rollback-detail>
|
|
879
|
+
Restores the DNS records captured before connect. Available once records
|
|
880
|
+
have been captured.
|
|
881
|
+
</p>
|
|
882
|
+
</div>
|
|
883
|
+
<button class="btn" type="button" data-domain-rollback disabled={!viewerCanShip}>
|
|
884
|
+
<svg><use href="#i-refresh"></use></svg>Roll back
|
|
885
|
+
</button>
|
|
886
|
+
</div>
|
|
887
|
+
</div>
|
|
711
888
|
</div>
|
|
712
|
-
|
|
713
|
-
<svg><use href="#i-refresh"></use></svg>Roll back
|
|
714
|
-
</button>
|
|
715
|
-
</div>
|
|
889
|
+
)}
|
|
716
890
|
</div>
|
|
717
|
-
</
|
|
718
|
-
|
|
891
|
+
</details>
|
|
892
|
+
</div>
|
|
719
893
|
|
|
720
894
|
<!-- Accept-to-preview LIFTOFF — the plan confirm + live integration flight +
|
|
721
895
|
outcome ceremony. One dialog, three phases (plan → flight → outcome).
|
|
@@ -725,44 +899,45 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
725
899
|
<div class="liftoff-backdrop" data-liftoff hidden>
|
|
726
900
|
<div class="liftoff-card" role="dialog" aria-modal="true" aria-labelledby="liftoff-title" tabindex="-1">
|
|
727
901
|
<div class="liftoff-phase" data-liftoff-plan>
|
|
728
|
-
<p class="liftoff-kicker">
|
|
729
|
-
<h3 class="liftoff-title" id="liftoff-title" data-liftoff-title>
|
|
902
|
+
<p class="liftoff-kicker">Add to release</p>
|
|
903
|
+
<h3 class="liftoff-title" id="liftoff-title" data-liftoff-title>Add to your next release</h3>
|
|
730
904
|
<dl class="liftoff-grid" data-liftoff-grid></dl>
|
|
731
905
|
<p class="note">
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
906
|
+
Adds this change to your next release, then rebuilds the preview and re-runs your
|
|
907
|
+
store's checks. <b>Nothing goes live</b> — publishing your release stays a
|
|
908
|
+
separate, explicit step.
|
|
735
909
|
</p>
|
|
736
910
|
<div class="liftoff-actions">
|
|
737
911
|
<button class="btn" type="button" data-liftoff-cancel>Cancel</button>
|
|
738
912
|
<button class="btn primary" type="button" data-liftoff-proceed>
|
|
739
|
-
<svg><use href="#i-check"></use></svg>
|
|
913
|
+
<svg><use href="#i-check"></use></svg>Add to release
|
|
740
914
|
</button>
|
|
741
915
|
</div>
|
|
742
916
|
</div>
|
|
743
917
|
|
|
744
918
|
<div class="liftoff-phase" data-liftoff-flight hidden>
|
|
745
|
-
<p class="liftoff-kicker">
|
|
746
|
-
<h3 class="liftoff-title" data-liftoff-flight-title>
|
|
919
|
+
<p class="liftoff-kicker">Adding to your release</p>
|
|
920
|
+
<h3 class="liftoff-title" data-liftoff-flight-title>Adding…</h3>
|
|
747
921
|
<ol class="liftoff-stages">
|
|
748
922
|
<li data-liftoff-stage="merge">
|
|
749
923
|
<span class="liftoff-dot"></span>
|
|
750
|
-
<div><b>
|
|
924
|
+
<div><b>Add</b><span>add this change to your next release</span></div>
|
|
751
925
|
</li>
|
|
752
926
|
<li data-liftoff-stage="build">
|
|
753
927
|
<span class="liftoff-dot"></span>
|
|
754
|
-
<div><b>
|
|
928
|
+
<div><b>Build</b><span>rebuild the preview with your change in it</span></div>
|
|
755
929
|
</li>
|
|
756
930
|
<li data-liftoff-stage="evidence">
|
|
757
931
|
<span class="liftoff-dot"></span>
|
|
758
|
-
<div><b>
|
|
932
|
+
<div><b>Check</b><span>re-run your store's checks on the preview</span></div>
|
|
759
933
|
</li>
|
|
760
934
|
<li data-liftoff-stage="green">
|
|
761
935
|
<span class="liftoff-dot"></span>
|
|
762
|
-
<div><b>
|
|
936
|
+
<div><b>Ready</b><span>your next release is ready to review and publish</span></div>
|
|
763
937
|
</li>
|
|
764
938
|
</ol>
|
|
765
939
|
<p class="liftoff-live" data-liftoff-live role="status" aria-live="polite">Working…</p>
|
|
940
|
+
<div class="stream-log" data-liftoff-log role="log" aria-live="polite"></div>
|
|
766
941
|
<div class="liftoff-meta">
|
|
767
942
|
<span class="publish-mono" data-liftoff-elapsed>0:00</span>
|
|
768
943
|
<button class="btn" type="button" data-liftoff-hide>Continue in background</button>
|
|
@@ -826,7 +1001,7 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
826
1001
|
<p class="note" data-conflict-intro>
|
|
827
1002
|
From the store checkout that submitted this change, bring it up to date and
|
|
828
1003
|
re-submit — the open PR updates in place. Once the new build is ready,
|
|
829
|
-
finish here with <b>
|
|
1004
|
+
finish here with <b>Add to release</b>, or from the terminal with
|
|
830
1005
|
<code>tot accept --tenant <store> --pr <N></code>.
|
|
831
1006
|
Check <code>git status</code> first — abort any half-finished rebase from an
|
|
832
1007
|
earlier attempt. Then <code>tot pr</code>: this change should be marked
|
|
@@ -843,6 +1018,11 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
843
1018
|
</div>
|
|
844
1019
|
<div class="liftoff-actions">
|
|
845
1020
|
<a class="btn" data-liftoff-review target="_blank" rel="noopener" hidden>Review the preview build</a>
|
|
1021
|
+
<!-- Fail-visible next step: when the merge LANDED but the preview build
|
|
1022
|
+
failed, this offers Rebuild (not a dead "did not land"); on an
|
|
1023
|
+
indeterminate outcome it offers Re-check. Hidden on success/conflict
|
|
1024
|
+
(conflict recovery owns its own primary action). -->
|
|
1025
|
+
<button class="btn primary" type="button" data-liftoff-rebuild hidden>Rebuild the preview build</button>
|
|
846
1026
|
<button class="btn primary" type="button" data-liftoff-done>Done</button>
|
|
847
1027
|
</div>
|
|
848
1028
|
</div>
|
|
@@ -881,8 +1061,10 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
881
1061
|
<p class="liftoff-live" data-shipoff-live role="status" aria-live="polite">
|
|
882
1062
|
Pinning the exact reviewed build to your live channel…
|
|
883
1063
|
</p>
|
|
1064
|
+
<div class="stream-log" data-shipoff-log role="log" aria-live="polite"></div>
|
|
884
1065
|
<div class="liftoff-meta">
|
|
885
1066
|
<span class="publish-mono" data-shipoff-elapsed>0:00</span>
|
|
1067
|
+
<button class="btn" type="button" data-shipoff-hide>Continue in background</button>
|
|
886
1068
|
</div>
|
|
887
1069
|
</div>
|
|
888
1070
|
|
|
@@ -890,8 +1072,23 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
890
1072
|
<div class="liftoff-seal" data-shipoff-seal aria-hidden="true"></div>
|
|
891
1073
|
<h3 class="liftoff-title" data-shipoff-outcome-title></h3>
|
|
892
1074
|
<p class="note" data-shipoff-outcome-detail></p>
|
|
1075
|
+
<!-- Failure detail + "Copy for your AI agent" — shown ONLY when the publish did
|
|
1076
|
+
not complete. Mirrors the build-flight failure affordance. -->
|
|
1077
|
+
<div class="liftoff-conflict" data-shipoff-failure hidden>
|
|
1078
|
+
<pre class="liftoff-commands publish-mono" data-shipoff-failure-detail></pre>
|
|
1079
|
+
<div class="liftoff-conflict-actions">
|
|
1080
|
+
<button class="btn" type="button" data-shipoff-copy>Copy for your AI agent</button>
|
|
1081
|
+
</div>
|
|
1082
|
+
</div>
|
|
893
1083
|
<div class="liftoff-actions">
|
|
894
|
-
<a class="btn primary" data-shipoff-view target="_blank" rel="noopener" hidden>View
|
|
1084
|
+
<a class="btn primary" data-shipoff-view target="_blank" rel="noopener" hidden>View live</a>
|
|
1085
|
+
<!-- r10 — right at the post-publish moment: jump straight to the rollback
|
|
1086
|
+
row for the version this release just replaced, pre-targeted, so a
|
|
1087
|
+
publish that looked wrong is one click from being undone. Reuses the
|
|
1088
|
+
existing Live Site rollback action; shown only on a successful ship. -->
|
|
1089
|
+
<button class="btn" type="button" data-shipoff-undo hidden>
|
|
1090
|
+
<svg><use href="#i-undo"></use></svg>Undo this release
|
|
1091
|
+
</button>
|
|
895
1092
|
<button class="btn" type="button" data-shipoff-done>Done</button>
|
|
896
1093
|
</div>
|
|
897
1094
|
</div>
|
|
@@ -899,6 +1096,103 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
899
1096
|
<div class="liftoff-confetti" data-shipoff-confetti aria-hidden="true"></div>
|
|
900
1097
|
</div>
|
|
901
1098
|
</div>
|
|
1099
|
+
|
|
1100
|
+
<!-- Build/check flight — the real-time counterpart of the accept liftoff for the
|
|
1101
|
+
"Build preview" / "Run checks" action. `POST /api/preview/build` streams its
|
|
1102
|
+
lifecycle phases over SSE (Accept: text/event-stream); this dialog reflects them
|
|
1103
|
+
live on the SAME stage-rail + "Continue in background" pattern as the liftoff.
|
|
1104
|
+
On a FAILURE the outcome shows the full detail the build reported plus a "Copy
|
|
1105
|
+
for your AI agent" button (mirrors the merge-conflict copy affordance). Progress
|
|
1106
|
+
reduction + copy assembly live in the tested buildStream.ts; this glue mirrors
|
|
1107
|
+
it (verified on preview). -->
|
|
1108
|
+
<div class="liftoff-backdrop" data-buildoff hidden>
|
|
1109
|
+
<div class="liftoff-card" role="dialog" aria-modal="true" aria-labelledby="buildoff-title" tabindex="-1">
|
|
1110
|
+
<div class="liftoff-phase" data-buildoff-flight>
|
|
1111
|
+
<p class="liftoff-kicker">Building preview</p>
|
|
1112
|
+
<h3 class="liftoff-title" id="buildoff-title" data-buildoff-flight-title>Building…</h3>
|
|
1113
|
+
<ol class="liftoff-stages">
|
|
1114
|
+
<li data-buildoff-stage="resolve">
|
|
1115
|
+
<span class="liftoff-dot"></span>
|
|
1116
|
+
<div><b>Locate commit</b><span>find the pull request's latest commit</span></div>
|
|
1117
|
+
</li>
|
|
1118
|
+
<li data-buildoff-stage="read">
|
|
1119
|
+
<span class="liftoff-dot"></span>
|
|
1120
|
+
<div><b>Read & validate</b><span>read your store's files and check them</span></div>
|
|
1121
|
+
</li>
|
|
1122
|
+
<li data-buildoff-stage="publish">
|
|
1123
|
+
<span class="liftoff-dot"></span>
|
|
1124
|
+
<div><b>Publish version</b><span>materialize this version's hosted preview</span></div>
|
|
1125
|
+
</li>
|
|
1126
|
+
<li data-buildoff-stage="check">
|
|
1127
|
+
<span class="liftoff-dot"></span>
|
|
1128
|
+
<div><b>Run checks</b><span>compute the evidence for this version</span></div>
|
|
1129
|
+
</li>
|
|
1130
|
+
</ol>
|
|
1131
|
+
<p class="liftoff-live" data-buildoff-live role="status" aria-live="polite">Starting…</p>
|
|
1132
|
+
<div class="stream-log" data-buildoff-log role="log" aria-live="polite"></div>
|
|
1133
|
+
<div class="liftoff-meta">
|
|
1134
|
+
<span class="publish-mono" data-buildoff-elapsed>0:00</span>
|
|
1135
|
+
<button class="btn" type="button" data-buildoff-hide>Continue in background</button>
|
|
1136
|
+
</div>
|
|
1137
|
+
</div>
|
|
1138
|
+
|
|
1139
|
+
<div class="liftoff-phase liftoff-outcome-phase" data-buildoff-outcome hidden>
|
|
1140
|
+
<div class="liftoff-seal" data-buildoff-seal aria-hidden="true"></div>
|
|
1141
|
+
<h3 class="liftoff-title" data-buildoff-outcome-title></h3>
|
|
1142
|
+
<p class="note" data-buildoff-outcome-detail></p>
|
|
1143
|
+
<!-- Failure detail + "Copy for your AI agent" — shown ONLY when the build did
|
|
1144
|
+
not succeed. The detail is the honest reason the build reported (errors +
|
|
1145
|
+
blocking findings); the copy button hands a framed brief to a coding agent. -->
|
|
1146
|
+
<div class="liftoff-conflict" data-buildoff-failure hidden>
|
|
1147
|
+
<pre class="liftoff-commands publish-mono" data-buildoff-failure-detail></pre>
|
|
1148
|
+
<div class="liftoff-conflict-actions">
|
|
1149
|
+
<button class="btn" type="button" data-buildoff-copy>Copy for your AI agent</button>
|
|
1150
|
+
</div>
|
|
1151
|
+
</div>
|
|
1152
|
+
<div class="liftoff-actions">
|
|
1153
|
+
<a class="btn" data-buildoff-review target="_blank" rel="noopener" hidden>Open the preview</a>
|
|
1154
|
+
<button class="btn primary" type="button" data-buildoff-done>Done</button>
|
|
1155
|
+
</div>
|
|
1156
|
+
</div>
|
|
1157
|
+
</div>
|
|
1158
|
+
</div>
|
|
1159
|
+
|
|
1160
|
+
<!-- Retry-build flight — the real-time counterpart for the aggregate "Retry build"
|
|
1161
|
+
action (`POST /api/changes/rebuild`), which re-runs ONLY the aggregate rebuild +
|
|
1162
|
+
combined evidence against the last merged commit (no new merge). It streams its
|
|
1163
|
+
reading/publishing/checking phases over SSE into the SAME shared scrolling
|
|
1164
|
+
live-log console; "Continue in background" hides it while the stream keeps
|
|
1165
|
+
running, and on a FAILURE the outcome shows the honest detail + a "Copy for your
|
|
1166
|
+
AI agent" button — the same affordances as the build/ship flights. -->
|
|
1167
|
+
<div class="liftoff-backdrop" data-rebuildoff hidden>
|
|
1168
|
+
<div class="liftoff-card" role="dialog" aria-modal="true" aria-labelledby="rebuildoff-title" tabindex="-1">
|
|
1169
|
+
<div class="liftoff-phase" data-rebuildoff-flight>
|
|
1170
|
+
<p class="liftoff-kicker">Retrying the build</p>
|
|
1171
|
+
<h3 class="liftoff-title" id="rebuildoff-title">Rebuilding your next release preview…</h3>
|
|
1172
|
+
<p class="liftoff-live" data-rebuildoff-live role="status" aria-live="polite">Starting…</p>
|
|
1173
|
+
<div class="stream-log" data-rebuildoff-log role="log" aria-live="polite"></div>
|
|
1174
|
+
<div class="liftoff-meta">
|
|
1175
|
+
<span class="publish-mono" data-rebuildoff-elapsed>0:00</span>
|
|
1176
|
+
<button class="btn" type="button" data-rebuildoff-hide>Continue in background</button>
|
|
1177
|
+
</div>
|
|
1178
|
+
</div>
|
|
1179
|
+
|
|
1180
|
+
<div class="liftoff-phase liftoff-outcome-phase" data-rebuildoff-outcome hidden>
|
|
1181
|
+
<div class="liftoff-seal" data-rebuildoff-seal aria-hidden="true"></div>
|
|
1182
|
+
<h3 class="liftoff-title" data-rebuildoff-outcome-title></h3>
|
|
1183
|
+
<p class="note" data-rebuildoff-outcome-detail></p>
|
|
1184
|
+
<div class="liftoff-conflict" data-rebuildoff-failure hidden>
|
|
1185
|
+
<pre class="liftoff-commands publish-mono" data-rebuildoff-failure-detail></pre>
|
|
1186
|
+
<div class="liftoff-conflict-actions">
|
|
1187
|
+
<button class="btn" type="button" data-rebuildoff-copy>Copy for your AI agent</button>
|
|
1188
|
+
</div>
|
|
1189
|
+
</div>
|
|
1190
|
+
<div class="liftoff-actions">
|
|
1191
|
+
<button class="btn primary" type="button" data-rebuildoff-done>Done</button>
|
|
1192
|
+
</div>
|
|
1193
|
+
</div>
|
|
1194
|
+
</div>
|
|
1195
|
+
</div>
|
|
902
1196
|
</section>
|
|
903
1197
|
|
|
904
1198
|
<script>
|
|
@@ -911,11 +1205,241 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
911
1205
|
min-width: 900px;
|
|
912
1206
|
}
|
|
913
1207
|
|
|
1208
|
+
/* r06 — responsive change queue. On a narrow screen the min-width:900px queue
|
|
1209
|
+
table forces horizontal scroll, unusable on a phone. Below ~700px, restack the
|
|
1210
|
+
existing rows into labeled cards — CSS-only, no DOM/JS change: the table, rows
|
|
1211
|
+
and cells become blocks, the visual header is hidden (kept for assistive tech),
|
|
1212
|
+
and each cell gains its column label via a ::before drawn from the fixed thead
|
|
1213
|
+
order. Scoped to #publish-queue so the aggregate/versions tables are untouched.
|
|
1214
|
+
Full-width colspan rows (empty state, sign-in notice, the inline review pane)
|
|
1215
|
+
stay unlabeled and full width. */
|
|
1216
|
+
@media (max-width: 700px) {
|
|
1217
|
+
#publish-queue .publish-table,
|
|
1218
|
+
#publish-queue .publish-table tbody,
|
|
1219
|
+
#publish-queue .publish-table tr,
|
|
1220
|
+
#publish-queue .publish-table td {
|
|
1221
|
+
display: block;
|
|
1222
|
+
min-width: 0;
|
|
1223
|
+
width: auto;
|
|
1224
|
+
}
|
|
1225
|
+
#publish-queue .publish-table thead {
|
|
1226
|
+
position: absolute;
|
|
1227
|
+
width: 1px;
|
|
1228
|
+
height: 1px;
|
|
1229
|
+
overflow: hidden;
|
|
1230
|
+
clip: rect(0 0 0 0);
|
|
1231
|
+
clip-path: inset(50%);
|
|
1232
|
+
white-space: nowrap;
|
|
1233
|
+
}
|
|
1234
|
+
#publish-queue .publish-table tbody tr {
|
|
1235
|
+
margin: 0 0 12px;
|
|
1236
|
+
padding: 10px 12px;
|
|
1237
|
+
border: 1px solid var(--admin-line);
|
|
1238
|
+
border-radius: var(--admin-radius-sm);
|
|
1239
|
+
background: var(--admin-surface, #fff);
|
|
1240
|
+
}
|
|
1241
|
+
#publish-queue .publish-table tbody td {
|
|
1242
|
+
padding: 4px 0;
|
|
1243
|
+
text-align: left;
|
|
1244
|
+
border: 0;
|
|
1245
|
+
}
|
|
1246
|
+
#publish-queue .publish-table tbody td:not([colspan])::before {
|
|
1247
|
+
display: block;
|
|
1248
|
+
margin-bottom: 2px;
|
|
1249
|
+
font-size: 11px;
|
|
1250
|
+
font-weight: 600;
|
|
1251
|
+
text-transform: uppercase;
|
|
1252
|
+
letter-spacing: 0.04em;
|
|
1253
|
+
opacity: 0.6;
|
|
1254
|
+
}
|
|
1255
|
+
#publish-queue .publish-table tbody td:not([colspan]):nth-of-type(1)::before {
|
|
1256
|
+
content: "Change";
|
|
1257
|
+
}
|
|
1258
|
+
#publish-queue .publish-table tbody td:not([colspan]):nth-of-type(2)::before {
|
|
1259
|
+
content: "Status";
|
|
1260
|
+
}
|
|
1261
|
+
#publish-queue .publish-table tbody td:not([colspan]):nth-of-type(3)::before {
|
|
1262
|
+
content: "Checks";
|
|
1263
|
+
}
|
|
1264
|
+
#publish-queue .publish-table tbody td:not([colspan]):nth-of-type(4)::before {
|
|
1265
|
+
content: "Head";
|
|
1266
|
+
}
|
|
1267
|
+
#publish-queue .publish-table tbody td:not([colspan]):nth-of-type(5)::before {
|
|
1268
|
+
content: "Updated";
|
|
1269
|
+
}
|
|
1270
|
+
#publish-queue .publish-table tbody td:not([colspan]):nth-of-type(6)::before {
|
|
1271
|
+
content: "Actions";
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/* Collapsible panels (What needs your approval, Next release, Live Site): the
|
|
1276
|
+
panel-head IS the summary. Kill the native marker, add a rotating chevron, and
|
|
1277
|
+
make the whole head a click target. Mirrors the Rollback options (.versions-details). */
|
|
1278
|
+
.publish-queue-details > summary.panel-head,
|
|
1279
|
+
.closed-changes-details > summary.panel-head,
|
|
1280
|
+
.agg-console-details > summary.panel-head,
|
|
1281
|
+
.live-site-details > summary.panel-head,
|
|
1282
|
+
.versions-details > summary.live-site-subhead {
|
|
1283
|
+
cursor: pointer;
|
|
1284
|
+
list-style: none;
|
|
1285
|
+
user-select: none;
|
|
1286
|
+
}
|
|
1287
|
+
.publish-queue-details > summary.panel-head::-webkit-details-marker,
|
|
1288
|
+
.closed-changes-details > summary.panel-head::-webkit-details-marker,
|
|
1289
|
+
.agg-console-details > summary.panel-head::-webkit-details-marker,
|
|
1290
|
+
.live-site-details > summary.panel-head::-webkit-details-marker,
|
|
1291
|
+
.versions-details > summary.live-site-subhead::-webkit-details-marker {
|
|
1292
|
+
display: none;
|
|
1293
|
+
}
|
|
1294
|
+
.publish-queue-details > summary.panel-head h3::before,
|
|
1295
|
+
.closed-changes-details > summary.panel-head h3::before,
|
|
1296
|
+
.agg-console-details > summary.panel-head h3::before,
|
|
1297
|
+
.live-site-details > summary.panel-head h3::before,
|
|
1298
|
+
.versions-details > summary.live-site-subhead h4::before {
|
|
1299
|
+
content: "";
|
|
1300
|
+
width: 7px;
|
|
1301
|
+
height: 7px;
|
|
1302
|
+
margin-right: 2px;
|
|
1303
|
+
border-right: 2px solid currentColor;
|
|
1304
|
+
border-bottom: 2px solid currentColor;
|
|
1305
|
+
transform: rotate(-45deg);
|
|
1306
|
+
transition: transform 0.15s ease;
|
|
1307
|
+
opacity: 0.6;
|
|
1308
|
+
}
|
|
1309
|
+
.publish-queue-details[open] > summary.panel-head h3::before,
|
|
1310
|
+
.closed-changes-details[open] > summary.panel-head h3::before,
|
|
1311
|
+
.agg-console-details[open] > summary.panel-head h3::before,
|
|
1312
|
+
.live-site-details[open] > summary.panel-head h3::before,
|
|
1313
|
+
.versions-details[open] > summary.live-site-subhead h4::before {
|
|
1314
|
+
transform: rotate(45deg);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
/* The collapsed release summary owns one mutually exclusive state affordance:
|
|
1318
|
+
a green current-state chip or the action that advances live. Both classes set
|
|
1319
|
+
display, so explicitly preserve the semantic hidden state. */
|
|
1320
|
+
[data-live-release-state][hidden],
|
|
1321
|
+
.live-release-publish[hidden] {
|
|
1322
|
+
display: none;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
/* Live Site — the two clickable public entry points, previously undiscoverable. */
|
|
1326
|
+
.live-site-links {
|
|
1327
|
+
list-style: none;
|
|
1328
|
+
margin: 0;
|
|
1329
|
+
padding: 0;
|
|
1330
|
+
display: grid;
|
|
1331
|
+
gap: 12px;
|
|
1332
|
+
}
|
|
1333
|
+
.live-site-links > li {
|
|
1334
|
+
display: grid;
|
|
1335
|
+
grid-template-columns: minmax(96px, auto) 1fr;
|
|
1336
|
+
align-items: baseline;
|
|
1337
|
+
gap: 4px 12px;
|
|
1338
|
+
}
|
|
1339
|
+
.live-site-link-label {
|
|
1340
|
+
font-weight: 600;
|
|
1341
|
+
font-size: 13px;
|
|
1342
|
+
color: var(--admin-fg, inherit);
|
|
1343
|
+
}
|
|
1344
|
+
.live-site-link-url {
|
|
1345
|
+
word-break: break-all;
|
|
1346
|
+
font-size: 13px;
|
|
1347
|
+
}
|
|
1348
|
+
.live-site-link-note {
|
|
1349
|
+
grid-column: 2;
|
|
1350
|
+
font-size: 12px;
|
|
1351
|
+
opacity: 0.7;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
/* r13 — Rollback + Public domain nested INSIDE Live Site read as a subsection,
|
|
1355
|
+
not a sibling panel: a single left rule + generous spacing rather than a boxed
|
|
1356
|
+
card, so the Live Site panel doesn't stack boxes-in-boxes. */
|
|
1357
|
+
.live-site-subsection {
|
|
1358
|
+
border-left: 2px solid var(--admin-line);
|
|
1359
|
+
padding-left: 16px;
|
|
1360
|
+
margin-top: 18px;
|
|
1361
|
+
display: grid;
|
|
1362
|
+
gap: 12px;
|
|
1363
|
+
}
|
|
1364
|
+
/* r13 — the Public-domain status trio (Serving from / Rollback records / Last run)
|
|
1365
|
+
were full `.field` cards (border + fill) nested inside the Live Site panel — the
|
|
1366
|
+
genuine boxes-in-boxes. Flatten them to plain label/value blocks (hooks kept);
|
|
1367
|
+
the subsection's left rule + grid gap carry the separation instead. */
|
|
1368
|
+
.live-site-subsection .field {
|
|
1369
|
+
border: 0;
|
|
1370
|
+
background: transparent;
|
|
1371
|
+
padding: 0;
|
|
1372
|
+
}
|
|
1373
|
+
.live-site-subhead {
|
|
1374
|
+
display: flex;
|
|
1375
|
+
align-items: center;
|
|
1376
|
+
justify-content: space-between;
|
|
1377
|
+
gap: 12px;
|
|
1378
|
+
}
|
|
1379
|
+
.live-site-subhead h4 {
|
|
1380
|
+
margin: 0;
|
|
1381
|
+
display: flex;
|
|
1382
|
+
align-items: center;
|
|
1383
|
+
gap: 8px;
|
|
1384
|
+
font-size: 14px;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
914
1387
|
.publish-mono {
|
|
915
1388
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
916
1389
|
font-size: 12px;
|
|
917
1390
|
}
|
|
918
1391
|
|
|
1392
|
+
/* r11 — the human release name beside the "Next release" heading. */
|
|
1393
|
+
.agg-release-name {
|
|
1394
|
+
font-size: 13px;
|
|
1395
|
+
font-weight: 600;
|
|
1396
|
+
color: var(--admin-muted);
|
|
1397
|
+
}
|
|
1398
|
+
.agg-release-name[hidden] {
|
|
1399
|
+
display: none;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
/* r02 — the humanized "Live version" metric: "v42" as a link to the live store,
|
|
1403
|
+
with the raw SHA tucked into a "Technical details" disclosure. */
|
|
1404
|
+
.live-version-link {
|
|
1405
|
+
color: inherit;
|
|
1406
|
+
text-decoration: none;
|
|
1407
|
+
border-bottom: 1px solid color-mix(in srgb, currentColor 35%, transparent);
|
|
1408
|
+
}
|
|
1409
|
+
.live-version-link:hover {
|
|
1410
|
+
border-bottom-color: currentColor;
|
|
1411
|
+
}
|
|
1412
|
+
.metric-tech,
|
|
1413
|
+
.ver-tech {
|
|
1414
|
+
margin-top: 4px;
|
|
1415
|
+
font-size: 12px;
|
|
1416
|
+
}
|
|
1417
|
+
.metric-tech > summary,
|
|
1418
|
+
.ver-tech > summary {
|
|
1419
|
+
cursor: pointer;
|
|
1420
|
+
color: var(--muted, #64716d);
|
|
1421
|
+
font-size: 11px;
|
|
1422
|
+
list-style: none;
|
|
1423
|
+
}
|
|
1424
|
+
.metric-tech > summary::-webkit-details-marker,
|
|
1425
|
+
.ver-tech > summary::-webkit-details-marker {
|
|
1426
|
+
display: none;
|
|
1427
|
+
}
|
|
1428
|
+
.ver-tech {
|
|
1429
|
+
margin-top: 6px;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/* r08 — the "Copy preview link" affordance (icon + text, never color-only). */
|
|
1433
|
+
.publish-copy-preview {
|
|
1434
|
+
display: inline-flex;
|
|
1435
|
+
align-items: center;
|
|
1436
|
+
gap: 5px;
|
|
1437
|
+
}
|
|
1438
|
+
.publish-copy-preview svg {
|
|
1439
|
+
width: 14px;
|
|
1440
|
+
height: 14px;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
919
1443
|
.publish-actions {
|
|
920
1444
|
white-space: nowrap;
|
|
921
1445
|
}
|
|
@@ -964,6 +1488,148 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
964
1488
|
color: var(--admin-green);
|
|
965
1489
|
}
|
|
966
1490
|
|
|
1491
|
+
/* ── State-driven hero (r01) ─────────────────────────────────────────────
|
|
1492
|
+
The single top-of-tab state element. One row: an icon whose tone conveys
|
|
1493
|
+
urgency (never color alone — a "Action needed" kicker rides the two blocker
|
|
1494
|
+
tones), the one-sentence state + supporting detail, and one primary CTA laid
|
|
1495
|
+
out to the trailing edge (like the paywall gate). Tone is set by
|
|
1496
|
+
renderHero() via [data-tone]. */
|
|
1497
|
+
.publish-hero-region {
|
|
1498
|
+
display: grid;
|
|
1499
|
+
gap: 12px;
|
|
1500
|
+
}
|
|
1501
|
+
.publish-hero {
|
|
1502
|
+
display: flex;
|
|
1503
|
+
align-items: center;
|
|
1504
|
+
justify-content: space-between;
|
|
1505
|
+
gap: 16px;
|
|
1506
|
+
flex-wrap: wrap;
|
|
1507
|
+
padding: 14px 16px;
|
|
1508
|
+
border: 1px solid var(--admin-line-strong);
|
|
1509
|
+
border-left-width: 4px;
|
|
1510
|
+
border-radius: var(--admin-radius, 12px);
|
|
1511
|
+
background: var(--admin-surface);
|
|
1512
|
+
}
|
|
1513
|
+
.publish-hero[hidden] {
|
|
1514
|
+
display: none;
|
|
1515
|
+
}
|
|
1516
|
+
.publish-hero-main {
|
|
1517
|
+
display: flex;
|
|
1518
|
+
align-items: center;
|
|
1519
|
+
gap: 13px;
|
|
1520
|
+
min-width: 0;
|
|
1521
|
+
}
|
|
1522
|
+
.publish-hero-icon {
|
|
1523
|
+
flex: none;
|
|
1524
|
+
width: 34px;
|
|
1525
|
+
height: 34px;
|
|
1526
|
+
display: grid;
|
|
1527
|
+
place-items: center;
|
|
1528
|
+
border-radius: 9px;
|
|
1529
|
+
background: var(--admin-surface-soft);
|
|
1530
|
+
}
|
|
1531
|
+
.publish-hero-icon svg {
|
|
1532
|
+
width: 19px;
|
|
1533
|
+
height: 19px;
|
|
1534
|
+
}
|
|
1535
|
+
.publish-hero-copy {
|
|
1536
|
+
display: grid;
|
|
1537
|
+
gap: 2px;
|
|
1538
|
+
min-width: 0;
|
|
1539
|
+
}
|
|
1540
|
+
.publish-hero-kicker {
|
|
1541
|
+
font-size: 10.5px;
|
|
1542
|
+
font-weight: 760;
|
|
1543
|
+
letter-spacing: 0.08em;
|
|
1544
|
+
text-transform: uppercase;
|
|
1545
|
+
color: var(--admin-red);
|
|
1546
|
+
}
|
|
1547
|
+
.publish-hero-kicker[hidden] {
|
|
1548
|
+
display: none;
|
|
1549
|
+
}
|
|
1550
|
+
.publish-hero-headline {
|
|
1551
|
+
font-size: 15.5px;
|
|
1552
|
+
line-height: 1.3;
|
|
1553
|
+
color: var(--admin-ink);
|
|
1554
|
+
}
|
|
1555
|
+
.publish-hero-detail {
|
|
1556
|
+
font-size: 13px;
|
|
1557
|
+
color: var(--admin-muted);
|
|
1558
|
+
line-height: 1.45;
|
|
1559
|
+
}
|
|
1560
|
+
.publish-hero-detail:empty {
|
|
1561
|
+
display: none;
|
|
1562
|
+
}
|
|
1563
|
+
.publish-hero-actions {
|
|
1564
|
+
flex: none;
|
|
1565
|
+
display: flex;
|
|
1566
|
+
gap: 8px;
|
|
1567
|
+
}
|
|
1568
|
+
.publish-hero-cta[hidden] {
|
|
1569
|
+
display: none;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
/* Tones — the accent rail + icon colour. Blocker/warn borrow the admin
|
|
1573
|
+
red/amber tokens; ready/attention the teal; calm stays neutral. */
|
|
1574
|
+
.publish-hero[data-tone="blocker"] {
|
|
1575
|
+
border-left-color: var(--admin-red);
|
|
1576
|
+
background: var(--admin-red-soft);
|
|
1577
|
+
}
|
|
1578
|
+
.publish-hero[data-tone="blocker"] .publish-hero-icon svg {
|
|
1579
|
+
color: var(--admin-red);
|
|
1580
|
+
}
|
|
1581
|
+
.publish-hero[data-tone="warn"] {
|
|
1582
|
+
border-left-color: var(--admin-amber);
|
|
1583
|
+
background: var(--admin-surface-soft);
|
|
1584
|
+
}
|
|
1585
|
+
.publish-hero[data-tone="warn"] .publish-hero-icon svg {
|
|
1586
|
+
color: var(--admin-amber);
|
|
1587
|
+
}
|
|
1588
|
+
.publish-hero[data-tone="attention"] {
|
|
1589
|
+
border-left-color: var(--admin-teal, #0f9d8f);
|
|
1590
|
+
}
|
|
1591
|
+
.publish-hero[data-tone="attention"] .publish-hero-icon svg {
|
|
1592
|
+
color: var(--admin-teal, #0f9d8f);
|
|
1593
|
+
}
|
|
1594
|
+
.publish-hero[data-tone="ready"] {
|
|
1595
|
+
border-left-color: var(--admin-green);
|
|
1596
|
+
background: var(--admin-green-soft);
|
|
1597
|
+
}
|
|
1598
|
+
.publish-hero[data-tone="ready"] .publish-hero-icon svg {
|
|
1599
|
+
color: var(--admin-green);
|
|
1600
|
+
}
|
|
1601
|
+
.publish-hero[data-tone="calm"] {
|
|
1602
|
+
border-left-color: var(--admin-line-strong);
|
|
1603
|
+
}
|
|
1604
|
+
.publish-hero[data-tone="calm"] .publish-hero-icon svg {
|
|
1605
|
+
color: var(--admin-green);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
/* r03 stale-public-site alarm — lays its "Open Live Site" deep-link to the
|
|
1609
|
+
trailing edge, like the paywall gate. Inherits the amber .risk-alert look. */
|
|
1610
|
+
.risk-alert.publish-stale-site {
|
|
1611
|
+
display: flex;
|
|
1612
|
+
align-items: center;
|
|
1613
|
+
justify-content: space-between;
|
|
1614
|
+
gap: 12px;
|
|
1615
|
+
flex-wrap: wrap;
|
|
1616
|
+
}
|
|
1617
|
+
.risk-alert.publish-stale-site .btn {
|
|
1618
|
+
flex: none;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
/* Per-row finding: the ownership-tag chip leads the row's action cell (what's
|
|
1622
|
+
wrong, in operator words), and the mapped action button gets a subtle ring so
|
|
1623
|
+
the operator sees which button resolves it. Tone (red/amber/neutral) rides the
|
|
1624
|
+
shared .chip convention; primed emphasis is added to the EXISTING button. */
|
|
1625
|
+
.publish-actions .publish-finding-chip {
|
|
1626
|
+
vertical-align: middle;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
.publish-actions .btn.publish-cta-primed {
|
|
1630
|
+
box-shadow: 0 0 0 2px var(--admin-amber);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
967
1633
|
/* ?pr=N deep link: "not in the queue" callout + row flash */
|
|
968
1634
|
.publish-pr-callout {
|
|
969
1635
|
border: 1px solid var(--admin-line-strong);
|
|
@@ -1139,7 +1805,7 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1139
1805
|
overflow-wrap: anywhere;
|
|
1140
1806
|
}
|
|
1141
1807
|
|
|
1142
|
-
/*
|
|
1808
|
+
/* Automate-first recovery: the primary action leads, option cards appear
|
|
1143
1809
|
only on a genuine overlap, the terminal guidance is a collapsed fallback. */
|
|
1144
1810
|
.liftoff-conflict-summary {
|
|
1145
1811
|
margin: 0 0 10px;
|
|
@@ -1320,6 +1986,31 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1320
1986
|
color: var(--admin-ink);
|
|
1321
1987
|
}
|
|
1322
1988
|
|
|
1989
|
+
/* The shared scrolling live-log console — a "CI build log" window reused across
|
|
1990
|
+
the build / integrate / rebuild / ship flight dialogs. Fixed height, scrolls,
|
|
1991
|
+
newest line auto-scrolled into view by the client (see makeLogConsole). */
|
|
1992
|
+
.stream-log {
|
|
1993
|
+
margin: 10px 0 0;
|
|
1994
|
+
max-height: 150px;
|
|
1995
|
+
overflow-y: auto;
|
|
1996
|
+
padding: 8px 10px;
|
|
1997
|
+
border: 1px solid var(--admin-border, rgba(0, 0, 0, 0.12));
|
|
1998
|
+
border-radius: 8px;
|
|
1999
|
+
background: var(--admin-code-bg, rgba(0, 0, 0, 0.04));
|
|
2000
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
|
2001
|
+
font-size: 12px;
|
|
2002
|
+
line-height: 1.5;
|
|
2003
|
+
color: var(--admin-ink);
|
|
2004
|
+
-webkit-overflow-scrolling: touch;
|
|
2005
|
+
}
|
|
2006
|
+
.stream-log:empty {
|
|
2007
|
+
display: none;
|
|
2008
|
+
}
|
|
2009
|
+
.stream-log-line {
|
|
2010
|
+
white-space: pre-wrap;
|
|
2011
|
+
word-break: break-word;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1323
2014
|
.liftoff-meta {
|
|
1324
2015
|
display: flex;
|
|
1325
2016
|
justify-content: space-between;
|
|
@@ -1444,7 +2135,7 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1444
2135
|
}
|
|
1445
2136
|
}
|
|
1446
2137
|
|
|
1447
|
-
/*
|
|
2138
|
+
/* Apex-cutover readiness itemization */
|
|
1448
2139
|
.domain-readiness {
|
|
1449
2140
|
margin: 0.75rem 0;
|
|
1450
2141
|
padding: 0.75rem 1rem;
|
|
@@ -1500,7 +2191,7 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1500
2191
|
opacity: 0.95;
|
|
1501
2192
|
}
|
|
1502
2193
|
|
|
1503
|
-
/*
|
|
2194
|
+
/* Aggregate card + ship plan */
|
|
1504
2195
|
.aggregate-prs {
|
|
1505
2196
|
display: grid;
|
|
1506
2197
|
gap: 6px;
|
|
@@ -1521,12 +2212,12 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1521
2212
|
font-size: 13px;
|
|
1522
2213
|
}
|
|
1523
2214
|
|
|
1524
|
-
/*
|
|
2215
|
+
/* Provenance ("integrated <age> by <email>") sits after the sha, subtle. */
|
|
1525
2216
|
.aggregate-pr-meta {
|
|
1526
2217
|
font-size: 12px;
|
|
1527
2218
|
}
|
|
1528
2219
|
|
|
1529
|
-
/*
|
|
2220
|
+
/* The per-change Undo (revert) button is pushed to the row's trailing edge
|
|
1530
2221
|
and kept compact so the batch reads as a list, not a stack of buttons. */
|
|
1531
2222
|
.aggregate-prs-list .btn-compact {
|
|
1532
2223
|
margin-left: auto;
|
|
@@ -1827,41 +2518,6 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1827
2518
|
font-weight: 720;
|
|
1828
2519
|
}
|
|
1829
2520
|
|
|
1830
|
-
/* Staged change rows (richer than the plain PR list) */
|
|
1831
|
-
.agg-changes li.agg-change {
|
|
1832
|
-
display: grid;
|
|
1833
|
-
grid-template-columns: 1fr auto;
|
|
1834
|
-
align-items: center;
|
|
1835
|
-
gap: 12px;
|
|
1836
|
-
padding: 10px 12px;
|
|
1837
|
-
border: 1px solid var(--admin-line);
|
|
1838
|
-
border-radius: var(--admin-radius-sm);
|
|
1839
|
-
background: var(--admin-surface);
|
|
1840
|
-
}
|
|
1841
|
-
.agg-change-main {
|
|
1842
|
-
display: grid;
|
|
1843
|
-
gap: 4px;
|
|
1844
|
-
min-width: 0;
|
|
1845
|
-
}
|
|
1846
|
-
.agg-change-line {
|
|
1847
|
-
display: flex;
|
|
1848
|
-
align-items: center;
|
|
1849
|
-
gap: 10px;
|
|
1850
|
-
flex-wrap: wrap;
|
|
1851
|
-
}
|
|
1852
|
-
.agg-change-pr {
|
|
1853
|
-
font-weight: 720;
|
|
1854
|
-
font-size: 13px;
|
|
1855
|
-
}
|
|
1856
|
-
.agg-change-title {
|
|
1857
|
-
font-weight: 600;
|
|
1858
|
-
font-size: 13.5px;
|
|
1859
|
-
}
|
|
1860
|
-
.agg-change-sub {
|
|
1861
|
-
color: var(--admin-muted);
|
|
1862
|
-
font-size: 12px;
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
2521
|
/* Publish plan → launch manifest */
|
|
1866
2522
|
[data-publish-aggregate] .agg-manifest {
|
|
1867
2523
|
display: block;
|
|
@@ -1896,13 +2552,10 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1896
2552
|
background: var(--admin-surface-soft);
|
|
1897
2553
|
}
|
|
1898
2554
|
|
|
1899
|
-
/* Openable "Included changes"
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
.agg-included[hidden] {
|
|
1904
|
-
display: none;
|
|
1905
|
-
}
|
|
2555
|
+
/* Openable "Included changes" — reused by the Published Versions "What
|
|
2556
|
+
shipped" per-version disclosure (.ver-changes below); the staged-delta
|
|
2557
|
+
table above no longer uses the <details> wrap itself, only the row/diff
|
|
2558
|
+
classes it shares with changeSummaryItem. */
|
|
1906
2559
|
.agg-included-details > summary {
|
|
1907
2560
|
list-style: none;
|
|
1908
2561
|
cursor: pointer;
|
|
@@ -1938,14 +2591,6 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
1938
2591
|
font-size: 11.5px;
|
|
1939
2592
|
font-weight: 720;
|
|
1940
2593
|
}
|
|
1941
|
-
.agg-included-hint {
|
|
1942
|
-
color: var(--admin-muted-2);
|
|
1943
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
1944
|
-
font-size: 11.5px;
|
|
1945
|
-
overflow: hidden;
|
|
1946
|
-
text-overflow: ellipsis;
|
|
1947
|
-
white-space: nowrap;
|
|
1948
|
-
}
|
|
1949
2594
|
.agg-chev {
|
|
1950
2595
|
margin-left: auto;
|
|
1951
2596
|
display: inline-flex;
|
|
@@ -2212,12 +2857,12 @@ const domainReadinessEndpoint = withBase(basePath || "", "/api/domain/readiness"
|
|
|
2212
2857
|
}
|
|
2213
2858
|
}
|
|
2214
2859
|
|
|
2215
|
-
/*
|
|
2860
|
+
/* Versions + diff */
|
|
2216
2861
|
.versions-table {
|
|
2217
2862
|
min-width: 780px;
|
|
2218
2863
|
}
|
|
2219
2864
|
|
|
2220
|
-
/*
|
|
2865
|
+
/* Unified review pane */
|
|
2221
2866
|
.publish-review-cell {
|
|
2222
2867
|
padding: 12px 14px;
|
|
2223
2868
|
background: var(--admin-surface-soft);
|