mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
* refactor(analysis): centralize resource budgets and recovery facts * feat(analysis): expose ASAR and Ghidra runtime admission controls * feat(artifacts): expose reader admission and preserve limited recognition * feat(javascript): expose recoverable semantic precision budgets * feat(web): add recoverable source-map budgets and compact retained views * feat(web): make historical capture decoding budgets recoverable * fix(desktop): enforce selected view policies across capture and export * feat(runtime): make Frida and LLDB retention budgets selectable * feat(native): expose diagnostic budgets and preserve exhaustion causes * feat(managed): expose recoverable snapshot and representation budgets * feat(metadata): make Go and Rust inspection budgets recoverable * feat(wasm): expose representation and producer admissions * feat(evm): expose per-call worker resource budgets * feat(android): make resource and string-pool omissions recoverable * feat(producers): expose command and recorded-capture budgets * docs(analysis): record recovery contracts and integrated validation * fix(docs): link calibration oracle from published verification pages * fix(docs): restore desktop task anchors and receipt links * test(analysis): align fixtures with selectable budget contracts * fix(analysis): remove source-location projector dependency cycle * test(analysis): refresh budget recovery and verifier regressions * test(analysis): preserve format and publication recovery expectations * test(windows): align conformance with owned runtime admission * fix(desktop): preserve selected alias kinds in exported state * test(analysis): align provider fixtures with recoverable budgets * test(desktop): validate emitted alias metadata structurally * fix(ghidra): classify bounded Windows endpoint refusals * test(cli): assert selectable artifact admission recovery * fix(cli): preserve capture provenance in environment builds
200 lines
6.7 KiB
TypeScript
200 lines
6.7 KiB
TypeScript
import { desktopLibraryPolicy } from "../domain/desktop/libraryPolicy.js";
|
|
import { existsSync } from "node:fs";
|
|
import { mkdir, realpath, symlink, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import { runHostQuery } from "./HostQuery.js";
|
|
import { inspectLibraryPackages } from "./LibraryPackageInventory.js";
|
|
import { elfImage } from "../domain/desktop/elfImage.fixture.js";
|
|
import { createTestTempDirectory } from "../../tests/fixtures/temporaryDirectory.js";
|
|
|
|
describe.skipIf(
|
|
process.platform !== "linux" || !existsSync("/var/lib/dpkg/status"),
|
|
)("inspectLibraryPackages on a Debian host", () => {
|
|
it("maps the running node binary's libraries to their packages", async () => {
|
|
const executable = await realpath(process.execPath);
|
|
|
|
const libraries = await inspectLibraryPackages(
|
|
executable,
|
|
"nodejs",
|
|
runHostQuery,
|
|
undefined,
|
|
);
|
|
|
|
expect(libraries).not.toHaveProperty("library_packages_reason");
|
|
expect(libraries.library_packages).toContain("libc6");
|
|
expect(libraries.missing_libraries).toEqual([]);
|
|
});
|
|
|
|
it("explains a launcher script instead of reading it as ELF", async () => {
|
|
const libraries = await inspectLibraryPackages(
|
|
"/usr/bin/ldd",
|
|
"libc-bin",
|
|
runHostQuery,
|
|
undefined,
|
|
);
|
|
|
|
expect(libraries).toEqual({
|
|
library_packages: [],
|
|
missing_libraries: [],
|
|
unpackaged_libraries: [],
|
|
library_packages_reason: expect.stringMatching(
|
|
/\/usr\/bin\/ldd.*not read.*not an ELF image/iu,
|
|
),
|
|
});
|
|
});
|
|
});
|
|
|
|
it.skipIf(process.platform === "win32")(
|
|
"preserves completed ownership batches when a later query fails",
|
|
async () => {
|
|
const root = await createTestTempDirectory("rea-library-owners-");
|
|
const bin = join(root, "bin");
|
|
const lib = join(root, "lib");
|
|
await Promise.all([mkdir(bin), mkdir(lib)]);
|
|
const paths = Array.from({ length: 102 }, (_, index) =>
|
|
join(lib, `lib${index}.so`),
|
|
);
|
|
const executable = join(bin, "app");
|
|
await Promise.all([
|
|
writeFile(executable, elfImage({ needed: paths })),
|
|
...paths.map((path) => writeFile(path, elfImage({}))),
|
|
]);
|
|
let batches = 0;
|
|
const result = await inspectLibraryPackages(
|
|
executable,
|
|
"app",
|
|
async (command) => {
|
|
if (command === "ldconfig") return { stdout: "", exitCode: 0 };
|
|
batches++;
|
|
if (batches === 1) return { stdout: `owner: ${paths[0]}`, exitCode: 1 };
|
|
return { stdout: "", exitCode: 2 };
|
|
},
|
|
undefined,
|
|
);
|
|
expect(batches).toBe(2);
|
|
expect(result.library_packages).toEqual(["owner"]);
|
|
expect(result.unpackaged_libraries).toContain(paths[1]);
|
|
expect(result.unpackaged_libraries).not.toContain(paths[101]);
|
|
expect(result.library_packages_reason).toContain("dpkg-query");
|
|
},
|
|
);
|
|
|
|
it.skipIf(process.platform === "win32")(
|
|
"keeps ownership unknown for paths dpkg would interpret as patterns",
|
|
async () => {
|
|
const root = await createTestTempDirectory("rea-library-pattern-");
|
|
const bin = join(root, "bin");
|
|
const lib = join(root, "lib[1]");
|
|
await Promise.all([mkdir(bin), mkdir(lib)]);
|
|
const library = join(lib, "libpattern.so");
|
|
const executable = join(bin, "app");
|
|
await Promise.all([
|
|
writeFile(executable, elfImage({ needed: [library] })),
|
|
writeFile(library, elfImage({})),
|
|
]);
|
|
const result = await inspectLibraryPackages(
|
|
executable,
|
|
"app",
|
|
async (command) => {
|
|
if (command === "ldconfig") return { stdout: "", exitCode: 0 };
|
|
throw new Error("pattern path must not be passed to dpkg-query");
|
|
},
|
|
undefined,
|
|
);
|
|
expect(result.unpackaged_libraries).toEqual([]);
|
|
expect(result.library_packages_reason).toContain("pattern characters");
|
|
},
|
|
);
|
|
|
|
it.skipIf(process.platform === "win32")(
|
|
"does not report a skipped pattern alias when its real path has a known owner",
|
|
async () => {
|
|
const root = await createTestTempDirectory("rea-library-alias-");
|
|
const bin = join(root, "bin");
|
|
const lib = join(root, "lib");
|
|
await Promise.all([mkdir(bin), mkdir(lib)]);
|
|
const physical = join(lib, "physical.so");
|
|
const alias = join(lib, "lib[1].so");
|
|
const executable = join(bin, "app");
|
|
await Promise.all([
|
|
writeFile(physical, elfImage({})),
|
|
writeFile(executable, elfImage({ needed: [alias] })),
|
|
]);
|
|
await symlink(physical, alias);
|
|
const resolved = await realpath(physical);
|
|
const result = await inspectLibraryPackages(
|
|
executable,
|
|
"app",
|
|
async (command, args) => {
|
|
if (command === "ldconfig") return { stdout: "", exitCode: 0 };
|
|
expect(args).not.toContain(alias);
|
|
return { stdout: `lib-owner: ${resolved}`, exitCode: 1 };
|
|
},
|
|
undefined,
|
|
);
|
|
expect(result.library_packages).toEqual(["lib-owner"]);
|
|
expect(result.unpackaged_libraries).toEqual([]);
|
|
expect(result).not.toHaveProperty("library_packages_reason");
|
|
},
|
|
);
|
|
|
|
it.skipIf(process.platform === "win32")(
|
|
"recovers a 513-library closure with the caller-selected capture policy",
|
|
async () => {
|
|
const root = await createTestTempDirectory("rea-library-policy-");
|
|
const bin = join(root, "bin");
|
|
const lib = join(root, "lib");
|
|
await Promise.all([mkdir(bin), mkdir(lib)]);
|
|
const paths = Array.from({ length: 513 }, (_, index) =>
|
|
join(lib, `lib${index}.so`),
|
|
);
|
|
const executable = join(bin, "app");
|
|
await Promise.all([
|
|
writeFile(executable, elfImage({ needed: [paths[0] ?? ""] })),
|
|
...paths.map((path, index) =>
|
|
writeFile(
|
|
path,
|
|
elfImage({
|
|
needed:
|
|
paths[index + 1] === undefined ? [] : [paths[index + 1] ?? ""],
|
|
}),
|
|
),
|
|
),
|
|
]);
|
|
const query = async (command: string, args: readonly string[]) => ({
|
|
stdout:
|
|
command === "ldconfig"
|
|
? ""
|
|
: args
|
|
.slice(1)
|
|
.map((path) => `owner-${paths.indexOf(path)}: ${path}`)
|
|
.join("\n"),
|
|
exitCode: 0,
|
|
});
|
|
const limited = await inspectLibraryPackages(
|
|
executable,
|
|
"app",
|
|
query,
|
|
undefined,
|
|
);
|
|
expect(limited.library_packages).toHaveLength(512);
|
|
expect(limited.library_packages_reason).toContain(
|
|
"library-policy.libraries=512",
|
|
);
|
|
expect(limited.library_packages_reason).toContain("--library-policy");
|
|
const recovered = await inspectLibraryPackages(
|
|
executable,
|
|
"app",
|
|
query,
|
|
undefined,
|
|
desktopLibraryPolicy({ libraries: 513 }),
|
|
);
|
|
expect(recovered.library_packages).toHaveLength(513);
|
|
expect(recovered.library_packages).toContain("owner-512");
|
|
expect(recovered.library_packages_reason).toBeUndefined();
|
|
},
|
|
);
|