@tokenoftrust/storefront-runner 2.0.16 → 2.0.18
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/env.d.ts +18 -0
- package/apps/storefront/migrations-apps/0012_test_destinations.sql +29 -0
- package/apps/storefront/src/components/blog/ReactionBar.astro +1 -1
- package/apps/storefront/src/components/islands/CheckoutComplianceGate.tsx +365 -49
- package/apps/storefront/src/components/islands/checkoutVerificationFlow.ts +251 -0
- package/apps/storefront/src/config/compliance/rulesets.ts +18 -7
- package/apps/storefront/src/config/devTenantSeed.ts +24 -1
- package/apps/storefront/src/config/evidenceTenantRoster.ts +25 -0
- package/apps/storefront/src/config/publicationSpaceConfig.ts +25 -0
- package/apps/storefront/src/config/resolver.ts +5 -0
- package/apps/storefront/src/config/tenantAnalyticsFiles.ts +43 -0
- package/apps/storefront/src/config/tenants.ts +11 -0
- package/apps/storefront/src/layouts/Layout.astro +5 -1
- package/apps/storefront/src/lib/activity/killSwitch.ts +1 -1
- package/apps/storefront/src/lib/admin/consentSettingsClient.ts +113 -0
- package/apps/storefront/src/lib/apps/consentConfigRead.ts +24 -0
- package/apps/storefront/src/lib/apps/gtmMigrationDraft.ts +103 -0
- package/apps/storefront/src/lib/apps/routeParams.ts +45 -0
- package/apps/storefront/src/lib/auth/loginGate.ts +25 -0
- package/apps/storefront/src/lib/checkoutCommerce.ts +1 -1
- package/apps/storefront/src/lib/compliance/enforcement.ts +25 -3
- package/apps/storefront/src/lib/d1/schema-apps.ts +44 -0
- package/apps/storefront/src/lib/env.ts +13 -111
- package/apps/storefront/src/lib/fixtures/regulated-commerce-truth/index.ts +540 -0
- package/apps/storefront/src/lib/fixtures/ws3-readonly-clone-preflight/index.ts +495 -0
- package/apps/storefront/src/lib/integration/tenantAnalyticsDeclarations.ts +198 -0
- package/apps/storefront/src/lib/monitoring/manifest.ts +1 -1
- package/apps/storefront/src/lib/rawMarketingHtml.ts +9 -1
- package/apps/storefront/src/lib/runtimeEnv.ts +124 -0
- package/apps/storefront/src/lib/verification/totVerificationClient.ts +485 -0
- package/apps/storefront/src/middleware/candidatePin.ts +35 -0
- package/apps/storefront/src/middleware/controlPlane.ts +270 -0
- package/apps/storefront/src/middleware/index.ts +100 -796
- package/apps/storefront/src/middleware/publicRender.ts +43 -0
- package/apps/storefront/src/middleware/renderChain.ts +685 -0
- package/apps/storefront/src/middleware/routeBranch.ts +160 -0
- package/apps/storefront/src/middleware/staticBundle.ts +109 -0
- package/apps/storefront/src/pages/[...slug].astro +1 -0
- package/apps/storefront/src/pages/api/compliance/preflight.ts +179 -2
- package/apps/storefront/src/pages/index.astro +1 -0
- package/apps/storefront/vitest.config.ts +5 -0
- package/package.json +1 -1
- package/packages/public-runtime/package.json +1 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/deliver-test-event-request.schema.json +122 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/get-test-destination-delivery-request.schema.json +79 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/register-test-destination-request.schema.json +93 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/test-destination-delivery.schema.json +106 -0
- package/packages/public-runtime/schemas/managed-analytics/v1/test-destination.schema.json +77 -0
- package/packages/public-runtime/schemas/publication-space/v1/manifest.schema.json +195 -0
- package/packages/public-runtime/schemas/publication-space/v1/normalized-mount.schema.json +80 -0
- package/packages/public-runtime/schemas/publication-space/v1/ref.schema.json +20 -0
- package/packages/public-runtime/schemas/publication-version/v1/pointer.schema.json +28 -0
- package/packages/public-runtime/schemas/publication-version/v1/transition-request.schema.json +44 -0
- package/packages/public-runtime/schemas/publication-version/v1/transition.schema.json +47 -0
- package/packages/public-runtime/schemas/publication-version/v1/version.schema.json +58 -0
- package/packages/public-runtime/src/activity/catalog.ts +1 -1
- package/packages/public-runtime/src/candidate-index.ts +6 -0
- package/packages/public-runtime/src/customization-reconcile.ts +8 -0
- package/packages/public-runtime/src/html-cache-policy.ts +57 -0
- package/packages/public-runtime/src/index.ts +7 -0
- package/packages/public-runtime/src/integration/consent-broker.ts +115 -0
- package/packages/public-runtime/src/integration/interim-bridge.ts +111 -27
- package/packages/public-runtime/src/integration/managed-analytics-api-v1.schemas.ts +65 -0
- package/packages/public-runtime/src/integration/managed-analytics-api-v1.ts +81 -0
- package/packages/public-runtime/src/integration/render-phases.ts +8 -3
- package/packages/public-runtime/src/publication-artifact.ts +203 -0
- package/packages/public-runtime/src/publication-space.ts +853 -0
- package/packages/public-runtime/src/publication-version.ts +587 -0
- package/packages/public-runtime/src/route-tier.ts +257 -0
- package/packages/public-runtime/src/static-bundle.ts +18 -5
- package/packages/public-runtime/src/tenant-assets.ts +85 -17
- package/packages/public-runtime/src/tenant.ts +70 -0
- package/packages/public-runtime/tests/conformance/fake-destination.ts +402 -0
- package/packages/public-runtime/tests/fixtures/publication-spaces/internal.json +32 -0
- package/packages/public-runtime/tests/fixtures/publication-spaces/mounted-public.json +38 -0
- package/packages/public-runtime/tests/fixtures/publication-spaces/normalized-mounts.json +39 -0
- package/packages/public-runtime/tests/fixtures/publication-spaces/ref.json +5 -0
- package/packages/public-runtime/tests/fixtures/publication-spaces/root-public.json +31 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/articles-v1.json +20 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/articles-v2.json +20 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/internal-v1.json +20 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/live-pointer.json +11 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/live-transition-request.json +14 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/live-transition.json +17 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/root-v1.json +20 -0
- package/packages/public-runtime/tests/fixtures/publication-versions/root-v2.json +20 -0
- package/scripts/dev/ai-edit.mjs +16 -3
- package/scripts/dev/port-check.mjs +18 -3
- package/scripts/dev/publish.mjs +26 -3
- package/scripts/tenant/validate.mjs +14 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"versionId": "pv_root-version-0001",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"spaceId": "root",
|
|
6
|
+
"source": {
|
|
7
|
+
"forge": "fixture",
|
|
8
|
+
"repo": "fixture.example",
|
|
9
|
+
"commitSha": "1111111111111111111111111111111111111111"
|
|
10
|
+
},
|
|
11
|
+
"renderer": {
|
|
12
|
+
"contractVersion": "storefront-v1",
|
|
13
|
+
"themeContractVersion": "theme-v1"
|
|
14
|
+
},
|
|
15
|
+
"artifactDigest": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
16
|
+
"createdAt": "2026-09-01T12:00:00.000Z",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"buildId": "build-root-0001"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"versionId": "pv_root-version-0002",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"spaceId": "root",
|
|
6
|
+
"source": {
|
|
7
|
+
"forge": "fixture",
|
|
8
|
+
"repo": "fixture.example",
|
|
9
|
+
"commitSha": "2222222222222222222222222222222222222222"
|
|
10
|
+
},
|
|
11
|
+
"renderer": {
|
|
12
|
+
"contractVersion": "storefront-v1",
|
|
13
|
+
"themeContractVersion": "theme-v1"
|
|
14
|
+
},
|
|
15
|
+
"artifactDigest": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
|
16
|
+
"createdAt": "2026-09-01T12:01:00.000Z",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"buildId": "build-root-0002"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/scripts/dev/ai-edit.mjs
CHANGED
|
@@ -25,6 +25,7 @@ import { createMcpClient } from "../../packages/cli/src/mcp.mjs";
|
|
|
25
25
|
import { resolveDeveloperSession, AuthUnavailableError } from "../../packages/cli/src/auth.mjs";
|
|
26
26
|
import { applyUnifiedDiff } from "./unified-diff.mjs";
|
|
27
27
|
import { tenantDirSegments } from "../lib/tenant-dirs.mjs";
|
|
28
|
+
import { recordDiagnostic } from "../../packages/cli/src/diagnostics.mjs";
|
|
28
29
|
|
|
29
30
|
const DEFAULT_MCP_URL = "https://mcp.tokenoftrust.com";
|
|
30
31
|
|
|
@@ -83,7 +84,7 @@ async function resolveClient(mcpBaseUrl) {
|
|
|
83
84
|
* not-configured all come back as `{ ok:false, status, message }`).
|
|
84
85
|
*/
|
|
85
86
|
export async function handleAiEdit({ repoRoot, tenantId, prompt, mcpBaseUrl }, deps = {}) {
|
|
86
|
-
const { resolveClientImpl = resolveClient } = deps;
|
|
87
|
+
const { resolveClientImpl = resolveClient, env = process.env } = deps;
|
|
87
88
|
const paths = tenantPaths(repoRoot, tenantId);
|
|
88
89
|
const files = [
|
|
89
90
|
{ path: "content/home.html", content: readFileIfPresent(paths.home) },
|
|
@@ -98,14 +99,26 @@ export async function handleAiEdit({ repoRoot, tenantId, prompt, mcpBaseUrl }, d
|
|
|
98
99
|
try {
|
|
99
100
|
client = await resolveClientImpl(mcpBaseUrl);
|
|
100
101
|
} catch (e) {
|
|
101
|
-
|
|
102
|
+
const diagnostic = recordDiagnostic(e, {
|
|
103
|
+
command: "dev-ai-edit", operation: "session_initialize", required: true,
|
|
104
|
+
}, env);
|
|
105
|
+
return {
|
|
106
|
+
ok: false, status: "unauthenticated", message: e.message,
|
|
107
|
+
diagnosticId: diagnostic.diagnosticId,
|
|
108
|
+
};
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
let result;
|
|
105
112
|
try {
|
|
106
113
|
result = await client.callTool("content_edit", { prompt, files });
|
|
107
114
|
} catch (e) {
|
|
108
|
-
|
|
115
|
+
const diagnostic = recordDiagnostic(e, {
|
|
116
|
+
command: "dev-ai-edit", operation: "content_edit", required: true,
|
|
117
|
+
}, env);
|
|
118
|
+
return {
|
|
119
|
+
ok: false, status: "error", message: e.message,
|
|
120
|
+
diagnosticId: diagnostic.diagnosticId,
|
|
121
|
+
};
|
|
109
122
|
}
|
|
110
123
|
if (result?.status && result.status !== "ok") {
|
|
111
124
|
return { ok: false, status: result.status, message: result.message || "content_edit refused the request." };
|
|
@@ -18,19 +18,34 @@ import net from "node:net";
|
|
|
18
18
|
* @param {number} port
|
|
19
19
|
* @returns {Promise<boolean>}
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* @param {number} port
|
|
23
|
+
* @param {string | undefined} [host]
|
|
24
|
+
* @param {boolean} [unsupportedIsFree]
|
|
25
|
+
*/
|
|
26
|
+
function canBind(port, host = undefined, unsupportedIsFree = false) {
|
|
22
27
|
return new Promise((resolve) => {
|
|
23
28
|
const srv = net.createServer();
|
|
24
|
-
srv.once("error", () =>
|
|
29
|
+
srv.once("error", (error) => {
|
|
30
|
+
const code = /** @type {NodeJS.ErrnoException} */ (error).code;
|
|
31
|
+
const unsupported = code === "EAFNOSUPPORT" || code === "EADDRNOTAVAIL";
|
|
32
|
+
resolve(unsupportedIsFree && unsupported);
|
|
33
|
+
});
|
|
25
34
|
srv.once("listening", () => srv.close(() => resolve(true)));
|
|
26
35
|
try {
|
|
27
|
-
srv.listen(port);
|
|
36
|
+
srv.listen({ port, ...(host ? { host } : {}) });
|
|
28
37
|
} catch {
|
|
29
38
|
resolve(false);
|
|
30
39
|
}
|
|
31
40
|
});
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
export async function isPortFree(port) {
|
|
44
|
+
if (!(await canBind(port))) return false;
|
|
45
|
+
if (!(await canBind(port, "127.0.0.1"))) return false;
|
|
46
|
+
return canBind(port, "::1", true);
|
|
47
|
+
}
|
|
48
|
+
|
|
34
49
|
/**
|
|
35
50
|
* The first free port at or after `preferred` (scanning upward). Lets `tot dev`
|
|
36
51
|
* boot on a busy default port by moving to the next open one and printing it —
|
package/scripts/dev/publish.mjs
CHANGED
|
@@ -32,6 +32,7 @@ import { matchesWriteAllowlist } from "./safe-path.mjs";
|
|
|
32
32
|
import { resolveTenantSourceRoot } from "./tenant-source-root.mjs";
|
|
33
33
|
import { createMcpClient } from "../../packages/cli/src/mcp.mjs";
|
|
34
34
|
import { resolveDeveloperSession, AuthUnavailableError } from "../../packages/cli/src/auth.mjs";
|
|
35
|
+
import { recordDiagnostic } from "../../packages/cli/src/diagnostics.mjs";
|
|
35
36
|
|
|
36
37
|
const DEFAULT_MCP_URL = "https://mcp.tokenoftrust.com";
|
|
37
38
|
|
|
@@ -90,13 +91,26 @@ export async function publishFile(env, sourceRoot, tenantId, relPath, deps = {})
|
|
|
90
91
|
session = await (deps.resolveSession || resolveDeveloperSession)(client, env);
|
|
91
92
|
await client.initialize();
|
|
92
93
|
} catch (e) {
|
|
94
|
+
const diagnostic = recordDiagnostic(e, {
|
|
95
|
+
command: "dev-publish", operation: "session_initialize", required: true,
|
|
96
|
+
}, env);
|
|
93
97
|
if (e instanceof AuthUnavailableError) {
|
|
94
98
|
return {
|
|
95
99
|
status: 503,
|
|
96
|
-
json: {
|
|
100
|
+
json: {
|
|
101
|
+
ok: false, status: "not_signed_in",
|
|
102
|
+
message: `${e.message}${e.hint ? ` — ${e.hint}` : ""}`,
|
|
103
|
+
diagnosticId: diagnostic.diagnosticId,
|
|
104
|
+
},
|
|
97
105
|
};
|
|
98
106
|
}
|
|
99
|
-
return {
|
|
107
|
+
return {
|
|
108
|
+
status: 502,
|
|
109
|
+
json: {
|
|
110
|
+
ok: false, status: "error", message: String(e?.message || e),
|
|
111
|
+
diagnosticId: diagnostic.diagnosticId,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
100
114
|
}
|
|
101
115
|
|
|
102
116
|
const repo = `${tenantId}-main`;
|
|
@@ -127,7 +141,16 @@ export async function publishFile(env, sourceRoot, tenantId, relPath, deps = {})
|
|
|
127
141
|
},
|
|
128
142
|
};
|
|
129
143
|
} catch (e) {
|
|
130
|
-
|
|
144
|
+
const diagnostic = recordDiagnostic(e, {
|
|
145
|
+
command: "dev-publish", operation: "candidate_open", required: true,
|
|
146
|
+
}, env);
|
|
147
|
+
return {
|
|
148
|
+
status: 502,
|
|
149
|
+
json: {
|
|
150
|
+
ok: false, status: "error", message: String(e?.message || e),
|
|
151
|
+
diagnosticId: diagnostic.diagnosticId,
|
|
152
|
+
},
|
|
153
|
+
};
|
|
131
154
|
}
|
|
132
155
|
}
|
|
133
156
|
|
|
@@ -738,7 +738,12 @@ export function discoverTenantIds() {
|
|
|
738
738
|
|
|
739
739
|
// --- link / asset extraction -------------------------------------------------
|
|
740
740
|
const HREF_RE = /\bhref\s*=\s*"([^"]*)"/gi;
|
|
741
|
-
const SRC_RE = /\
|
|
741
|
+
const SRC_RE = /\bsrc\s*=\s*"([^"]*)"/gi;
|
|
742
|
+
// `srcset` carries a comma-separated list of `url descriptor` pairs (e.g.
|
|
743
|
+
// "a.webp 480w, b.webp 800w"), not a single URL — each candidate must be split
|
|
744
|
+
// off its descriptor before being checked as an asset. Mirrors
|
|
745
|
+
// scripts/publish/lib/asset-reachability.mjs's srcset handling.
|
|
746
|
+
const SRCSET_RE = /\bsrcset\s*=\s*"([^"]*)"/gi;
|
|
742
747
|
const STYLE_OPEN_WITH_ATTRS_RE = /<style\s+[^>]*>/i;
|
|
743
748
|
/** An in-page skip link: an anchor to a #main-ish target, or one carrying a skip class. */
|
|
744
749
|
const SKIP_LINK_RE = /<a\b[^>]*(?:class="[^"]*\bskip[-\w]*\b[^"]*"|href="#(?:main|content|main-content)\b")/i;
|
|
@@ -981,6 +986,14 @@ export function validateTenant(tenantDir, opts = {}) {
|
|
|
981
986
|
const f = checkAsset(m[1].trim(), r, publicDir, opts.tenantId || config?.tenant);
|
|
982
987
|
if (f) findings.push(f);
|
|
983
988
|
}
|
|
989
|
+
for (const m of html.matchAll(SRCSET_RE)) {
|
|
990
|
+
for (const candidate of m[1].split(",")) {
|
|
991
|
+
const url = candidate.trim().split(/\s+/)[0];
|
|
992
|
+
if (!url) continue;
|
|
993
|
+
const f = checkAsset(url, r, publicDir, opts.tenantId || config?.tenant);
|
|
994
|
+
if (f) findings.push(f);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
984
997
|
}
|
|
985
998
|
|
|
986
999
|
// 5. git conflict markers — advisory (never blocks), but LOUD: a half-resolved
|