A single-file build inlines every import, dynamic ones included, so packet-strings.json (~115 KB minified: every language's prayer points, captions and headings) rode in every bundle that can print a packet, list or card deck. With the wall's print messages translated, country-posters crossed the 1.5 MB ceiling (1,502,226 bytes). The table is now served at <assets>/lib/packet-strings.json and fetched at the first print by library/packet/packetStrings.js, the same move as the sheet generator and ne-places.json: - Pinned like them: PACKET_STRINGS_SHA384 in poster-render.integrity.js (pin-poster-render.mjs); the text is hashed before it is parsed, and an unmatched table is not used. These strings are laid into the print document, so an unverified copy never reaches it. - English is bundled as the fallback (a named import of the JSON, so only the en block ships): with no asset base, on file://, on a network error or an integrity mismatch the print comes out in English and the console says why. A print never fails for want of this file. - generate-tree copies it into the pool AND the served allowlist; verified by regenerating the tree (the served copy is byte-identical to source). - check:poster-render-pinned, two-sided: the pin matches source and served copy, the genuine copy loads all 11 languages, a tampered copy falls back to English (mutation-tested: disabling the hash check fails it), and an unserved one falls back rather than failing. - sha384 is one shared helper (library/packet/sha384.js). Sizes: country-posters 1,378,463 (was 1,484,053), my-upg-100-list 1,143,456 (was 1,243,509), regions-dashboard 973,802 (was 1,079,448).
9 lines
525 B
JavaScript
9 lines
525 B
JavaScript
// The Subresource-Integrity form of a text's SHA-384 ("sha384-<base64>"), via WebCrypto, so a file fetched at
|
|
// print time can be compared with the pin baked into the bundle (poster-render.integrity.js) before it is used.
|
|
// The same value pin-poster-render.mjs computes with node:crypto.
|
|
export async function sha384(text) {
|
|
const d = new Uint8Array(await crypto.subtle.digest('SHA-384', new TextEncoder().encode(text)))
|
|
let bin = ''
|
|
for (const b of d) bin += String.fromCharCode(b)
|
|
return `sha384-${btoa(bin)}`
|
|
}
|