@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,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* `/admin/review-release` — the merchant Review-and-Release workspace.
|
|
4
|
+
*
|
|
5
|
+
* The two-decision merchant surface (`docs/review-release-ux-contract.md`): a
|
|
6
|
+
* merchant only ever (1) adds a ready change to the next release, and (2) publishes
|
|
7
|
+
* the next release live. Everything mechanical — candidate prep, checks, retries,
|
|
8
|
+
* reconciliation, conflict handling, exact-digest pins — runs UNDERNEATH and is
|
|
9
|
+
* never a merchant control. This is an ADDITIVE surface; the operator/developer
|
|
10
|
+
* "Publish" tab (`AdminPublishTab.astro`) keeps the retry/reject/rollback/
|
|
11
|
+
* domain controls.
|
|
12
|
+
*
|
|
13
|
+
* ROUTING / AUTH — mirrors `admin.astro` + `admin/ops-timeline.astro`: middleware
|
|
14
|
+
* resolves the tenant, injects CSP/security headers, and holds anonymous/non-member
|
|
15
|
+
* visitors at the sign-in gate. Tenant context is already resolved by the time this
|
|
16
|
+
* renders. Ship capability is stamped server-side (owner/admin, or an explicit
|
|
17
|
+
* ship-on-behalf grant) — the SAME model the `/api/changes` + `/api/changes/ship`
|
|
18
|
+
* endpoints re-authorize on every request; this is UX mirroring only.
|
|
19
|
+
*
|
|
20
|
+
* The page renders a static shell (three section containers, a persistent
|
|
21
|
+
* ARIA-live announcer, an undo toast, and a focus-trapped publish-confirm dialog);
|
|
22
|
+
* the client controller (`reviewReleaseWorkspace/controller.ts`) fetches
|
|
23
|
+
* `GET /api/changes`, derives the two-decision view model with the pure
|
|
24
|
+
* `lib/publish/reviewRelease` seam, and renders it.
|
|
25
|
+
*/
|
|
26
|
+
export const prerender = false;
|
|
27
|
+
|
|
28
|
+
import { readViewerSession } from "@/lib/auth/route";
|
|
29
|
+
import { resolveViewerShipCapability } from "@/lib/change";
|
|
30
|
+
import { withBase } from "@/lib/basePath";
|
|
31
|
+
import { isInternalTestTenant } from "@tot/public-runtime";
|
|
32
|
+
|
|
33
|
+
const { tenant, basePath, cspNonce } = Astro.locals;
|
|
34
|
+
const adminPath = `${basePath || ""}/admin`;
|
|
35
|
+
const storeName = tenant.displayName || tenant.appDomain || tenant.tenant_id;
|
|
36
|
+
|
|
37
|
+
const viewerSession = await readViewerSession(Astro);
|
|
38
|
+
|
|
39
|
+
// Ship capability, mirrored from the same session model the API routes gate on.
|
|
40
|
+
// UX-only: the server re-authorizes every action. Owner/admin of THIS tenant, or a
|
|
41
|
+
// signed-in developer holding a LIVE ship-on-behalf grant.
|
|
42
|
+
const sessionCapability =
|
|
43
|
+
viewerSession?.resource === tenant.appDomain ? viewerSession.capability : undefined;
|
|
44
|
+
const viewerCapability = Astro.locals.viewer?.capability ?? sessionCapability ?? "none";
|
|
45
|
+
let canShip = viewerCapability === "owner" || viewerCapability === "admin";
|
|
46
|
+
if (!canShip && Astro.locals.viewer?.email) {
|
|
47
|
+
const shipGrant = await resolveViewerShipCapability(Astro.locals.viewer.email, tenant.appDomain);
|
|
48
|
+
if (shipGrant === "ship-on-behalf") canShip = true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const internalTestStore = isInternalTestTenant(tenant);
|
|
52
|
+
|
|
53
|
+
const changesEndpoint = withBase(basePath || "", "/api/changes");
|
|
54
|
+
const acceptEndpoint = withBase(basePath || "", "/api/changes/accept");
|
|
55
|
+
const shipEndpoint = withBase(basePath || "", "/api/changes/ship");
|
|
56
|
+
const buildEndpoint = withBase(basePath || "", "/api/preview/build");
|
|
57
|
+
const liveHref = withBase(basePath || "", "/");
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
<!doctype html>
|
|
61
|
+
<html lang="en">
|
|
62
|
+
<head>
|
|
63
|
+
<meta charset="utf-8" />
|
|
64
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
65
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
66
|
+
<title>{storeName} · Review and Release</title>
|
|
67
|
+
<style is:global nonce={cspNonce}>
|
|
68
|
+
:root {
|
|
69
|
+
color-scheme: light;
|
|
70
|
+
--rr-bg: #f5f7f6;
|
|
71
|
+
--rr-surface: #ffffff;
|
|
72
|
+
--rr-surface-soft: #f9fbfa;
|
|
73
|
+
--rr-ink: #16211f;
|
|
74
|
+
--rr-muted: #5b6a65;
|
|
75
|
+
--rr-line: #dce5e2;
|
|
76
|
+
--rr-teal: #007f79;
|
|
77
|
+
--rr-green-soft: #e3f5eb;
|
|
78
|
+
--rr-green: #137a55;
|
|
79
|
+
--rr-amber-soft: #fff0d5;
|
|
80
|
+
--rr-amber: #a45d00;
|
|
81
|
+
--rr-red-soft: #fde7e4;
|
|
82
|
+
--rr-red: #b42318;
|
|
83
|
+
--rr-blue-soft: #e7efff;
|
|
84
|
+
--rr-blue: #2458c7;
|
|
85
|
+
--rr-radius: 10px;
|
|
86
|
+
--rr-font: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
87
|
+
--rr-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
88
|
+
}
|
|
89
|
+
* { box-sizing: border-box; }
|
|
90
|
+
body { margin: 0; background: var(--rr-bg); color: var(--rr-ink); font: 15px/1.55 var(--rr-font); }
|
|
91
|
+
a { color: var(--rr-teal); }
|
|
92
|
+
code.rr-mono { font-family: var(--rr-mono); font-size: 0.85em; }
|
|
93
|
+
.rr-wrap { max-width: 860px; margin: 0 auto; padding: 28px 20px 72px; }
|
|
94
|
+
header.rr-page { margin-bottom: 22px; }
|
|
95
|
+
header.rr-page h1 { margin: 0; font-size: 24px; font-weight: 780; letter-spacing: -0.01em; }
|
|
96
|
+
header.rr-page p { margin: 5px 0 0; color: var(--rr-muted); font-size: 13px; }
|
|
97
|
+
|
|
98
|
+
.rr-notice {
|
|
99
|
+
padding: 14px 16px; border: 1px solid var(--rr-amber); border-radius: var(--rr-radius);
|
|
100
|
+
background: var(--rr-amber-soft); color: #5c3600; margin-bottom: 18px; font-size: 14px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.rr-section {
|
|
104
|
+
background: var(--rr-surface); border: 1px solid var(--rr-line);
|
|
105
|
+
border-radius: var(--rr-radius); padding: 18px 20px; margin-bottom: 18px;
|
|
106
|
+
}
|
|
107
|
+
.rr-section-title { margin: 0 0 4px; font-size: 17px; font-weight: 720; }
|
|
108
|
+
.rr-note { color: var(--rr-muted); font-size: 13px; margin: 8px 0 0; }
|
|
109
|
+
.rr-empty { color: var(--rr-muted); font-size: 14px; margin: 12px 0 0; }
|
|
110
|
+
|
|
111
|
+
/* Change list */
|
|
112
|
+
.rr-change-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 10px; }
|
|
113
|
+
.rr-change {
|
|
114
|
+
display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
|
|
115
|
+
padding: 12px 14px; border: 1px solid var(--rr-line); border-radius: 8px;
|
|
116
|
+
background: var(--rr-surface-soft);
|
|
117
|
+
}
|
|
118
|
+
.rr-change-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
|
|
119
|
+
.rr-change-title { font-weight: 640; }
|
|
120
|
+
.rr-subline { margin: 4px 0 0; color: var(--rr-muted); font-size: 13px; }
|
|
121
|
+
.rr-change-actions { display: flex; gap: 8px; flex: none; }
|
|
122
|
+
|
|
123
|
+
/* Status chips — ALWAYS carry the state WORD (never color alone, a11y §8). */
|
|
124
|
+
.rr-chip {
|
|
125
|
+
display: inline-flex; align-items: center; min-height: 20px; padding: 1px 9px;
|
|
126
|
+
border-radius: 999px; font-size: 11px; font-weight: 720; white-space: nowrap;
|
|
127
|
+
background: var(--rr-surface); border: 1px solid var(--rr-line); color: #3f4d49;
|
|
128
|
+
}
|
|
129
|
+
.rr-chip-preparing { background: var(--rr-blue-soft); color: var(--rr-blue); border-color: transparent; }
|
|
130
|
+
.rr-chip-ready-to-add { background: var(--rr-green-soft); color: var(--rr-green); border-color: transparent; }
|
|
131
|
+
.rr-chip-in-next-release { background: var(--rr-surface-soft); color: var(--rr-teal); border-color: var(--rr-teal); }
|
|
132
|
+
.rr-chip-needs-attention { background: var(--rr-amber-soft); color: var(--rr-amber); border-color: transparent; }
|
|
133
|
+
.rr-chip-published { background: var(--rr-green-soft); color: var(--rr-green); border-color: transparent; }
|
|
134
|
+
|
|
135
|
+
/* Release panel */
|
|
136
|
+
.rr-release-body { margin: 2px 0 0; color: var(--rr-muted); font-size: 14px; }
|
|
137
|
+
.rr-contents { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--rr-line); }
|
|
138
|
+
.rr-contents-title { margin: 0 0 8px; font-size: 13px; font-weight: 720; text-transform: uppercase; letter-spacing: 0.04em; color: var(--rr-muted); }
|
|
139
|
+
.rr-contents-list { margin: 0; padding-left: 18px; display: grid; gap: 4px; font-size: 14px; }
|
|
140
|
+
.rr-release-action { margin-top: 16px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
|
|
141
|
+
.rr-paywall { flex-direction: column; align-items: flex-start; }
|
|
142
|
+
.rr-success { margin: 12px 0 0; color: var(--rr-green); font-weight: 640; }
|
|
143
|
+
.rr-live-body { margin: 4px 0 12px; color: var(--rr-muted); font-size: 14px; }
|
|
144
|
+
|
|
145
|
+
/* Buttons */
|
|
146
|
+
.rr-btn {
|
|
147
|
+
min-height: 40px; display: inline-flex; align-items: center; justify-content: center;
|
|
148
|
+
padding: 0 18px; border-radius: 8px; font: inherit; font-weight: 660; font-size: 14px;
|
|
149
|
+
cursor: pointer; text-decoration: none; border: 1px solid var(--rr-teal);
|
|
150
|
+
background: var(--rr-surface); color: var(--rr-teal);
|
|
151
|
+
}
|
|
152
|
+
.rr-btn-primary { background: var(--rr-teal); color: #fff; }
|
|
153
|
+
.rr-btn-ghost { border-color: var(--rr-line); color: var(--rr-ink); }
|
|
154
|
+
.rr-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
155
|
+
.rr-btn:focus-visible { outline: 3px solid var(--rr-blue); outline-offset: 2px; }
|
|
156
|
+
a.rr-btn:focus-visible { outline: 3px solid var(--rr-blue); outline-offset: 2px; }
|
|
157
|
+
|
|
158
|
+
/* Announcer (SR-only) + undo toast */
|
|
159
|
+
.rr-announce {
|
|
160
|
+
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
|
|
161
|
+
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
|
|
162
|
+
}
|
|
163
|
+
.rr-toast {
|
|
164
|
+
position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
|
|
165
|
+
background: var(--rr-ink); color: #fff; padding: 10px 16px; border-radius: 8px;
|
|
166
|
+
font-size: 13px; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18); z-index: 40;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Publish-confirm dialog */
|
|
170
|
+
.rr-confirm-backdrop {
|
|
171
|
+
position: fixed; inset: 0; background: rgba(22, 33, 31, 0.45);
|
|
172
|
+
display: flex; align-items: center; justify-content: center; padding: 20px; z-index: 50;
|
|
173
|
+
}
|
|
174
|
+
/* `display: flex` above beats the UA `[hidden]{display:none}` rule at equal
|
|
175
|
+
specificity (author styles always win) — without this, toggling the
|
|
176
|
+
`hidden` attribute in JS has no visual effect and the dialog looks stuck. */
|
|
177
|
+
.rr-confirm-backdrop[hidden] {
|
|
178
|
+
display: none;
|
|
179
|
+
}
|
|
180
|
+
.rr-confirm-dialog {
|
|
181
|
+
background: var(--rr-surface); border-radius: var(--rr-radius); padding: 22px 24px;
|
|
182
|
+
max-width: 440px; width: 100%; box-shadow: 0 12px 48px rgba(0, 0, 0, 0.28);
|
|
183
|
+
}
|
|
184
|
+
.rr-confirm-dialog h2 { margin: 0 0 8px; font-size: 19px; font-weight: 740; }
|
|
185
|
+
.rr-confirm-dialog p { margin: 0 0 20px; color: var(--rr-muted); font-size: 14px; }
|
|
186
|
+
.rr-confirm-actions { display: flex; justify-content: flex-end; gap: 10px; }
|
|
187
|
+
|
|
188
|
+
.rr-loading { color: var(--rr-muted); font-size: 14px; padding: 8px 0; }
|
|
189
|
+
|
|
190
|
+
@media (max-width: 560px) {
|
|
191
|
+
.rr-change { flex-direction: column; }
|
|
192
|
+
.rr-change-actions { width: 100%; }
|
|
193
|
+
.rr-btn { width: 100%; }
|
|
194
|
+
}
|
|
195
|
+
@media (prefers-reduced-motion: reduce) {
|
|
196
|
+
* { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
|
|
197
|
+
}
|
|
198
|
+
</style>
|
|
199
|
+
</head>
|
|
200
|
+
<body>
|
|
201
|
+
<div class="rr-wrap">
|
|
202
|
+
<header class="rr-page">
|
|
203
|
+
<h1>Review and release</h1>
|
|
204
|
+
<p>{storeName} · review changes and publish your next release · <a href={adminPath}>← Admin</a></p>
|
|
205
|
+
</header>
|
|
206
|
+
|
|
207
|
+
{!viewerSession && (
|
|
208
|
+
<div class="rr-notice">
|
|
209
|
+
Sign in as an owner or admin of {storeName} to review changes and publish releases.
|
|
210
|
+
<a href="/auth/login">Sign in</a>.
|
|
211
|
+
</div>
|
|
212
|
+
)}
|
|
213
|
+
|
|
214
|
+
{viewerSession && (
|
|
215
|
+
<div
|
|
216
|
+
data-rr-root
|
|
217
|
+
data-changes-endpoint={changesEndpoint}
|
|
218
|
+
data-accept-endpoint={acceptEndpoint}
|
|
219
|
+
data-ship-endpoint={shipEndpoint}
|
|
220
|
+
data-build-endpoint={buildEndpoint}
|
|
221
|
+
data-live-href={liveHref}
|
|
222
|
+
data-can-ship={canShip ? "true" : "false"}
|
|
223
|
+
data-internal-test-store={internalTestStore ? "true" : "false"}
|
|
224
|
+
data-store-name={storeName}
|
|
225
|
+
>
|
|
226
|
+
<div class="rr-announce" data-rr-announce role="status" aria-live="polite"></div>
|
|
227
|
+
|
|
228
|
+
<div data-rr-workspace>
|
|
229
|
+
<p class="rr-loading" data-rr-loading>Loading your changes and next release…</p>
|
|
230
|
+
</div>
|
|
231
|
+
|
|
232
|
+
<div class="rr-toast" data-rr-toast role="status" aria-live="polite" hidden></div>
|
|
233
|
+
|
|
234
|
+
<!-- Publish-confirm dialog — a single plain-language step (the human go-live
|
|
235
|
+
gate). role=dialog, focus-trapped, Esc cancels, focus returns to the
|
|
236
|
+
invoking button. No typed-domain confirm, no digest to verify. -->
|
|
237
|
+
<div class="rr-confirm-backdrop" data-rr-confirm hidden>
|
|
238
|
+
<div
|
|
239
|
+
class="rr-confirm-dialog"
|
|
240
|
+
data-rr-confirm-dialog
|
|
241
|
+
role="dialog"
|
|
242
|
+
aria-modal="true"
|
|
243
|
+
aria-labelledby="rr-confirm-heading"
|
|
244
|
+
tabindex="-1"
|
|
245
|
+
>
|
|
246
|
+
<h2 id="rr-confirm-heading" data-rr-confirm-heading>Publish your next release?</h2>
|
|
247
|
+
<p data-rr-confirm-body></p>
|
|
248
|
+
<div class="rr-confirm-actions">
|
|
249
|
+
<button type="button" class="rr-btn rr-btn-ghost" data-rr-confirm-cancel>Cancel</button>
|
|
250
|
+
<button type="button" class="rr-btn rr-btn-primary" data-rr-confirm-ok>Publish now</button>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
)}
|
|
256
|
+
</div>
|
|
257
|
+
|
|
258
|
+
{viewerSession && (
|
|
259
|
+
<script>
|
|
260
|
+
import { initReviewReleaseWorkspace } from "@/lib/publish/reviewReleaseWorkspace/controller";
|
|
261
|
+
initReviewReleaseWorkspace();
|
|
262
|
+
</script>
|
|
263
|
+
)}
|
|
264
|
+
</body>
|
|
265
|
+
</html>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* /admin/select — the canonical admin tenant picker.
|
|
4
|
+
*
|
|
5
|
+
* Reached when an AUTHENTICATED viewer hits the admin of a tenant they are NOT a
|
|
6
|
+
* member of (a stale/shared deep link, or a host that fell back to the registry
|
|
7
|
+
* default). The middleware routes them here instead of a sign-in loop or the
|
|
8
|
+
* wrong tenant's data. This page holds no identity of its own: it reads the
|
|
9
|
+
* session's tenant memberships and offers each as a link INTO that tenant's own
|
|
10
|
+
* admin (`/<resource>/admin`, the DNS-free path form).
|
|
11
|
+
*
|
|
12
|
+
* 0 memberships → honest "nothing to manage".
|
|
13
|
+
* 1 membership → straight into that tenant's admin.
|
|
14
|
+
* ≥2 → a picker.
|
|
15
|
+
*/
|
|
16
|
+
export const prerender = false;
|
|
17
|
+
|
|
18
|
+
import { readViewerSession } from "@/lib/auth/route";
|
|
19
|
+
import { selectTenant } from "@/lib/dashboard/tenantSelection";
|
|
20
|
+
import { adminUrlForTenant } from "@/lib/auth/adminLanding";
|
|
21
|
+
|
|
22
|
+
const cspNonce = Astro.locals.cspNonce;
|
|
23
|
+
const session = await readViewerSession(Astro);
|
|
24
|
+
if (!session) {
|
|
25
|
+
return Astro.redirect("/auth/login?next=%2Fadmin%2Fselect", 302);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const selection = selectTenant(session.tenants);
|
|
29
|
+
if (selection.mode === "single") {
|
|
30
|
+
return Astro.redirect(adminUrlForTenant(selection.tenant.resource), 302);
|
|
31
|
+
}
|
|
32
|
+
const tenants = selection.mode === "picker" ? selection.tenants : [];
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<html lang="en">
|
|
36
|
+
<head>
|
|
37
|
+
<meta charset="utf-8" />
|
|
38
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
39
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
40
|
+
<title>Choose a store — Token of Trust Admin</title>
|
|
41
|
+
<style nonce={cspNonce}>
|
|
42
|
+
:root { color-scheme: light dark; }
|
|
43
|
+
* { box-sizing: border-box; }
|
|
44
|
+
body { font: 15px/1.6 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
|
|
45
|
+
margin: 0; min-height: 100vh; padding: 2.5rem 1.25rem; background: #f5f4f0; color: #1c1c1c; }
|
|
46
|
+
@media (prefers-color-scheme: dark) { body { background: #14141a; color: #ececf1; } }
|
|
47
|
+
main { max-width: 40rem; margin-inline: auto; }
|
|
48
|
+
.eyebrow { font: 600 .68rem/1 ui-monospace, monospace; letter-spacing: .12em; text-transform: uppercase; color: #8a7f66; margin: 0 0 .5rem; }
|
|
49
|
+
h1 { font-size: 1.5rem; letter-spacing: -.01em; margin: 0 0 .3rem; }
|
|
50
|
+
.sub { color: #6a6a6a; margin: 0 0 1.75rem; }
|
|
51
|
+
@media (prefers-color-scheme: dark) { .sub { color: #a2a2ad; } }
|
|
52
|
+
ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .75rem; }
|
|
53
|
+
a.store { display: flex; align-items: center; justify-content: space-between; text-decoration: none;
|
|
54
|
+
background: #fff; border: 1px solid #e6e4de; border-radius: 12px; padding: 1rem 1.25rem; color: inherit; }
|
|
55
|
+
@media (prefers-color-scheme: dark) { a.store { background: #1e1e28; border-color: #33333f; } }
|
|
56
|
+
a.store:hover { border-color: #b7d0ff; }
|
|
57
|
+
.name { font-weight: 600; }
|
|
58
|
+
.role { font: 600 .68rem/1 ui-monospace, monospace; text-transform: uppercase; letter-spacing: .06em;
|
|
59
|
+
color: #4a6; border: 1px solid currentColor; border-radius: 999px; padding: .2rem .55rem; }
|
|
60
|
+
.empty { background: #fff; border: 1px solid #e6e4de; border-radius: 12px; padding: 1.5rem; }
|
|
61
|
+
@media (prefers-color-scheme: dark) { .empty { background: #1e1e28; border-color: #33333f; } }
|
|
62
|
+
.who { margin-top: 2rem; font-size: .82rem; color: #8a8a8a; }
|
|
63
|
+
.linkbtn { background: none; border: 0; color: inherit; font: inherit; text-decoration: underline; cursor: pointer; padding: 0; }
|
|
64
|
+
.logout { display: inline; }
|
|
65
|
+
</style>
|
|
66
|
+
</head>
|
|
67
|
+
<body>
|
|
68
|
+
<main>
|
|
69
|
+
<p class="eyebrow">Token of Trust Admin</p>
|
|
70
|
+
<h1>Choose a store</h1>
|
|
71
|
+
{tenants.length ? (
|
|
72
|
+
<>
|
|
73
|
+
<p class="sub">You're a member of more than one store. Pick one to open its admin.</p>
|
|
74
|
+
<ul>
|
|
75
|
+
{tenants.map((t) => (
|
|
76
|
+
<li>
|
|
77
|
+
<a class="store" href={adminUrlForTenant(t.resource)}>
|
|
78
|
+
<span class="name">{t.resource}</span>
|
|
79
|
+
<span class="role">{t.role}</span>
|
|
80
|
+
</a>
|
|
81
|
+
</li>
|
|
82
|
+
))}
|
|
83
|
+
</ul>
|
|
84
|
+
</>
|
|
85
|
+
) : (
|
|
86
|
+
<div class="empty">
|
|
87
|
+
<p style="margin:0">You're signed in as <strong>{session.email}</strong>, but you don't
|
|
88
|
+
have admin access to any store yet. Ask a store's owner to invite you.</p>
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
|
|
92
|
+
<p class="who">Signed in as {session.email} ·
|
|
93
|
+
<form class="logout" method="post" action="/api/auth/logout"><button type="submit" class="linkbtn">Sign out</button></form></p>
|
|
94
|
+
</main>
|
|
95
|
+
</body>
|
|
96
|
+
</html>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* SHELL CONTRACT — every AdminXTab.astro component mounted below must preserve:
|
|
14
14
|
* - A `<section id="{tab}" data-admin-panel data-agent-scope="{tab}">` root,
|
|
15
15
|
* where {tab} is one of: orders, products, subscriptions, customers, fulfillment,
|
|
16
|
-
* reporting, ai-workflows, publish, settings. The shell's hash router shows/hides
|
|
16
|
+
* reporting, ai-workflows, publish, integrations, settings. The shell's hash router shows/hides
|
|
17
17
|
* panels by matching `html[data-admin-tab]` to this id, and the AI Ask
|
|
18
18
|
* envelope reads `data-agent-scope` to label its active context.
|
|
19
19
|
* - No tab-switching chrome of its own — `#{tab}` deep links and the shell's
|
|
@@ -39,6 +39,7 @@ import AdminSubscriptionsTab from "../components/admin/AdminSubscriptionsTab.ast
|
|
|
39
39
|
import AdminReportingTab from "../components/admin/AdminReportingTab.astro";
|
|
40
40
|
import AdminBlogTab from "../components/admin/AdminBlogTab.astro";
|
|
41
41
|
import AdminPublishTab from "../components/admin/AdminPublishTab.astro";
|
|
42
|
+
import AdminIntegrationsTab from "../components/admin/AdminIntegrationsTab.astro";
|
|
42
43
|
import AdminSettingsTab from "../components/admin/AdminSettingsTab.astro";
|
|
43
44
|
import { readViewerSession } from "@/lib/auth/route";
|
|
44
45
|
import { resolveAdminTenantMode } from "@/lib/adminTenantEnvelope";
|
|
@@ -102,7 +103,7 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
102
103
|
<title>{tenantLabel} Admin</title>
|
|
103
104
|
<script is:inline nonce={cspNonce}>
|
|
104
105
|
(() => {
|
|
105
|
-
const adminTabs = ["orders", "products", "subscriptions", "customers", "fulfillment", "reporting", "ai-workflows", "blog", "publish", "settings"];
|
|
106
|
+
const adminTabs = ["orders", "products", "subscriptions", "customers", "fulfillment", "reporting", "ai-workflows", "blog", "publish", "integrations", "settings"];
|
|
106
107
|
const canViewInternalGuide = document.documentElement.dataset.internalAdminGuide === "true";
|
|
107
108
|
const defaultTab = canViewInternalGuide ? "orders" : "settings";
|
|
108
109
|
// A deep link may carry a query suffix in the hash (e.g. #publish?pr=42);
|
|
@@ -135,6 +136,8 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
135
136
|
<symbol id="i-file" viewBox="0 0 24 24"><path d="M7 3h7l5 5v13H7z"></path><path d="M14 3v5h5"></path><path d="M10 13h6M10 17h4"></path></symbol>
|
|
136
137
|
<symbol id="i-refresh" viewBox="0 0 24 24"><path d="M20 12a8 8 0 0 1-13.6 5.7L4 15"></path><path d="M4 20v-5h5"></path><path d="M4 12A8 8 0 0 1 17.6 6.3L20 9"></path><path d="M20 4v5h-5"></path></symbol>
|
|
137
138
|
<symbol id="i-export" viewBox="0 0 24 24"><path d="M12 3v12"></path><path d="m7 8 5-5 5 5"></path><path d="M5 15v4h14v-4"></path></symbol>
|
|
139
|
+
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="9" y="9" width="11" height="11" rx="2"></rect><path d="M5 15V6a2 2 0 0 1 2-2h9"></path></symbol>
|
|
140
|
+
<symbol id="i-undo" viewBox="0 0 24 24"><path d="M9 14 4 9l5-5"></path><path d="M4 9h11a5 5 0 0 1 0 10h-4"></path></symbol>
|
|
138
141
|
</svg>
|
|
139
142
|
|
|
140
143
|
<div class="shell">
|
|
@@ -190,6 +193,7 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
190
193
|
<a href="#ai-workflows" data-admin-tab-link><svg><use href="#i-workflows"></use></svg><span>AI Workflows</span></a>
|
|
191
194
|
<a href="#blog" data-admin-tab-link><svg><use href="#i-file"></use></svg><span>Blog</span></a>
|
|
192
195
|
<a href="#publish" data-admin-tab-link><svg><use href="#i-export"></use></svg><span>Publish</span></a>
|
|
196
|
+
<a href="#integrations" data-admin-tab-link><svg><use href="#i-workflows"></use></svg><span>Integrations</span></a>
|
|
193
197
|
<a href="#settings" data-admin-tab-link><svg><use href="#i-gear"></use></svg><span>Settings</span></a>
|
|
194
198
|
</nav>
|
|
195
199
|
|
|
@@ -206,6 +210,13 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
206
210
|
<svg><use href="#i-gear"></use></svg><span>Developer cockpit</span>
|
|
207
211
|
</a>
|
|
208
212
|
|
|
213
|
+
<!-- Cross-surface hop: the merchant Review-and-Release workspace — the
|
|
214
|
+
two-decision (add to next release / publish now) surface, a SIBLING
|
|
215
|
+
page (not a tab), additive to the operator Publish tab above. -->
|
|
216
|
+
<a class="cockpit-link" href={`${basePath || ""}/admin/review-release`}>
|
|
217
|
+
<svg><use href="#i-export"></use></svg><span>Review & release</span>
|
|
218
|
+
</a>
|
|
219
|
+
|
|
209
220
|
<div class="account" data-admin-account>
|
|
210
221
|
<span class="account-avatar" aria-hidden="true"><svg><use href="#i-user"></use></svg></span>
|
|
211
222
|
<span class="account-meta">
|
|
@@ -256,6 +267,7 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
256
267
|
<a class="tab" href="#ai-workflows" role="tab" aria-controls="ai-workflows" aria-selected="false" data-admin-tab-link>AI Workflows</a>
|
|
257
268
|
<a class="tab" href="#blog" role="tab" aria-controls="blog" aria-selected="false" data-admin-tab-link>Blog</a>
|
|
258
269
|
<a class="tab" href="#publish" role="tab" aria-controls="publish" aria-selected="false" data-admin-tab-link>Publish</a>
|
|
270
|
+
<a class="tab" href="#integrations" role="tab" aria-controls="integrations" aria-selected="false" data-admin-tab-link>Integrations</a>
|
|
259
271
|
<a class="tab" href="#settings" role="tab" aria-controls="settings" aria-selected="false" data-admin-tab-link>Settings</a>
|
|
260
272
|
</div>
|
|
261
273
|
|
|
@@ -305,6 +317,7 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
305
317
|
<a id="admin-tab-ai-workflows" class="tab" href="#ai-workflows" role="tab" aria-controls="ai-workflows" aria-selected="false" data-admin-tab-link>AI Workflows</a>
|
|
306
318
|
<a id="admin-tab-blog" class="tab" href="#blog" role="tab" aria-controls="blog" aria-selected="false" data-admin-tab-link>Blog</a>
|
|
307
319
|
<a id="admin-tab-publish" class="tab" href="#publish" role="tab" aria-controls="publish" aria-selected="false" data-admin-tab-link>Publish</a>
|
|
320
|
+
<a id="admin-tab-integrations" class="tab" href="#integrations" role="tab" aria-controls="integrations" aria-selected="false" data-admin-tab-link>Integrations</a>
|
|
308
321
|
<a id="admin-tab-settings" class="tab" href="#settings" role="tab" aria-controls="settings" aria-selected="false" data-admin-tab-link>Settings</a>
|
|
309
322
|
</div>
|
|
310
323
|
|
|
@@ -432,6 +445,7 @@ const { envelope: tenantEnvelope, isStaff, pickerTenants, deniedTarget } = admin
|
|
|
432
445
|
<AdminAIWorkflowsTab envelope={tenantEnvelope} />
|
|
433
446
|
<AdminBlogTab envelope={tenantEnvelope} />
|
|
434
447
|
<AdminPublishTab envelope={tenantEnvelope} />
|
|
448
|
+
<AdminIntegrationsTab envelope={tenantEnvelope} />
|
|
435
449
|
<AdminSettingsTab envelope={tenantEnvelope} />
|
|
436
450
|
|
|
437
451
|
{canViewInternalGuide && (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* POST /api/activity — the ingest endpoint of the operational activity telemetry
|
|
3
|
-
* spine
|
|
4
|
-
* the emitter cohorts — the CLI
|
|
3
|
+
* spine. Accepts one `ActivityEvent` (or a batch array) as JSON from
|
|
4
|
+
* the emitter cohorts — the CLI and the UI, both posting the wire shape
|
|
5
5
|
* of `packages/public-runtime/src/activity/event.ts` — authenticates the caller,
|
|
6
6
|
* re-redacts server-side, and fans each accepted event out to the sink(s) its
|
|
7
7
|
* catalog entry declares. See DECISIONS.md §8 for the store decision.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* DEFENSE IN DEPTH — every event is rebuilt through `createActivityEvent()`
|
|
19
19
|
* (`ingestEvents`), re-applying the default-deny allowlist + canary scan even
|
|
20
20
|
* though emitters already redacted. A value-canary trip is self-telemetried as
|
|
21
|
-
* `system.ingest.rejected` so a leak attempt is visible
|
|
21
|
+
* `system.ingest.rejected` so a leak attempt is visible for alerting.
|
|
22
22
|
*
|
|
23
23
|
* OFF THE CRITICAL PATH — auth + parse + validate + redact are cheap synchronous
|
|
24
24
|
* CPU; the sink WRITES (D1 + Analytics Engine) run past the response via
|
|
@@ -50,7 +50,7 @@ function json(body: unknown, status: number): Response {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export async function POST(context: APIContext): Promise<Response> {
|
|
53
|
-
// Kill switch
|
|
53
|
+
// Kill switch: telemetry off ⇒ accept-and-drop. Fail-open toward the EMITTER —
|
|
54
54
|
// a 202 (never a 4xx/5xx) so a CLI/UI poster never errors, retries, or is delayed by
|
|
55
55
|
// the switch; nothing is validated, stored, or fanned out.
|
|
56
56
|
if (isActivityDisabled()) {
|
|
@@ -96,8 +96,8 @@ export async function POST(context: APIContext): Promise<Response> {
|
|
|
96
96
|
|
|
97
97
|
// Self-telemetry: a value-canary trip during server-side redaction means an
|
|
98
98
|
// emitter leaked (or tried to leak) a secret/PII into the payload. Emit a
|
|
99
|
-
// `system.ingest.rejected` event (itself routed to logs+analytics) so
|
|
100
|
-
//
|
|
99
|
+
// `system.ingest.rejected` event (itself routed to logs+analytics) so it can be
|
|
100
|
+
// alerted on — the fact of the trip, the action, never the offending value. Rejected
|
|
101
101
|
// events get the same self-telemetry so a spoof/unknown-action attempt is
|
|
102
102
|
// visible. Built here (synchronously) but fanned out off-path below.
|
|
103
103
|
const selfTelemetry = [
|
|
@@ -127,9 +127,9 @@ export async function POST(context: APIContext): Promise<Response> {
|
|
|
127
127
|
|
|
128
128
|
// Fan every accepted event + the self-telemetry out to its sinks, PAST the
|
|
129
129
|
// response. Best-effort per sink (never throws). The adapter's per-request
|
|
130
|
-
// ExecutionContext lives at `locals.
|
|
130
|
+
// ExecutionContext lives at `locals.cfContext`; runAfterResponse floats the
|
|
131
131
|
// promise in dev/Node when it is absent.
|
|
132
|
-
const cfContext = (context.locals as {
|
|
132
|
+
const cfContext = (context.locals as { cfContext?: CfExecutionContextLike })?.cfContext ?? null;
|
|
133
133
|
const work = Promise.all([...accepted.map((a) => a.event), ...selfTelemetry].map((e) => fanOutActivity(e, sinks)));
|
|
134
134
|
runAfterResponse(work, cfContext);
|
|
135
135
|
|
|
@@ -25,9 +25,7 @@
|
|
|
25
25
|
* ops-timeline; never a URL/query value.
|
|
26
26
|
*/
|
|
27
27
|
import type { APIContext } from "astro";
|
|
28
|
-
import {
|
|
29
|
-
import { resolveAdminEntry } from "@/lib/auth/adminEntry";
|
|
30
|
-
import { resolveAdminTenantMode } from "@/lib/adminTenantEnvelope";
|
|
28
|
+
import { requireAdminApiEntry } from "@/lib/auth/adminApiGuard";
|
|
31
29
|
import { readD1 } from "@/lib/env";
|
|
32
30
|
import { fromD1 } from "@/lib/d1/catalog";
|
|
33
31
|
import { checkActivityAlerts } from "@/lib/activity/alerts";
|
|
@@ -46,24 +44,11 @@ function json(body: unknown, status = 200): Response {
|
|
|
46
44
|
|
|
47
45
|
export async function GET(context: APIContext): Promise<Response> {
|
|
48
46
|
const { tenant } = context.locals;
|
|
49
|
-
const nowSeconds = Math.floor(Date.now() / 1000);
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
record: viewerSession,
|
|
56
|
-
hostResource: tenant.appDomain,
|
|
57
|
-
nowSeconds,
|
|
58
|
-
});
|
|
59
|
-
const { isStaff } = resolveAdminTenantMode({
|
|
60
|
-
session: viewerSession,
|
|
61
|
-
adminAppTenant: tenant.appDomain,
|
|
62
|
-
requestedTarget: null,
|
|
63
|
-
nowSeconds,
|
|
64
|
-
});
|
|
65
|
-
const authorized = adminEntry.isOwnerViewer || isStaff;
|
|
66
|
-
if (!authorized) return json({ ok: false, reason: "not_authorized" }, 403);
|
|
48
|
+
// Owner/admin-of-tenant or ToT-staff only — same bar as /admin/ops-timeline,
|
|
49
|
+
// fail-closed and bound to the Host-resolved tenant.
|
|
50
|
+
const access = await requireAdminApiEntry(context, { requireOwner: true });
|
|
51
|
+
if (!access.ok) return json({ ok: false, reason: access.reason }, access.status);
|
|
67
52
|
|
|
68
53
|
const d1 = await readD1("STOREFRONT_APPS_DB");
|
|
69
54
|
if (!d1) return json({ ok: true, dbAvailable: false, alerts: [] });
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `GET /api/admin/orders/:id` — one order's full detail for the Orders tab
|
|
2
|
+
* `GET /api/admin/orders/:id` — one order's full detail for the Orders tab.
|
|
3
3
|
*
|
|
4
4
|
* Server-side proxy to checkout `GET /commerce/orders/:orderId` for the
|
|
5
5
|
* resolved tenant + env. Bearer stays server-side; response is the CheckoutOrderDetail
|
|
6
|
-
* DTO. `verificationDetail` is empty
|
|
6
|
+
* DTO. `verificationDetail` is currently empty — consumers tolerate that.
|
|
7
7
|
* Read-only (scope-locks).
|
|
8
8
|
*/
|
|
9
9
|
import type { APIContext } from "astro";
|
|
10
10
|
import { readEnv } from "@/lib/env";
|
|
11
|
+
import { requireAdminApiEntry } from "@/lib/auth/adminApiGuard";
|
|
11
12
|
import {
|
|
12
13
|
createCheckoutOrderClient,
|
|
13
14
|
orderApiBaseUrl,
|
|
@@ -31,6 +32,10 @@ function jsonError(code: string, status: number): Response {
|
|
|
31
32
|
|
|
32
33
|
export async function GET(context: APIContext): Promise<Response> {
|
|
33
34
|
const { tenant, customizationEnv } = context.locals;
|
|
35
|
+
|
|
36
|
+
const access = await requireAdminApiEntry(context);
|
|
37
|
+
if (!access.ok) return jsonError(access.reason, access.status);
|
|
38
|
+
|
|
34
39
|
const orderId = context.params.id;
|
|
35
40
|
if (!orderId) return jsonError("order_not_found", 404);
|
|
36
41
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `GET /api/admin/orders` — internal admin route backing the Orders tab
|
|
2
|
+
* `GET /api/admin/orders` — internal admin route backing the Orders tab.
|
|
3
3
|
*
|
|
4
4
|
* Server-side proxy to the checkout order READ API for the resolved tenant +
|
|
5
5
|
* environment. The per-tenant bearer key stays on the Worker (never in the
|
|
6
6
|
* response); the browser only ever sees order DTO JSON. Read-only (scope-locks).
|
|
7
|
-
*
|
|
7
|
+
* The admin UI consumes this and maps the DTO → OrdersViewModel.
|
|
8
8
|
*
|
|
9
9
|
* Access control matches the rest of the admin surface (owned by the admin
|
|
10
10
|
* host/approver layer) — same posture as `api/evidence.json.ts`; no new gate here.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import type { APIContext } from "astro";
|
|
13
13
|
import type { CheckoutOrderListFilters } from "@tot/public-runtime";
|
|
14
14
|
import { readEnv } from "@/lib/env";
|
|
15
|
+
import { requireAdminApiEntry } from "@/lib/auth/adminApiGuard";
|
|
15
16
|
import {
|
|
16
17
|
createCheckoutOrderClient,
|
|
17
18
|
orderApiBaseUrl,
|
|
@@ -36,6 +37,11 @@ function jsonError(code: string, status: number): Response {
|
|
|
36
37
|
export async function GET(context: APIContext): Promise<Response> {
|
|
37
38
|
const { tenant, customizationEnv } = context.locals;
|
|
38
39
|
|
|
40
|
+
// Fail closed: require a signed-in member/owner of THIS tenant, bound to the
|
|
41
|
+
// Host-resolved appDomain — never trusting the conditional login gate for auth.
|
|
42
|
+
const access = await requireAdminApiEntry(context);
|
|
43
|
+
if (!access.ok) return jsonError(access.reason, access.status);
|
|
44
|
+
|
|
39
45
|
const bearer = await readEnv("FOXY_ORDER_API_KEY");
|
|
40
46
|
if (!bearer) {
|
|
41
47
|
// Worker secret not provisioned for this env — a config error, not the
|