项目文件夹

文件
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

706 行
19 KiB
JavaScript

// Exercises OS release pipeline scripts and evidence checks.
import assert from "node:assert/strict";
import { execFile } from "node:child_process";
import { existsSync } from "node:fs";
import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import {
defaultManifestPath,
parseChecksumFile,
readJson,
sha256CanonicalJson,
validateManifest,
validateTeeMeasurements,
} from "../os-release-lib.mjs";
import {
buildBoundEvidence,
goldenMeasurementsOf,
} from "../tee-evidence-bridge.mjs";
const execFileAsync = promisify(execFile);
const repoRoot = path.resolve(
fileURLToPath(new URL("../../../..", import.meta.url)),
);
const confidentialManifestPath = path.join(
repoRoot,
"packages/os/release/confidential-2026-05-21/manifest.json",
);
const digest = (char) => `sha256:${char.repeat(64)}`;
const releaseFixtureTest = (name, fn) =>
test(
name,
existsSync(defaultManifestPath) && existsSync(confidentialManifestPath)
? {}
: { skip: "release manifest fixtures are not checked in" },
fn,
);
releaseFixtureTest(
"beta manifest carries required beta dates, presale terms, and artifact classes",
async () => {
const manifest = await readJson(defaultManifestPath);
const result = validateManifest(manifest);
assert.equal(result.ok, true, result.errors.join("\n"));
assert.equal(manifest.release.availableDate, "2026-05-16");
assert.equal(manifest.commerce.usbKeyPresale.priceUsd, 49);
assert.equal(
manifest.commerce.usbKeyPresale.estimatedShipWindow.starts,
"2026-10-01",
);
assert.equal(
manifest.commerce.usbKeyPresale.estimatedShipWindow.ends,
"2026-10-31",
);
assert.ok(
manifest.artifacts.some((artifact) => artifact.kind === "raw-image"),
);
assert.ok(
manifest.artifacts.some((artifact) => artifact.kind === "vm-image"),
);
assert.ok(
manifest.artifacts.some((artifact) => artifact.kind === "android-image"),
);
},
);
releaseFixtureTest(
"all-zero sha256 placeholders are rejected even outside strict mode",
async () => {
const manifest = await readJson(defaultManifestPath);
const poisoned = {
...manifest,
artifacts: manifest.artifacts.map((artifact, index) =>
index === 0
? { ...artifact, sha256: "0".repeat(64), sizeBytes: 1 }
: artifact,
),
};
const lenient = validateManifest(poisoned);
assert.equal(lenient.ok, false);
assert.ok(
lenient.errors.some((error) => error.includes("all-zero placeholder")),
`expected all-zero rejection, got: ${lenient.errors.join("\n")}`,
);
const strict = validateManifest(poisoned, {
requirePublishableChecksums: true,
});
assert.equal(strict.ok, false);
assert.ok(
strict.errors.some((error) => error.includes("all-zero placeholder")),
);
assert.ok(
strict.errors.some((error) => error.includes("sha256 is required")),
);
},
);
releaseFixtureTest(
"publishable validation requires concrete checksums and sizes",
async () => {
const manifest = await readJson(defaultManifestPath);
const result = validateManifest(manifest, {
requirePublishableChecksums: true,
});
assert.equal(result.ok, false);
assert.ok(
result.errors.some((error) => error.includes("downloadUrl is required")),
);
assert.ok(
result.errors.some((error) => error.includes("sha256 is required")),
);
assert.ok(
result.errors.some((error) => error.includes("sizeBytes is required")),
);
},
);
releaseFixtureTest(
"TEE release policy validation accepts complete measured boot policy",
async () => {
const manifest = await readJson(defaultManifestPath);
const digest = `sha256:${"a".repeat(64)}`;
const result = validateManifest({
...manifest,
tee: {
enabled: true,
policyDigest: digest,
measurements: {
boot: digest,
os: digest,
agent: digest,
policy: digest,
},
requiredClaims: {
debugDisabled: true,
secureBoot: true,
memoryEncrypted: true,
},
providers: ["dstack", "tdx", "cove", "eliza-vault"],
},
});
assert.equal(result.ok, true, result.errors.join("\n"));
},
);
releaseFixtureTest(
"TEE release policy validation rejects missing required production claims",
async () => {
const manifest = await readJson(defaultManifestPath);
const digest = `sha256:${"a".repeat(64)}`;
const result = validateManifest({
...manifest,
tee: {
enabled: true,
policyDigest: digest,
measurements: {
boot: digest,
os: digest,
agent: digest,
policy: digest,
},
requiredClaims: {
debugDisabled: true,
secureBoot: false,
},
providers: ["dstack"],
},
});
assert.equal(result.ok, false);
assert.ok(
result.errors.some((error) =>
error.includes("tee.requiredClaims.secureBoot"),
),
);
},
);
releaseFixtureTest(
"checksum generation and verification round-trip local artifacts",
async () => {
const sourceManifest = await readJson(defaultManifestPath);
const tmp = await mkdtemp(path.join(os.tmpdir(), "elizaos-release-"));
const manifestPath = path.join(tmp, "manifest.json");
const artifactRoot = path.join(tmp, "artifacts");
await mkdir(artifactRoot, { recursive: true });
const fixtureArtifacts = [
sourceManifest.artifacts.find(
(artifact) => artifact.kind === "raw-image",
),
sourceManifest.artifacts.find((artifact) => artifact.kind === "vm-image"),
sourceManifest.artifacts.find(
(artifact) => artifact.kind === "android-image",
),
];
const manifest = {
...sourceManifest,
artifacts: fixtureArtifacts.map((artifact) => ({
...artifact,
status: "candidate",
sizeBytes: null,
sha256: null,
validation: {
...artifact.validation,
evidence: [],
},
})),
checksumPolicy: {
...sourceManifest.checksumPolicy,
generatedFile: path.join(tmp, "SHA256SUMS"),
},
};
for (const artifact of manifest.artifacts) {
await writeFile(
path.join(artifactRoot, artifact.filename),
`fixture payload for ${artifact.id}\n`,
);
}
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
const checksumsPath = path.join(tmp, "SHA256SUMS");
await execFileAsync(
process.execPath,
[
"packages/os/scripts/generate-release-checksums.mjs",
"--manifest",
manifestPath,
"--artifact-root",
artifactRoot,
"--output",
checksumsPath,
"--update-manifest",
],
{ cwd: repoRoot },
);
const checksumRecords = parseChecksumFile(
await readFile(checksumsPath, "utf8"),
);
assert.equal(checksumRecords.length, 3);
const updated = await readJson(manifestPath);
assert.ok(
updated.artifacts.every((artifact) =>
/^[a-f0-9]{64}$/.test(artifact.sha256),
),
);
assert.ok(
updated.artifacts.every((artifact) =>
Number.isInteger(artifact.sizeBytes),
),
);
await execFileAsync(
process.execPath,
[
"packages/os/scripts/verify-release-checksums.mjs",
"--manifest",
manifestPath,
"--artifact-root",
artifactRoot,
"--checksums",
checksumsPath,
],
{ cwd: repoRoot },
);
},
);
test("legacy checksum updater preserves valid candidate manifest status", async () => {
const tmp = await mkdtemp(path.join(os.tmpdir(), "elizaos-update-sums-"));
const manifestPath = path.join(tmp, "manifest.json");
const artifactRoot = path.join(tmp, "artifacts");
await mkdir(artifactRoot);
const manifest = {
schemaVersion: 1,
release: {
id: "test-release",
channel: "beta",
version: "2.0.0-test",
availableDate: "2026-05-16",
status: "candidate",
},
commerce: {
usbKeyPresale: {
enabled: true,
priceUsd: 49,
saleStarts: "2026-05-16",
estimatedShipWindow: {
starts: "2026-10-01",
ends: "2026-10-31",
},
},
},
artifacts: [
{
id: "raw",
kind: "raw-image",
status: "candidate",
target: { platform: "linux", architecture: "amd64" },
filename: "raw.img.zst",
downloadUrl: null,
sha256: null,
sizeBytes: null,
validation: {
requiredEvidence: ["sha256-generated"],
evidence: [],
},
},
{
id: "vm",
kind: "vm-image",
status: "candidate",
target: { platform: "linux", architecture: "amd64" },
filename: "vm.ova.zip",
downloadUrl: null,
sha256: null,
sizeBytes: null,
validation: {
requiredEvidence: ["sha256-generated"],
evidence: [],
},
},
{
id: "android",
kind: "android-image",
status: "candidate",
target: { platform: "android", architecture: "arm64" },
filename: "android.zip",
downloadUrl: null,
sha256: null,
sizeBytes: null,
validation: {
requiredEvidence: ["sha256-generated"],
evidence: [],
},
},
],
checksumPolicy: {
algorithm: "sha256",
generatedFile: "SHA256SUMS",
verificationScript: "packages/os/scripts/verify-release-checksums.mjs",
},
validation: {
evidenceDirectory: "evidence",
promotionGates: [],
},
};
for (const artifact of manifest.artifacts) {
await writeFile(
path.join(artifactRoot, artifact.filename),
`fixture payload for ${artifact.id}\n`,
);
}
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
await execFileAsync(
process.execPath,
[
"packages/os/scripts/update-manifest-checksums.mjs",
"--manifest",
manifestPath,
"--artifacts-dir",
artifactRoot,
],
{ cwd: repoRoot },
);
const updated = await readJson(manifestPath);
assert.deepEqual(
updated.artifacts.map((artifact) => artifact.status),
["candidate", "candidate", "candidate"],
);
assert.ok(
updated.artifacts.every((artifact) =>
artifact.validation.evidence.includes("sha256-generated"),
),
);
assert.equal(
updated.artifacts.every((artifact) =>
/^[a-f0-9]{64}$/.test(artifact.sha256),
),
true,
);
const validation = validateManifest(updated);
assert.equal(validation.ok, true, validation.errors.join("\n"));
});
test("TEE measurement generation hashes required release inputs", async () => {
const tmp = await mkdtemp(path.join(os.tmpdir(), "elizaos-tee-"));
const inputs = {
boot: path.join(tmp, "boot.bin"),
os: path.join(tmp, "os.img"),
agent: path.join(tmp, "agent.tar"),
policy: path.join(tmp, "policy.json"),
container: path.join(tmp, "compose.json"),
};
for (const [name, filePath] of Object.entries(inputs)) {
// `policy` is hashed as canonicalized JSON (it is the source of
// measurements.policy), so it must be valid JSON; the rest hash raw bytes.
const contents =
name === "policy"
? JSON.stringify({ z: 1, a: { b: 2 } })
: `fixture for ${name}\n`;
await writeFile(filePath, contents);
}
const output = path.join(tmp, "tee-measurements.json");
await execFileAsync(
process.execPath,
[
"packages/os/scripts/generate-tee-measurements.mjs",
"--output",
output,
"--boot",
inputs.boot,
"--os",
inputs.os,
"--agent",
inputs.agent,
"--policy",
inputs.policy,
"--container",
inputs.container,
],
{ cwd: repoRoot },
);
const generated = await readJson(output);
assert.equal(generated.schemaVersion, 1);
for (const name of Object.keys(inputs)) {
assert.match(generated.measurements[name], /^sha256:[a-f0-9]{64}$/);
}
assert.equal(validateTeeMeasurements(generated).ok, true);
// The policy measurement is the canonical-JSON digest, independent of key
// order in the source file.
assert.equal(
generated.measurements.policy,
sha256CanonicalJson({ z: 1, a: { b: 2 } }),
);
});
test("TEE measurement validator rejects missing required digests", () => {
const result = validateTeeMeasurements({
schemaVersion: 1,
generatedBy: "test",
measurements: {
boot: `sha256:${"a".repeat(64)}`,
os: `sha256:${"b".repeat(64)}`,
agent: "bad",
policy: `sha256:${"d".repeat(64)}`,
},
});
assert.equal(result.ok, false);
assert.ok(
result.errors.some((error) => error.includes("measurements.agent")),
);
});
releaseFixtureTest(
"confidential manifest with a valid TEE block validates",
async () => {
const manifest = await readJson(confidentialManifestPath);
const result = validateManifest(manifest);
assert.equal(result.ok, true, result.errors.join("\n"));
assert.equal(manifest.tee.enabled, true);
for (const name of ["boot", "os", "agent", "policy"]) {
assert.match(manifest.tee.measurements[name], /^sha256:[a-f0-9]{64}$/);
}
},
);
releaseFixtureTest(
"manifest declaring TEE but missing a required digest fails closed",
async () => {
const manifest = await readJson(confidentialManifestPath);
const broken = {
...manifest,
tee: {
...manifest.tee,
measurements: { ...manifest.tee.measurements, agent: undefined },
},
};
const result = validateManifest(broken);
assert.equal(result.ok, false);
assert.ok(
result.errors.some((error) => error.includes("tee.measurements.agent")),
result.errors.join("\n"),
);
},
);
releaseFixtureTest(
"manifest declaring an inference measurement must assert npuProtected + ioProtected",
async () => {
const manifest = await readJson(confidentialManifestPath);
const broken = {
...manifest,
tee: {
...manifest.tee,
requiredClaims: {
...manifest.tee.requiredClaims,
npuProtected: false,
ioProtected: false,
},
},
};
const result = validateManifest(broken);
assert.equal(result.ok, false);
assert.ok(
result.errors.some((error) => error.includes("npuProtected")),
result.errors.join("\n"),
);
assert.ok(
result.errors.some((error) => error.includes("ioProtected")),
result.errors.join("\n"),
);
},
);
releaseFixtureTest(
"TEE block rejects unknown / malformed measurement names",
async () => {
const manifest = await readJson(confidentialManifestPath);
const unknownName = {
...manifest,
tee: {
...manifest.tee,
measurements: { ...manifest.tee.measurements, bogus: digest("a") },
},
};
const unknownResult = validateManifest(unknownName);
assert.equal(unknownResult.ok, false);
assert.ok(
unknownResult.errors.some((error) =>
error.includes("tee.measurements.bogus"),
),
);
const malformed = {
...manifest,
tee: {
...manifest.tee,
measurements: { ...manifest.tee.measurements, monitor: "deadbeef" },
},
};
const malformedResult = validateManifest(malformed);
assert.equal(malformedResult.ok, false);
assert.ok(
malformedResult.errors.some((error) =>
error.includes("tee.measurements.monitor"),
),
);
},
);
test("new measurement names round-trip through generate -> validate", async () => {
const tmp = await mkdtemp(path.join(os.tmpdir(), "elizaos-tee-rt-"));
const names = [
"boot",
"os",
"agent",
"policy",
"device",
"container",
"compose",
"gpuFirmware",
"npuFirmware",
"modelWeights",
"monitor",
];
const cliArgs = [
"packages/os/scripts/generate-tee-measurements.mjs",
"--output",
path.join(tmp, "out.json"),
];
for (const name of names) {
const filePath = path.join(tmp, `${name}.bin`);
// `policy` is canonicalized JSON (source of measurements.policy); the rest
// hash raw component bytes.
await writeFile(
filePath,
name === "policy" ? JSON.stringify({ k: name }) : `fixture for ${name}\n`,
);
cliArgs.push(`--${name}`, filePath);
}
await execFileAsync(process.execPath, cliArgs, { cwd: repoRoot });
const generated = await readJson(path.join(tmp, "out.json"));
for (const name of names) {
assert.match(generated.measurements[name], /^sha256:[a-f0-9]{64}$/);
}
assert.equal(validateTeeMeasurements(generated).ok, true);
});
test("standalone measurements validator rejects an unknown measurement name", () => {
const result = validateTeeMeasurements({
schemaVersion: 1,
generatedBy: "test",
measurements: {
boot: digest("a"),
os: digest("b"),
agent: digest("c"),
policy: digest("d"),
mystery: digest("e"),
},
});
assert.equal(result.ok, false);
assert.ok(
result.errors.some((error) => error.includes("measurements.mystery")),
);
});
releaseFixtureTest(
"evidence bridge emits a normalized shape bound to golden measurements",
async () => {
const manifest = await readJson(confidentialManifestPath);
const golden = goldenMeasurementsOf(manifest);
const evidence = await readJson(
path.join(repoRoot, "packages/os/release/schema/tee-evidence.mock.json"),
);
const bound = buildBoundEvidence(evidence, golden);
assert.equal(bound.kind, "dstack");
assert.equal(bound.provider, "dstack");
assert.equal(bound.measurements.os, golden.os);
assert.equal(bound.claims.npuProtected, true);
assert.equal(bound.claims.ioProtected, true);
assert.match(bound.reportData, /^sha256:[a-f0-9]{64}$/);
for (const name of ["boot", "os", "agent", "policy"]) {
assert.match(bound.measurements[name], /^sha256:[a-f0-9]{64}$/);
}
},
);
releaseFixtureTest(
"evidence bridge fails closed on a runtime-vs-golden mismatch",
async () => {
const manifest = await readJson(confidentialManifestPath);
const golden = goldenMeasurementsOf(manifest);
const tampered = await readJson(
path.join(
repoRoot,
"packages/os/release/schema/tee-evidence.tampered.mock.json",
),
);
assert.throws(
() => buildBoundEvidence(tampered, golden),
/measurement-mismatch/,
);
},
);
test("evidence bridge rejects an unknown runtime measurement name", () => {
const golden = {
boot: digest("b"),
os: digest("c"),
agent: digest("d"),
policy: digest("a"),
};
const evidence = {
kind: "dstack",
measurements: { ...golden, bogus: digest("e") },
};
assert.throws(
() => buildBoundEvidence(evidence, golden),
/unknown runtime measurement/,
);
});
test("evidence bridge CLI fails closed when real hardware quote is requested", async () => {
await assert.rejects(
execFileAsync(
process.execPath,
[
"packages/os/scripts/tee-evidence-bridge.mjs",
"--quote-source",
"tappd",
],
{ cwd: repoRoot },
),
(error) => {
assert.equal(error.code, 2);
assert.match(error.stderr, /BLOCKED/);
assert.match(error.stderr, /--quote-source tappd/);
return true;
},
);
});