@tokenoftrust/storefront-runner 2.0.17 → 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/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/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/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,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"id": "articles",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"source": {
|
|
6
|
+
"forge": "fixture",
|
|
7
|
+
"repo": "fixture-publications",
|
|
8
|
+
"defaultBranch": "main"
|
|
9
|
+
},
|
|
10
|
+
"routes": {
|
|
11
|
+
"canonicalMount": "/blog",
|
|
12
|
+
"aliases": [
|
|
13
|
+
{
|
|
14
|
+
"from": "/the-build",
|
|
15
|
+
"behavior": "redirect-308",
|
|
16
|
+
"to": "/blog"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"visibility": "public",
|
|
21
|
+
"authorization": {
|
|
22
|
+
"policy": "public"
|
|
23
|
+
},
|
|
24
|
+
"discovery": {
|
|
25
|
+
"sitemap": true,
|
|
26
|
+
"feeds": true,
|
|
27
|
+
"publicSearch": true,
|
|
28
|
+
"llms": true
|
|
29
|
+
},
|
|
30
|
+
"assets": {
|
|
31
|
+
"namespace": "articles",
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"renderer": {
|
|
35
|
+
"contractVersion": "storefront-v1",
|
|
36
|
+
"themeContractVersion": "theme-v1"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"version": 1,
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"spaceId": "knowledge",
|
|
6
|
+
"kind": "canonical",
|
|
7
|
+
"mount": "/knowledge",
|
|
8
|
+
"canonicalMount": "/knowledge",
|
|
9
|
+
"behavior": "render"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"version": 1,
|
|
13
|
+
"tenant": "fixture.example",
|
|
14
|
+
"spaceId": "articles",
|
|
15
|
+
"kind": "alias",
|
|
16
|
+
"mount": "/the-build",
|
|
17
|
+
"canonicalMount": "/blog",
|
|
18
|
+
"behavior": "redirect-308",
|
|
19
|
+
"redirectTo": "/blog"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"version": 1,
|
|
23
|
+
"tenant": "fixture.example",
|
|
24
|
+
"spaceId": "articles",
|
|
25
|
+
"kind": "canonical",
|
|
26
|
+
"mount": "/blog",
|
|
27
|
+
"canonicalMount": "/blog",
|
|
28
|
+
"behavior": "render"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"version": 1,
|
|
32
|
+
"tenant": "fixture.example",
|
|
33
|
+
"spaceId": "root",
|
|
34
|
+
"kind": "canonical",
|
|
35
|
+
"mount": "/",
|
|
36
|
+
"canonicalMount": "/",
|
|
37
|
+
"behavior": "render"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"id": "root",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"source": {
|
|
6
|
+
"forge": "fixture",
|
|
7
|
+
"repo": "fixture.example",
|
|
8
|
+
"defaultBranch": "main"
|
|
9
|
+
},
|
|
10
|
+
"routes": {
|
|
11
|
+
"canonicalMount": "/"
|
|
12
|
+
},
|
|
13
|
+
"visibility": "public",
|
|
14
|
+
"authorization": {
|
|
15
|
+
"policy": "public"
|
|
16
|
+
},
|
|
17
|
+
"discovery": {
|
|
18
|
+
"sitemap": true,
|
|
19
|
+
"feeds": true,
|
|
20
|
+
"publicSearch": true,
|
|
21
|
+
"llms": true
|
|
22
|
+
},
|
|
23
|
+
"assets": {
|
|
24
|
+
"namespace": "root",
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"renderer": {
|
|
28
|
+
"contractVersion": "storefront-v1",
|
|
29
|
+
"themeContractVersion": "theme-v1"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"versionId": "pv_articles-version-0001",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"spaceId": "articles",
|
|
6
|
+
"source": {
|
|
7
|
+
"forge": "fixture",
|
|
8
|
+
"repo": "fixture-publications",
|
|
9
|
+
"commitSha": "3333333333333333333333333333333333333333"
|
|
10
|
+
},
|
|
11
|
+
"renderer": {
|
|
12
|
+
"contractVersion": "storefront-v1",
|
|
13
|
+
"themeContractVersion": "theme-v1"
|
|
14
|
+
},
|
|
15
|
+
"artifactDigest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
16
|
+
"createdAt": "2026-09-01T12:02:00.000Z",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"buildId": "build-articles-0001"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"versionId": "pv_articles-version-0002",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"spaceId": "articles",
|
|
6
|
+
"source": {
|
|
7
|
+
"forge": "fixture",
|
|
8
|
+
"repo": "fixture-publications",
|
|
9
|
+
"commitSha": "4444444444444444444444444444444444444444"
|
|
10
|
+
},
|
|
11
|
+
"renderer": {
|
|
12
|
+
"contractVersion": "storefront-v1",
|
|
13
|
+
"themeContractVersion": "theme-v1"
|
|
14
|
+
},
|
|
15
|
+
"artifactDigest": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
|
|
16
|
+
"createdAt": "2026-09-01T12:03:00.000Z",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"buildId": "build-articles-0002"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"versionId": "pv_knowledge-version-0001",
|
|
4
|
+
"tenant": "fixture.example",
|
|
5
|
+
"spaceId": "knowledge",
|
|
6
|
+
"source": {
|
|
7
|
+
"forge": "fixture",
|
|
8
|
+
"repo": "fixture-private-publications",
|
|
9
|
+
"commitSha": "5555555555555555555555555555555555555555"
|
|
10
|
+
},
|
|
11
|
+
"renderer": {
|
|
12
|
+
"contractVersion": "storefront-v1",
|
|
13
|
+
"themeContractVersion": "theme-v1"
|
|
14
|
+
},
|
|
15
|
+
"artifactDigest": "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
|
|
16
|
+
"createdAt": "2026-09-01T12:04:00.000Z",
|
|
17
|
+
"metadata": {
|
|
18
|
+
"buildId": "build-knowledge-0001"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"tenant": "fixture.example",
|
|
4
|
+
"spaceId": "articles",
|
|
5
|
+
"channel": "live",
|
|
6
|
+
"revision": 1,
|
|
7
|
+
"versionId": "pv_articles-version-0001",
|
|
8
|
+
"sourceSha": "3333333333333333333333333333333333333333",
|
|
9
|
+
"artifactDigest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
10
|
+
"updatedAt": "2026-09-01T12:05:00.000Z"
|
|
11
|
+
}
|
package/packages/public-runtime/tests/fixtures/publication-versions/live-transition-request.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"transitionId": "activate-articles-0001",
|
|
4
|
+
"operation": "activate",
|
|
5
|
+
"tenant": "fixture.example",
|
|
6
|
+
"spaceId": "articles",
|
|
7
|
+
"channel": "live",
|
|
8
|
+
"targetVersionId": "pv_articles-version-0001",
|
|
9
|
+
"expectedSourceSha": "3333333333333333333333333333333333333333",
|
|
10
|
+
"expectedArtifactDigest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
11
|
+
"expectedRevision": 0,
|
|
12
|
+
"principal": "publisher.fixture",
|
|
13
|
+
"occurredAt": "2026-09-01T12:05:00.000Z"
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"transitionId": "activate-articles-0001",
|
|
4
|
+
"operation": "activate",
|
|
5
|
+
"tenant": "fixture.example",
|
|
6
|
+
"spaceId": "articles",
|
|
7
|
+
"channel": "live",
|
|
8
|
+
"previous": null,
|
|
9
|
+
"next": {
|
|
10
|
+
"revision": 1,
|
|
11
|
+
"versionId": "pv_articles-version-0001",
|
|
12
|
+
"sourceSha": "3333333333333333333333333333333333333333",
|
|
13
|
+
"artifactDigest": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
|
|
14
|
+
},
|
|
15
|
+
"principal": "publisher.fixture",
|
|
16
|
+
"occurredAt": "2026-09-01T12:05:00.000Z"
|
|
17
|
+
}
|
|
@@ -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
|