@tokenoftrust/storefront-runner 1.4.2-rc.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/storefront/astro.config.mjs +3 -3
- package/apps/storefront/env.d.ts +54 -5
- package/apps/storefront/integrations/materialize-guard.mjs +12 -14
- package/apps/storefront/migrations-apps/0004_deep_morph.sql +36 -0
- package/apps/storefront/migrations-apps/0005_common_mystique.sql +23 -0
- package/apps/storefront/migrations-apps/0006_broad_microchip.sql +16 -0
- package/apps/storefront/migrations-apps/0007_brave_outlaw_kid.sql +15 -0
- package/apps/storefront/migrations-apps/0008_blue_dazzler.sql +11 -0
- package/apps/storefront/migrations-apps/0009_bored_shinobi_shaw.sql +15 -0
- package/apps/storefront/migrations-apps/0010_ws4_verified_provider_measurement.sql +35 -0
- package/apps/storefront/migrations-apps/meta/0004_snapshot.json +1474 -0
- package/apps/storefront/migrations-apps/meta/0005_snapshot.json +1617 -0
- package/apps/storefront/migrations-apps/meta/0006_snapshot.json +1716 -0
- package/apps/storefront/migrations-apps/meta/0007_snapshot.json +1812 -0
- package/apps/storefront/migrations-apps/meta/0008_snapshot.json +1881 -0
- package/apps/storefront/migrations-apps/meta/0009_snapshot.json +1979 -0
- package/apps/storefront/migrations-apps/meta/_journal.json +42 -0
- package/apps/storefront/public/apps/tot.demo.analytics/0.1.0/entry.js +42 -0
- package/apps/storefront/public/platform/amplitude-http/v1/entry.mjs +19 -0
- package/apps/storefront/public/platform/google-measurement/v1/entry.mjs +19 -0
- package/apps/storefront/public/shared/commerce-chrome.css +20 -2
- package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +68 -0
- package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +111 -0
- package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +2 -0
- package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +247 -0
- package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +73 -0
- package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +79 -0
- package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +10982 -0
- package/apps/storefront/scripts/import-v84-through-ws2.ts +38 -0
- package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +2 -0
- package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +4 -0
- package/apps/storefront/scripts/install-v84-native-through-ws1.ts +185 -0
- package/apps/storefront/scripts/prove-clone-isolation.ts +506 -0
- package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +148 -0
- package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +35 -0
- package/apps/storefront/scripts/replay-v84-clean-clone.ts +214 -0
- package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +18 -0
- package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +18 -0
- package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +18 -0
- package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +17 -0
- package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +15 -0
- package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +21 -0
- package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +42 -0
- package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +145 -0
- package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +18 -0
- package/apps/storefront/src/components/Img.astro +1 -1
- package/apps/storefront/src/components/admin/AdminBlogTab.astro +19 -16
- package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +105 -0
- package/apps/storefront/src/components/admin/AdminPublishTab.astro +1057 -412
- package/apps/storefront/src/components/admin/AdminSettingsTab.astro +2 -2
- package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +5 -5
- package/apps/storefront/src/components/chrome/NavDropdown.astro +12 -0
- package/apps/storefront/src/components/chrome/SiteFooter.astro +7 -2
- package/apps/storefront/src/components/chrome/SiteHeader.astro +46 -10
- package/apps/storefront/src/components/compliance/AdultSignatureNotice.astro +1 -1
- package/apps/storefront/src/components/compliance/ComplianceNotice.astro +1 -2
- package/apps/storefront/src/components/compliance/ExciseTaxNotice.astro +1 -2
- package/apps/storefront/src/components/compliance/PactActNotice.astro +1 -1
- package/apps/storefront/src/components/compliance/Prop65Warning.astro +1 -2
- package/apps/storefront/src/components/compliance/PurchaseLimitNotice.astro +2 -3
- package/apps/storefront/src/components/compliance/ShippingRestrictionNotice.astro +2 -2
- package/apps/storefront/src/components/compliance/StateEligibilityNotice.astro +2 -3
- package/apps/storefront/src/components/content/TrustStrip.astro +4 -4
- package/apps/storefront/src/components/islands/MobileNav.tsx +26 -1
- package/apps/storefront/src/components/islands/VariantSelector.tsx +27 -2
- package/apps/storefront/src/components/islands/useCheckoutHandoffCorrelation.ts +75 -0
- package/apps/storefront/src/components/membership/IllustrativeLabel.astro +1 -2
- package/apps/storefront/src/components/membership/TierCards.astro +2 -2
- package/apps/storefront/src/components/membership/TierComparisonTable.astro +2 -2
- package/apps/storefront/src/components/subscription/SavingsExplainer.astro +2 -2
- package/apps/storefront/src/config/adminTenantLookup.ts +35 -0
- package/apps/storefront/src/config/devTenantSeed.ts +9 -9
- package/apps/storefront/src/config/resolver.ts +4 -4
- package/apps/storefront/src/layouts/Layout.astro +100 -20
- package/apps/storefront/src/lib/activity/candidateSubmitLease.ts +87 -0
- package/apps/storefront/src/lib/activity/changeActorAttribution.ts +86 -6
- package/apps/storefront/src/lib/activity/deployVersion.ts +1 -1
- package/apps/storefront/src/lib/admin/adminShell.ts +2 -0
- package/apps/storefront/src/lib/admin/envelope.ts +1 -2
- package/apps/storefront/src/lib/apps/adminService.ts +10 -0
- package/apps/storefront/src/lib/apps/adminSession.ts +1 -1
- package/apps/storefront/src/lib/apps/appVersionStore.ts +281 -0
- package/apps/storefront/src/lib/apps/consentConfigStore.ts +228 -0
- package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +447 -0
- package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +367 -0
- package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +315 -0
- package/apps/storefront/src/lib/apps/integrationLifecycle.ts +614 -0
- package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +125 -0
- package/apps/storefront/src/lib/apps/integrationReadModel.ts +563 -0
- package/apps/storefront/src/lib/apps/integrationsTab.ts +547 -0
- package/apps/storefront/src/lib/apps/integrationsView.ts +106 -0
- package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +599 -0
- package/apps/storefront/src/lib/apps/orders/orderConversionD1.ts +150 -0
- package/apps/storefront/src/lib/apps/orders/orderForwardReceiver.ts +8 -0
- package/apps/storefront/src/lib/apps/orders/ordersStore.ts +1 -1
- package/apps/storefront/src/lib/apps/orders/verifiedProviderMeasurement.ts +117 -0
- package/apps/storefront/src/lib/apps/registryService.ts +264 -10
- package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +170 -0
- package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +16 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +105 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +177 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +251 -0
- package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +241 -0
- package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +211 -0
- package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +409 -0
- package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +368 -0
- package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +188 -0
- package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +291 -0
- package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +95 -0
- package/apps/storefront/src/lib/auth/adminApiGuard.ts +66 -0
- package/apps/storefront/src/lib/auth/adminEntry.ts +2 -2
- package/apps/storefront/src/lib/auth/adminLanding.ts +88 -0
- package/apps/storefront/src/lib/blog/collection.ts +97 -10
- package/apps/storefront/src/lib/blog/markdown.ts +1 -1
- package/apps/storefront/src/lib/blog/provider.ts +57 -3
- package/apps/storefront/src/lib/blog/types.ts +9 -9
- package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome-assignments.example.json +6 -0
- package/apps/storefront/src/lib/chrome/examples/tokenoftrust.chrome.example.json +79 -0
- package/apps/storefront/src/lib/chrome/model.ts +48 -253
- package/apps/storefront/src/lib/chrome/navCurrent.ts +29 -0
- package/apps/storefront/src/lib/chrome/parseConfig.ts +18 -32
- package/apps/storefront/src/lib/chrome/variant.ts +39 -0
- package/apps/storefront/src/lib/commerce/checkoutHandoffCorrelation.ts +105 -0
- package/apps/storefront/src/lib/compliance/tamper-sentinel-boot.ts +152 -0
- package/apps/storefront/src/lib/compliance/tamper-sentinel.ts +327 -0
- package/apps/storefront/src/lib/content/index.ts +5 -5
- package/apps/storefront/src/lib/content-edit/applyDiff.ts +1 -1
- package/apps/storefront/src/lib/content-edit/route.ts +1 -1
- package/apps/storefront/src/lib/d1/catalog.ts +12 -0
- package/apps/storefront/src/lib/d1/schema-apps.ts +276 -0
- package/apps/storefront/src/lib/dev/cockpit/ask.ts +49 -0
- package/apps/storefront/src/lib/dev/cockpit/clickToSource.ts +71 -0
- package/apps/storefront/src/lib/dev/cockpit/copyCommand.ts +227 -0
- package/apps/storefront/src/lib/dev/cockpit/files.ts +249 -0
- package/apps/storefront/src/lib/dev/cockpit/hostedActivity.ts +500 -0
- package/apps/storefront/src/lib/dev/cockpit/infoPopover.ts +12 -0
- package/apps/storefront/src/lib/dev/cockpit/mcpCopy.ts +34 -0
- package/apps/storefront/src/lib/dev/cockpit/monitor.ts +107 -0
- package/apps/storefront/src/lib/dev/cockpit/stepper.ts +116 -0
- package/apps/storefront/src/lib/dev/cockpit/themeToggle.ts +23 -0
- package/apps/storefront/src/lib/dev/runtimeStore.ts +1 -1
- package/apps/storefront/src/lib/edgeCache.ts +18 -6
- package/apps/storefront/src/lib/email/candidateConflictEmail.ts +80 -0
- package/apps/storefront/src/lib/integration/browserEnvironment.ts +137 -0
- package/apps/storefront/src/lib/integration/managedInstallDeclarations.ts +72 -0
- package/apps/storefront/src/lib/integration/nonceStamp.ts +49 -0
- package/apps/storefront/src/lib/integration/tenantDeclarations.ts +116 -0
- package/apps/storefront/src/lib/membership/eligibility.ts +1 -1
- package/apps/storefront/src/lib/membership/model.ts +1 -2
- package/apps/storefront/src/lib/newsletter/confirmationEmail.ts +2 -2
- package/apps/storefront/src/lib/newsletter/consent.ts +2 -2
- package/apps/storefront/src/lib/newsletter/send.ts +3 -3
- package/apps/storefront/src/lib/previewReload.ts +57 -1
- package/apps/storefront/src/lib/publish/adminPublishTab.ts +1775 -669
- package/apps/storefront/src/lib/publish/buildStream.ts +269 -0
- package/apps/storefront/src/lib/publish/collapsePersistence.ts +72 -0
- package/apps/storefront/src/lib/publish/lifecycleState.ts +369 -0
- package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +29 -0
- package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +78 -0
- package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +62 -0
- package/apps/storefront/src/lib/publish/mergeRowFindings.ts +124 -0
- package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +75 -0
- package/apps/storefront/src/lib/publish/publish-guard.ts +88 -0
- package/apps/storefront/src/lib/publish/publishFormat.ts +165 -0
- package/apps/storefront/src/lib/publish/publishHero.ts +177 -0
- package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +66 -0
- package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +141 -0
- package/apps/storefront/src/lib/publish/reviewRelease/index.ts +41 -0
- package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +47 -0
- package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +42 -0
- package/apps/storefront/src/lib/publish/reviewRelease/types.ts +59 -0
- package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +440 -0
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +161 -0
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +325 -0
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +241 -0
- package/apps/storefront/src/lib/publish/shipWorkspace.ts +22 -3
- package/apps/storefront/src/lib/publish/sseRoute.ts +119 -0
- package/apps/storefront/src/lib/publish/streamLogConsole.ts +142 -0
- package/apps/storefront/src/lib/publish/versionNumber.ts +52 -0
- package/apps/storefront/src/lib/rawChrome.ts +125 -47
- package/apps/storefront/src/lib/rawMarketingHtml.ts +74 -3
- package/apps/storefront/src/lib/seo/alternates.ts +1 -1
- package/apps/storefront/src/lib/social/notify.ts +4 -4
- package/apps/storefront/src/lib/storyblok/content-model.ts +7 -33
- package/apps/storefront/src/lib/storyblok/provider.ts +168 -60
- package/apps/storefront/src/lib/subscription/model.ts +4 -4
- package/apps/storefront/src/lib/the-build/provider.ts +9 -4
- package/apps/storefront/src/middleware/index.ts +273 -51
- package/apps/storefront/src/pages/[...slug].astro +9 -4
- package/apps/storefront/src/pages/admin/review-release.astro +265 -0
- package/apps/storefront/src/pages/admin/select.astro +96 -0
- package/apps/storefront/src/pages/admin.astro +16 -2
- package/apps/storefront/src/pages/api/activity.ts +8 -8
- package/apps/storefront/src/pages/api/admin/activity-alerts.ts +5 -20
- package/apps/storefront/src/pages/api/admin/orders/[id].ts +7 -2
- package/apps/storefront/src/pages/api/admin/orders.ts +8 -2
- package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +174 -0
- package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +96 -0
- package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +118 -0
- package/apps/storefront/src/pages/api/apps/admin/integrations.ts +89 -0
- package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +85 -0
- package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +74 -2
- package/apps/storefront/src/pages/api/commerce/checkout-handoff.ts +77 -0
- package/apps/storefront/src/pages/api/compliance/tamper.ts +88 -0
- package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +108 -0
- package/apps/storefront/src/pages/api/rum/vitals.ts +1 -2
- package/apps/storefront/src/pages/blog/[slug].astro +5 -5
- package/apps/storefront/src/pages/blog/author/[author].astro +3 -3
- package/apps/storefront/src/pages/blog/category/[category].astro +2 -2
- package/apps/storefront/src/pages/blog/index.astro +2 -2
- package/apps/storefront/src/pages/blog/tag/[tag].astro +2 -2
- package/apps/storefront/src/pages/cockpit.astro +61 -1362
- package/apps/storefront/src/pages/index.astro +10 -5
- package/apps/storefront/src/pages/llms.txt.ts +1 -1
- package/apps/storefront/src/pages/products/[handle].astro +7 -6
- package/apps/storefront/src/pages/sitemap.xml.ts +2 -2
- package/apps/storefront/src/pages/style-guide/[tenant]/[theme].astro +31 -27
- package/apps/storefront/src/pages/style-guide/[tenant]/chrome/[theme].astro +1 -1
- package/apps/storefront/src/pages/tenants/[id]/[...path].ts +38 -2
- package/apps/storefront/src/pages/the-build/[slug].astro +4 -4
- package/apps/storefront/src/pages/the-build/index.astro +2 -2
- package/apps/storefront/src/pages/the-build/rss.xml.ts +2 -2
- package/apps/storefront/src/styles/admin.css +27 -1
- package/apps/storefront/tsconfig.json +1 -1
- package/package.json +1 -1
- package/packages/public-runtime/package.json +2 -1
- package/packages/public-runtime/schemas/managed-analytics/v1/adapter-definition.schema.json +427 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/create-integration-install-request.schema.json +161 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/create-migration-draft-request.schema.json +157 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/delete-integration-install-request.schema.json +84 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/delete-migration-draft-request.schema.json +84 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/error-envelope.schema.json +180 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-adapter-definition-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-install-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-integration-revision-request.schema.json +79 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-migration-draft-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/integration-install.schema.json +167 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/integration-revision.schema.json +208 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/list-adapter-definitions-request.schema.json +53 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-installs-request.schema.json +53 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/list-integration-revisions-request.schema.json +82 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/migration-draft.schema.json +218 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/mutation-request.schema.json +52 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/mutation-success-envelope.schema.json +49 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/read-request.schema.json +20 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/read-success-envelope.schema.json +45 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/revise-integration-install-request.schema.json +156 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/set-integration-install-status-request.schema.json +92 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/update-migration-draft-request.schema.json +184 -0
- package/packages/public-runtime/scripts/generate-managed-analytics-api-v1-schemas.mjs +13 -0
- package/packages/public-runtime/src/activity/catalog.ts +41 -37
- package/packages/public-runtime/src/activity/event.ts +6 -6
- package/packages/public-runtime/src/activity/index.ts +2 -2
- package/packages/public-runtime/src/activity/redaction.ts +4 -4
- package/packages/public-runtime/src/candidate-index.ts +42 -8
- package/packages/public-runtime/src/checkout-orders.ts +2 -2
- package/packages/public-runtime/src/checkout-style-publish.ts +2 -2
- package/packages/public-runtime/src/checkout-style.ts +7 -7
- package/packages/public-runtime/src/checkout.ts +3 -3
- package/packages/public-runtime/src/chrome.ts +777 -0
- package/packages/public-runtime/src/compliance-obligations.ts +310 -0
- package/packages/public-runtime/src/csp.ts +99 -0
- package/packages/public-runtime/src/customization-runtime.ts +32 -1
- package/packages/public-runtime/src/destination-webhook/contract.ts +353 -0
- package/packages/public-runtime/src/embed-catalog.d.mts +9 -0
- package/packages/public-runtime/src/embed-catalog.mjs +40 -0
- package/packages/public-runtime/src/evidence.ts +288 -0
- package/packages/public-runtime/src/gtm-migration/bounds.ts +138 -0
- package/packages/public-runtime/src/gtm-migration/disposition-rules.ts +361 -0
- package/packages/public-runtime/src/gtm-migration/dispositions.ts +181 -0
- package/packages/public-runtime/src/gtm-migration/draft-generator.ts +400 -0
- package/packages/public-runtime/src/gtm-migration/graph.ts +468 -0
- package/packages/public-runtime/src/gtm-migration/index.ts +95 -0
- package/packages/public-runtime/src/gtm-migration/parse.ts +410 -0
- package/packages/public-runtime/src/gtm-migration/references.ts +266 -0
- package/packages/public-runtime/src/gtm-migration/types.ts +86 -0
- package/packages/public-runtime/src/index.ts +16 -1
- package/packages/public-runtime/src/integration/assurance-decision.ts +259 -0
- package/packages/public-runtime/src/integration/assurance.ts +228 -0
- package/packages/public-runtime/src/integration/candidate-evidence.ts +377 -0
- package/packages/public-runtime/src/integration/commerce-broker.ts +497 -0
- package/packages/public-runtime/src/integration/consent-broker.ts +337 -0
- package/packages/public-runtime/src/integration/consent-cmp-demand.ts +115 -0
- package/packages/public-runtime/src/integration/consent-config.ts +260 -0
- package/packages/public-runtime/src/integration/consent-preview.ts +125 -0
- package/packages/public-runtime/src/integration/correlation-token.ts +444 -0
- package/packages/public-runtime/src/integration/csp-compiler.ts +267 -0
- package/packages/public-runtime/src/integration/csp.ts +105 -0
- package/packages/public-runtime/src/integration/digest.ts +43 -0
- package/packages/public-runtime/src/integration/environment.ts +228 -0
- package/packages/public-runtime/src/integration/events-catalog.ts +186 -0
- package/packages/public-runtime/src/integration/events.ts +701 -0
- package/packages/public-runtime/src/integration/g2-action-boundary.ts +106 -0
- package/packages/public-runtime/src/integration/index.ts +90 -0
- package/packages/public-runtime/src/integration/interim-bridge.ts +138 -0
- package/packages/public-runtime/src/integration/lifecycle-boot.ts +317 -0
- package/packages/public-runtime/src/integration/lifecycle-runtime.ts +393 -0
- package/packages/public-runtime/src/integration/lifecycle.ts +94 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.d.mts +2 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1-safety.mjs +10 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +382 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +684 -0
- package/packages/public-runtime/src/integration/managed-analytics-bridge.ts +383 -0
- package/packages/public-runtime/src/integration/managed-analytics-value-safety.ts +14 -0
- package/packages/public-runtime/src/integration/managed-analytics.ts +277 -0
- package/packages/public-runtime/src/integration/manifest.ts +470 -0
- package/packages/public-runtime/src/integration/native-amplitude.ts +362 -0
- package/packages/public-runtime/src/integration/native-ga4.ts +352 -0
- package/packages/public-runtime/src/integration/observability.ts +451 -0
- package/packages/public-runtime/src/integration/order-conversion.ts +0 -0
- package/packages/public-runtime/src/integration/phases.ts +182 -0
- package/packages/public-runtime/src/integration/plan.ts +112 -0
- package/packages/public-runtime/src/integration/platform-adapter-runtime.ts +146 -0
- package/packages/public-runtime/src/integration/platform-adapters.ts +671 -0
- package/packages/public-runtime/src/integration/promotion-gate.ts +451 -0
- package/packages/public-runtime/src/integration/provider-checkout-extension.ts +425 -0
- package/packages/public-runtime/src/integration/receipt-measurement.ts +370 -0
- package/packages/public-runtime/src/integration/regulated-parent-cert.ts +311 -0
- package/packages/public-runtime/src/integration/render-phases.ts +267 -0
- package/packages/public-runtime/src/integration/resolve.ts +465 -0
- package/packages/public-runtime/src/integration/result.ts +239 -0
- package/packages/public-runtime/src/integration/secrets.ts +92 -0
- package/packages/public-runtime/src/integration/tamper-evidence.ts +205 -0
- package/packages/public-runtime/src/integration/tamper-recovery.ts +127 -0
- package/packages/public-runtime/src/integration/version.ts +92 -0
- package/packages/public-runtime/src/integration-capabilities.ts +520 -0
- package/packages/public-runtime/src/membership.ts +2 -2
- package/packages/public-runtime/src/raw-html-policy.ts +2 -4
- package/packages/public-runtime/src/regulated-commerce/broker/consent-dedupe.ts +144 -0
- package/packages/public-runtime/src/regulated-commerce/correlation/contract.ts +177 -0
- package/packages/public-runtime/src/regulated-commerce/diagnostics/local-dispatch.ts +24 -0
- package/packages/public-runtime/src/regulated-commerce/diagnostics/read-model.ts +69 -0
- package/packages/public-runtime/src/regulated-commerce/dispatch/core.ts +134 -0
- package/packages/public-runtime/src/regulated-commerce/events/contract.ts +113 -0
- package/packages/public-runtime/src/regulated-commerce/ledger/core.ts +81 -0
- package/packages/public-runtime/src/regulated-commerce/mappings/ga4-ads.ts +87 -0
- package/packages/public-runtime/src/regulated-commerce/provider-order/bridge.ts +52 -0
- package/packages/public-runtime/src/regulated-commerce/purchase-truth/contract.ts +252 -0
- package/packages/public-runtime/src/regulated-commerce/sources/accepted-browser-operation.ts +67 -0
- package/packages/public-runtime/src/regulated-commerce/testing/fake-destination.ts +93 -0
- package/packages/public-runtime/src/static-bundle.ts +5 -5
- package/packages/public-runtime/src/tenant-assets.ts +143 -4
- package/packages/public-runtime/src/tenant.ts +45 -9
- package/packages/public-runtime/tests/fixtures/integration/browser-environment.example.json +8 -0
- package/packages/public-runtime/tests/fixtures/integration/commerce-event.example.json +44 -0
- package/packages/public-runtime/tests/fixtures/integration/commerce-order-event.example.json +44 -0
- package/packages/public-runtime/tests/fixtures/integration/compliance-assurance-record.example.json +50 -0
- package/packages/public-runtime/tests/fixtures/integration/integration-manifest-v2.example.json +120 -0
- package/packages/public-runtime/tests/fixtures/integration/managed-analytics-v1/fake-adapter-catalog.json +35 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-action-registry.example.json +11 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/README.md +22 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/entry.js +30 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/manifest.json +75 -0
- package/packages/public-runtime/tests/fixtures/integration/tenant-local-example/public-config.json +3 -0
- package/packages/public-runtime/tests/fixtures/regulated-commerce/fake-destinations.ts +38 -0
- package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.provenance.json +29 -0
- package/packages/public-runtime/tests/gtm-migration/fixtures/gtm-sample-container-v84.redacted.json +3397 -0
- package/scripts/dev/file-browser.mjs +2 -2
- package/scripts/dev/file-writer.mjs +2 -2
- package/scripts/dev/integration-guardrails.mjs +498 -0
- package/scripts/dev/safe-path.mjs +2 -2
- package/scripts/dev/tenant-source-root.mjs +1 -1
- package/scripts/tot-dev.mjs +2 -2
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trustworthy integration-candidate evidence (ADR 0014 public-values-only,
|
|
3
|
+
* ADR 0018 nonce non-serialization; ext-kernel-06).
|
|
4
|
+
*
|
|
5
|
+
* Evidence is NOT a separate description of a candidate — it is DERIVED from the
|
|
6
|
+
* exact same inputs the mounts serve: the resolved {@link EffectivePlan}
|
|
7
|
+
* (ext-kernel-03), the fixed-phase render engine's emissions (ext-kernel-04,
|
|
8
|
+
* {@link renderIntegrationPhases}), the compiled CSP additions (ext-policy-02,
|
|
9
|
+
* {@link CompiledIntegrationCsp}), and the fail-closed materialized-asset verify
|
|
10
|
+
* (ext-prereq-01, {@link AssetVerificationResult}). So the evidence's served
|
|
11
|
+
* fingerprint is a property of calling the render engine, not a claim kept in sync
|
|
12
|
+
* with it.
|
|
13
|
+
*
|
|
14
|
+
* Three trust properties hold by construction:
|
|
15
|
+
* 1. PARITY — evidence equals what is served. {@link buildCandidateEvidence}
|
|
16
|
+
* records a fingerprint (a digest over the nonce-free phase markup, the plan/
|
|
17
|
+
* version cache identity, the environment stage, and the CSP origin diff);
|
|
18
|
+
* {@link verifyServedParity} re-derives that fingerprint from what a mount
|
|
19
|
+
* ACTUALLY served and reports every contradiction.
|
|
20
|
+
* 2. CONTRADICTIONS BLOCK PROMOTION — {@link verifyCandidatePromotable} is the
|
|
21
|
+
* fail-closed gate (same {ok, blockers} shape as the promotion-evidence gate):
|
|
22
|
+
* an unreadable/forged asset or forge response, a missing app asset, a
|
|
23
|
+
* candidate that reports `live`, secret material, or ANY served-parity
|
|
24
|
+
* contradiction leaves the candidate un-promotable. Unobserved served output
|
|
25
|
+
* is itself a blocker — you cannot promote what you cannot prove is served.
|
|
26
|
+
* 3. PUBLIC VALUES ONLY — the assembled evidence is scanned with
|
|
27
|
+
* {@link findForbiddenFields} (ext-kernel-01): a nonce, token, credential, or
|
|
28
|
+
* signed URL makes the evidence invalid to build AND un-promotable.
|
|
29
|
+
*
|
|
30
|
+
* Consent and assurance surfaces are recorded from whatever the plan/record
|
|
31
|
+
* resolves today (ext-policy-03/05 fill them); the evidence FRAMEWORK surfaces the
|
|
32
|
+
* resolved state without inventing a value the plan does not carry.
|
|
33
|
+
*/
|
|
34
|
+
import type { ContractResult, ContractViolation } from "./result.js";
|
|
35
|
+
import { findForbiddenFields } from "./secrets.js";
|
|
36
|
+
import type { BrowserEnvironment, IntegrationEnvironment } from "./environment.js";
|
|
37
|
+
import type { ReservedPhase, ExecutionTier, ContributionKind, EntryFormat } from "./phases.js";
|
|
38
|
+
import type { IntegrationOrigin } from "./manifest.js";
|
|
39
|
+
import type { AssuranceClassification } from "./manifest.js";
|
|
40
|
+
import type { EffectivePlan } from "./plan.js";
|
|
41
|
+
import { planCacheIdentity } from "./resolve.js";
|
|
42
|
+
import {
|
|
43
|
+
renderIntegrationPhases,
|
|
44
|
+
IntegrationRenderError,
|
|
45
|
+
INTEGRATION_NONCE_PLACEHOLDER,
|
|
46
|
+
type IntegrationPhaseMarkup,
|
|
47
|
+
} from "./render-phases.js";
|
|
48
|
+
import type { CompiledIntegrationCsp, IntegrationCspAdditions } from "./csp-compiler.js";
|
|
49
|
+
import type { ComplianceAssuranceRecord, AssuranceSurface } from "./assurance.js";
|
|
50
|
+
import type { AssetVerificationResult } from "../tenant-assets.js";
|
|
51
|
+
import { fnv1a128Hex, stableStringify } from "./digest.js";
|
|
52
|
+
|
|
53
|
+
export const INTEGRATION_CANDIDATE_EVIDENCE_SCHEMA_VERSION = 1 as const;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Asset-existence evidence: the public counts + missing served paths from the
|
|
57
|
+
* ext-prereq-01 verify. `unreadable` is set only when the verification itself could
|
|
58
|
+
* not run — a fail-closed non-pass, never treated as "materialized".
|
|
59
|
+
*/
|
|
60
|
+
export interface AssetExistenceEvidence {
|
|
61
|
+
expected: number;
|
|
62
|
+
verified: number;
|
|
63
|
+
missing: string[];
|
|
64
|
+
unreadable?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The exact-version entry module surfaced in evidence — the URL the runtime loads. */
|
|
68
|
+
export interface EvidenceEntryModule {
|
|
69
|
+
url: string;
|
|
70
|
+
format: EntryFormat;
|
|
71
|
+
phase: ReservedPhase;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** One resolved integration, public identity only, plus the entry module it loads. */
|
|
75
|
+
export interface EvidenceIntegration {
|
|
76
|
+
origin: IntegrationOrigin;
|
|
77
|
+
appId: string;
|
|
78
|
+
version: string;
|
|
79
|
+
digest: string;
|
|
80
|
+
executionTier: ExecutionTier;
|
|
81
|
+
/** The same-origin, exact-version entry module the lifecycle runtime imports. */
|
|
82
|
+
entry: EvidenceEntryModule;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** One resolved contribution entry — public shape only; the executable source bytes never appear. */
|
|
86
|
+
export interface EvidenceEntry {
|
|
87
|
+
id: string;
|
|
88
|
+
origin: IntegrationOrigin;
|
|
89
|
+
phase: ReservedPhase;
|
|
90
|
+
kind: ContributionKind;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The assurance state surfaced in evidence. `present:false` is the honest partial
|
|
95
|
+
* case (no elevated-integration record resolved yet); the sub-fields are the
|
|
96
|
+
* public, non-waivable floor — never an acknowledgement token or actor secret.
|
|
97
|
+
*/
|
|
98
|
+
export interface EvidenceAssurance {
|
|
99
|
+
present: boolean;
|
|
100
|
+
surface?: AssuranceSurface;
|
|
101
|
+
classification?: AssuranceClassification;
|
|
102
|
+
/** The regulated floor is non-waivable; always false when a record is present. */
|
|
103
|
+
regulatedSharedRuntimeWaiver?: false;
|
|
104
|
+
eligibleForOutsideGuarantee?: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The identity of exactly what the mounts serve for this plan — the parity anchor.
|
|
109
|
+
* `markupDigest` is over the NONCE-FREE (cache-template) phase markup, so cold
|
|
110
|
+
* (placeholder) and warm (stamped) served forms fingerprint identically and a live
|
|
111
|
+
* nonce is never part of the served identity (ADR 0018).
|
|
112
|
+
*/
|
|
113
|
+
export interface ServedFingerprint {
|
|
114
|
+
markupDigest: string;
|
|
115
|
+
planCacheIdentity: string;
|
|
116
|
+
environment: IntegrationEnvironment;
|
|
117
|
+
cspAdditions: IntegrationCspAdditions;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** The full, tenant-scoped, public-values-only candidate evidence. */
|
|
121
|
+
export interface IntegrationCandidateEvidence {
|
|
122
|
+
schemaVersion: typeof INTEGRATION_CANDIDATE_EVIDENCE_SCHEMA_VERSION;
|
|
123
|
+
tenantPublicId: string;
|
|
124
|
+
environment: BrowserEnvironment;
|
|
125
|
+
planRevision: string;
|
|
126
|
+
integrations: EvidenceIntegration[];
|
|
127
|
+
entries: EvidenceEntry[];
|
|
128
|
+
order: string[];
|
|
129
|
+
consentNeeds: string[];
|
|
130
|
+
/** Per-integration resolved public config; redaction is proved by the secret scan. */
|
|
131
|
+
publicConfig: Record<string, Record<string, unknown>>;
|
|
132
|
+
/** The CSP origin diff a live response's header carries beyond the strict base. */
|
|
133
|
+
cspAdditions: IntegrationCspAdditions;
|
|
134
|
+
assurance: EvidenceAssurance;
|
|
135
|
+
assets: AssetExistenceEvidence;
|
|
136
|
+
served: ServedFingerprint;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface BuildCandidateEvidenceInput {
|
|
140
|
+
/** The resolved plan (ext-kernel-03). */
|
|
141
|
+
plan: EffectivePlan;
|
|
142
|
+
/** The compiled CSP for THIS plan (ext-policy-02); its `planRevision` must match. */
|
|
143
|
+
compiledCsp: CompiledIntegrationCsp;
|
|
144
|
+
/** The fail-closed materialized-asset verify (ext-prereq-01). */
|
|
145
|
+
assets: AssetVerificationResult;
|
|
146
|
+
/** The elevated-integration assurance record, when one is resolved (ext-policy-05). */
|
|
147
|
+
assurance?: ComplianceAssuranceRecord | null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Collapse any live CSP nonce attribute back to the placeholder and join the three
|
|
152
|
+
* phase regions, so the digest is over the nonce-free served identity — invariant
|
|
153
|
+
* across cold/warm responses (ADR 0018).
|
|
154
|
+
*/
|
|
155
|
+
export function canonicalizeServedMarkup(markup: IntegrationPhaseMarkup): string {
|
|
156
|
+
const joined = `${markup.head}\n${markup.bodyStart}\n${markup.bodyDeferred}`;
|
|
157
|
+
return joined.replace(/ nonce="[^"]*"/g, ` nonce="${INTEGRATION_NONCE_PLACEHOLDER}"`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The served phase-markup digest for a resolved plan — the parity anchor both sides re-derive. */
|
|
161
|
+
export function candidateServedMarkupDigest(plan: EffectivePlan): string {
|
|
162
|
+
return fnv1a128Hex(canonicalizeServedMarkup(renderIntegrationPhases(plan, INTEGRATION_NONCE_PLACEHOLDER)));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Derive candidate evidence from the resolved plan, compiled CSP, and asset verify.
|
|
167
|
+
* Fail-closed: a plan that cannot render (unknown phase, duplicate id, secret
|
|
168
|
+
* material), a CSP compiled for a different plan revision, or any secret field in
|
|
169
|
+
* the assembled evidence yields violations and NO evidence — never a partial claim.
|
|
170
|
+
*/
|
|
171
|
+
export function buildCandidateEvidence(
|
|
172
|
+
input: BuildCandidateEvidenceInput,
|
|
173
|
+
): ContractResult<IntegrationCandidateEvidence> {
|
|
174
|
+
const { plan, compiledCsp, assets } = input;
|
|
175
|
+
const violations: ContractViolation[] = [];
|
|
176
|
+
|
|
177
|
+
if (compiledCsp.planRevision !== plan.planRevision) {
|
|
178
|
+
violations.push({
|
|
179
|
+
path: "compiledCsp.planRevision",
|
|
180
|
+
code: "plan_revision_mismatch",
|
|
181
|
+
message:
|
|
182
|
+
`Compiled CSP is bound to plan revision "${compiledCsp.planRevision}" but the plan ` +
|
|
183
|
+
`resolved to "${plan.planRevision}"; evidence must derive from one plan.`,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Derive the served fingerprint from the SAME render engine both mounts call.
|
|
188
|
+
// An unrenderable plan cannot become promotable — surface why, fail closed.
|
|
189
|
+
let markupDigest: string;
|
|
190
|
+
try {
|
|
191
|
+
markupDigest = fnv1a128Hex(
|
|
192
|
+
canonicalizeServedMarkup(renderIntegrationPhases(plan, INTEGRATION_NONCE_PLACEHOLDER)),
|
|
193
|
+
);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
if (err instanceof IntegrationRenderError) {
|
|
196
|
+
for (const reason of err.violations) {
|
|
197
|
+
violations.push({ path: "plan", code: "render_blocked", message: reason });
|
|
198
|
+
}
|
|
199
|
+
return { ok: false, violations };
|
|
200
|
+
}
|
|
201
|
+
throw err;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const evidence: IntegrationCandidateEvidence = {
|
|
205
|
+
schemaVersion: INTEGRATION_CANDIDATE_EVIDENCE_SCHEMA_VERSION,
|
|
206
|
+
tenantPublicId: plan.tenantPublicId,
|
|
207
|
+
environment: plan.environment,
|
|
208
|
+
planRevision: plan.planRevision,
|
|
209
|
+
integrations: plan.integrations.map((i) => ({
|
|
210
|
+
origin: i.origin,
|
|
211
|
+
appId: i.appId,
|
|
212
|
+
version: i.version,
|
|
213
|
+
digest: i.digest,
|
|
214
|
+
executionTier: i.executionTier,
|
|
215
|
+
entry: { url: i.entry.url, format: i.entry.format, phase: i.entry.phase },
|
|
216
|
+
})),
|
|
217
|
+
entries: plan.contributions.map((c) => ({
|
|
218
|
+
id: c.id,
|
|
219
|
+
origin: c.origin,
|
|
220
|
+
phase: c.phase,
|
|
221
|
+
kind: c.kind,
|
|
222
|
+
})),
|
|
223
|
+
order: [...plan.order],
|
|
224
|
+
consentNeeds: [...plan.consentNeeds],
|
|
225
|
+
publicConfig: plan.publicConfig,
|
|
226
|
+
cspAdditions: compiledCsp.additions,
|
|
227
|
+
assurance: summarizeAssurance(input.assurance),
|
|
228
|
+
assets: summarizeAssets(assets),
|
|
229
|
+
served: {
|
|
230
|
+
markupDigest,
|
|
231
|
+
planCacheIdentity: planCacheIdentity(plan),
|
|
232
|
+
environment: plan.environment.environment,
|
|
233
|
+
cspAdditions: compiledCsp.additions,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// Public-values-only: no nonce, token, credential, or signed URL anywhere in the
|
|
238
|
+
// assembled evidence. Defense in depth beyond the closed plan/CSP contracts.
|
|
239
|
+
for (const violation of findForbiddenFields(evidence, "evidence")) violations.push(violation);
|
|
240
|
+
|
|
241
|
+
if (violations.length > 0) return { ok: false, violations };
|
|
242
|
+
return { ok: true, value: evidence };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function summarizeAssurance(record: ComplianceAssuranceRecord | null | undefined): EvidenceAssurance {
|
|
246
|
+
if (!record) return { present: false };
|
|
247
|
+
return {
|
|
248
|
+
present: true,
|
|
249
|
+
surface: record.surface,
|
|
250
|
+
classification: record.classification,
|
|
251
|
+
regulatedSharedRuntimeWaiver: record.compliance.regulatedSharedRuntimeWaiver,
|
|
252
|
+
eligibleForOutsideGuarantee: record.compliance.eligibleForOutsideGuarantee,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function summarizeAssets(result: AssetVerificationResult): AssetExistenceEvidence {
|
|
257
|
+
return {
|
|
258
|
+
expected: result.expected,
|
|
259
|
+
verified: result.verified,
|
|
260
|
+
missing: [...result.missing],
|
|
261
|
+
...(result.error ? { unreadable: result.error } : {}),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* What a mount ACTUALLY served for a candidate, as observed off the wire/cache. The
|
|
267
|
+
* markup may be in cold (placeholder) or warm (live nonce) form — parity
|
|
268
|
+
* canonicalizes both to the nonce-free identity.
|
|
269
|
+
*/
|
|
270
|
+
export interface ServedObservation {
|
|
271
|
+
markup: IntegrationPhaseMarkup;
|
|
272
|
+
planCacheIdentity: string;
|
|
273
|
+
environment: IntegrationEnvironment;
|
|
274
|
+
cspAdditions: IntegrationCspAdditions;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export interface ParityResult {
|
|
278
|
+
ok: boolean;
|
|
279
|
+
contradictions: string[];
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Re-derive the served fingerprint from what a mount actually served and report
|
|
284
|
+
* every field that contradicts the evidence. Equal fingerprint ⇒ the evidence IS
|
|
285
|
+
* the served candidate; any contradiction is a promotion blocker.
|
|
286
|
+
*/
|
|
287
|
+
export function verifyServedParity(
|
|
288
|
+
evidence: IntegrationCandidateEvidence,
|
|
289
|
+
served: ServedObservation,
|
|
290
|
+
): ParityResult {
|
|
291
|
+
const contradictions: string[] = [];
|
|
292
|
+
|
|
293
|
+
const observedDigest = fnv1a128Hex(canonicalizeServedMarkup(served.markup));
|
|
294
|
+
if (observedDigest !== evidence.served.markupDigest) {
|
|
295
|
+
contradictions.push(
|
|
296
|
+
`phase markup digest ${observedDigest} != evidence ${evidence.served.markupDigest}`,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
if (served.planCacheIdentity !== evidence.served.planCacheIdentity) {
|
|
300
|
+
contradictions.push(
|
|
301
|
+
`plan cache identity "${served.planCacheIdentity}" != evidence "${evidence.served.planCacheIdentity}"`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
if (served.environment !== evidence.served.environment) {
|
|
305
|
+
contradictions.push(
|
|
306
|
+
`environment "${served.environment}" != evidence "${evidence.served.environment}"`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
if (stableStringify(served.cspAdditions) !== stableStringify(evidence.served.cspAdditions)) {
|
|
310
|
+
contradictions.push("CSP additions differ from evidence");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return { ok: contradictions.length === 0, contradictions };
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface CandidatePromotionVerdict {
|
|
317
|
+
ok: boolean;
|
|
318
|
+
blockers: string[];
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export interface VerifyCandidatePromotableOptions {
|
|
322
|
+
/**
|
|
323
|
+
* The message from a forge-response integrity failure (ext-prereq-02), when the
|
|
324
|
+
* reconcile that produced this candidate hit one. A forged/unreadable forge
|
|
325
|
+
* response can never become promotable.
|
|
326
|
+
*/
|
|
327
|
+
forgeIntegrityError?: string | null;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* The fail-closed promotion gate (same `{ok, blockers}` shape as the
|
|
332
|
+
* promotion-evidence gate). A candidate is promotable ONLY when: the evidence
|
|
333
|
+
* carries no secret material; it does not report the live environment (a candidate
|
|
334
|
+
* is never live); every declared app asset materialized and the verify ran; no
|
|
335
|
+
* forge-integrity failure is reported; the served output WAS observed; and that
|
|
336
|
+
* observation re-derives to the same fingerprint. An unobserved served output is
|
|
337
|
+
* itself a blocker — parity cannot be confirmed by assertion.
|
|
338
|
+
*/
|
|
339
|
+
export function verifyCandidatePromotable(
|
|
340
|
+
evidence: IntegrationCandidateEvidence,
|
|
341
|
+
served: ServedObservation | null,
|
|
342
|
+
opts?: VerifyCandidatePromotableOptions,
|
|
343
|
+
): CandidatePromotionVerdict {
|
|
344
|
+
const blockers: string[] = [];
|
|
345
|
+
|
|
346
|
+
for (const violation of findForbiddenFields(evidence, "evidence")) {
|
|
347
|
+
blockers.push(`evidence carries secret material at ${violation.path}`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (evidence.environment.environment === "live") {
|
|
351
|
+
blockers.push("candidate reports the live environment; a candidate is never live");
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const a = evidence.assets;
|
|
355
|
+
if (a.unreadable) {
|
|
356
|
+
blockers.push(`asset verification could not run (fail closed): ${a.unreadable}`);
|
|
357
|
+
} else if (a.missing.length > 0 || a.verified !== a.expected) {
|
|
358
|
+
const count = a.missing.length || a.expected - a.verified;
|
|
359
|
+
blockers.push(
|
|
360
|
+
`${count} app asset(s) did not materialize: ${a.missing.join(", ") || "(count mismatch)"}`,
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (opts?.forgeIntegrityError) {
|
|
365
|
+
blockers.push(`forge response integrity failed: ${opts.forgeIntegrityError}`);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (!served) {
|
|
369
|
+
blockers.push("served output not observed; parity with evidence is unconfirmed");
|
|
370
|
+
} else {
|
|
371
|
+
for (const contradiction of verifyServedParity(evidence, served).contradictions) {
|
|
372
|
+
blockers.push(`served output contradicts evidence: ${contradiction}`);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return { ok: blockers.length === 0, blockers };
|
|
377
|
+
}
|