@tokenoftrust/storefront-runner 2.4.15 → 2.4.17
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/src/config/publicationSpaceConfig.ts +37 -0
- package/apps/storefront/src/config/publicationSpaceRegistry.ts +47 -19
- package/apps/storefront/src/config/publicationSpaceTopology.ts +73 -0
- package/package.json +1 -1
- package/packages/public-runtime/src/publication-artifact.ts +3 -0
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
PublicationSpaceAliasV1,
|
|
3
3
|
PublicationSpaceManifestV1,
|
|
4
4
|
PublicationSpaceSourceV1,
|
|
5
|
+
PublicationSpaceVisibilityV1,
|
|
5
6
|
} from "@tot/public-runtime";
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -34,3 +35,39 @@ export function rootPublicationSpaceConfig(
|
|
|
34
35
|
},
|
|
35
36
|
};
|
|
36
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A mounted publication space for a tenant — public or internal, at any
|
|
41
|
+
* declared, non-root mount. Visibility drives the authorization, discovery,
|
|
42
|
+
* and asset-access triad together, the same invariant
|
|
43
|
+
* `validatePublicationSpaceManifestV1` enforces: public spaces are open and
|
|
44
|
+
* discoverable, internal spaces are capability-gated and excluded from every
|
|
45
|
+
* public discovery surface.
|
|
46
|
+
*/
|
|
47
|
+
export function mountedPublicationSpaceConfig(
|
|
48
|
+
tenant: string,
|
|
49
|
+
id: string,
|
|
50
|
+
source: PublicationSpaceSourceV1,
|
|
51
|
+
mount: string,
|
|
52
|
+
visibility: PublicationSpaceVisibilityV1 = "public",
|
|
53
|
+
aliases: readonly PublicationSpaceAliasV1[] = [],
|
|
54
|
+
): PublicationSpaceManifestV1 {
|
|
55
|
+
const internal = visibility === "internal";
|
|
56
|
+
return {
|
|
57
|
+
version: 1,
|
|
58
|
+
id,
|
|
59
|
+
tenant,
|
|
60
|
+
source,
|
|
61
|
+
routes: aliases.length ? { canonicalMount: mount, aliases: [...aliases] } : { canonicalMount: mount },
|
|
62
|
+
visibility,
|
|
63
|
+
authorization: internal ? { policy: "capability", capability: "internal-content-reader" } : { policy: "public" },
|
|
64
|
+
discovery: internal
|
|
65
|
+
? { sitemap: false, feeds: false, publicSearch: false, llms: false }
|
|
66
|
+
: { sitemap: true, feeds: true, publicSearch: true, llms: true },
|
|
67
|
+
assets: { namespace: id, access: internal ? "authorized" : "public" },
|
|
68
|
+
renderer: {
|
|
69
|
+
contractVersion: "storefront-v1",
|
|
70
|
+
themeContractVersion: "tenant-theme-v1",
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -1,25 +1,53 @@
|
|
|
1
1
|
import type { PublicationSpaceManifestV1, PublicationSpaceSourceV1 } from "@tot/public-runtime";
|
|
2
|
-
import { rootPublicationSpaceConfig } from "./publicationSpaceConfig.js";
|
|
2
|
+
import { mountedPublicationSpaceConfig, rootPublicationSpaceConfig } from "./publicationSpaceConfig.js";
|
|
3
|
+
import { PUBLICATION_SPACE_TOPOLOGY, type PublicationTopologyDeclarationV1 } from "./publicationSpaceTopology.js";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
/**
|
|
6
|
+
* A declared source belongs to its tenant when the repo IS the tenant id, or is
|
|
7
|
+
* namespaced under it (`<tenant>-<suffix>`) — the naming convention every
|
|
8
|
+
* declared source in `publicationSpaceTopology.ts` already follows. This is the
|
|
9
|
+
* one check that stops a mounted space from naming a different tenant's
|
|
10
|
+
* repository, by construction rather than by a tenant-id branch here.
|
|
11
|
+
*/
|
|
12
|
+
function sourceBelongsToTenant(tenant: string, source: PublicationSpaceSourceV1): boolean {
|
|
13
|
+
return source.repo === tenant || source.repo.startsWith(`${tenant}-`);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build one tenant's full publication-space manifest set — root plus any
|
|
18
|
+
* mounted public or internal spaces — from its declared topology. Pure
|
|
19
|
+
* resolution over the declaration: no tenant identity is ever branched on
|
|
20
|
+
* here, so this function is identical for every tenant and every mount count.
|
|
21
|
+
*/
|
|
22
|
+
export function publicationSpacesFromTopology(
|
|
23
|
+
tenant: string,
|
|
24
|
+
declaration: PublicationTopologyDeclarationV1,
|
|
25
|
+
): PublicationSpaceManifestV1[] {
|
|
26
|
+
const spaces: PublicationSpaceManifestV1[] = [
|
|
27
|
+
rootPublicationSpaceConfig(tenant, declaration.root.source, declaration.root.aliases ?? []),
|
|
28
|
+
...(declaration.mounted ?? []).map((mounted) =>
|
|
29
|
+
mountedPublicationSpaceConfig(
|
|
30
|
+
tenant,
|
|
31
|
+
mounted.id,
|
|
32
|
+
mounted.source,
|
|
33
|
+
mounted.mount,
|
|
34
|
+
mounted.visibility ?? "public",
|
|
35
|
+
mounted.aliases ?? [],
|
|
36
|
+
)),
|
|
37
|
+
];
|
|
38
|
+
const foreign = spaces.find((space) => !sourceBelongsToTenant(tenant, space.source));
|
|
39
|
+
if (foreign) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`publication_foreign_source: space '${foreign.id}' for tenant '${tenant}' declares a source ` +
|
|
42
|
+
`('${foreign.source.forge}:${foreign.source.repo}') that is not namespaced under its own tenant.`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return spaces;
|
|
46
|
+
}
|
|
19
47
|
|
|
20
48
|
/** Node-safe publication topology authority shared by runtime config and CI composition. */
|
|
21
49
|
export function publicationSpacesForTenant(tenant: string): PublicationSpaceManifestV1[] {
|
|
22
|
-
const
|
|
23
|
-
if (!
|
|
24
|
-
return
|
|
50
|
+
const declaration = PUBLICATION_SPACE_TOPOLOGY[tenant];
|
|
51
|
+
if (!declaration) return [];
|
|
52
|
+
return publicationSpacesFromTopology(tenant, declaration);
|
|
25
53
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PublicationSpaceAliasV1, PublicationSpaceSourceV1, PublicationSpaceVisibilityV1 } from "@tot/public-runtime";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* One declared non-root publication space: a mount, its source, and its
|
|
5
|
+
* visibility. Defaults to "public" — an "internal" declaration is the only
|
|
6
|
+
* way a tenant gets a capability-gated space.
|
|
7
|
+
*/
|
|
8
|
+
export interface MountedPublicationSpaceDeclarationV1 {
|
|
9
|
+
id: string;
|
|
10
|
+
source: PublicationSpaceSourceV1;
|
|
11
|
+
mount: string;
|
|
12
|
+
visibility?: PublicationSpaceVisibilityV1;
|
|
13
|
+
aliases?: readonly PublicationSpaceAliasV1[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** A tenant's complete declared publication topology: exactly one root, plus any mounted spaces. */
|
|
17
|
+
export interface PublicationTopologyDeclarationV1 {
|
|
18
|
+
root: {
|
|
19
|
+
source: PublicationSpaceSourceV1;
|
|
20
|
+
aliases?: readonly PublicationSpaceAliasV1[];
|
|
21
|
+
};
|
|
22
|
+
mounted?: readonly MountedPublicationSpaceDeclarationV1[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The declared publication topology for every provisioned tenant — the ONLY place a tenant's
|
|
27
|
+
* publication sources are named. `publicationSpaceRegistry.ts` resolves this generically, with
|
|
28
|
+
* no branching on tenant id; runtime config, CI composition, and both CDN publish paths all
|
|
29
|
+
* consume what it resolves, never this table directly.
|
|
30
|
+
*/
|
|
31
|
+
export const PUBLICATION_SPACE_TOPOLOGY: Readonly<Record<string, PublicationTopologyDeclarationV1>> = {
|
|
32
|
+
home: { root: { source: { forge: "fixture", repo: "home", defaultBranch: "main" } } },
|
|
33
|
+
"tokenoftrust.com": {
|
|
34
|
+
root: { source: { forge: "gitea", repo: "tokenoftrust.com-main", defaultBranch: "main" } },
|
|
35
|
+
},
|
|
36
|
+
"storefront.tokenoftrust.store": {
|
|
37
|
+
root: { source: { forge: "gitea", repo: "storefront.tokenoftrust.store", defaultBranch: "main" } },
|
|
38
|
+
},
|
|
39
|
+
"sample-store.com": {
|
|
40
|
+
root: { source: { forge: "gitea", repo: "sample-store.com", defaultBranch: "main" } },
|
|
41
|
+
},
|
|
42
|
+
"sample-store.e2e.test": {
|
|
43
|
+
root: { source: { forge: "gitea", repo: "sample-store.e2e.test", defaultBranch: "main" } },
|
|
44
|
+
},
|
|
45
|
+
"verify.e2e.test": {
|
|
46
|
+
root: { source: { forge: "fixture", repo: "verify.e2e.test", defaultBranch: "main" } },
|
|
47
|
+
},
|
|
48
|
+
// Carries the mounted public + mounted internal coverage every tenant topology can declare —
|
|
49
|
+
// see publicationSpaces.test.ts for the 3-space resolution this exercises.
|
|
50
|
+
"fixture.e2e.test": {
|
|
51
|
+
root: { source: { forge: "fixture", repo: "fixture.e2e.test", defaultBranch: "main" } },
|
|
52
|
+
mounted: [
|
|
53
|
+
{
|
|
54
|
+
id: "fixture-docs",
|
|
55
|
+
source: { forge: "fixture", repo: "fixture.e2e.test-docs", defaultBranch: "main" },
|
|
56
|
+
mount: "/docs",
|
|
57
|
+
visibility: "public",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "fixture-internal",
|
|
61
|
+
source: { forge: "fixture", repo: "fixture.e2e.test-internal", defaultBranch: "main" },
|
|
62
|
+
mount: "/internal-docs",
|
|
63
|
+
visibility: "internal",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
"chrome.e2e.test": {
|
|
68
|
+
root: { source: { forge: "fixture", repo: "chrome.e2e.test", defaultBranch: "main" } },
|
|
69
|
+
},
|
|
70
|
+
"catalog.e2e.test": {
|
|
71
|
+
root: { source: { forge: "fixture", repo: "catalog.e2e.test", defaultBranch: "main" } },
|
|
72
|
+
},
|
|
73
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.17",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|
|
@@ -205,6 +205,9 @@ export function publicationArtifactKeyV1(
|
|
|
205
205
|
return `publications/${tenant}/${spaceId}/${versionId}/${lane}/${relativePath}`;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
/** The largest `bundle.json` marker review admission reads; a larger one is never built. */
|
|
209
|
+
export const PUBLICATION_ARTIFACT_MARKER_MAX_BYTES = 16 * 1024 * 1024;
|
|
210
|
+
|
|
208
211
|
/** Marker address for one immutable tenant+space+version bundle. */
|
|
209
212
|
export function publicationArtifactBundleKeyV1(
|
|
210
213
|
tenant: string,
|