@tokenoftrust/storefront-runner 2.0.2 → 2.0.4
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/content.d.ts +159 -0
- package/apps/storefront/.astro/integrations/_astrojs_cloudflare/cloudflare.d.ts +1 -0
- package/apps/storefront/.astro/types.d.ts +3 -0
- package/apps/storefront/node_modules/.bin/acorn +43 -0
- package/apps/storefront/node_modules/.bin/astro +43 -0
- package/apps/storefront/node_modules/.bin/astro-check +43 -0
- package/apps/storefront/node_modules/.bin/browserslist +43 -0
- package/apps/storefront/node_modules/.bin/cf-wrangler +43 -0
- package/apps/storefront/node_modules/.bin/depcruise +43 -0
- package/apps/storefront/node_modules/.bin/depcruise-baseline +43 -0
- package/apps/storefront/node_modules/.bin/depcruise-fmt +43 -0
- package/apps/storefront/node_modules/.bin/depcruise-wrap-stream-in-html +43 -0
- package/apps/storefront/node_modules/.bin/dependency-cruise +43 -0
- package/apps/storefront/node_modules/.bin/dependency-cruiser +43 -0
- package/apps/storefront/node_modules/.bin/drizzle-kit +43 -0
- package/apps/storefront/node_modules/.bin/esbuild +43 -0
- package/apps/storefront/node_modules/.bin/jiti +43 -0
- package/apps/storefront/node_modules/.bin/playwright +43 -0
- package/apps/storefront/node_modules/.bin/playwright-core +43 -0
- package/apps/storefront/node_modules/.bin/prettier +43 -0
- package/apps/storefront/node_modules/.bin/rollup +43 -0
- package/apps/storefront/node_modules/.bin/tsc +43 -0
- package/apps/storefront/node_modules/.bin/tsserver +43 -0
- package/apps/storefront/node_modules/.bin/tsx +43 -0
- package/apps/storefront/node_modules/.bin/vite +43 -0
- package/apps/storefront/node_modules/.bin/vitest +43 -0
- package/apps/storefront/node_modules/.bin/workerd +43 -0
- package/apps/storefront/node_modules/.bin/wrangler +43 -0
- package/apps/storefront/node_modules/.bin/wrangler2 +43 -0
- package/apps/storefront/node_modules/.bin/yaml +43 -0
- package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_client__js.js +58 -0
- package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_client__js.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_n_@preact_signals.js +741 -0
- package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_n_@preact_signals.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_server__js.js +2549 -0
- package/apps/storefront/node_modules/.vite/deps/@astrojs_preact_server__js.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/_metadata.json +150 -0
- package/apps/storefront/node_modules/.vite/deps/astro-BIHuWFxm.js +434 -0
- package/apps/storefront/node_modules/.vite/deps/astro-BIHuWFxm.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/apps/storefront/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/astro_n_axobject-query.js +2705 -0
- package/apps/storefront/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/apps/storefront/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/apps/storefront/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/audit-DKDpcdEI.js +1535 -0
- package/apps/storefront/node_modules/.vite/deps/audit-DKDpcdEI.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/highlight-B9UoX1wa.js +48 -0
- package/apps/storefront/node_modules/.vite/deps/highlight-B9UoX1wa.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/icons-BWi2wI9n.js +42 -0
- package/apps/storefront/node_modules/.vite/deps/icons-BWi2wI9n.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/package.json +3 -0
- package/apps/storefront/node_modules/.vite/deps/preact.js +310 -0
- package/apps/storefront/node_modules/.vite/deps/preact.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/preact_compat.js +420 -0
- package/apps/storefront/node_modules/.vite/deps/preact_compat.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/preact_compat_jsx-runtime.js +4 -0
- package/apps/storefront/node_modules/.vite/deps/preact_debug.js +236 -0
- package/apps/storefront/node_modules/.vite/deps/preact_debug.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/preact_devtools.js +12 -0
- package/apps/storefront/node_modules/.vite/deps/preact_devtools.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/preact_hooks.js +192 -0
- package/apps/storefront/node_modules/.vite/deps/preact_hooks.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/preact_jsx-dev-runtime.js +3 -0
- package/apps/storefront/node_modules/.vite/deps/preact_jsx-runtime.js +92 -0
- package/apps/storefront/node_modules/.vite/deps/preact_jsx-runtime.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/preact_test-utils.js +59 -0
- package/apps/storefront/node_modules/.vite/deps/preact_test-utils.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/rolldown-runtime-BPOCksWG.js +24 -0
- package/apps/storefront/node_modules/.vite/deps/settings-BVDV0Roj.js +189 -0
- package/apps/storefront/node_modules/.vite/deps/settings-BVDV0Roj.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/static-html-DveYqwMo.js +13 -0
- package/apps/storefront/node_modules/.vite/deps/static-html-DveYqwMo.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/toolbar-B3VIHCXg.js +458 -0
- package/apps/storefront/node_modules/.vite/deps/toolbar-B3VIHCXg.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/ui-library-BK6ricUd.js +1016 -0
- package/apps/storefront/node_modules/.vite/deps/ui-library-BK6ricUd.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/window-BvxDenKN.js +32 -0
- package/apps/storefront/node_modules/.vite/deps/window-BvxDenKN.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps/xray-YFiRUU0Z.js +113 -0
- package/apps/storefront/node_modules/.vite/deps/xray-YFiRUU0Z.js.map +1 -0
- package/apps/storefront/node_modules/.vite/deps_ssr/_metadata.json +8 -0
- package/apps/storefront/node_modules/.vite/deps_ssr/package.json +3 -0
- package/apps/storefront/src/layouts/Layout.astro +1 -1
- package/apps/storefront/src/lib/apps/registryAccess.ts +45 -0
- package/apps/storefront/src/lib/auth/adminEntry.ts +4 -4
- package/apps/storefront/src/lib/shared/capability.ts +68 -0
- package/apps/storefront/src/lib/shared/developerInvites.ts +1250 -0
- package/apps/storefront/src/lib/shared/invitePreflight.ts +123 -0
- package/apps/storefront/src/lib/webhooks/deliveryEngine.ts +38 -4
- package/apps/storefront/src/lib/webhooks/emit.ts +1 -1
- package/apps/storefront/src/lib/webhooks/getDispatcher.ts +1 -1
- package/apps/storefront/src/pages/api/auth/magic-exchange.ts +1 -1
- package/apps/storefront/src/pages/index.astro +1 -1
- package/apps/storefront/src/pages/products/[handle].astro +1 -1
- package/package.json +1 -1
- package/packages/public-runtime/node_modules/.bin/tsc +43 -0
- package/packages/public-runtime/node_modules/.bin/tsserver +43 -0
- package/packages/public-runtime/node_modules/.bin/vitest +43 -0
- package/pnpm-workspace.yaml +3 -0
- package/scripts/lib/tenant-dirs.mjs +80 -0
- package/scripts/tenant/lint-embeds.mjs +180 -0
- package/scripts/tenant/materialize-tenant-content.mjs +533 -0
- package/scripts/tenant/validate.mjs +837 -0
- package/apps/storefront/scripts/build-v84-clean-clone-standalone.mjs +0 -68
- package/apps/storefront/scripts/deny-v84-clean-clone-standalone-capabilities.mjs +0 -111
- package/apps/storefront/scripts/deny-v84-dogfood-capabilities.mjs +0 -2
- package/apps/storefront/scripts/deny-v84-lifecycle-capabilities.mjs +0 -247
- package/apps/storefront/scripts/dogfood-v84-nonportable-routes.ts +0 -73
- package/apps/storefront/scripts/fixed-v84-native-install-producer.ts +0 -79
- package/apps/storefront/scripts/generated/v84-clean-clone-replay.bundle.mjs +0 -10982
- package/apps/storefront/scripts/import-v84-through-ws2.ts +0 -38
- package/apps/storefront/scripts/initialize-v84-lifecycle-tooling-dependency.ts +0 -2
- package/apps/storefront/scripts/initialize-v84-lifecycle-tooling.ts +0 -4
- package/apps/storefront/scripts/install-v84-native-through-ws1.ts +0 -185
- package/apps/storefront/scripts/prove-clone-isolation.ts +0 -506
- package/apps/storefront/scripts/replay-v84-clean-clone-pass.ts +0 -148
- package/apps/storefront/scripts/replay-v84-clean-clone-standalone.ts +0 -35
- package/apps/storefront/scripts/replay-v84-clean-clone.ts +0 -214
- package/apps/storefront/scripts/run-fixed-v84-native-install-producer.mjs +0 -18
- package/apps/storefront/scripts/run-v84-clone-isolation-proof.mjs +0 -18
- package/apps/storefront/scripts/run-v84-clone-lifecycle-proof.mjs +0 -18
- package/apps/storefront/scripts/run-v84-import-through-ws2-proof.mjs +0 -17
- package/apps/storefront/scripts/run-v84-nonportable-route-dogfood.mjs +0 -15
- package/apps/storefront/scripts/sanitize-v84-proof-environment.mjs +0 -21
- package/apps/storefront/scripts/v84CleanCloneGraphPin.ts +0 -42
- package/apps/storefront/scripts/v84CleanCloneSourceGraph.ts +0 -145
- package/apps/storefront/scripts/validate-v84-clone-lifecycle.ts +0 -18
- package/apps/storefront/src/components/admin/AdminAIWorkflowsTab.astro +0 -531
- package/apps/storefront/src/components/admin/AdminBlogDetailRail.astro +0 -878
- package/apps/storefront/src/components/admin/AdminBlogTab.astro +0 -1435
- package/apps/storefront/src/components/admin/AdminCheckoutSettingsPanel.astro +0 -226
- package/apps/storefront/src/components/admin/AdminCustomersTab.astro +0 -593
- package/apps/storefront/src/components/admin/AdminFulfillmentTab.astro +0 -465
- package/apps/storefront/src/components/admin/AdminIntegrationsTab.astro +0 -105
- package/apps/storefront/src/components/admin/AdminProductsTab.astro +0 -901
- package/apps/storefront/src/components/admin/AdminPublishTab.astro +0 -2983
- package/apps/storefront/src/components/admin/AdminReportingTab.astro +0 -435
- package/apps/storefront/src/components/admin/AdminSettingsTab.astro +0 -782
- package/apps/storefront/src/components/admin/AdminSubscriptionsTab.astro +0 -611
- package/apps/storefront/src/components/admin/orders/OrdersWorkspace.astro +0 -1223
- package/apps/storefront/src/lib/apps/adminService.ts +0 -116
- package/apps/storefront/src/lib/apps/adminSession.ts +0 -214
- package/apps/storefront/src/lib/apps/apiAuth.ts +0 -91
- package/apps/storefront/src/lib/apps/apiRoute.ts +0 -35
- package/apps/storefront/src/lib/apps/catalogMapper.ts +0 -39
- package/apps/storefront/src/lib/apps/consentConfigStore.ts +0 -228
- package/apps/storefront/src/lib/apps/gtmMigrationInstall.ts +0 -447
- package/apps/storefront/src/lib/apps/gtmMigrationReport.ts +0 -367
- package/apps/storefront/src/lib/apps/gtmMigrationTab.ts +0 -315
- package/apps/storefront/src/lib/apps/healthAggregate.ts +0 -66
- package/apps/storefront/src/lib/apps/integrationLifecycle.ts +0 -614
- package/apps/storefront/src/lib/apps/integrationLifecycleController.ts +0 -125
- package/apps/storefront/src/lib/apps/integrationReadModel.ts +0 -563
- package/apps/storefront/src/lib/apps/integrationsTab.ts +0 -547
- package/apps/storefront/src/lib/apps/integrationsView.ts +0 -106
- package/apps/storefront/src/lib/apps/managedAnalyticsService.ts +0 -599
- package/apps/storefront/src/lib/apps/tenantIntegrationMaterialization.ts +0 -170
- package/apps/storefront/src/lib/apps/tokenIssuer.ts +0 -121
- package/apps/storefront/src/lib/apps/tokenVerifier.ts +0 -148
- package/apps/storefront/src/lib/apps/v84CleanCloneReplayContext.ts +0 -16
- package/apps/storefront/src/lib/apps/v84CloneLifecycleCacheEvidence.ts +0 -105
- package/apps/storefront/src/lib/apps/v84CloneLifecycleEvidence.ts +0 -177
- package/apps/storefront/src/lib/apps/v84CloneLifecycleMaterialization.ts +0 -251
- package/apps/storefront/src/lib/apps/v84CloneLifecycleSemantics.ts +0 -241
- package/apps/storefront/src/lib/apps/v84CloneMigrationEvidence.ts +0 -211
- package/apps/storefront/src/lib/apps/v84CloneNativeInstallEvidence.ts +0 -409
- package/apps/storefront/src/lib/apps/v84NonportableCodeCoaching.ts +0 -368
- package/apps/storefront/src/lib/apps/v84NonportableRouteContract.ts +0 -188
- package/apps/storefront/src/lib/apps/v84NonportableRouteDogfood.ts +0 -291
- package/apps/storefront/src/lib/apps/ws1ManagedAnalyticsClient.ts +0 -95
- package/apps/storefront/src/lib/content-edit/applyDiff.ts +0 -91
- package/apps/storefront/src/lib/content-edit/client.ts +0 -286
- package/apps/storefront/src/lib/content-edit/index.ts +0 -14
- package/apps/storefront/src/lib/content-edit/route.ts +0 -25
- package/apps/storefront/src/lib/content-edit/types.ts +0 -19
- package/apps/storefront/src/lib/dev/cockpitStore.ts +0 -57
- package/apps/storefront/src/lib/publish/adminPublishTab.ts +0 -4625
- package/apps/storefront/src/lib/publish/apex-readiness.ts +0 -360
- package/apps/storefront/src/lib/publish/buildStream.ts +0 -269
- package/apps/storefront/src/lib/publish/collapsePersistence.ts +0 -72
- package/apps/storefront/src/lib/publish/dispatchHealth.ts +0 -267
- package/apps/storefront/src/lib/publish/domainState.ts +0 -360
- package/apps/storefront/src/lib/publish/lifecycleState.ts +0 -369
- package/apps/storefront/src/lib/publish/liveReleaseSummary.ts +0 -29
- package/apps/storefront/src/lib/publish/mergeDoctorOnFailure.ts +0 -78
- package/apps/storefront/src/lib/publish/mergeHealthBanner.ts +0 -62
- package/apps/storefront/src/lib/publish/mergeRowFindings.ts +0 -124
- package/apps/storefront/src/lib/publish/mergeSupportEscalation.ts +0 -75
- package/apps/storefront/src/lib/publish/panelPolling.ts +0 -78
- package/apps/storefront/src/lib/publish/publish-guard.ts +0 -88
- package/apps/storefront/src/lib/publish/publishFormat.ts +0 -165
- package/apps/storefront/src/lib/publish/publishHero.ts +0 -177
- package/apps/storefront/src/lib/publish/reviewRelease/changeState.ts +0 -66
- package/apps/storefront/src/lib/publish/reviewRelease/copy.ts +0 -141
- package/apps/storefront/src/lib/publish/reviewRelease/index.ts +0 -41
- package/apps/storefront/src/lib/publish/reviewRelease/permissions.ts +0 -47
- package/apps/storefront/src/lib/publish/reviewRelease/releaseState.ts +0 -42
- package/apps/storefront/src/lib/publish/reviewRelease/types.ts +0 -59
- package/apps/storefront/src/lib/publish/reviewRelease/viewModel.ts +0 -440
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/actions.ts +0 -161
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/controller.ts +0 -325
- package/apps/storefront/src/lib/publish/reviewReleaseWorkspace/render.ts +0 -241
- package/apps/storefront/src/lib/publish/shipWorkspace.ts +0 -439
- package/apps/storefront/src/lib/publish/sseRoute.ts +0 -119
- package/apps/storefront/src/lib/publish/stageBundleUpload.ts +0 -215
- package/apps/storefront/src/lib/publish/streamLogConsole.ts +0 -142
- package/apps/storefront/src/lib/publish/versionNumber.ts +0 -52
- package/apps/storefront/src/pages/admin/ops-timeline.astro +0 -420
- package/apps/storefront/src/pages/admin/review-release.astro +0 -265
- package/apps/storefront/src/pages/admin/select.astro +0 -96
- package/apps/storefront/src/pages/admin.astro +0 -570
- package/apps/storefront/src/pages/api/apps/admin/credentials/rotate.ts +0 -86
- package/apps/storefront/src/pages/api/apps/admin/gtm-migration-install.ts +0 -174
- package/apps/storefront/src/pages/api/apps/admin/gtm-migration.ts +0 -96
- package/apps/storefront/src/pages/api/apps/admin/health.ts +0 -44
- package/apps/storefront/src/pages/api/apps/admin/install.ts +0 -125
- package/apps/storefront/src/pages/api/apps/admin/integration-lifecycle.ts +0 -118
- package/apps/storefront/src/pages/api/apps/admin/integrations.ts +0 -89
- package/apps/storefront/src/pages/api/apps/admin/list.ts +0 -26
- package/apps/storefront/src/pages/api/apps/admin/platform-adapters.ts +0 -85
- package/apps/storefront/src/pages/api/apps/admin/resume.ts +0 -79
- package/apps/storefront/src/pages/api/apps/admin/suspend.ts +0 -80
- package/apps/storefront/src/pages/api/apps/admin/uninstall.ts +0 -98
- package/apps/storefront/src/pages/api/apps/admin/update.ts +0 -126
- package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries/[deliveryId]/replay.ts +0 -70
- package/apps/storefront/src/pages/api/apps/admin/webhooks/deliveries.ts +0 -51
- package/apps/storefront/src/pages/api/apps/internal/order-forward.ts +0 -255
- package/apps/storefront/src/pages/api/apps/oauth/token.ts +0 -87
- package/apps/storefront/src/pages/api/apps/v1/attribution.ts +0 -162
- package/apps/storefront/src/pages/api/apps/v1/catalog/products/[handle].ts +0 -39
- package/apps/storefront/src/pages/api/apps/v1/catalog/products.ts +0 -49
- package/apps/storefront/src/pages/api/apps/v1/health.ts +0 -32
- package/apps/storefront/src/pages/api/apps/v1/inventory.ts +0 -59
- package/apps/storefront/src/pages/api/apps/v1/orders/[id].ts +0 -48
- package/apps/storefront/src/pages/api/apps/v1/orders.ts +0 -73
- package/apps/storefront/src/pages/api/apps/v1/reports.ts +0 -21
- package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries/[deliveryId]/replay.ts +0 -74
- package/apps/storefront/src/pages/api/apps/v1/webhooks/deliveries.ts +0 -47
- package/apps/storefront/src/pages/api/cache-purge.ts +0 -55
- package/apps/storefront/src/pages/api/compliance/tamper.ts +0 -88
- package/apps/storefront/src/pages/api/content-edit/ai-edit.ts +0 -164
- package/apps/storefront/src/pages/api/dashboard/enter-vendor.ts +0 -154
- package/apps/storefront/src/pages/api/dashboard/vendor-search.ts +0 -120
- package/apps/storefront/src/pages/api/integrations/v1/[operation].ts +0 -108
- package/apps/storefront/src/pages/api/publish/stage-bundle.ts +0 -70
- package/apps/storefront/src/pages/api/test/dev-session.ts +0 -133
- package/apps/storefront/src/pages/cockpit.astro +0 -1548
- package/apps/storefront/src/pages/dashboard/[appDomain]/apps/index.astro +0 -119
- package/apps/storefront/src/pages/dashboard/[appDomain]/index.astro +0 -105
- package/apps/storefront/src/pages/dashboard/[appDomain]/team.astro +0 -177
- package/apps/storefront/src/pages/dashboard/index.astro +0 -160
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Offline dogfood of the eight v84 nonportable-code dispositions.
|
|
3
|
-
*
|
|
4
|
-
* This module sees only reviewed, redacted dossier metadata. It can emit typed
|
|
5
|
-
* semantic events into an in-memory callback, evaluate a pure path mapping, or
|
|
6
|
-
* record an inert retirement. It has no destination, browser, renderer,
|
|
7
|
-
* persistence, network, install, publish, or source-tenant capability.
|
|
8
|
-
*/
|
|
9
|
-
import {
|
|
10
|
-
CONSENT_CONFIG_SCHEMA_VERSION,
|
|
11
|
-
CommerceEventBroker,
|
|
12
|
-
ManagedAnalyticsEventBrokerBridge,
|
|
13
|
-
buildTenantConsentBroker,
|
|
14
|
-
validateConsentConfig,
|
|
15
|
-
validateTenantActionRegistry,
|
|
16
|
-
type CommerceEvent,
|
|
17
|
-
} from "@tot/public-runtime";
|
|
18
|
-
import type {
|
|
19
|
-
V84NonportableCodeIntentDossier,
|
|
20
|
-
} from "./v84NonportableCodeCoaching.js";
|
|
21
|
-
import type { V84CloneMigrationEvidence } from "./v84CloneMigrationEvidence.js";
|
|
22
|
-
import { assertExactV84DogfoodContract } from "./v84NonportableRouteContract.js";
|
|
23
|
-
import {
|
|
24
|
-
sameV84ReplayValue,
|
|
25
|
-
type V84CleanCloneReplayContext,
|
|
26
|
-
} from "./v84CleanCloneReplayContext.js";
|
|
27
|
-
|
|
28
|
-
const SOURCE = "tokenoftrust.com" as const;
|
|
29
|
-
const CLONE = "tokenoftrust.com~clone~gtm-migration-v84" as const;
|
|
30
|
-
const AT = "2026-08-30T00:00:00.000Z";
|
|
31
|
-
const CORRELATION = { id: "corr-v84-nonportable-dogfood", expiresAt: "2026-08-30T02:00:00.000Z" };
|
|
32
|
-
const PROTECTED = ["admin", "account", "identity", "age-assurance", "checkout", "payment"] as const;
|
|
33
|
-
|
|
34
|
-
export type V84DogfoodOutcome = "converted" | "retired" | "evidence-rejected";
|
|
35
|
-
|
|
36
|
-
export interface V84DogfoodLedgerRow {
|
|
37
|
-
readonly identity: string;
|
|
38
|
-
readonly intent: string;
|
|
39
|
-
readonly route: string;
|
|
40
|
-
readonly attemptedSteps: readonly string[];
|
|
41
|
-
readonly artifact: Readonly<Record<string, unknown>>;
|
|
42
|
-
readonly expectedVersusActual: { readonly expected: string; readonly actual: string };
|
|
43
|
-
readonly testsAndCloneQa: readonly string[];
|
|
44
|
-
readonly rollbackProof: string;
|
|
45
|
-
readonly finalOutcome: V84DogfoodOutcome;
|
|
46
|
-
readonly productRunbookGap: string | null;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function consentBroker() {
|
|
50
|
-
const checked = validateConsentConfig({
|
|
51
|
-
schemaVersion: CONSENT_CONFIG_SCHEMA_VERSION,
|
|
52
|
-
purposes: [{ purpose: "analytics", legalBasis: "consent", defaultState: "denied" }],
|
|
53
|
-
cmp: { mode: "none" },
|
|
54
|
-
});
|
|
55
|
-
if (!checked.ok) throw new Error("The fixed local consent policy is invalid.");
|
|
56
|
-
const broker = buildTenantConsentBroker(checked.value);
|
|
57
|
-
broker.setDecisions({ analytics: "granted" });
|
|
58
|
-
return broker;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function vendorAdapterId(dossier: V84NonportableCodeIntentDossier): string {
|
|
62
|
-
const ids: Readonly<Record<string, string>> = {
|
|
63
|
-
"tag:4": "platform.hubspot",
|
|
64
|
-
"tag:18": "platform.capterra",
|
|
65
|
-
"tag:29": "platform.linkedin",
|
|
66
|
-
"tag:31": "platform.g2",
|
|
67
|
-
};
|
|
68
|
-
const adapterId = ids[dossier.sourceObject.nodeKey];
|
|
69
|
-
if (!adapterId) throw new Error("The vendor destination route is not reviewed.");
|
|
70
|
-
return adapterId;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function exerciseNativeHook(dossier: V84NonportableCodeIntentDossier) {
|
|
74
|
-
const catalogLookup = { adapterId: vendorAdapterId(dossier), found: false } as const;
|
|
75
|
-
if (dossier.requiredContract.actionSelection === "owner-selection-required") {
|
|
76
|
-
return {
|
|
77
|
-
kind: "native-contract-refusal",
|
|
78
|
-
hook: dossier.recommendedTotPort.nativeHook,
|
|
79
|
-
approvedChoices: [...dossier.requiredContract.approvedActionNames],
|
|
80
|
-
deliveryCount: 0,
|
|
81
|
-
reason: "owner-action-selection-required",
|
|
82
|
-
catalogLookup,
|
|
83
|
-
} as const;
|
|
84
|
-
}
|
|
85
|
-
const registry = validateTenantActionRegistry({
|
|
86
|
-
schemaVersion: 1,
|
|
87
|
-
actions: dossier.requiredContract.approvedActionNames.map((name) => ({ name })),
|
|
88
|
-
});
|
|
89
|
-
if (!registry.ok) throw new Error("The dossier action contract is invalid.");
|
|
90
|
-
const consent = consentBroker();
|
|
91
|
-
const delivered: CommerceEvent[] = [];
|
|
92
|
-
const broker = new CommerceEventBroker({
|
|
93
|
-
trusted: { tenant: CLONE, environment: "candidate", siteSurface: "marketing" },
|
|
94
|
-
source: `urn:tot:storefront:v84-dogfood:${dossier.dossierId}`,
|
|
95
|
-
consentSnapshot: () => consent.getSnapshot(),
|
|
96
|
-
tenantActionRegistry: registry.value,
|
|
97
|
-
now: () => AT,
|
|
98
|
-
});
|
|
99
|
-
broker.subscribe({
|
|
100
|
-
id: `fake-local-${dossier.dossierId}`,
|
|
101
|
-
consentPurpose: "analytics",
|
|
102
|
-
types: dossier.recommendedTotPort.nativeHook ? [dossier.recommendedTotPort.nativeHook] : [],
|
|
103
|
-
sink: { kind: "callback", handler: (event) => delivered.push(event) },
|
|
104
|
-
});
|
|
105
|
-
const bridge = new ManagedAnalyticsEventBrokerBridge({ broker });
|
|
106
|
-
let results;
|
|
107
|
-
if (dossier.recommendedTotPort.nativeHook === "storefront.action.activated.v1") {
|
|
108
|
-
const initialized = bridge.initialize({ logicalId: `${dossier.dossierId}-document`, path: "/v84-dogfood", correlation: CORRELATION });
|
|
109
|
-
if (!initialized.ok || !initialized.emitted) throw new Error("The local action bridge did not initialize safely.");
|
|
110
|
-
results = dossier.requiredContract.approvedActionNames.map((name, index) =>
|
|
111
|
-
bridge.activate({ logicalId: `${dossier.dossierId}-action-${index + 1}`, name, correlation: CORRELATION }));
|
|
112
|
-
} else {
|
|
113
|
-
results = [bridge.initialize({ logicalId: dossier.dossierId, path: "/v84-dogfood", correlation: CORRELATION })];
|
|
114
|
-
}
|
|
115
|
-
bridge.dispose();
|
|
116
|
-
if (results.some((result) => !result.ok || !result.emitted) || delivered.length !== results.length) {
|
|
117
|
-
throw new Error("The local native-hook exercise did not deliver the exact typed event set.");
|
|
118
|
-
}
|
|
119
|
-
if (delivered.some((event) => event.storefront.tenant !== CLONE || event.storefront.environment === "live")) {
|
|
120
|
-
throw new Error("The local native-hook exercise escaped the diagnostic clone.");
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
kind: "in-memory-native-event-proof",
|
|
124
|
-
hook: delivered[0]?.type,
|
|
125
|
-
payloads: delivered.map((event) => event.data),
|
|
126
|
-
payloadKeys: [...new Set(delivered.flatMap((event) => Object.keys(event.data)))].sort(),
|
|
127
|
-
deliveryCount: delivered.length,
|
|
128
|
-
destination: "fake-local-callback",
|
|
129
|
-
disposed: true,
|
|
130
|
-
catalogLookup,
|
|
131
|
-
} as const;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function retire(dossier: V84NonportableCodeIntentDossier, replayContext?: V84CleanCloneReplayContext) {
|
|
135
|
-
if (dossier.recommendedTotPort.nativeHook !== null) {
|
|
136
|
-
throw new Error("A retirement dossier unexpectedly requested runtime authority.");
|
|
137
|
-
}
|
|
138
|
-
const cloneLocalMarkers = new Set<string>();
|
|
139
|
-
const marker = `${CLONE}:retired:${dossier.sourceObject.nodeKey}`;
|
|
140
|
-
const markerKey = `stage/dogfood/retirement/${dossier.sourceObject.nodeKey}`;
|
|
141
|
-
if (replayContext) replayContext.write(markerKey, marker);
|
|
142
|
-
else cloneLocalMarkers.add(marker);
|
|
143
|
-
const markerObserved = replayContext
|
|
144
|
-
? replayContext.read<string>(markerKey) === marker
|
|
145
|
-
: cloneLocalMarkers.has(marker);
|
|
146
|
-
if (replayContext) replayContext.delete(markerKey);
|
|
147
|
-
else cloneLocalMarkers.delete(marker);
|
|
148
|
-
const markerRemoved = replayContext
|
|
149
|
-
? replayContext.read<string>(markerKey) === undefined
|
|
150
|
-
: !cloneLocalMarkers.has(marker);
|
|
151
|
-
if (!markerObserved || !markerRemoved) throw new Error("The inert retirement marker was not reversible.");
|
|
152
|
-
return {
|
|
153
|
-
kind: "inert-retirement-record",
|
|
154
|
-
retained: { nodeKey: dossier.sourceObject.nodeKey, dossierId: dossier.dossierId },
|
|
155
|
-
runtimeAuthority: "none",
|
|
156
|
-
installCreated: false,
|
|
157
|
-
markerObserved,
|
|
158
|
-
markerRemoved,
|
|
159
|
-
} as const;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
function rejectedGap(dossier: V84NonportableCodeIntentDossier): string {
|
|
163
|
-
if (dossier.sourceObject.nodeKey === "variable:38") {
|
|
164
|
-
return "consumer decision required: name the consumer and approve a closed output enum before conversion";
|
|
165
|
-
}
|
|
166
|
-
const gap = dossier.recommendedTotPort.owningProductGap;
|
|
167
|
-
if (!gap) throw new Error("A non-retirement route lacks an exact owning-product gap.");
|
|
168
|
-
const ownerGap = dossier.requiredContract.actionSelection === "owner-selection-required"
|
|
169
|
-
? "; consumer owner must select one approved action name"
|
|
170
|
-
: "";
|
|
171
|
-
return `owning product capability unavailable: ${gap}${ownerGap}`;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function exercise(
|
|
175
|
-
dossier: V84NonportableCodeIntentDossier,
|
|
176
|
-
replayContext?: V84CleanCloneReplayContext,
|
|
177
|
-
): V84DogfoodLedgerRow {
|
|
178
|
-
if (dossier.recommendedTotPort.route === "retire") {
|
|
179
|
-
return {
|
|
180
|
-
identity: dossier.sourceObject.nodeKey,
|
|
181
|
-
intent: dossier.recoveredBusinessIntent,
|
|
182
|
-
route: "retire",
|
|
183
|
-
attemptedSteps: ["matched the exact redacted identity and graph role", "asserted no native hook", "created and observed a clone-local inert marker", "removed the marker"],
|
|
184
|
-
artifact: retire(dossier, replayContext),
|
|
185
|
-
expectedVersusActual: {
|
|
186
|
-
expected: "retain audit identity with zero runtime behavior",
|
|
187
|
-
actual: "inert retirement recorded; no install, hook, destination, or runtime authority created",
|
|
188
|
-
},
|
|
189
|
-
testsAndCloneQa: ["identity accounted once", "dependency graph checked", "marker observed then removed", "no hook requested", "clone effect counters remain zero"],
|
|
190
|
-
rollbackProof: "No runtime state exists to restore; removing the inert record leaves behavior unchanged.",
|
|
191
|
-
finalOutcome: "retired",
|
|
192
|
-
productRunbookGap: null,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
const isMapping = dossier.recommendedTotPort.route === "declarative-typed-mapping";
|
|
196
|
-
const artifact = isMapping ? {
|
|
197
|
-
kind: "declarative-conversion-refusal",
|
|
198
|
-
observedGraph: { consumer: "trigger:39", variable: "variable:38", consumingTagCount: 0 },
|
|
199
|
-
mappingCreated: false,
|
|
200
|
-
reason: "named-consumer-and-output-enum-unresolved",
|
|
201
|
-
} as const : exerciseNativeHook(dossier);
|
|
202
|
-
const gap = rejectedGap(dossier);
|
|
203
|
-
return {
|
|
204
|
-
identity: dossier.sourceObject.nodeKey,
|
|
205
|
-
intent: dossier.recoveredBusinessIntent,
|
|
206
|
-
route: dossier.recommendedTotPort.route,
|
|
207
|
-
attemptedSteps: isMapping
|
|
208
|
-
? ["verified trigger:39 references variable:38", "verified no tag consumes trigger:39", "looked for a named consumer and approved output enum", "refused to invent a mapping"]
|
|
209
|
-
: dossier.requiredContract.actionSelection === "owner-selection-required"
|
|
210
|
-
? ["validated the closed action choice set", "refused to choose for the owner", "confirmed zero delivery", "looked up the owned destination"]
|
|
211
|
-
: ["validated the closed native event contract", "granted local analytics consent", "delivered the exact typed event set to an in-memory callback", "disposed the bridge", "looked up the owned destination"],
|
|
212
|
-
artifact,
|
|
213
|
-
expectedVersusActual: {
|
|
214
|
-
expected: dossier.recommendedTotPort.saferAlternative,
|
|
215
|
-
actual: dossier.requiredContract.actionSelection === "owner-selection-required"
|
|
216
|
-
? `closed choice set validated with zero emission; exercise stopped: ${gap}`
|
|
217
|
-
: isMapping
|
|
218
|
-
? `no mapping was created; exercise stopped: ${gap}`
|
|
219
|
-
: `safe local native contract exercise passed, but conversion stopped: ${gap}`,
|
|
220
|
-
},
|
|
221
|
-
testsAndCloneQa: isMapping
|
|
222
|
-
? ["exact graph edge is present", "consumer tag count is zero", "no mapping or destination effect exists"]
|
|
223
|
-
: dossier.requiredContract.actionSelection === "owner-selection-required"
|
|
224
|
-
? ["all approved choices retained", "zero events emitted before owner selection", "managed vendor adapter absent"]
|
|
225
|
-
: ["typed payload set delivered exactly once each", "clone tenant and candidate environment pinned", "fake callback disposed", "protected surfaces excluded"],
|
|
226
|
-
rollbackProof: isMapping
|
|
227
|
-
? "Discarding the refusal artifact leaves the prior no-mapping state unchanged; no consumer was connected."
|
|
228
|
-
: dossier.requiredContract.actionSelection === "owner-selection-required"
|
|
229
|
-
? "No subscriber, event, install, or destination state was created before the required owner decision."
|
|
230
|
-
: "Disposal removes the only in-memory subscriber; no install or destination state exists.",
|
|
231
|
-
finalOutcome: "evidence-rejected",
|
|
232
|
-
productRunbookGap: gap,
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/** Exercise every reviewed route and return a terminal eight-row ledger. */
|
|
237
|
-
export function buildV84NonportableRouteDogfood(
|
|
238
|
-
evidence: V84CloneMigrationEvidence,
|
|
239
|
-
catalogAdapterIds: readonly string[],
|
|
240
|
-
replayContext?: V84CleanCloneReplayContext,
|
|
241
|
-
) {
|
|
242
|
-
if (replayContext && !sameV84ReplayValue(
|
|
243
|
-
replayContext.read<V84CloneMigrationEvidence>("stage/import/handoff"),
|
|
244
|
-
evidence,
|
|
245
|
-
)) {
|
|
246
|
-
throw new Error("The dogfood proof did not receive the shared import handoff.");
|
|
247
|
-
}
|
|
248
|
-
const safe = assertExactV84DogfoodContract(evidence, catalogAdapterIds);
|
|
249
|
-
const coaching = safe.evidence.nonportableCodeCoaching;
|
|
250
|
-
if (!coaching.policy.sourceReadOnly || !coaching.policy.importedArtifactsInert || coaching.policy.installsOrPublishes) {
|
|
251
|
-
throw new Error("The coaching policy is outside the inert diagnostic scope.");
|
|
252
|
-
}
|
|
253
|
-
if (coaching.dossiers.length !== 8 || new Set(coaching.dossiers.map((item) => item.sourceObject.nodeKey)).size !== 8) {
|
|
254
|
-
throw new Error("The dogfood gate requires exactly eight unique dossiers.");
|
|
255
|
-
}
|
|
256
|
-
if (coaching.dossiers.some((item) => item.recommendedTotPort.status !== "not-installed")) {
|
|
257
|
-
throw new Error("The dogfood input must be the reviewed pre-install coaching state.");
|
|
258
|
-
}
|
|
259
|
-
const ledger = coaching.dossiers.map((dossier) => exercise(dossier, replayContext));
|
|
260
|
-
if (ledger.some((row) => !["converted", "retired", "evidence-rejected"].includes(row.finalOutcome))) {
|
|
261
|
-
throw new Error("Every dogfood route must end in an explicit terminal outcome.");
|
|
262
|
-
}
|
|
263
|
-
const result = {
|
|
264
|
-
schemaVersion: 1 as const,
|
|
265
|
-
scope: { sourceTenant: SOURCE, sourceMode: "read-only-fixture" as const, cloneTenant: CLONE, destinationMode: "fake-local-only" as const },
|
|
266
|
-
ledger,
|
|
267
|
-
summary: {
|
|
268
|
-
total: ledger.length,
|
|
269
|
-
converted: ledger.filter((row) => row.finalOutcome === "converted").length,
|
|
270
|
-
retired: ledger.filter((row) => row.finalOutcome === "retired").length,
|
|
271
|
-
evidenceRejected: ledger.filter((row) => row.finalOutcome === "evidence-rejected").length,
|
|
272
|
-
unexplainedNotInstalled: 0,
|
|
273
|
-
},
|
|
274
|
-
catalogLookup: {
|
|
275
|
-
presentAdapterIds: [...safe.catalogAdapterIds].sort(),
|
|
276
|
-
requestedVendorAdapterIds: ["platform.hubspot", "platform.capterra", "platform.linkedin", "platform.g2"],
|
|
277
|
-
missingVendorAdapterIds: ["platform.hubspot", "platform.capterra", "platform.linkedin", "platform.g2"],
|
|
278
|
-
},
|
|
279
|
-
safety: {
|
|
280
|
-
sourceReads: 0, sourceWrites: 0, clonePersistentWrites: 0, externalNetworkRequests: 0,
|
|
281
|
-
liveSecretsUsed: 0, productionActions: 0, importedCodeExecuted: false,
|
|
282
|
-
originalMarkupRendered: false, runtimeLoaderInitialized: false, dataLayerTouched: false,
|
|
283
|
-
},
|
|
284
|
-
protectedSurfaces: [...PROTECTED],
|
|
285
|
-
};
|
|
286
|
-
if (replayContext) {
|
|
287
|
-
for (const row of ledger) replayContext.write(`stage/dogfood/artifacts/${row.identity}`, row.artifact);
|
|
288
|
-
replayContext.write("stage/dogfood/handoff", result);
|
|
289
|
-
}
|
|
290
|
-
return result;
|
|
291
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The EDGE transport for the pinned managed-analytics v1 contract: a thin HTTP
|
|
3
|
-
* adapter that satisfies {@link Ws1ManagedAnalyticsClient} by POSTing each
|
|
4
|
-
* pinned request to WS1's lifecycle service and returning the pinned response
|
|
5
|
-
* shape. WS1 owns the actual service; this file only carries the request over
|
|
6
|
-
* the wire.
|
|
7
|
-
*
|
|
8
|
-
* Tenant authority is server-derived, exactly as the pinned contract demands
|
|
9
|
-
* ("no request in this module accepts a tenant id"): the tenant is sent as a
|
|
10
|
-
* server-to-server header alongside the service credential — NEVER in a request
|
|
11
|
-
* body, and NEVER read from the caller's request body. Unconfigured service URL
|
|
12
|
-
* -> `null` (the route answers 503), never a guess.
|
|
13
|
-
*/
|
|
14
|
-
import type { APIContext } from "astro";
|
|
15
|
-
import {
|
|
16
|
-
MANAGED_ANALYTICS_API_V1_VERSION_POLICY,
|
|
17
|
-
type CreateMigrationDraftRequest,
|
|
18
|
-
type CreateMigrationDraftResponse,
|
|
19
|
-
} from "@tot/public-runtime";
|
|
20
|
-
import { readEnv } from "../env.js";
|
|
21
|
-
import type { Ws1ManagedAnalyticsClient } from "./gtmMigrationInstall.js";
|
|
22
|
-
|
|
23
|
-
export interface Ws1ManagedAnalyticsMigrationClient extends Ws1ManagedAnalyticsClient {
|
|
24
|
-
createMigrationDraft(request: CreateMigrationDraftRequest): Promise<CreateMigrationDraftResponse>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type Ws1Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
28
|
-
|
|
29
|
-
/** Base URL of WS1's managed-analytics lifecycle service (scheme + host). */
|
|
30
|
-
const SERVICE_URL_ENV = "MANAGED_ANALYTICS_API_URL";
|
|
31
|
-
/** Server-to-server bearer credential for WS1 (scopes the tenant server-side). */
|
|
32
|
-
const SERVICE_SECRET_ENV = "MANAGED_ANALYTICS_API_SECRET";
|
|
33
|
-
|
|
34
|
-
/** The versioned base path, taken from the pinned version policy — never hard-coded twice. */
|
|
35
|
-
const V1_PATH = MANAGED_ANALYTICS_API_V1_VERSION_POLICY.path;
|
|
36
|
-
|
|
37
|
-
/** POST one pinned request to `<base><v1>/<operation>` and return the parsed pinned response. */
|
|
38
|
-
function post<TReq, TRes>(
|
|
39
|
-
fetchImpl: Ws1Fetch,
|
|
40
|
-
baseUrl: string,
|
|
41
|
-
operation: string,
|
|
42
|
-
headers: Record<string, string>,
|
|
43
|
-
): (request: TReq) => Promise<TRes> {
|
|
44
|
-
return async (request: TReq): Promise<TRes> => {
|
|
45
|
-
const res = await fetchImpl(`${baseUrl}${V1_PATH}/${operation}`, {
|
|
46
|
-
method: "POST",
|
|
47
|
-
headers: { "content-type": "application/json", ...headers },
|
|
48
|
-
body: JSON.stringify(request),
|
|
49
|
-
});
|
|
50
|
-
// WS1 returns the pinned success OR error envelope as JSON for every status.
|
|
51
|
-
return (await res.json()) as TRes;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** Build the tenant-bound public WS1 HTTP client; tests may inject a no-network fetch. */
|
|
56
|
-
export function createWs1ManagedAnalyticsClient(input: {
|
|
57
|
-
readonly baseUrl: string;
|
|
58
|
-
readonly tenantId: string;
|
|
59
|
-
readonly authorization?: string;
|
|
60
|
-
readonly fetchImpl?: Ws1Fetch;
|
|
61
|
-
}): Ws1ManagedAnalyticsMigrationClient {
|
|
62
|
-
const baseUrl = input.baseUrl.replace(/\/$/, "");
|
|
63
|
-
const headers: Record<string, string> = { "x-tot-tenant": input.tenantId };
|
|
64
|
-
if (input.authorization) headers.authorization = input.authorization;
|
|
65
|
-
const fetchImpl = input.fetchImpl ?? fetch;
|
|
66
|
-
return {
|
|
67
|
-
getMigrationDraft: post(fetchImpl, baseUrl, "getMigrationDraft", headers),
|
|
68
|
-
createMigrationDraft: post(fetchImpl, baseUrl, "createMigrationDraft", headers),
|
|
69
|
-
getAdapterDefinition: post(fetchImpl, baseUrl, "getAdapterDefinition", headers),
|
|
70
|
-
getIntegrationInstall: post(fetchImpl, baseUrl, "getIntegrationInstall", headers),
|
|
71
|
-
createIntegrationInstall: post(fetchImpl, baseUrl, "createIntegrationInstall", headers),
|
|
72
|
-
reviseIntegrationInstall: post(fetchImpl, baseUrl, "reviseIntegrationInstall", headers),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Build an HTTP-backed {@link Ws1ManagedAnalyticsClient} for `tenantId`, or
|
|
78
|
-
* `null` when WS1's service URL isn't configured in this runtime. `tenantId`
|
|
79
|
-
* comes from the resolved operator session — never the request body — and is
|
|
80
|
-
* sent as a server-to-server header, keeping every request body tenant-free per
|
|
81
|
-
* the pinned contract.
|
|
82
|
-
*/
|
|
83
|
-
export async function resolveWs1ManagedAnalyticsClient(
|
|
84
|
-
_context: APIContext,
|
|
85
|
-
tenantId: string,
|
|
86
|
-
): Promise<Ws1ManagedAnalyticsClient | null> {
|
|
87
|
-
const baseUrl = (await readEnv(SERVICE_URL_ENV))?.replace(/\/$/, "");
|
|
88
|
-
if (!baseUrl) return null;
|
|
89
|
-
const secret = await readEnv(SERVICE_SECRET_ENV);
|
|
90
|
-
return createWs1ManagedAnalyticsClient({
|
|
91
|
-
baseUrl,
|
|
92
|
-
tenantId,
|
|
93
|
-
...(secret ? { authorization: `Bearer ${secret}` } : {}),
|
|
94
|
-
});
|
|
95
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Apply a unified diff to a source string — the missing half of the content_edit wire
|
|
3
|
-
* contract. tot-mcp's `content_edit` returns per-file unified DIFFS (`--- a/…` /
|
|
4
|
-
* `+++ b/…` / `@@` hunks), not updated contents; to materialize a draft artifact
|
|
5
|
-
* the storefront must re-apply the diff to the
|
|
6
|
-
* exact content it sent.
|
|
7
|
-
*
|
|
8
|
-
* STRICT + FAIL-CLOSED by design: every hunk's context and deletion lines must match
|
|
9
|
-
* the source exactly at the stated position (no fuzz, no offset search). Any mismatch
|
|
10
|
-
* throws {@link DiffApplyError} and the caller writes NOTHING — a wrong-base apply must
|
|
11
|
-
* never silently corrupt a draft. This is safe because we apply to the same string we
|
|
12
|
-
* handed content_edit moments earlier; a mismatch means the model produced a bad diff.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
export class DiffApplyError extends Error {
|
|
16
|
-
constructor(message: string) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.name = "DiffApplyError";
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface Hunk {
|
|
23
|
-
/** 1-based start line in the ORIGINAL content (0 allowed for empty-file inserts). */
|
|
24
|
-
oldStart: number;
|
|
25
|
-
/** Body lines: " " context, "-" deletion, "+" addition. */
|
|
26
|
-
lines: string[];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const HUNK_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;
|
|
30
|
-
|
|
31
|
-
function parseHunks(diff: string): Hunk[] {
|
|
32
|
-
const hunks: Hunk[] = [];
|
|
33
|
-
let current: Hunk | null = null;
|
|
34
|
-
for (const raw of diff.split("\n")) {
|
|
35
|
-
const m = HUNK_RE.exec(raw);
|
|
36
|
-
if (m) {
|
|
37
|
-
current = { oldStart: parseInt(m[1] ?? "0", 10), lines: [] };
|
|
38
|
-
hunks.push(current);
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (!current) continue; // header lines (--- / +++ / diff --git) before the first hunk
|
|
42
|
-
if (raw === "" || raw === "\") continue;
|
|
43
|
-
const tag = raw[0];
|
|
44
|
-
if (tag === " " || tag === "-" || tag === "+") current.lines.push(raw);
|
|
45
|
-
else current = null; // trailing junk / next file header — stop collecting
|
|
46
|
-
}
|
|
47
|
-
return hunks;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Apply `diff` (unified format) to `source`; returns the patched string. Throws
|
|
52
|
-
* {@link DiffApplyError} on any malformed hunk or context mismatch. A diff with no
|
|
53
|
-
* hunks returns the source unchanged.
|
|
54
|
-
*/
|
|
55
|
-
export function applyUnifiedDiff(source: string, diff: string): string {
|
|
56
|
-
const hunks = parseHunks(diff);
|
|
57
|
-
if (hunks.length === 0) return source;
|
|
58
|
-
|
|
59
|
-
const src = source.split("\n");
|
|
60
|
-
const out: string[] = [];
|
|
61
|
-
// Cursor into src (0-based) of the next line not yet copied to out.
|
|
62
|
-
let cursor = 0;
|
|
63
|
-
|
|
64
|
-
for (const hunk of hunks) {
|
|
65
|
-
// oldStart is 1-based; a 0 means "insert into an empty file" (keep cursor).
|
|
66
|
-
const start = Math.max(hunk.oldStart - 1, 0);
|
|
67
|
-
if (start < cursor) throw new DiffApplyError("hunks overlap or are out of order");
|
|
68
|
-
if (start > src.length) throw new DiffApplyError("hunk start beyond end of content");
|
|
69
|
-
out.push(...src.slice(cursor, start));
|
|
70
|
-
cursor = start;
|
|
71
|
-
|
|
72
|
-
for (const line of hunk.lines) {
|
|
73
|
-
const tag = line[0];
|
|
74
|
-
const text = line.slice(1);
|
|
75
|
-
if (tag === "+") {
|
|
76
|
-
out.push(text);
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
// context (" ") and deletion ("-") must match the source exactly.
|
|
80
|
-
if (cursor >= src.length || src[cursor] !== text) {
|
|
81
|
-
throw new DiffApplyError(
|
|
82
|
-
`context mismatch at line ${cursor + 1}: expected ${JSON.stringify(text)}, found ${JSON.stringify(src[cursor] ?? "<eof>")}`,
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
if (tag === " ") out.push(text);
|
|
86
|
-
cursor++;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
out.push(...src.slice(cursor));
|
|
90
|
-
return out.join("\n");
|
|
91
|
-
}
|