mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
865 lines
25 KiB
JavaScript
865 lines
25 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { test } = require('node:test');
|
|
const {
|
|
assertPrivateEvidenceFile,
|
|
buildEvidenceReport,
|
|
mountForPath,
|
|
normalizeManifest,
|
|
parseArguments,
|
|
parseMountTable,
|
|
parseOsRelease,
|
|
readFaultEvidence,
|
|
readIdleEvidence,
|
|
readAdoptionScaleEvidence,
|
|
readApplicationStartEvidence,
|
|
readComposeStorageEvidence,
|
|
validateAdoptionScaleEvidenceReport,
|
|
validateApplicationStartEvidenceReport,
|
|
validateComposeStorageEvidenceReport,
|
|
validateFaultEvidenceReport,
|
|
validateIdleEvidenceReport,
|
|
validateObservedPlatform,
|
|
writeNoReplace,
|
|
} = require('../../scripts/ql3-physical-edge-evidence.cjs');
|
|
const {
|
|
runBenchmark: runPluginPackageRecoveryEdgeBenchmark,
|
|
} = require('../../scripts/ql3-plugin-package-recovery-edge-benchmark.cjs');
|
|
const {
|
|
buildReport: buildAdoptionScaleReport,
|
|
normalizeManifest: normalizeAdoptionScaleManifest,
|
|
} = require('../../scripts/ql3-physical-edge-adoption-scale.cjs');
|
|
const {
|
|
buildComposeStorageReport,
|
|
normalizeComposeStorageManifest,
|
|
} = require('../../scripts/ql3-physical-edge-compose-storage.cjs');
|
|
const {
|
|
buildApplicationStartReport,
|
|
normalizeApplicationStartManifest,
|
|
} = require('../../scripts/ql3-physical-edge-application-start.cjs');
|
|
|
|
test('rejects relative fault evidence paths and foreign-owned reports', () => {
|
|
assert.throws(
|
|
() =>
|
|
parseArguments([
|
|
'--manifest=/etc/ql3/device.json',
|
|
'--data-path=/data',
|
|
'--fault-evidence=relative.json',
|
|
]),
|
|
/faultEvidencePath must be absolute/,
|
|
);
|
|
const effectiveUserId = process.geteuid();
|
|
const privateFile = {
|
|
isFile: () => true,
|
|
isSymbolicLink: () => false,
|
|
mode: 0o100600,
|
|
uid: effectiveUserId,
|
|
};
|
|
assert.doesNotThrow(() =>
|
|
assertPrivateEvidenceFile(privateFile, 'supplemental evidence'),
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
assertPrivateEvidenceFile(
|
|
{ ...privateFile, uid: effectiveUserId + 1 },
|
|
'supplemental evidence',
|
|
),
|
|
/current-user-owned private regular file/,
|
|
);
|
|
});
|
|
|
|
function manifest(overrides = {}) {
|
|
return normalizeManifest({
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_candidate',
|
|
profile: 'edge',
|
|
deviceId: 'router-a1',
|
|
deviceModel: 'Example Router A1',
|
|
soc: 'Example SoC',
|
|
storageMedium: 'emmc',
|
|
expectedArchitecture: 'arm64',
|
|
memoryBytes: {
|
|
minimum: 240 * 1024 * 1024,
|
|
maximum: 320 * 1024 * 1024,
|
|
},
|
|
expectedFilesystem: 'ext4',
|
|
...overrides,
|
|
});
|
|
}
|
|
|
|
function observed(overrides = {}) {
|
|
return {
|
|
platform: 'linux',
|
|
architecture: 'arm64',
|
|
node: 'v24.18.0',
|
|
bootId: '019f0000-0000-7000-8000-000000000001',
|
|
kernel: '6.6.0',
|
|
distribution: { id: 'openwrt', versionId: '24.10' },
|
|
libc: 'musl-ld-musl-aarch64.so.1',
|
|
cpuModel: 'Example CPU',
|
|
cpuCount: 1,
|
|
totalMemoryBytes: 256 * 1024 * 1024,
|
|
observedModel: 'Example Router A1',
|
|
dataPath: '/opt/qinglong/data',
|
|
dataFilesystem: 'ext4',
|
|
dataMountOptions: ['rw', 'noatime'],
|
|
dataBytes: 4 * 1024 * 1024 * 1024,
|
|
dataAvailableBytes: 2 * 1024 * 1024 * 1024,
|
|
virtualizationIndicators: [],
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('accepts one exact physical Edge device manifest', () => {
|
|
const value = manifest();
|
|
assert.equal(value.deviceId, 'router-a1');
|
|
assert.equal(value.profile, 'edge');
|
|
assert.equal(value.memoryBytes.minimum, 240 * 1024 * 1024);
|
|
});
|
|
|
|
test('rejects widened, virtual and under-specified manifests', () => {
|
|
assert.throws(
|
|
() => manifest({ extra: true }),
|
|
/manifest keys must be exactly/,
|
|
);
|
|
assert.throws(
|
|
() => manifest({ storageMedium: 'virtual' }),
|
|
/storageMedium must be one of/,
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
manifest({
|
|
memoryBytes: { minimum: 64 * 1024 * 1024, maximum: 128 * 1024 * 1024 },
|
|
}),
|
|
/128 MiB to 64 GiB/,
|
|
);
|
|
});
|
|
|
|
test('finds the most specific data mount and parses OS identity', () => {
|
|
const mounts = parseMountTable(
|
|
'root / ext4 rw,noatime 0 0\ndata /opt/qinglong ext4 rw,nodev 0 0\ntmp /tmp tmpfs rw,nosuid 0 0\n',
|
|
);
|
|
assert.equal(
|
|
mountForPath(mounts, '/opt/qinglong/data').path,
|
|
'/opt/qinglong',
|
|
);
|
|
assert.deepEqual(parseOsRelease('ID=openwrt\nVERSION_ID="24.10"\n'), {
|
|
id: 'openwrt',
|
|
versionId: '24.10',
|
|
});
|
|
});
|
|
|
|
test('fails closed on architecture, memory, filesystem and virtualization drift', () => {
|
|
assert.deepEqual(
|
|
validateObservedPlatform(
|
|
manifest(),
|
|
observed({
|
|
architecture: 'x64',
|
|
totalMemoryBytes: 512 * 1024 * 1024,
|
|
dataFilesystem: 'overlay',
|
|
virtualizationIndicators: ['DMI'],
|
|
}),
|
|
),
|
|
[
|
|
'architecture x64 did not equal arm64',
|
|
'observed memory is outside the declared device range',
|
|
'filesystem overlay did not equal ext4',
|
|
'virtualization indicators found: DMI',
|
|
],
|
|
);
|
|
});
|
|
|
|
test('produces digest-bound candidate evidence but never supported status', async () => {
|
|
const pluginPackageRecovery = await runPluginPackageRecoveryEdgeBenchmark({
|
|
maxDatabaseGrowthBytes: 4 * 1024 * 1024,
|
|
maxDurationMs: 10_000,
|
|
maxRssDeltaBytes: 96 * 1024 * 1024,
|
|
});
|
|
const workloads = [
|
|
{
|
|
name: 'edge-executor',
|
|
report: {
|
|
schemaVersion: 1,
|
|
profile: 'edge',
|
|
host: { platform: 'linux', architecture: 'arm64' },
|
|
gates: { passed: true, violations: [] },
|
|
},
|
|
},
|
|
{
|
|
name: 'node-sqlite-on-device-storage',
|
|
report: {
|
|
platform: 'linux',
|
|
arch: 'arm64',
|
|
journalMode: 'delete',
|
|
synchronous: 'full',
|
|
integrityCheck: 'ok',
|
|
databaseBytes: 16_384,
|
|
rssDeltaMb: 1,
|
|
},
|
|
},
|
|
{
|
|
name: 'plugin-package-failed-upgrade',
|
|
report: {
|
|
...pluginPackageRecovery,
|
|
identity: {
|
|
...pluginPackageRecovery.identity,
|
|
platform: 'linux',
|
|
architecture: 'arm64',
|
|
},
|
|
},
|
|
},
|
|
];
|
|
const report = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads,
|
|
generatedAt: '2026-07-22T00:00:00.000Z',
|
|
});
|
|
assert.equal(report.supported, false);
|
|
assert.equal(report.qualification.physicalCandidate, true);
|
|
assert.ok(
|
|
report.qualification.collectedEvidence.includes(
|
|
'plugin_package_failed_upgrade_retains_active_generation',
|
|
),
|
|
);
|
|
assert.equal(report.sha256.length, 64);
|
|
const foreignWorkload = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads: [
|
|
workloads[0],
|
|
workloads[1],
|
|
{
|
|
...workloads[2],
|
|
report: {
|
|
...workloads[2].report,
|
|
identity: {
|
|
...workloads[2].report.identity,
|
|
platform: 'darwin',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
generatedAt: '2026-07-22T00:00:00.000Z',
|
|
});
|
|
assert.equal(foreignWorkload.qualification.physicalCandidate, false);
|
|
assert.match(
|
|
foreignWorkload.qualification.violations.join('; '),
|
|
/runtime identity did not match/,
|
|
);
|
|
const changed = buildEvidenceReport({
|
|
manifest: manifest({ deviceId: 'router-a2' }),
|
|
observed: observed(),
|
|
workloads: [],
|
|
generatedAt: '2026-07-22T00:00:00.000Z',
|
|
});
|
|
assert.equal(changed.qualification.physicalCandidate, false);
|
|
assert.ok(
|
|
changed.qualification.remainingRequiredEvidence.includes(
|
|
'plugin_package_failed_upgrade_retains_active_generation',
|
|
),
|
|
);
|
|
assert.notEqual(changed.sha256, report.sha256);
|
|
});
|
|
|
|
test('requires canonical absolute input paths', () => {
|
|
assert.deepEqual(
|
|
parseArguments([
|
|
'--',
|
|
'--manifest=/etc/ql3/device.json',
|
|
'--data-path=/opt/qinglong/data',
|
|
'--output=/opt/qinglong/evidence.json',
|
|
'--idle-evidence=/opt/qinglong/idle.json',
|
|
'--adoption-scale-evidence=/opt/qinglong/adoption.json',
|
|
'--compose-storage-evidence=/opt/qinglong/compose-storage.json',
|
|
'--application-start-evidence=/opt/qinglong/application-start.json',
|
|
'--fault-evidence=/opt/qinglong/enospc.json',
|
|
'--fault-evidence=/opt/qinglong/readonly.json',
|
|
'--json',
|
|
]),
|
|
{
|
|
manifestPath: '/etc/ql3/device.json',
|
|
dataPath: '/opt/qinglong/data',
|
|
outputPath: '/opt/qinglong/evidence.json',
|
|
idleEvidencePath: '/opt/qinglong/idle.json',
|
|
adoptionScaleEvidencePath: '/opt/qinglong/adoption.json',
|
|
composeStorageEvidencePath: '/opt/qinglong/compose-storage.json',
|
|
applicationStartEvidencePath: '/opt/qinglong/application-start.json',
|
|
faultEvidencePaths: [
|
|
'/opt/qinglong/enospc.json',
|
|
'/opt/qinglong/readonly.json',
|
|
],
|
|
json: true,
|
|
},
|
|
);
|
|
assert.throws(
|
|
() => parseArguments(['--manifest=device.json', '--data-path=/data']),
|
|
/manifestPath must be absolute/,
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
parseArguments([
|
|
'--',
|
|
'--',
|
|
'--manifest=/etc/ql3/device.json',
|
|
'--data-path=/data',
|
|
]),
|
|
/unsupported argument --/,
|
|
);
|
|
});
|
|
|
|
test('imports exact same-boot ENOSPC and read-only evidence independently', (t) => {
|
|
const directory = fs.realpathSync(
|
|
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-fault-import-test-')),
|
|
);
|
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
const createFault = (fault) => {
|
|
const errorCode = fault === 'enospc_filesystem' ? 'ENOSPC' : 'EROFS';
|
|
const body = {
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_fault_candidate',
|
|
supported: false,
|
|
generatedAt: '2026-07-22T00:00:00.000Z',
|
|
manifest: {
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_fault_candidate',
|
|
profile: 'edge',
|
|
deviceId: 'router-a1',
|
|
fault,
|
|
probePath: `/mnt/${fault}`,
|
|
expectedFilesystem: 'ext4',
|
|
maximumFilesystemBytes: 64 * 1024 * 1024,
|
|
},
|
|
observed: {
|
|
platform: 'linux',
|
|
architecture: 'arm64',
|
|
node: 'v24.18.0',
|
|
bootId: observed().bootId,
|
|
processUid: 1000,
|
|
probePath: `/mnt/${fault}`,
|
|
mountPath: `/mnt/${fault}`,
|
|
filesystem: 'ext4',
|
|
mountOptions: [fault === 'enospc_filesystem' ? 'rw' : 'ro', 'nodev'],
|
|
totalBytes: 32 * 1024 * 1024,
|
|
availableBytes: fault === 'enospc_filesystem' ? 0 : 4096,
|
|
expectedErrorCode: errorCode,
|
|
probeEntryCreated: false,
|
|
probeEntryRemained: false,
|
|
},
|
|
qualification: {
|
|
passed: true,
|
|
violations: [],
|
|
scope: fault,
|
|
doesNotProve: [
|
|
'main_data_filesystem_fault',
|
|
'application_level_recovery',
|
|
'power_loss_survival',
|
|
],
|
|
},
|
|
};
|
|
return {
|
|
...body,
|
|
sha256: require('node:crypto')
|
|
.createHash('sha256')
|
|
.update(JSON.stringify(body))
|
|
.digest('hex'),
|
|
};
|
|
};
|
|
const enospc = createFault('enospc_filesystem');
|
|
const readonly = createFault('read_only_filesystem');
|
|
assert.deepEqual(
|
|
validateFaultEvidenceReport(enospc, manifest(), observed()),
|
|
[],
|
|
);
|
|
const enospcPath = path.join(directory, 'enospc.json');
|
|
writeNoReplace(enospcPath, `${JSON.stringify(enospc)}\n`);
|
|
assert.equal(
|
|
readFaultEvidence(enospcPath, manifest(), observed()).manifest.fault,
|
|
'enospc_filesystem',
|
|
);
|
|
const report = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads: [],
|
|
supplementalEvidence: [enospc, readonly],
|
|
generatedAt: '2026-07-22T00:01:00.000Z',
|
|
});
|
|
assert.ok(
|
|
report.qualification.collectedEvidence.includes('real_enospc_filesystem'),
|
|
);
|
|
assert.ok(
|
|
report.qualification.collectedEvidence.includes('read_only_filesystem'),
|
|
);
|
|
assert.ok(
|
|
!report.qualification.remainingRequiredEvidence.includes(
|
|
'real_enospc_filesystem',
|
|
),
|
|
);
|
|
assert.ok(
|
|
!report.qualification.remainingRequiredEvidence.includes(
|
|
'read_only_filesystem',
|
|
),
|
|
);
|
|
const widened = {
|
|
...enospc,
|
|
observed: { ...enospc.observed, availableBytes: 4096 },
|
|
};
|
|
assert.match(
|
|
validateFaultEvidenceReport(widened, manifest(), observed()).join('; '),
|
|
/SHA-256 did not match.*ENOSPC evidence did not prove/,
|
|
);
|
|
});
|
|
|
|
test('imports one same-device 100000-row adoption report into aggregate evidence', (t) => {
|
|
const directory = fs.realpathSync(
|
|
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-adoption-import-test-')),
|
|
);
|
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
const adoptionManifest = normalizeAdoptionScaleManifest({
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_adoption_scale_candidate',
|
|
profile: 'edge',
|
|
deviceId: manifest().deviceId,
|
|
expectedArchitecture: manifest().expectedArchitecture,
|
|
expectedFilesystem: manifest().expectedFilesystem,
|
|
rowCount: 100_000,
|
|
maxReviewFileBytes: 32 * 1024 * 1024,
|
|
});
|
|
const measurement = {
|
|
durationMs: 100,
|
|
peakRssBytes: 30_000_000,
|
|
sampleCount: 10,
|
|
readBytes: 4096,
|
|
writeBytes: 8192,
|
|
cancelledWriteBytes: 0,
|
|
exitCode: 0,
|
|
};
|
|
const adoption = buildAdoptionScaleReport({
|
|
manifest: adoptionManifest,
|
|
observed: observed(),
|
|
preflight: {
|
|
sourceRowCount: 100_000,
|
|
reviewFileBytes: 20_000_000,
|
|
targetLedgerCount: 0,
|
|
targetStorage: {
|
|
logicalBytes: 4096,
|
|
allocatedBytes: 4096,
|
|
files: [],
|
|
},
|
|
},
|
|
issue: measurement,
|
|
commit: measurement,
|
|
final: {
|
|
ledgerCount: 1,
|
|
adoptedTaskCount: 100_000,
|
|
adoptedTriggerCount: 100_000,
|
|
targetStorage: {
|
|
logicalBytes: 8192,
|
|
allocatedBytes: 8192,
|
|
files: [],
|
|
},
|
|
},
|
|
generatedAt: '2026-07-22T00:00:00.000Z',
|
|
});
|
|
assert.deepEqual(
|
|
validateAdoptionScaleEvidenceReport(adoption, manifest(), observed()),
|
|
[],
|
|
);
|
|
const evidencePath = path.join(directory, 'adoption.json');
|
|
writeNoReplace(evidencePath, `${JSON.stringify(adoption)}\n`);
|
|
assert.equal(
|
|
readAdoptionScaleEvidence(evidencePath, manifest(), observed()).sha256,
|
|
adoption.sha256,
|
|
);
|
|
const aggregate = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads: [],
|
|
supplementalEvidence: [adoption],
|
|
generatedAt: '2026-07-22T00:01:00.000Z',
|
|
});
|
|
assert.ok(
|
|
aggregate.qualification.collectedEvidence.includes(
|
|
'legacy_adoption_100000_row_scaling',
|
|
),
|
|
);
|
|
assert.ok(
|
|
!aggregate.qualification.remainingRequiredEvidence.includes(
|
|
'legacy_adoption_100000_row_scaling',
|
|
),
|
|
);
|
|
assert.match(
|
|
validateAdoptionScaleEvidenceReport(
|
|
{ ...adoption, sha256: '0'.repeat(64) },
|
|
manifest(),
|
|
observed(),
|
|
).join('; '),
|
|
/SHA-256/,
|
|
);
|
|
});
|
|
|
|
test('imports only private digest-bound idle evidence from the same device boot', (t) => {
|
|
const directory = fs.realpathSync(
|
|
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-idle-import-test-')),
|
|
);
|
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
const idleManifest = {
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_idle_candidate',
|
|
profile: 'edge',
|
|
deviceId: 'router-a1',
|
|
processId: 123,
|
|
expectedExecutable: '/usr/bin/node',
|
|
durationSeconds: 30,
|
|
sampleIntervalMs: 10_000,
|
|
};
|
|
const body = {
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_idle_candidate',
|
|
supported: false,
|
|
generatedAt: '2026-07-22T00:00:00.000Z',
|
|
manifest: idleManifest,
|
|
identity: {
|
|
platform: 'linux',
|
|
architecture: 'arm64',
|
|
node: 'v24.18.0',
|
|
bootId: observed().bootId,
|
|
processId: 123,
|
|
processUid: 1000,
|
|
executable: '/usr/bin/node',
|
|
commandSha256: 'a'.repeat(64),
|
|
startTicks: 100,
|
|
},
|
|
summary: { sampleCount: 4, actualDurationMs: 30_000 },
|
|
qualification: {
|
|
passed: true,
|
|
violations: [],
|
|
measures: [
|
|
'process_rss',
|
|
'process_cpu_ticks',
|
|
'process_context_switches',
|
|
'process_io',
|
|
],
|
|
doesNotProve: [
|
|
'whole_device_cpu_wakeups',
|
|
'whole_device_flash_write_amplification',
|
|
'cold_start_or_first_ready',
|
|
],
|
|
},
|
|
};
|
|
const idle = {
|
|
...body,
|
|
sha256: require('node:crypto')
|
|
.createHash('sha256')
|
|
.update(JSON.stringify(body))
|
|
.digest('hex'),
|
|
};
|
|
assert.deepEqual(
|
|
validateIdleEvidenceReport(idle, manifest(), observed()),
|
|
[],
|
|
);
|
|
const idlePath = path.join(directory, 'idle.json');
|
|
writeNoReplace(idlePath, `${JSON.stringify(idle)}\n`);
|
|
assert.equal(
|
|
readIdleEvidence(idlePath, manifest(), observed()).sha256,
|
|
idle.sha256,
|
|
);
|
|
const report = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads: [],
|
|
supplementalEvidence: [idle],
|
|
generatedAt: '2026-07-22T00:01:00.000Z',
|
|
});
|
|
assert.deepEqual(report.qualification.collectedEvidence, [
|
|
'idle_process_rss_cpu_ticks_context_switches_and_io',
|
|
]);
|
|
assert.ok(
|
|
!report.qualification.remainingRequiredEvidence.includes(
|
|
'idle_process_rss_cpu_ticks_context_switches_and_io',
|
|
),
|
|
);
|
|
assert.ok(
|
|
report.qualification.remainingRequiredEvidence.includes(
|
|
'whole_device_cpu_wakeups_and_flash_write_amplification',
|
|
),
|
|
);
|
|
const drifted = {
|
|
...idle,
|
|
identity: { ...idle.identity, bootId: 'different' },
|
|
};
|
|
assert.match(
|
|
validateIdleEvidenceReport(drifted, manifest(), observed()).join('; '),
|
|
/SHA-256 did not match.*runtime identity did not match/,
|
|
);
|
|
});
|
|
|
|
test('publishes private evidence without replacing an existing record', (t) => {
|
|
const directory = fs.realpathSync(
|
|
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-evidence-test-')),
|
|
);
|
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
const outputPath = path.join(directory, 'evidence.json');
|
|
writeNoReplace(outputPath, '{"schemaVersion":1}\n');
|
|
assert.equal(fs.statSync(outputPath).mode & 0o777, 0o600);
|
|
assert.equal(fs.readFileSync(outputPath, 'utf8'), '{"schemaVersion":1}\n');
|
|
assert.throws(
|
|
() => writeNoReplace(outputPath, 'replacement'),
|
|
(error) => error?.code === 'EEXIST',
|
|
);
|
|
});
|
|
|
|
test('imports a different-boot Compose collection storage candidate without widening power-loss claims', (t) => {
|
|
const directory = fs.realpathSync(
|
|
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-compose-storage-import-')),
|
|
);
|
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
const supplementalManifest = normalizeComposeStorageManifest({
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_compose_storage_candidate',
|
|
profile: 'edge',
|
|
deviceId: manifest().deviceId,
|
|
expectedArchitecture: manifest().expectedArchitecture,
|
|
expectedFilesystem: manifest().expectedFilesystem,
|
|
snapshotCount: 3,
|
|
databasePayloadBytes: 4 * 1024 * 1024,
|
|
maximumPrepareWriteAmplificationPermille: 50_000,
|
|
maximumResumeWriteAmplificationPermille: 50_000,
|
|
});
|
|
const targetSnapshot = {
|
|
contractVersion: 44,
|
|
sha256: 'a'.repeat(64),
|
|
bytes: 4_000_000,
|
|
pageCount: 1000,
|
|
pageSize: 4096,
|
|
};
|
|
const before = {
|
|
platform: 'linux',
|
|
architecture: 'arm64',
|
|
bootId: '019f0000-0000-4000-8000-000000000001',
|
|
mountPath: observed().dataPath,
|
|
filesystem: 'ext4',
|
|
mountOptions: ['rw', 'noatime'],
|
|
blockDevice: '/dev/mmcblk0p3',
|
|
sectorsWritten: 10_000,
|
|
};
|
|
const afterStart = {
|
|
...before,
|
|
bootId: observed().bootId,
|
|
sectorsWritten: 200,
|
|
};
|
|
const after = { ...afterStart, sectorsWritten: 220 };
|
|
const session = {
|
|
sessionId: '019f0000-0000-4000-8000-000000000010',
|
|
sha256: 'b'.repeat(64),
|
|
preparedAt: '2026-07-29T00:00:00.000Z',
|
|
dataPath: observed().dataPath,
|
|
collection: {
|
|
target: {
|
|
rolloutId: '019f0000-0000-4000-8000-000000000011',
|
|
snapshot: targetSnapshot,
|
|
},
|
|
},
|
|
};
|
|
const composeStorage = buildComposeStorageReport({
|
|
manifest: supplementalManifest,
|
|
session,
|
|
observed: { before, afterStart, after },
|
|
measurements: {
|
|
logicalSnapshotBytes: 12_000_000,
|
|
collectedSnapshotBytes: 4_000_000,
|
|
prepareDeviceBytesWritten: 24_000_000,
|
|
resumeDeviceBytesWritten: 10_240,
|
|
prepareWriteAmplificationPermille: 2000,
|
|
resumeWriteAmplificationPermille: 3,
|
|
barrierAllocatedBytes: 20_500_000,
|
|
finalAllocatedBytes: 16_400_000,
|
|
reclaimedAllocatedBytes: 4_100_000,
|
|
},
|
|
outcomes: {
|
|
commitStatus: 'collected',
|
|
replayStatus: 'existing',
|
|
sqliteIntegrity: 'ok',
|
|
stageRemoved: true,
|
|
tombstonePresent: true,
|
|
retainedSnapshots: 2,
|
|
},
|
|
generatedAt: '2026-07-29T00:01:00.000Z',
|
|
});
|
|
assert.deepEqual(
|
|
validateComposeStorageEvidenceReport(
|
|
composeStorage,
|
|
manifest(),
|
|
observed(),
|
|
),
|
|
[],
|
|
);
|
|
const evidencePath = path.join(directory, 'compose-storage.json');
|
|
writeNoReplace(evidencePath, `${JSON.stringify(composeStorage)}\n`);
|
|
assert.equal(
|
|
readComposeStorageEvidence(evidencePath, manifest(), observed()).sha256,
|
|
composeStorage.sha256,
|
|
);
|
|
const aggregate = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads: [],
|
|
supplementalEvidence: [composeStorage],
|
|
generatedAt: '2026-07-29T00:02:00.000Z',
|
|
});
|
|
assert.ok(
|
|
aggregate.qualification.collectedEvidence.includes(
|
|
'compose_sqlite_collection_reboot_and_partition_write_upper_bound',
|
|
),
|
|
);
|
|
assert.ok(
|
|
!aggregate.qualification.remainingRequiredEvidence.includes(
|
|
'compose_sqlite_collection_reboot_and_partition_write_upper_bound',
|
|
),
|
|
);
|
|
assert.ok(
|
|
aggregate.qualification.remainingRequiredEvidence.includes(
|
|
'power_loss_restart',
|
|
),
|
|
);
|
|
assert.ok(
|
|
composeStorage.qualification.doesNotProve.includes(
|
|
'abrupt_power_interruption_provenance',
|
|
),
|
|
);
|
|
});
|
|
|
|
test('imports post-reboot warm-Node native application activation while retaining the full cold-start gate', (t) => {
|
|
const directory = fs.realpathSync(
|
|
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-application-start-import-')),
|
|
);
|
|
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
|
const artifact = {
|
|
artifactSha256: 'a'.repeat(64),
|
|
artifactMetadataSha256: 'e'.repeat(64),
|
|
artifactFiles: 320,
|
|
artifactBytes: 2_000_000,
|
|
entrypointSha256: 'b'.repeat(64),
|
|
packages: [
|
|
'@qinglong/local-admin',
|
|
'@qinglong/local-application',
|
|
'@qinglong/local-command-file',
|
|
'@qinglong/local-execution',
|
|
'@qinglong/local-process',
|
|
'@qinglong/local-secret',
|
|
'@qinglong/local-sqlite',
|
|
'@qinglong/runtime-core',
|
|
'croner',
|
|
'semver',
|
|
],
|
|
};
|
|
const applicationManifest = normalizeApplicationStartManifest({
|
|
schemaVersion: 1,
|
|
evidenceClass: 'physical_edge_application_start_candidate',
|
|
profile: 'edge',
|
|
deviceId: manifest().deviceId,
|
|
expectedArchitecture: manifest().expectedArchitecture,
|
|
expectedFilesystem: manifest().expectedFilesystem,
|
|
expectedArtifactSha256: artifact.artifactSha256,
|
|
expectedArtifactFiles: artifact.artifactFiles,
|
|
expectedArtifactBytes: artifact.artifactBytes,
|
|
expectedNodeSha256: 'c'.repeat(64),
|
|
maximumBootAgeMs: 180_000,
|
|
maximumFirstActiveMs: 30_000,
|
|
maximumSampledRssBytes: 256 * 1024 * 1024,
|
|
sampleIntervalMs: 10,
|
|
});
|
|
const previousBoot = {
|
|
platform: 'linux',
|
|
architecture: 'arm64',
|
|
bootId: '019f0000-0000-4000-8000-000000000001',
|
|
dataFilesystem: 'ext4',
|
|
nodeExecutable: '/usr/bin/node',
|
|
nodeSha256: 'c'.repeat(64),
|
|
nodeVersion: 'v24.18.0',
|
|
bootAgeMs: 50_000,
|
|
};
|
|
const currentBoot = {
|
|
...previousBoot,
|
|
bootId: observed().bootId,
|
|
bootAgeMs: 5_000,
|
|
};
|
|
const session = {
|
|
sessionId: '019f0000-0000-4000-8000-000000000010',
|
|
sha256: 'd'.repeat(64),
|
|
preparedAt: '2026-07-29T00:00:00.000Z',
|
|
artifact,
|
|
paths: { dataPath: observed().dataPath },
|
|
};
|
|
const applicationStart = buildApplicationStartReport({
|
|
manifest: applicationManifest,
|
|
session,
|
|
observed: {
|
|
before: previousBoot,
|
|
after: currentBoot,
|
|
artifact,
|
|
},
|
|
measurements: {
|
|
firstActiveMs: 1200,
|
|
maximumSampledRssBytes: 80 * 1024 * 1024,
|
|
processReadBytes: 4096,
|
|
processWriteBytes: 8192,
|
|
sampleCount: 20,
|
|
eventCount: 5,
|
|
},
|
|
outcomes: {
|
|
activeEventCount: 1,
|
|
aiStatus: 'deployment_excluded',
|
|
gracefulStop: true,
|
|
exitCode: 0,
|
|
exitSignal: null,
|
|
stderrBytes: 0,
|
|
sqliteContractVersion: 41,
|
|
},
|
|
generatedAt: '2026-07-29T00:01:00.000Z',
|
|
});
|
|
assert.deepEqual(
|
|
validateApplicationStartEvidenceReport(
|
|
applicationStart,
|
|
manifest(),
|
|
observed(),
|
|
),
|
|
[],
|
|
);
|
|
const evidencePath = path.join(directory, 'application-start.json');
|
|
writeNoReplace(evidencePath, `${JSON.stringify(applicationStart)}\n`);
|
|
assert.equal(
|
|
readApplicationStartEvidence(evidencePath, manifest(), observed()).sha256,
|
|
applicationStart.sha256,
|
|
);
|
|
const aggregate = buildEvidenceReport({
|
|
manifest: manifest(),
|
|
observed: observed(),
|
|
workloads: [],
|
|
supplementalEvidence: [applicationStart],
|
|
generatedAt: '2026-07-29T00:02:00.000Z',
|
|
});
|
|
assert.ok(
|
|
aggregate.qualification.collectedEvidence.includes(
|
|
'post_reboot_warm_node_native_application_start_to_active',
|
|
),
|
|
);
|
|
assert.ok(
|
|
!aggregate.qualification.remainingRequiredEvidence.includes(
|
|
'cold_start_and_first_ready',
|
|
),
|
|
);
|
|
assert.ok(
|
|
aggregate.qualification.remainingRequiredEvidence.includes(
|
|
'power_on_cold_node_and_service_manager_start_to_first_ready',
|
|
),
|
|
);
|
|
assert.ok(
|
|
aggregate.qualification.remainingRequiredEvidence.includes(
|
|
'power_loss_restart',
|
|
),
|
|
);
|
|
});
|