@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,286 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JsonRpcContentEditClient — the storefront's server-to-server caller for
|
|
3
|
-
* tot-mcp's `content_edit` tool (the inline-AI edit loop, WS5 G1). Mirrors
|
|
4
|
-
* {@link JsonRpcChangeClient} exactly (same transport, same session-validation,
|
|
5
|
-
* same tool-result unwrap, same typed errors) — reusing the forge seam's
|
|
6
|
-
* exported transport + error types so there is ONE wire contract, not two.
|
|
7
|
-
*
|
|
8
|
-
* AUTH SHAPE (Option A, `content-edit-machine-identity` — mirrors change/B3):
|
|
9
|
-
* the storefront backend calls `content_edit` with the SAME machine-identity
|
|
10
|
-
* APP token the change/forge clients use — a `client_credentials` +
|
|
11
|
-
* `private_key_jwt` token minted against the MCP's OAuth token endpoint via
|
|
12
|
-
* {@link AppTokenProvider}, attached as Bearer at `initialize` and on every
|
|
13
|
-
* request by {@link FetchTransport} — NOT the retired `credential_validate`
|
|
14
|
-
* handshake and NOT a human `TOT_ACCESS_TOKEN`. Developer-level authorization
|
|
15
|
-
* is, and remains, the caller's job: `/dev`'s own `readViewerSession()` +
|
|
16
|
-
* capability check (BEFORE this client is ever constructed) derives the
|
|
17
|
-
* tenant from the signed-in developer's OWN session, never from a
|
|
18
|
-
* caller-supplied value — tenant isolation is enforced there, unaffected by
|
|
19
|
-
* this change. This client only proves "a legitimate storefront backend
|
|
20
|
-
* (machine identity) is asking", the same trust boundary
|
|
21
|
-
* `/api/changes/accept` already relies on post-B3.
|
|
22
|
-
*/
|
|
23
|
-
import {
|
|
24
|
-
FetchTransport,
|
|
25
|
-
ForgeAuthError,
|
|
26
|
-
ForgeConfigError,
|
|
27
|
-
ForgeTransportError,
|
|
28
|
-
SESSION_HEADER,
|
|
29
|
-
AppTokenProvider,
|
|
30
|
-
deriveMcpOauthEndpoints,
|
|
31
|
-
type McpTransport,
|
|
32
|
-
type JsonRpcRequest,
|
|
33
|
-
type TotCredentials,
|
|
34
|
-
type TransportResponse,
|
|
35
|
-
type BearerProvider,
|
|
36
|
-
} from "@/lib/forge";
|
|
37
|
-
import { mapForgeError } from "@/lib/forge/errors.js";
|
|
38
|
-
import { readEnv } from "@/lib/env";
|
|
39
|
-
import type { ContentEditFile, ContentEditResult } from "./types.js";
|
|
40
|
-
|
|
41
|
-
export const CONTENT_EDIT_TOOL = {
|
|
42
|
-
/**
|
|
43
|
-
* Session-validation tool for the NON-OAuth (api-key/secret) construction —
|
|
44
|
-
* kept ONLY for backward-compatible test-transport injection (no
|
|
45
|
-
* bearerProvider). The deployed path never calls this — see the module
|
|
46
|
-
* header.
|
|
47
|
-
*/
|
|
48
|
-
validate: "credential_validate",
|
|
49
|
-
edit: "content_edit",
|
|
50
|
-
} as const;
|
|
51
|
-
|
|
52
|
-
export { SESSION_HEADER } from "@/lib/forge";
|
|
53
|
-
|
|
54
|
-
// --- MCP tool-result envelope (mirrors the change client) -------------------
|
|
55
|
-
|
|
56
|
-
interface McpToolResult {
|
|
57
|
-
content?: Array<{ type?: string; text?: string }>;
|
|
58
|
-
structuredContent?: unknown;
|
|
59
|
-
isError?: boolean;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function parseTextContent(content: McpToolResult["content"]): unknown {
|
|
63
|
-
const text = content?.find((c) => c.type === "text" || c.text != null)?.text;
|
|
64
|
-
if (text == null) return undefined;
|
|
65
|
-
try {
|
|
66
|
-
return JSON.parse(text);
|
|
67
|
-
} catch {
|
|
68
|
-
return text;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function unwrapToolResult<T>(result: unknown): T {
|
|
73
|
-
const env = (result ?? {}) as McpToolResult;
|
|
74
|
-
const payload =
|
|
75
|
-
env.structuredContent !== undefined
|
|
76
|
-
? env.structuredContent
|
|
77
|
-
: parseTextContent(env.content);
|
|
78
|
-
|
|
79
|
-
if (env.isError) {
|
|
80
|
-
const p = (payload ?? {}) as Record<string, unknown>;
|
|
81
|
-
throw mapForgeError({
|
|
82
|
-
code: typeof p.code === "number" ? p.code : undefined,
|
|
83
|
-
message: typeof p.message === "string" ? p.message : "content_edit tool error",
|
|
84
|
-
data: (p.data as Record<string, unknown>) ?? p,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return payload as T;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// --- Config -------------------------------------------------------------
|
|
91
|
-
|
|
92
|
-
export interface JsonRpcContentEditClientConfig {
|
|
93
|
-
/** MCP base URL (the `POST /mcp` endpoint). */
|
|
94
|
-
baseUrl: string;
|
|
95
|
-
/** Storefront's ToT credentials for the legacy `credential_validate` path. */
|
|
96
|
-
credentials: TotCredentials;
|
|
97
|
-
/** Transport override (defaults to fetch). Injected by tests. */
|
|
98
|
-
transport?: McpTransport;
|
|
99
|
-
/**
|
|
100
|
-
* Machine-identity app-token source (mirrors forge's B2 / change's B3,
|
|
101
|
-
* binding `c0-forge-auth-supersede`). When present, the client
|
|
102
|
-
* authenticates PURELY via a `client_credentials` + `private_key_jwt` app
|
|
103
|
-
* token — attached as Bearer at `initialize` and on every request by
|
|
104
|
-
* {@link FetchTransport}, re-minted on expiry/401 — and NEVER calls the
|
|
105
|
-
* retired `credential_validate` handshake. Built by
|
|
106
|
-
* {@link createContentEditClient} from `MCP_BASE_URL`; tests may inject
|
|
107
|
-
* their own {@link BearerProvider}.
|
|
108
|
-
*/
|
|
109
|
-
bearerProvider?: BearerProvider;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// --- The client -----------------------------------------------------------
|
|
113
|
-
|
|
114
|
-
export class JsonRpcContentEditClient {
|
|
115
|
-
private readonly baseUrl: string;
|
|
116
|
-
private readonly credentials: TotCredentials;
|
|
117
|
-
private readonly transport: McpTransport;
|
|
118
|
-
private nextId = 1;
|
|
119
|
-
/** Cached session validation — validate once, reuse (lazily). */
|
|
120
|
-
private sessionPromise?: Promise<string | undefined>;
|
|
121
|
-
/** True when a machine-identity app token authenticates the session (mirrors forge B2 / change B3). */
|
|
122
|
-
private readonly usesServiceAuth: boolean;
|
|
123
|
-
|
|
124
|
-
constructor(config: JsonRpcContentEditClientConfig) {
|
|
125
|
-
if (!config.baseUrl) {
|
|
126
|
-
throw new ForgeConfigError("content-edit: MCP_BASE_URL is not configured");
|
|
127
|
-
}
|
|
128
|
-
if (!config.credentials?.apiKey) {
|
|
129
|
-
throw new ForgeConfigError(
|
|
130
|
-
"content-edit: storefront ToT credentials are not configured",
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
this.baseUrl = config.baseUrl;
|
|
134
|
-
this.credentials = config.credentials;
|
|
135
|
-
this.usesServiceAuth = config.bearerProvider != null;
|
|
136
|
-
this.transport =
|
|
137
|
-
config.transport ?? new FetchTransport(config.baseUrl, config.bearerProvider);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async editContent(
|
|
141
|
-
prompt: string,
|
|
142
|
-
files: readonly ContentEditFile[],
|
|
143
|
-
): Promise<ContentEditResult> {
|
|
144
|
-
const sessionId = await this.ensureSession();
|
|
145
|
-
const result = await this.rpc(
|
|
146
|
-
"tools/call",
|
|
147
|
-
{ name: CONTENT_EDIT_TOOL.edit, arguments: { prompt, files } },
|
|
148
|
-
sessionId,
|
|
149
|
-
);
|
|
150
|
-
return unwrapToolResult<ContentEditResult>(result);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// --- internals (mirror JsonRpcChangeClient) --------------------------------
|
|
154
|
-
|
|
155
|
-
private ensureSession(): Promise<string | undefined> {
|
|
156
|
-
// Service-auth (mirrors forge B2 / change B3 / binding
|
|
157
|
-
// `c0-forge-auth-supersede`): the app token is attached as Bearer at the
|
|
158
|
-
// transport layer (initialize + every request), so the legacy
|
|
159
|
-
// `credential_validate` round-trip is skipped entirely — it was retired
|
|
160
|
-
// MCP-side and would now be rejected. FetchTransport still threads the
|
|
161
|
-
// real `Mcp-Session-Id` the Bearer-authed handshake minted, so a session
|
|
162
|
-
// id is never needed from here. Without a bearerProvider (e.g. an
|
|
163
|
-
// injected mock transport in unit tests) the legacy validate path is kept.
|
|
164
|
-
this.sessionPromise ??= this.usesServiceAuth
|
|
165
|
-
? Promise.resolve(undefined)
|
|
166
|
-
: this.validateSession();
|
|
167
|
-
return this.sessionPromise;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
private async validateSession(): Promise<string | undefined> {
|
|
171
|
-
const args = this.credentialArgs();
|
|
172
|
-
let res: TransportResponse;
|
|
173
|
-
try {
|
|
174
|
-
res = await this.rpcRaw(
|
|
175
|
-
"tools/call",
|
|
176
|
-
{ name: CONTENT_EDIT_TOOL.validate, arguments: args },
|
|
177
|
-
undefined,
|
|
178
|
-
);
|
|
179
|
-
} catch (err) {
|
|
180
|
-
this.sessionPromise = undefined; // let a later call retry
|
|
181
|
-
throw err;
|
|
182
|
-
}
|
|
183
|
-
if (res.body.error) {
|
|
184
|
-
this.sessionPromise = undefined;
|
|
185
|
-
throw new ForgeAuthError(
|
|
186
|
-
res.body.error.message ?? "content-edit: credential validation failed",
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
try {
|
|
190
|
-
const validated = unwrapToolResult<{ session?: string; sessionId?: string }>(
|
|
191
|
-
res.body.result,
|
|
192
|
-
);
|
|
193
|
-
return (
|
|
194
|
-
res.sessionId ?? validated?.session ?? validated?.sessionId ?? undefined
|
|
195
|
-
);
|
|
196
|
-
} catch (err) {
|
|
197
|
-
this.sessionPromise = undefined;
|
|
198
|
-
throw err instanceof ForgeAuthError
|
|
199
|
-
? err
|
|
200
|
-
: new ForgeAuthError("content-edit: credential validation was rejected", {
|
|
201
|
-
cause: err,
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/** Build the credential payload; omits absent secrets. Never logged. */
|
|
207
|
-
private credentialArgs(): Record<string, unknown> {
|
|
208
|
-
const c = this.credentials;
|
|
209
|
-
const out: Record<string, unknown> = { apiKey: c.apiKey };
|
|
210
|
-
if (c.secretKey) out.secretKey = c.secretKey;
|
|
211
|
-
if (c.accessToken) out.accessToken = c.accessToken;
|
|
212
|
-
return out;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private async rpc(
|
|
216
|
-
method: string,
|
|
217
|
-
params: unknown,
|
|
218
|
-
sessionId: string | undefined,
|
|
219
|
-
): Promise<unknown> {
|
|
220
|
-
const res = await this.rpcRaw(method, params, sessionId);
|
|
221
|
-
if (res.body.error) throw mapForgeError(res.body.error);
|
|
222
|
-
return res.body.result;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
private async rpcRaw(
|
|
226
|
-
method: string,
|
|
227
|
-
params: unknown,
|
|
228
|
-
sessionId: string | undefined,
|
|
229
|
-
): Promise<TransportResponse> {
|
|
230
|
-
const headers: Record<string, string> = {};
|
|
231
|
-
if (sessionId) headers[SESSION_HEADER] = sessionId;
|
|
232
|
-
const body: JsonRpcRequest = {
|
|
233
|
-
jsonrpc: "2.0",
|
|
234
|
-
id: this.nextId++,
|
|
235
|
-
method,
|
|
236
|
-
params,
|
|
237
|
-
};
|
|
238
|
-
try {
|
|
239
|
-
return await this.transport.post({ body, headers });
|
|
240
|
-
} catch (err) {
|
|
241
|
-
if (err instanceof ForgeTransportError) throw err;
|
|
242
|
-
throw new ForgeTransportError(
|
|
243
|
-
`content-edit: transport failure calling ${method}`,
|
|
244
|
-
{ cause: err },
|
|
245
|
-
);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// --- Factory ----------------------------------------------------------------
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Build a {@link JsonRpcContentEditClient} from the runtime env — the SAME env
|
|
254
|
-
* the change client reads:
|
|
255
|
-
* - `MCP_BASE_URL` — the `POST /mcp` endpoint (its ORIGIN also hosts the OAuth
|
|
256
|
-
* token endpoint + resource the app token binds to; already `…/storefront`
|
|
257
|
-
* per B4, so the app token's resource + this RPC endpoint match).
|
|
258
|
-
* - `TOT_API_KEY` (+ optional `TOT_SECRET_KEY`) — storefront's OWN ToT
|
|
259
|
-
* credentials (retained for legacy/local paths; the deployed content-edit
|
|
260
|
-
* session no longer uses them for auth).
|
|
261
|
-
*
|
|
262
|
-
* Machine identity (mirrors forge B2 / change B3 / binding
|
|
263
|
-
* `c0-forge-auth-supersede`): the content-edit session authenticates with a
|
|
264
|
-
* `client_credentials` + `private_key_jwt` APP token minted against the MCP's
|
|
265
|
-
* OAuth token endpoint via {@link AppTokenProvider} — NOT a human
|
|
266
|
-
* `TOT_ACCESS_TOKEN` and NOT a shared secret. `TOT_ACCESS_TOKEN` is
|
|
267
|
-
* deliberately NOT read here.
|
|
268
|
-
*
|
|
269
|
-
* Throws {@link ForgeConfigError} when the base URL or api key is missing.
|
|
270
|
-
* Secrets are read via {@link readEnv} and never logged.
|
|
271
|
-
*/
|
|
272
|
-
export async function createContentEditClient(
|
|
273
|
-
overrides: Partial<JsonRpcContentEditClientConfig> = {},
|
|
274
|
-
): Promise<JsonRpcContentEditClient> {
|
|
275
|
-
const baseUrl = overrides.baseUrl ?? (await readEnv("MCP_BASE_URL")) ?? "";
|
|
276
|
-
const credentials =
|
|
277
|
-
overrides.credentials ??
|
|
278
|
-
({
|
|
279
|
-
apiKey: (await readEnv("TOT_API_KEY")) ?? "",
|
|
280
|
-
secretKey: await readEnv("TOT_SECRET_KEY"),
|
|
281
|
-
} satisfies TotCredentials);
|
|
282
|
-
const bearerProvider =
|
|
283
|
-
overrides.bearerProvider ??
|
|
284
|
-
(baseUrl ? new AppTokenProvider(deriveMcpOauthEndpoints(baseUrl)) : undefined);
|
|
285
|
-
return new JsonRpcContentEditClient({ ...overrides, baseUrl, credentials, bearerProvider });
|
|
286
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* content_edit integration — public barrel. Import the typed client and its
|
|
3
|
-
* route helper from here (`@/lib/content-edit`) so call sites never reach into
|
|
4
|
-
* individual files.
|
|
5
|
-
*/
|
|
6
|
-
export type { ContentEditFile, ContentEditFileDiff, ContentEditResult } from "./types.js";
|
|
7
|
-
export {
|
|
8
|
-
JsonRpcContentEditClient,
|
|
9
|
-
createContentEditClient,
|
|
10
|
-
CONTENT_EDIT_TOOL,
|
|
11
|
-
SESSION_HEADER,
|
|
12
|
-
} from "./client.js";
|
|
13
|
-
export type { JsonRpcContentEditClientConfig } from "./client.js";
|
|
14
|
-
export { getContentEditClient } from "./route.js";
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Route helper for `/api/content-edit/ai-edit` — mirrors `@/lib/change/route/route.ts`'s
|
|
3
|
-
* `getChangeClient`: build the env-configured client, or a 503 Response when
|
|
4
|
-
* the MCP integration isn't configured (missing `MCP_BASE_URL`/credentials).
|
|
5
|
-
*/
|
|
6
|
-
import { ForgeError } from "@/lib/forge";
|
|
7
|
-
import { createContentEditClient } from "./client.js";
|
|
8
|
-
import { json } from "@/lib/grants/route.js";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Build a content-edit client over the real MCP from env, or return a 503
|
|
12
|
-
* Response when the integration is not configured. Never leaks secret values.
|
|
13
|
-
*/
|
|
14
|
-
export async function getContentEditClient(): Promise<
|
|
15
|
-
Awaited<ReturnType<typeof createContentEditClient>> | Response
|
|
16
|
-
> {
|
|
17
|
-
try {
|
|
18
|
-
return await createContentEditClient();
|
|
19
|
-
} catch (err) {
|
|
20
|
-
if (err instanceof ForgeError && err.kind === "config") {
|
|
21
|
-
return json({ error: "content_edit integration not configured" }, 503);
|
|
22
|
-
}
|
|
23
|
-
throw err;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/** Wire shape for tot-mcp's `content_edit` tool — mirrors tot-mcp's own
|
|
2
|
-
* ContentFile/ContentFileDiff/ContentEditResult (src/services/content-editor.ts). */
|
|
3
|
-
|
|
4
|
-
export interface ContentEditFile {
|
|
5
|
-
/** e.g. "content/home.html" or "theme.json" — content_edit's own allowlist. */
|
|
6
|
-
path: string;
|
|
7
|
-
content: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface ContentEditFileDiff {
|
|
11
|
-
path: string;
|
|
12
|
-
/** Unified diff (`--- a/<path>` / `+++ b/<path>`) against the given content. */
|
|
13
|
-
diff: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ContentEditResult {
|
|
17
|
-
diffs: ContentEditFileDiff[];
|
|
18
|
-
summary: string;
|
|
19
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* "Which store is this cockpit request about?" — the ONE resolver the hosted
|
|
3
|
-
* cockpit page, its /api/dev/* routes, and the CLI sign-in-code mint all share, so
|
|
4
|
-
* they never disagree about the developer's store.
|
|
5
|
-
*
|
|
6
|
-
* Rule: the URL wins WHEN THE VIEWER CAN ACCESS IT. The middleware has already
|
|
7
|
-
* resolved the request's host/path to `locals.tenant` (the trusted, authenticated
|
|
8
|
-
* store seam — never client body input), so when that is a SPECIFIC store (not the
|
|
9
|
-
* public marketing home) and the signed-in developer holds a membership for it (or a
|
|
10
|
-
* live staff admission), that store is authoritative. Otherwise we fall back to the
|
|
11
|
-
* session's own first store (the generic-host `/cockpit` case), and for an
|
|
12
|
-
* anonymous viewer to the path store's branding, else the caller-supplied `?tenant=`.
|
|
13
|
-
*
|
|
14
|
-
* Access is gated with the SAME primitive (`viewerCanAccess`) the vendor dashboard
|
|
15
|
-
* uses, so a developer can never steer the mint at a store they don't belong to; a
|
|
16
|
-
* store they can't access simply falls through to their own.
|
|
17
|
-
*/
|
|
18
|
-
import type { APIContext } from "astro";
|
|
19
|
-
import type { SessionRecord } from "@/lib/auth/session";
|
|
20
|
-
import { PUBLIC_HOME_TENANT_ID } from "@/lib/auth/loginGate";
|
|
21
|
-
import { viewerCanAccess, type StaffAdmission } from "@/lib/dashboard/tenantSelection";
|
|
22
|
-
|
|
23
|
-
/** The request's host/path-resolved store resource, or "" when it's the marketing home. */
|
|
24
|
-
function pathStoreResource(context: Pick<APIContext, "locals">): string {
|
|
25
|
-
const t = context.locals?.tenant;
|
|
26
|
-
if (!t || t.tenant_id === PUBLIC_HOME_TENANT_ID) return "";
|
|
27
|
-
return (t.appDomain || t.tenant_id || "").toLowerCase();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Resolve the store this cockpit request is scoped to, as a lowercased resource
|
|
32
|
-
* (appDomain/tenant_id). Empty string when nothing resolves (e.g. anonymous on the
|
|
33
|
-
* generic host with no `?tenant=`).
|
|
34
|
-
*/
|
|
35
|
-
export function resolveCockpitStoreResource(
|
|
36
|
-
context: Pick<APIContext, "locals" | "url">,
|
|
37
|
-
session: SessionRecord | null,
|
|
38
|
-
): string {
|
|
39
|
-
const pathStore = pathStoreResource(context);
|
|
40
|
-
|
|
41
|
-
if (session) {
|
|
42
|
-
// The URL wins when the signed-in developer can actually access that store.
|
|
43
|
-
if (pathStore) {
|
|
44
|
-
const staff: StaffAdmission | undefined = session.staffSelection
|
|
45
|
-
? { selection: session.staffSelection, nowSeconds: Math.floor(Date.now() / 1000) }
|
|
46
|
-
: undefined;
|
|
47
|
-
if (viewerCanAccess(session.tenants, pathStore, staff)) return pathStore;
|
|
48
|
-
}
|
|
49
|
-
// Generic host, or a store the viewer doesn't belong to: their own first store.
|
|
50
|
-
return (session.tenants?.[0]?.resource ?? session.resource ?? "").toLowerCase();
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Anonymous: the path store is just branding (no privileged mint happens), else the
|
|
54
|
-
// caller-supplied preview hint. Never overrides a signed-in developer (handled above).
|
|
55
|
-
if (pathStore) return pathStore;
|
|
56
|
-
return (context.url?.searchParams.get("tenant") ?? "").toLowerCase();
|
|
57
|
-
}
|