@tokenoftrust/cli 2.2.15 → 2.2.16
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/package.json +1 -1
- package/src/declared-config.mjs +5 -1
- package/src/validate.mjs +20 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.16",
|
|
4
4
|
"description": "Token of Trust developer CLI — clone a tenant store, run it locally with save→reload, and submit it for preview. Installs the `tot` command.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Token of Trust",
|
package/src/declared-config.mjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
export const TOT_CONFIG_KEYS = [
|
|
13
13
|
"$schema", "tenant", "scope", "mappings", "hostPlatform", "sample", "seed",
|
|
14
|
-
"siteType", "compliance", "capabilities", "features",
|
|
14
|
+
"siteType", "compliance", "capabilities", "features", "embeds",
|
|
15
15
|
];
|
|
16
16
|
// Keys other tooling has written that the platform does NOT read, with the key it does.
|
|
17
17
|
const RENAMED_CONFIG_KEYS = { appDomain: "scope", tenantId: "tenant" };
|
|
@@ -74,5 +74,9 @@ export function validateDeclaredConfig(config, file = ".tot/config.json") {
|
|
|
74
74
|
if (config.capabilities !== undefined && !isObject(config.capabilities)) {
|
|
75
75
|
out.push(mk(ERROR, "config-capabilities", file, "`capabilities` must be an object"));
|
|
76
76
|
}
|
|
77
|
+
if (config.embeds !== undefined
|
|
78
|
+
&& !(Array.isArray(config.embeds) && config.embeds.every((/** @type {unknown} */ s) => typeof s === "string"))) {
|
|
79
|
+
out.push(mk(ERROR, "config-embeds", file, '`embeds` must be an array of embed slugs, e.g. ["youtube"]'));
|
|
80
|
+
}
|
|
77
81
|
return out;
|
|
78
82
|
}
|
package/src/validate.mjs
CHANGED
|
@@ -224,7 +224,7 @@ function providesChrome(contentDir) {
|
|
|
224
224
|
|
|
225
225
|
const CAPABILITY_KEYS = new Set(["cartCheckout", "ageVerification", "exciseTax"]);
|
|
226
226
|
|
|
227
|
-
// Compact mirror of EMBED_PROVIDERS (
|
|
227
|
+
// Compact mirror of EMBED_PROVIDERS (agency-kit/tools/lib/embed-catalog.mjs)
|
|
228
228
|
// for the embed-CSP shift-left scan. The published `tot` CLI bundle can't reach
|
|
229
229
|
// the repo's public-runtime package at runtime, so this is a copy — but a parity
|
|
230
230
|
// test (packages/public-runtime/tests/embed-catalog-parity.test.ts) pins it to
|
|
@@ -237,6 +237,18 @@ export const KNOWN_EMBEDS = [
|
|
|
237
237
|
markers: ["webforms.pipedrive.com", "pipedriveWebForms"],
|
|
238
238
|
origins: ["https://webforms.pipedrive.com"],
|
|
239
239
|
},
|
|
240
|
+
{
|
|
241
|
+
slug: "youtube",
|
|
242
|
+
label: "YouTube video (privacy-enhanced)",
|
|
243
|
+
markers: ["www.youtube-nocookie.com/embed/"],
|
|
244
|
+
origins: ["https://www.youtube-nocookie.com"],
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
slug: "vimeo",
|
|
248
|
+
label: "Vimeo video",
|
|
249
|
+
markers: ["player.vimeo.com/video/"],
|
|
250
|
+
origins: ["https://player.vimeo.com"],
|
|
251
|
+
},
|
|
240
252
|
];
|
|
241
253
|
const KNOWN_EMBED_SLUGS = new Set(KNOWN_EMBEDS.map((p) => p.slug));
|
|
242
254
|
const EMBED_SRC_RE = /<(?:script|iframe)\b[^>]*\bsrc\s*=\s*["']([^"']+)["']/gi;
|
|
@@ -1263,10 +1275,15 @@ export function validateTenant(tenantDir, opts = {}) {
|
|
|
1263
1275
|
// provider not opted into embeds.json, or an unknown external <script>/<iframe>
|
|
1264
1276
|
// origin, is blocking; advisory (info) when there's no embeds.json to compare.
|
|
1265
1277
|
{
|
|
1266
|
-
|
|
1278
|
+
// The opt-in is the `embeds` .tot/config.json declares, plus an embeds.json.
|
|
1279
|
+
let declaredEmbeds = Array.isArray(config?.embeds)
|
|
1280
|
+
? new Set(config.embeds.filter((/** @type {unknown} */ s) => typeof s === "string"))
|
|
1281
|
+
: null;
|
|
1267
1282
|
if (existsSync(embedsPath)) {
|
|
1268
1283
|
const { value } = readJsonSafe(embedsPath);
|
|
1269
|
-
if (Array.isArray(value))
|
|
1284
|
+
if (Array.isArray(value)) {
|
|
1285
|
+
declaredEmbeds = new Set([...(declaredEmbeds ?? []), ...value.filter((s) => typeof s === "string")]);
|
|
1286
|
+
}
|
|
1270
1287
|
}
|
|
1271
1288
|
for (const file of walk(contentDir, (p) => p.endsWith(".html"))) {
|
|
1272
1289
|
const { knownSlugs, unknownOrigins } = scanHtmlForEmbeds(readFileSync(file, "utf8"));
|