@tokenoftrust/storefront-runner 3.0.0 → 3.0.1
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.
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
* catalog images, and the source store is never shut down before that check passes. This decides,
|
|
6
6
|
* from a listing of the store's `public/` tree, whether the repo is carrying binaries it must not.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Findings, each naming its remedy:
|
|
9
9
|
*
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
10
|
+
* - one per entry of {@link FORBIDDEN_PUBLIC_DIRS}: any file under a directory a media download
|
|
11
|
+
* writes (`public/catalog-images/` is `catalog-images-in-repo`, `public/blog/wp-content/uploads/`
|
|
12
|
+
* is `blog-media-in-repo`). Decided from paths alone, so a caller without sizes still refuses
|
|
13
|
+
* it. This list is the one source the validators and the reconcile read; the Gitea
|
|
14
|
+
* pre-receive size guard names the same directories.
|
|
12
15
|
* - `public-binary-oversized` — one raster or media file over {@link PUBLIC_BINARY_LIMITS}
|
|
13
16
|
* `maxFileBytes`.
|
|
14
17
|
* - `public-tree-over-budget` — the whole `public/` tree over `maxTotalBytes`.
|
|
@@ -28,13 +31,25 @@ export const PUBLIC_BINARY_LIMITS = Object.freeze({
|
|
|
28
31
|
maxTotalBytes: 32 * 1024 * 1024,
|
|
29
32
|
});
|
|
30
33
|
|
|
31
|
-
/**
|
|
32
|
-
|
|
34
|
+
/**
|
|
35
|
+
* The directories under `public/` a media download writes. No file under one may be committed.
|
|
36
|
+
*
|
|
37
|
+
* @type {ReadonlyArray<Readonly<{ dir: string, code: string, noun: string }>>}
|
|
38
|
+
*/
|
|
39
|
+
export const FORBIDDEN_PUBLIC_DIRS = Object.freeze([
|
|
40
|
+
Object.freeze({ dir: "catalog-images/", code: "catalog-images-in-repo", noun: "catalog image" }),
|
|
41
|
+
Object.freeze({ dir: "blog/wp-content/uploads/", code: "blog-media-in-repo", noun: "blog media" }),
|
|
42
|
+
]);
|
|
33
43
|
|
|
34
|
-
/** The finding
|
|
35
|
-
export const
|
|
44
|
+
/** The finding codes decided from paths alone. */
|
|
45
|
+
export const PATH_DECIDED_FINDING_CODES = Object.freeze(new Set(FORBIDDEN_PUBLIC_DIRS.map((d) => d.code)));
|
|
46
|
+
|
|
47
|
+
/** True for a path (relative to `public/`, `/` separators) under a forbidden directory. */
|
|
48
|
+
export function isForbiddenPublicPath(rel) {
|
|
49
|
+
return FORBIDDEN_PUBLIC_DIRS.some((d) => rel.startsWith(d.dir));
|
|
50
|
+
}
|
|
36
51
|
|
|
37
|
-
/** The kit command that moves
|
|
52
|
+
/** The kit command that moves downloaded catalog images and blog media back to their source URLs. */
|
|
38
53
|
export const UNHOST_IMAGES_COMMAND = "node agency-kit/tools/import-catalog.mjs --store <checkout> --unhost-images --write";
|
|
39
54
|
|
|
40
55
|
const RASTER_OR_MEDIA = /\.(?:jpe?g|png|gif|webp|avif|bmp|tiff?|heic|heif|ico|jxl|mp4|m4v|mov|webm|mkv|avi|mpe?g|mp3|wav|ogg|oga|m4a|aac|flac|opus)$/i;
|
|
@@ -51,19 +66,20 @@ export function publicBinaryFindings(entries, limits = {}) {
|
|
|
51
66
|
const maxFileBytes = limits.maxFileBytes ?? PUBLIC_BINARY_LIMITS.maxFileBytes;
|
|
52
67
|
const maxTotalBytes = limits.maxTotalBytes ?? PUBLIC_BINARY_LIMITS.maxTotalBytes;
|
|
53
68
|
const findings = [];
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
for (const { dir, code, noun } of FORBIDDEN_PUBLIC_DIRS) {
|
|
70
|
+
const files = entries.filter((e) => e.rel.startsWith(dir));
|
|
71
|
+
if (files.length === 0) continue;
|
|
72
|
+
const bytes = files.reduce((n, e) => n + (e.bytes ?? 0), 0);
|
|
57
73
|
findings.push({
|
|
58
|
-
code
|
|
59
|
-
path: `public/${
|
|
60
|
-
message: `${
|
|
74
|
+
code,
|
|
75
|
+
path: `public/${dir}`,
|
|
76
|
+
message: `${files.length} ${noun} file(s)${bytes ? ` (${mb(bytes)})` : ""} are committed to the store repo; ` +
|
|
61
77
|
"images belong in the platform pool, not the repo; until platform capture owns them, keep each image at its source URL",
|
|
62
78
|
remedy: UNHOST_IMAGES_COMMAND,
|
|
63
79
|
});
|
|
64
80
|
}
|
|
65
81
|
for (const e of entries) {
|
|
66
|
-
if (e.rel
|
|
82
|
+
if (isForbiddenPublicPath(e.rel) || e.bytes === undefined) continue;
|
|
67
83
|
if (e.bytes > maxFileBytes && RASTER_OR_MEDIA.test(e.rel)) {
|
|
68
84
|
findings.push({
|
|
69
85
|
code: "public-binary-oversized",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
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",
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
parseMappingTarget,
|
|
46
46
|
workspacePathForTenantRelative,
|
|
47
47
|
} from "../../agency-kit/tools/lib/tot-repo-mappings.mjs";
|
|
48
|
-
import {
|
|
48
|
+
import { isForbiddenPublicPath, publicBinaryFindings } from "../../agency-kit/tools/lib/public-binaries.mjs";
|
|
49
49
|
import { validateVisualParityClosure } from "../../packages/cli/src/visual-parity.mjs";
|
|
50
50
|
import { declaredObligations, isRegulatedCompliance, validateDeclaredConfig } from "../../packages/cli/src/declared-config.mjs";
|
|
51
51
|
|
|
@@ -1367,8 +1367,8 @@ function checkAsset(src, file, publicDir, tenantId) {
|
|
|
1367
1367
|
function findLargePublicAssets(publicDir, rel) {
|
|
1368
1368
|
const out = [];
|
|
1369
1369
|
for (const p of walk(publicDir, () => true)) {
|
|
1370
|
-
//
|
|
1371
|
-
if (relative(publicDir, p).split("\\").join("/")
|
|
1370
|
+
// a forbidden media directory is already an error (catalog-images-in-repo, blog-media-in-repo); one line, not thousands.
|
|
1371
|
+
if (isForbiddenPublicPath(relative(publicDir, p).split("\\").join("/"))) continue;
|
|
1372
1372
|
const size = statSync(p).size;
|
|
1373
1373
|
if (size >= LARGE_PUBLIC_ASSET_BYTES) {
|
|
1374
1374
|
out.push(mk(WARN, "large-public-asset", rel(p), `${(size / 1024).toFixed(0)}KB`));
|