import assert from 'node:assert/strict' import crypto from 'node:crypto' import fsp from 'node:fs/promises' import os from 'node:os' import path from 'node:path' import { pathToFileURL } from 'node:url' import { build } from 'esbuild' import { DEFAULT_BASE_URL, DEFAULT_PUBLIC_KEY, REPO_ROOT, generateEd25519KeyPair, normalizeBaseUrl, readPublicKey, signPayload } from './lib.mjs' async function main() { const temporary = await fsp.mkdtemp(path.join(os.tmpdir(), 'ycode-contract-selftest-')) try { const bundlePath = path.join(temporary, 'manifest.mjs') await build({ entryPoints: [path.join(REPO_ROOT, 'src', 'main', 'updates', 'manifest.ts')], bundle: true, platform: 'node', format: 'esm', outfile: bundlePath, logLevel: 'silent' }) const backend = await import(`${pathToFileURL(bundlePath).href}?v=${Date.now()}`) assert.equal(typeof backend.verifySignedManifest, 'function') const trustAnchor = await readPublicKey(DEFAULT_PUBLIC_KEY) const trustKey = crypto.createPublicKey(trustAnchor) assert.equal(trustKey.asymmetricKeyType, 'ed25519') const keys = generateEd25519KeyPair() const baseUrl = normalizeBaseUrl(DEFAULT_BASE_URL) const payload = { schemaVersion: 1, version: '9.9.9', publishedAt: '2026-10-20T10:00:00.000Z', notes: { zh: '契约自测', en: 'Contract self-test' }, platforms: { 'windows-x64': { url: `${baseUrl}versions/9.9.9/YCode-9.9.9-Setup-x64.exe`, size: 123, sha256: 'a'.repeat(64) } } } const document = { payload, signature: signPayload(payload, keys.privatePem) } const raw = Buffer.from(`${JSON.stringify(document)}\n`, 'utf8') const verified = backend.verifySignedManifest(raw, { manifestUrl: `${baseUrl}latest.json`, publicKeyPem: keys.publicPem }) assert.equal(verified.payload.version, payload.version) assert.equal(verified.asset.url, payload.platforms['windows-x64'].url) const tampered = structuredClone(document) tampered.payload.notes.en = 'tampered' assert.throws( () => backend.verifySignedManifest(Buffer.from(JSON.stringify(tampered), 'utf8'), { manifestUrl: `${baseUrl}latest.json`, publicKeyPem: keys.publicPem }), /签名验证失败/ ) console.log('Release manifest matches update_backend parser/signature/path policy.') console.log('Repository public key is a valid Ed25519 SPKI PEM trust anchor.') } finally { await fsp.rm(temporary, { recursive: true, force: true }) } } main().catch((error) => { console.error(error) process.exitCode = 1 })