const allowedManifestFields = new Set([ 'file', 'name', 'src', 'isEntry', 'isDynamicEntry', 'imports', 'dynamicImports', 'css', 'assets', ]); const safeOutputPath = /^assets\/[a-zA-Z0-9][a-zA-Z0-9._-]*$/u; const safeBuildId = /^[a-z0-9][a-z0-9._-]{0,127}$/u; const sha256Pattern = /^[a-f0-9]{64}$/u; const sorted = (values) => [...new Set(values)].sort(); const assertStringArray = (value, label) => { if (value === undefined) return []; if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) { throw new Error(`${label} must be an array of strings.`); } return value; }; const validateRecord = (key, record) => { if (typeof record !== 'object' || record === null || Array.isArray(record)) { throw new Error(`Vite manifest record must be an object: ${key}`); } for (const field of Object.keys(record)) { if (!allowedManifestFields.has(field)) throw new Error(`Unknown Vite manifest field: ${field}`); } if (typeof record.file !== 'string' || !safeOutputPath.test(record.file)) { throw new Error(`Vite manifest contains an unsafe emitted path: ${String(record.file)}`); } for (const field of ['css', 'assets']) { for (const path of assertStringArray(record[field], `Vite manifest ${field}`)) { if (!safeOutputPath.test(path)) throw new Error(`Vite manifest contains an unsafe emitted path: ${path}`); } } for (const field of ['imports', 'dynamicImports']) { assertStringArray(record[field], `Vite manifest ${field}`); } for (const field of ['src', 'name']) { if (record[field] !== undefined && typeof record[field] !== 'string') { throw new Error(`Vite manifest ${field} must be a string.`); } } for (const field of ['isEntry', 'isDynamicEntry']) { if (record[field] !== undefined && typeof record[field] !== 'boolean') { throw new Error(`Vite manifest ${field} must be boolean.`); } } }; export const resolveViteAssetClosure = (manifest) => { if (typeof manifest !== 'object' || manifest === null || Array.isArray(manifest)) { throw new Error('Vite manifest must be an object.'); } const entry = manifest['index.html']; if (entry === undefined || entry.isEntry !== true || entry.src !== 'index.html') { throw new Error('Vite manifest must contain the exact index.html entry.'); } for (const [key, record] of Object.entries(manifest)) { validateRecord(key, record); if (key !== 'index.html' && record.isEntry === true) { throw new Error(`Unexpected additional Vite entry: ${key}`); } } const allReachable = new Set(); const staticReachable = new Set(); const visit = (key, staticImport) => { const record = manifest[key]; if (record === undefined) throw new Error(`Missing manifest import: ${key}`); if (staticImport) staticReachable.add(key); if (allReachable.has(key)) return; allReachable.add(key); for (const importedKey of record.imports ?? []) visit(importedKey, staticImport); for (const importedKey of record.dynamicImports ?? []) visit(importedKey, false); }; visit('index.html', true); const unreachable = Object.keys(manifest).filter((key) => !allReachable.has(key)); if (unreachable.length > 0) throw new Error(`Unreachable manifest record: ${unreachable.join(', ')}`); const executableModules = []; const modulePreloads = []; const styles = []; const viteAssets = []; for (const key of allReachable) { const record = manifest[key]; executableModules.push(record.file); if (staticReachable.has(key)) modulePreloads.push(record.file); styles.push(...(record.css ?? [])); viteAssets.push(...(record.assets ?? [])); } return { entryModule: entry.file, executableModules: sorted(executableModules), modulePreloads: sorted(modulePreloads), styles: sorted(styles), viteAssets: sorted(viteAssets), }; }; const assertSortedUniquePaths = (value, label) => { if (!Array.isArray(value) || value.some((path) => typeof path !== 'string' || !safeOutputPath.test(path))) { throw new Error(`${label} must contain only safe asset paths.`); } if (JSON.stringify(value) !== JSON.stringify(sorted(value))) { throw new Error(`${label} must be sorted and unique.`); } return value; }; export const parseArtifactContract = (input) => { const fields = [ 'schema', 'buildId', 'entryModule', 'executableModules', 'modulePreloads', 'styles', 'viteAssets', 'publicAssets', 'files', ]; if (typeof input !== 'object' || input === null || Array.isArray(input) || JSON.stringify(Object.keys(input).sort()) !== JSON.stringify([...fields].sort())) { throw new Error('Artifact contract has unknown or missing fields.'); } if (input.schema !== 'portfolio-artifact-contract/v1' || typeof input.buildId !== 'string' || !safeBuildId.test(input.buildId) || typeof input.entryModule !== 'string' || !safeOutputPath.test(input.entryModule)) { throw new Error('Artifact contract identity is invalid.'); } const executableModules = assertSortedUniquePaths(input.executableModules, 'Executable modules'); const modulePreloads = assertSortedUniquePaths(input.modulePreloads, 'Module preloads'); const styles = assertSortedUniquePaths(input.styles, 'Styles'); const viteAssets = assertSortedUniquePaths(input.viteAssets, 'Vite assets'); const publicAssets = assertSortedUniquePaths(input.publicAssets, 'Public assets'); if (!executableModules.includes(input.entryModule) || !modulePreloads.includes(input.entryModule) || modulePreloads.some((path) => !executableModules.includes(path))) { throw new Error('Artifact contract module closure is inconsistent.'); } if (!Array.isArray(input.files)) throw new Error('Artifact contract files must be an array.'); const files = input.files.map((record) => { if (typeof record !== 'object' || record === null || Array.isArray(record) || JSON.stringify(Object.keys(record).sort()) !== JSON.stringify(['path', 'sha256']) || typeof record.path !== 'string' || !safeOutputPath.test(record.path) || typeof record.sha256 !== 'string' || !sha256Pattern.test(record.sha256)) { throw new Error('Artifact contract file record is invalid.'); } return record; }); if (JSON.stringify(files.map((record) => record.path)) !== JSON.stringify(sorted(files.map((record) => record.path)))) { throw new Error('Artifact contract files must be sorted and unique.'); } const expectedFiles = sorted([...executableModules, ...styles, ...viteAssets, ...publicAssets]); if (JSON.stringify(files.map((record) => record.path)) !== JSON.stringify(expectedFiles)) { throw new Error('Artifact contract file inventory does not equal its trusted closure.'); } return input; }; export const createArtifactContract = (closure, publicManifest, digestByPath, buildId) => { const publicAssets = sorted(publicManifest.assets.map((asset) => `assets/${asset.fileName}`)); const expectedPaths = sorted([ ...closure.executableModules, ...closure.styles, ...closure.viteAssets, ...publicAssets, ]); const digestPaths = Object.keys(digestByPath).sort(); if (JSON.stringify(digestPaths) !== JSON.stringify(expectedPaths)) { throw new Error('Asset digests must exactly cover the trusted artifact closure.'); } return parseArtifactContract({ schema: 'portfolio-artifact-contract/v1', buildId, entryModule: closure.entryModule, executableModules: sorted(closure.executableModules), modulePreloads: sorted(closure.modulePreloads), styles: sorted(closure.styles), viteAssets: sorted(closure.viteAssets), publicAssets, files: expectedPaths.map((path) => ({ path, sha256: digestByPath[path] })), }); }; export const serializeArtifactContract = (contract) => `${JSON.stringify(parseArtifactContract(contract), null, 2)}\n`; export const createBuildAuthority = (viteManifest, artifactContract) => ({ schema: 'portfolio-build-authority/v1', viteManifest, artifactContract: parseArtifactContract(artifactContract), }); export const parseBuildAuthority = (input) => { if (typeof input !== 'object' || input === null || Array.isArray(input) || JSON.stringify(Object.keys(input).sort()) !== JSON.stringify(['artifactContract', 'schema', 'viteManifest'])) { throw new Error('Build authority has unknown or missing fields.'); } if (input.schema !== 'portfolio-build-authority/v1') throw new Error('Build authority schema is invalid.'); const closure = resolveViteAssetClosure(input.viteManifest); const contract = parseArtifactContract(input.artifactContract); for (const field of ['entryModule', 'executableModules', 'modulePreloads', 'styles', 'viteAssets']) { if (JSON.stringify(contract[field]) !== JSON.stringify(closure[field])) { throw new Error(`Build authority manifest disagrees with artifact contract: ${field}`); } } return input; }; export const serializeBuildAuthority = (authority) => `${JSON.stringify(parseBuildAuthority(authority), null, 2)}\n`;