Skip to content

Commit e70af8f

Browse files
committed
Address review round 3: homepage type check, preserve MPL notice
1. The homepage check coerced with String(), so ["https://example.com"] passed by array-to-string coercion. It now requires a string, then https, then a parseable URL. Verified against array, object, number, boolean, null and "https://" with no host; a valid string and an absent homepage still pass. 2. The updater stripped every upstream comment, including the Public Suffix List's MPL 2.0 notice, leaving the snapshot with no licence while the repository declares MIT. The notice is now carried into the generated file, read from upstream rather than hardcoded so a reworded notice still lands, and the updater refuses to write if it cannot find it. README records that the snapshot is MPL 2.0 and dev-only, outside the files allowlist, so the published package remains MIT. Guards are now 34 must-fail plus 6 must-pass, all verified by mutation, and the licence guard was verified by serving the updater a list with the notice removed.
1 parent 68c25a8 commit e70af8f

4 files changed

Lines changed: 47 additions & 7 deletions

File tree

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ function canonicalLink(entry, defaultScheme = DEFAULT_SCHEME) {
8080
good/bad overlap, public suffixes and `apps.json` placeholders. CI runs it on every pull
8181
request and again before publish. No dependencies to install.
8282
83+
The public suffix check reads `scripts/public-suffix-list.txt`, a snapshot of the
84+
[Public Suffix List](https://publicsuffix.org/list/) refreshed by
85+
`node scripts/update-public-suffix-list.mjs`. That snapshot is MPL 2.0, carries its upstream
86+
notice, and is development tooling only: it is outside the `files` allowlist, so the npm
87+
package stays MIT.
88+
8389
### Adding or changing an app
8490
8591
Open a pull request against `apps.json`. Entries are sorted by key. A `url_scheme` must be

scripts/public-suffix-list.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
# https://publicsuffix.org/list/public_suffix_list.dat, punycode normalised.
1+
# This Source Code Form is subject to the terms of the Mozilla Public
2+
# License, v. 2.0. If a copy of the MPL was not distributed with this
3+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
#
5+
# Generated from https://publicsuffix.org/list/public_suffix_list.dat, punycode normalised.
6+
# Licensed under MPL 2.0: https://mozilla.org/MPL/2.0/. Not part of the npm package.
27
# Rule types are significant: '*.' is a wildcard, '!' is an exception.
38
# Refresh with: node scripts/update-public-suffix-list.mjs
49
!city.kawasaki.jp

scripts/update-public-suffix-list.mjs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,25 @@ if (!res.ok) throw new Error(`public suffix list fetch failed: ${res.status}`);
1414

1515
const toPunycode = (domain) => new URL(`https://${domain}`).hostname;
1616

17+
const lines = (await res.text()).split("\n");
18+
19+
// The list is MPL 2.0 and this repository is MIT, so the upstream notice travels with the
20+
// snapshot. Taken from the file rather than hardcoded, so a reworded notice still lands.
21+
const notice = [];
22+
for (const line of lines) {
23+
if (!line.trim()) {
24+
if (notice.length) break;
25+
continue;
26+
}
27+
if (!line.startsWith("//")) break;
28+
notice.push(`#${line.slice(2)}`);
29+
}
30+
if (!notice.join(" ").includes("Mozilla Public")) {
31+
throw new Error("upstream licence notice not found, refusing to write");
32+
}
33+
1734
const rules = new Set();
18-
for (const line of (await res.text()).split("\n")) {
35+
for (const line of lines) {
1936
const s = line.trim();
2037
if (!s || s.startsWith("//")) continue;
2138

@@ -28,9 +45,15 @@ if (rules.size < 5000) throw new Error(`only ${rules.size} rules parsed, refusin
2845

2946
writeFileSync(
3047
new URL("./public-suffix-list.txt", import.meta.url),
31-
"# https://publicsuffix.org/list/public_suffix_list.dat, punycode normalised.\n" +
32-
"# Rule types are significant: '*.' is a wildcard, '!' is an exception.\n" +
33-
"# Refresh with: node scripts/update-public-suffix-list.mjs\n" +
48+
[
49+
...notice,
50+
"#",
51+
"# Generated from https://publicsuffix.org/list/public_suffix_list.dat, punycode normalised.",
52+
"# Licensed under MPL 2.0: https://mozilla.org/MPL/2.0/. Not part of the npm package.",
53+
"# Rule types are significant: '*.' is a wildcard, '!' is an exception.",
54+
"# Refresh with: node scripts/update-public-suffix-list.mjs",
55+
].join("\n") +
56+
"\n" +
3457
[...rules].sort().join("\n") +
3558
"\n"
3659
);

scripts/validate.mjs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,14 @@ if (apps) {
148148
if (typeof app?.name !== "string" || !app.name) fail("apps.json", `${id}: missing "name"`);
149149

150150
// Common fields first: entries without a url_scheme still have a homepage.
151-
if (app?.homepage !== undefined && !String(app.homepage).startsWith("https://")) {
152-
fail("apps.json", `${id}: homepage must be https`);
151+
if (app?.homepage !== undefined) {
152+
if (typeof app.homepage !== "string") {
153+
fail("apps.json", `${id}: homepage must be a string`);
154+
} else if (!app.homepage.startsWith("https://")) {
155+
fail("apps.json", `${id}: homepage must be https`);
156+
} else if (!URL.canParse(app.homepage)) {
157+
fail("apps.json", `${id}: homepage is not a valid URL: ${app.homepage}`);
158+
}
153159
}
154160

155161
// url_scheme is optional: publishing tools with no web home of their own omit it.

0 commit comments

Comments
 (0)