import assert from 'node:assert/strict'; import test from 'node:test'; import { buildAppDataArchive, verifyAppDataArchive, } from './lib/appdata-archive.mjs'; test('builds and verifies an AppData archive with deterministic checksums', () => { const archive = buildAppDataArchive( [ { key: 'dev-tasks', value: [{ id: 'dt-1', title: '开发任务' }], updatedAt: new Date('2026-07-08T08:00:00.000Z'), }, { key: 'products-overview', value: [{ id: 'p1', name: 'FTB' }], updatedAt: new Date('2026-07-08T08:01:00.000Z'), }, ], { appVersion: 'test-version', appBuildTime: '2026-07-08T08:02:00.000Z', exportedAt: '2026-07-08T08:03:00.000Z', sourceCommit: 'test-commit', }, ); assert.deepEqual(archive.keys, ['dev-tasks', 'products-overview']); assert.equal(archive.metadata.rowCount, 2); assert.equal(archive.metadata.keyCount, 2); assert.match(archive.metadata.payloadChecksum, /^[a-f0-9]{64}$/); const verification = verifyAppDataArchive(archive); assert.equal(verification.ok, true); assert.deepEqual(verification.errors, []); }); test('verification fails when archived row content is tampered', () => { const archive = buildAppDataArchive( [ { key: 'dev-tasks', value: [{ id: 'dt-1', title: '开发任务' }], updatedAt: new Date('2026-07-08T08:00:00.000Z'), }, ], { appVersion: 'test-version', appBuildTime: '2026-07-08T08:02:00.000Z', exportedAt: '2026-07-08T08:03:00.000Z', sourceCommit: 'test-commit', }, ); archive.rows[0].value[0].title = '被篡改'; const verification = verifyAppDataArchive(archive); assert.equal(verification.ok, false); assert.match(verification.errors.join('\n'), /checksum/i); });