build(site): [SITE-07] preserve historical Codicons attribution

This commit is contained in:
Harvey Zhao committed 2026-09-15 05:06:58 +08:00
1 parent a4234230e6
commit bf432ed62a
25 files changed
+1637 -18

No files matched your search

+1
View File
@@ -7,5 +7,6 @@ assert(process.argv.slice(2).every(arg => arg === '--check'), 'Use yarn build:si
/** @type {import('./site-vendor/notices.ts').VendorManifest} */
const manifest = JSON.parse(fs.readFileSync('scripts/site-vendor/manifest.json', 'utf8'))
assert.deepEqual(manifest.groups.map(group => group.name).sort(), ['monaco-editor', 'vconsole'], 'Do not silently drop a verified site component')
assert.deepEqual(manifest.groups.flatMap(group => (group.components || []).map(component => component.name)), ['@vscode/codicons'], 'Do not silently drop the verified Codicons attribution')
const count = writeOrCheckNotices(process.cwd(), manifest, process.argv.includes('--check'))
console.log(`Verified site notices: ${count} outputs; Monaco/vConsole only, other provenance gates remain open.`)
+23 -5
View File
@@ -5,9 +5,11 @@ archives, corresponding files and upstream notice texts. It does not clear other
site dependencies or grant rights to samples/fonts. The vConsole LICENSE is
preserved verbatim but is incomplete: it promises an MIT copy that is absent.
Its completion and bundled dependency notices remain open under SITE-07.
Monaco's supplied notices also lack a Codicons entry. Match the included font to
its historical source and attribution before claiming the font review complete;
the Monaco MIT statement does not establish the separate font's license.
Monaco's supplied notices lack a Codicons entry. The bundled font now has an
exact byte match to the official `@vscode/codicons@0.0.26` archive. Its historical
README, CC BY 4.0 content license and MIT code license are preserved, alongside
ArtPlayer's attribution, in `docs/licenses/monaco-editor/codicons/`. This evidence
does not derive the font license from Monaco's MIT statement or today's Codicons.
`notices.ts` validates the exact file inventory and fingerprints before preparing
outputs. JavaScript/CSS comparisons normalize CRLF to LF; font bytes are exact.
@@ -18,13 +20,20 @@ files retain their exact upstream bytes, including final blank lines.
`../build-site-notices.mjs` provides `yarn build:site-notices` and read-only
`yarn check:site-notices`. The write command cannot bless altered vendor assets;
review the new archive and license evidence before changing the manifest. The
CLI prevents accidentally dropping either verified component. Source notices
CLI prevents accidentally dropping either verified group or the Codicons component.
Component references require their runtime assets and every notice before writing.
Source notices
live in `refactor/baselines/site-vendor/`; generated delivery files live under
`docs/licenses/` with an explicitly limited `docs/THIRD_PARTY_NOTICES.md` index.
CI runs the read-only check before building, and generation during ci:build.
Library builds remain independent. Pages preparation copies the notices into its
own fingerprinted site. `.gitattributes` preserves text bytes across Windows/Linux.
The historical Codicons files use explicit `-text` overrides to retain archive
CRLF bytes. Their frozen README source uses `.txt` to avoid interpreting upstream
repository links as local refactor links; delivery restores `README.md` unchanged.
Only these immutable upstream paths allow their original trailing whitespace;
the notice hash check, rather than formatting, protects their contents.
`yarn test:site-notices` tests missing/extra/modified assets, changed or incomplete
inputs, path escape and read-only output drift. The browser fixture
@@ -34,6 +43,15 @@ old-build reproduction are maintained in `vconsole/README.md`; generated asset
checks run before the notice checks. Do not skip destruction or catch page errors.
Existing desktop TypeScript editor tests cover the real Monaco worker and Run.
Follow-up: restore complete licensing from fixed upstream evidence, then recover the
The Codicons archive identity, integrity, notice members and negative comparison
with version 0.0.25 are recorded in `refactor/baselines/site-codicons-provenance.json`.
For an independent reproduction, download the pinned `comparisons[0].tarball` into
an ignored cache directory. In Node, verify its SHA-512 SRI and SHA-256 against
that record before using `execFileSync('tar', ['-xOzf', archive, member])` to read
members as Buffers. Compare `package/dist/codicon.ttf` directly with `fontPath`,
and each non-null notice member with its frozen `source`. Do not pipe binary font
output through PowerShell text redirection. No dependency installation is needed.
Follow-up: finish the broader bundled-component notice audit, then recover the
console.js build and resolve remaining fonts/media. Do not upgrade these assets
without verifying globals, AMD/worker paths, CSS, consoleLog and user interaction.
+37 -1
View File
@@ -744,9 +744,45 @@
"source": "refactor/baselines/site-vendor/monaco-editor-ThirdPartyNotices.txt.txt",
"target": "docs/licenses/monaco-editor/ThirdPartyNotices.txt",
"sha256": "b23ab6e9a1a31ce6948a98b16a83474c999a384ece75643dd0affc83ea1724ef"
},
{
"source": "refactor/baselines/site-vendor/codicons-0.0.26/LICENSE",
"target": "docs/licenses/monaco-editor/codicons/LICENSE",
"sha256": "d6239afa918961b465b07bf7411cbe34ff6685854f58553db7966f4881a0211f"
},
{
"source": "refactor/baselines/site-vendor/codicons-0.0.26/LICENSE-CODE",
"target": "docs/licenses/monaco-editor/codicons/LICENSE-CODE",
"sha256": "9906940f61b1f0b533fa7d99baf55178b2808fbe113ea51dfbfad8572ccd5f2b"
},
{
"source": "refactor/baselines/site-vendor/codicons-0.0.26/README.txt",
"target": "docs/licenses/monaco-editor/codicons/README.md",
"sha256": "3d53172e204bcbf282c360fe58bf0697de97ddd27c964a6e48823fb4f7cd6689"
},
{
"source": "refactor/baselines/site-vendor/codicons-0.0.26/ATTRIBUTION.txt",
"target": "docs/licenses/monaco-editor/codicons/ATTRIBUTION.md",
"sha256": "ac4a57ce60aebaec1796b715d075273c4fd849853cd943fb92790c61ad038a5f"
}
],
"review": "The upstream Monaco LICENSE and ThirdPartyNotices are retained in full. The included codicon.ttf still needs matching Codicons version/attribution evidence; the Monaco package license alone does not close that font review."
"review": "The complete upstream Monaco LICENSE/ThirdPartyNotices are retained. The unmodified bundled Codicons font exactly matches @vscode/codicons 0.0.26; its historical README, CC BY 4.0 content license, MIT code license and added attribution are distributed below. Other site assets remain subject to their separate provenance reviews.",
"components": [
{
"name": "@vscode/codicons",
"version": "0.0.26",
"tarball": "https://registry.npmjs.org/@vscode/codicons/-/codicons-0.0.26.tgz",
"assets": [
"docs/assets/js/vs/base/browser/ui/codicons/codicon/codicon.ttf"
],
"notices": [
"docs/licenses/monaco-editor/codicons/LICENSE",
"docs/licenses/monaco-editor/codicons/LICENSE-CODE",
"docs/licenses/monaco-editor/codicons/README.md",
"docs/licenses/monaco-editor/codicons/ATTRIBUTION.md"
]
}
]
}
]
}
+16 -1
View File
@@ -5,7 +5,14 @@ import path from 'node:path'
interface Asset { path: string, sha256: string, mode: string }
interface Notice { source: string, target: string, sha256: string }
interface Group { name: string, version: string, tarball: string, review?: string, roots: string[], files: Asset[], notices: Notice[] }
interface Component {
name: string
version: string
tarball: string
assets: string[]
notices: string[]
}
interface Group { name: string, version: string, tarball: string, review?: string, roots: string[], files: Asset[], notices: Notice[], components?: Component[] }
export interface VendorManifest { schemaVersion: number, scope: string, groups: Group[] }
const hash = (bytes: Uint8Array) => createHash('sha256').update(bytes).digest('hex')
@@ -44,6 +51,14 @@ export function generateNotices(root: string, manifest: VendorManifest): Map<str
summary.push(`## ${group.name} ${group.version}`, '', `Source: ${group.tarball}`, '')
if (group.review)
summary.push(group.review, '')
for (const component of group.components || []) {
assert(component.assets.length > 0 && component.notices.length > 0, `Missing component evidence: ${component.name}`)
for (const asset of component.assets)
assert(group.files.some(file => file.path === asset), `Missing component asset: ${asset}`)
for (const target of component.notices)
assert(group.notices.some(notice => notice.target === target), `Missing component notice: ${target}`)
summary.push(`Included component: ${component.name} ${component.version}`, '', `Source: ${component.tarball}`, '')
}
for (const notice of group.notices) {
const bytes = fs.readFileSync(resolve(root, notice.source))
assert.equal(hash(bytes), notice.sha256, `Upstream notice changed: ${notice.source}`)