build(site): [SITE-07] reproduce console-feed vendor modules

This commit is contained in:
Harvey Zhao committed 2026-09-15 06:29:06 +08:00
1 parent 3dba82a453
commit b47ede011a
13 files changed
+663 -9

No files matched your search

+31
View File
@@ -67,3 +67,34 @@ No new dependency is required. Existing esbuild 0.27.7 and TypeScript 5.9.3 prov
generation and structural parsing. Full console dependency provenance and notices
remain SITE-07 / VENDOR-08; this build does not close them. See
`refactor/console-modernization.md` for contracts and evidence.
## Historical source reconstruction
`refactor/baselines/console-feed-provenance.json` maps all 32 modules reachable
through relative imports from m6b6 to the official console-feed 3.2.2 archive.
Their rebuilt bodies exactly match the frozen bundle. The 68 remaining vendor
modules and Parcel wrapper need further provenance; this does not establish a
unique original installed version or recover its missing lockfile.
```sh
node scripts/site-vendor/console/reproduce.ts --fetch
node scripts/site-vendor/console/reproduce.ts
yarn test:site-console
```
The first command downloads two pinned npm archives into the dedicated ignored
`refactor/.cache/console-feed-reproduction/` directory. The second uses that cache
offline. Both verify SHA-512 SRI, archive SHA-256, source member fingerprints,
compiler bytes and exact output. They load Terser 3.17.0 as a historical build
tool with the already installed source-map 0.6.1; they do not install dependencies,
change Yarn or execute the archived console-feed runtime. Canonical Node is required.
The minification recipe is recovered from Parcel 1.12.5's archive; this proves a
reproducing transform, not that the original author used precisely that Parcel
version. `provenance.ts` separately verifies complete traversal, relative source
mapping and external dependency boundaries. Missing, unreachable, duplicate or
changed evidence fails instead of silently shrinking the comparison.
The archived LICENSE is preserved verbatim with its Facebook attribution under
`refactor/baselines/site-vendor/console-feed-3.2.2-LICENSE.txt`. Do not rewrite it
or infer it covers every embedded/external component. Complete notices remain
open, including the bundled replicator and remaining dependencies.
+84
View File
@@ -0,0 +1,84 @@
import assert from 'node:assert/strict'
import { createHash } from 'node:crypto'
import path from 'node:path'
import ts from 'typescript'
export interface Module { id: string, body: string, dependencies: Record<string, string> }
export interface Source { id: string, member: string, sourceSha256: string, generatedSha256: string, bodySha256: string }
export interface External { from: string, dependency: string, id: string }
export interface Archive { name: string, version: string, tarball: string, integrity: string, sha256: string }
export const hash = (bytes: string | Uint8Array) => createHash('sha256').update(bytes).digest('hex')
export function verifyArchive(bytes: Uint8Array, archive: Archive) {
const [algorithm, expected] = archive.integrity.split('-')
assert(algorithm === 'sha512' && expected, 'Expected SHA-512 archive integrity')
assert.equal(createHash(algorithm).update(bytes).digest('base64'), expected, `Archive integrity changed: ${archive.name}`)
assert.equal(hash(bytes), archive.sha256, `Archive bytes changed: ${archive.name}`)
}
export function parcelModules(text: string): Map<string, Module> {
const source = ts.createSourceFile('console.js', text, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS)
let table: ts.ObjectLiteralExpression | undefined
function visit(node: ts.Node) {
if (ts.isObjectLiteralExpression(node) && node.properties.some(property => property.name && ts.isStringLiteral(property.name) && property.name.text === 'Focm')) {
assert(!table, 'Duplicate Parcel module tables')
table = node
}
ts.forEachChild(node, visit)
}
visit(source)
assert(table, 'Missing Parcel module table')
const result = new Map<string, Module>()
for (const property of table.properties) {
assert(ts.isPropertyAssignment(property) && ts.isStringLiteral(property.name) && ts.isArrayLiteralExpression(property.initializer))
const [fn, deps] = property.initializer.elements
assert(fn && ts.isFunctionExpression(fn) && deps && ts.isObjectLiteralExpression(deps))
const id = property.name.text
assert(!result.has(id), `Duplicate Parcel module: ${id}`)
const dependencies: Record<string, string> = {}
for (const dep of deps.properties) {
assert(ts.isPropertyAssignment(dep) && ts.isStringLiteral(dep.name) && ts.isStringLiteral(dep.initializer))
assert(!(dep.name.text in dependencies), 'Duplicate Parcel dependency')
dependencies[dep.name.text] = dep.initializer.text
}
result.set(id, { id, dependencies, body: text.slice(fn.body.getStart(source) + 1, fn.body.end - 1).trim() })
}
return result
}
export function verifyModules(modules: Map<string, Module>, sources: Source[], external: External[], read: (member: string) => string, compile: (source: string) => string) {
const mapped = new Map(sources.map(source => [source.id, source]))
assert.equal(mapped.size, sources.length, 'Duplicate source mapping')
const visited = new Set<string>()
const dependencies: External[] = []
function visit(id: string) {
if (visited.has(id))
return
const item = mapped.get(id)
const module = modules.get(id)
assert(item && module, `Missing console-feed module mapping: ${id}`)
assert(item.member.startsWith('package/lib/') && item.member.endsWith('.js') && path.posix.normalize(item.member) === item.member, 'Invalid source member')
visited.add(id)
const source = read(item.member)
assert.equal(hash(source), item.sourceSha256, `Source changed: ${item.member}`)
const compiled = compile(source)
assert.equal(hash(compiled), item.generatedSha256, `Compiler output changed: ${id}`)
assert.equal(hash(module.body), item.bodySha256, `Frozen module changed: ${id}`)
assert.equal(compiled, module.body, `Rebuilt module differs: ${id}`)
for (const [dependency, child] of Object.entries(module.dependencies)) {
assert(modules.has(child), `Unresolved Parcel dependency: ${child}`)
if (!dependency.startsWith('.')) {
dependencies.push({ from: id, dependency, id: child })
continue
}
const base = path.posix.join(path.posix.dirname(item.member), dependency)
const target = mapped.get(child)?.member
assert(target && [base, `${base}.js`, `${base}/index.js`].includes(target), `Source dependency mapping changed: ${id} ${dependency}`)
visit(child)
}
}
visit('m6b6')
assert.equal(visited.size, sources.length, 'Unreachable source mapping')
assert.deepEqual(dependencies, external, 'External dependency boundary changed')
return visited.size
}
+60
View File
@@ -0,0 +1,60 @@
import type { Archive, External, Source } from './provenance.ts'
import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
import fs from 'node:fs'
import { createRequire } from 'node:module'
import path from 'node:path'
import process from 'node:process'
import { fileURLToPath } from 'node:url'
import { hash, parcelModules, verifyArchive, verifyModules } from './provenance.ts'
interface CompilerOptions { warnings: boolean, safari10: boolean, mangle: { toplevel: boolean } }
interface Provenance {
archive: Archive
frozen: { path: string, sha256: string }
compiler: { archive: Archive, member: string, sha256: string, sourceMapVersion: string, options: CompilerOptions }
sources: Source[]
external: External[]
}
interface Minifier { minify: (source: string, options: CompilerOptions) => { code?: string, error?: unknown } }
const root = fileURLToPath(new URL('../../../', import.meta.url))
const record: Provenance = JSON.parse(fs.readFileSync(path.join(root, 'refactor/baselines/console-feed-provenance.json'), 'utf8'))
assert(process.argv.slice(2).every(arg => arg === '--fetch'), 'Use reproduce.ts [--fetch]')
assert.equal(process.version, `v${fs.readFileSync(path.join(root, '.node-version'), 'utf8').trim()}`, 'Use canonical Node')
const cacheRoot = fs.realpathSync(path.join(root, 'refactor/.cache'))
const cache = path.join(cacheRoot, 'console-feed-reproduction')
fs.mkdirSync(cache, { recursive: true })
assert.equal(fs.realpathSync(cache), cache, 'Reproduction cache must not redirect')
for (const archive of [record.archive, record.compiler.archive]) {
const target = path.join(cache, `${archive.name}-${archive.version}.tgz`)
if (process.argv.includes('--fetch')) {
const response = await fetch(archive.tarball)
assert(response.ok, `Archive request failed: ${response.status}`)
const bytes = new Uint8Array(await response.arrayBuffer())
verifyArchive(bytes, archive)
fs.writeFileSync(target, bytes)
}
verifyArchive(fs.readFileSync(target), archive)
}
const readMember = (name: string, member: string) => execFileSync('tar', ['-xOzf', path.join(cache, name), member], { maxBuffer: 8 * 1024 * 1024 })
const compilerBytes = readMember('terser-3.17.0.tgz', record.compiler.member)
assert.equal(hash(compilerBytes), record.compiler.sha256, 'Compiler member changed')
const compilerPath = path.join(cache, 'terser.cjs')
fs.writeFileSync(compilerPath, compilerBytes)
const require = createRequire(compilerPath)
assert.equal(require('source-map/package.json').version, record.compiler.sourceMapVersion, 'Source-map dependency changed')
const { minify } = require(compilerPath) as Minifier
const frozen = fs.readFileSync(path.join(root, record.frozen.path), 'utf8')
assert.equal(hash(frozen), record.frozen.sha256, 'Frozen console changed')
assert.equal(record.sources.length, 32, 'Incomplete console-feed scope')
const count = verifyModules(parcelModules(frozen), record.sources, record.external, member => readMember('console-feed-3.2.2.tgz', member).toString('utf8'), (source) => {
const result = minify(source, record.compiler.options)
if (result.error)
throw result.error
assert(typeof result.code === 'string')
return result.code
})
console.log(JSON.stringify({ exactModules: count, totalVendorModules: 100, archive: record.archive.sha256, licenseClosure: false }))