mirror of
https://github.com/morluto/rea.git
synced 2026-11-06 23:06:18 +00:00
inspect-desktop-application took --max_entries and --max_probe_bytes through Number(), so 0x1 examined one entry and 1e1 ten. Admit decimal text only and keep the shared fields' bounds and defaults.
244 lines
7.7 KiB
TypeScript
244 lines
7.7 KiB
TypeScript
import { readEvidenceBundle } from "../../../src/application/EvidenceBundleFiles.js";
|
|
import { chmod, mkdir, writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
import { expect } from "vitest";
|
|
import { cliTest } from "../../support/cli/cliFixture.js";
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
import { createDesktopApplicationService } from "../../../src/composition/desktop.js";
|
|
import { parseEvidence } from "../../../src/domain/evidence.js";
|
|
|
|
cliTest(
|
|
"rejects an empty desktop selection while explicit . selects the working directory",
|
|
async ({ cli }) => {
|
|
const root = await createTestTempDirectory("rea-desktop-empty-");
|
|
await writeFile(join(root, "marker.txt"), "selected cwd control");
|
|
const empty = await cli.run({
|
|
arguments: ["inspect-desktop-application", "", "--json"],
|
|
cwd: root,
|
|
});
|
|
expect(empty.exitCode).not.toBe(0);
|
|
expect(empty.json).toMatchObject({
|
|
code: "VALIDATION_ERROR",
|
|
fieldErrors: expect.arrayContaining([
|
|
expect.objectContaining({ path: "path", code: "too_small" }),
|
|
]),
|
|
});
|
|
const explicit = await cli.run({
|
|
arguments: ["inspect-desktop-application", ".", "--json"],
|
|
cwd: root,
|
|
});
|
|
expect(explicit.exitCode).toBe(0);
|
|
expect(parseEvidence(explicit.json).normalized_result).toMatchObject({
|
|
files: [{ path: "marker.txt" }],
|
|
});
|
|
},
|
|
);
|
|
|
|
cliTest(
|
|
"shares directory facts and exact retained-field semantics with the public CLI",
|
|
async ({ cli }) => {
|
|
const root = await createTestTempDirectory("rea-desktop-cli-");
|
|
const installation = join(root, "installation");
|
|
await mkdir(join(installation, "resources"), { recursive: true });
|
|
await writeFile(
|
|
join(installation, "resources/app.asar"),
|
|
"path convention",
|
|
);
|
|
const refused = await cli.run({
|
|
arguments: [
|
|
"inspect-desktop-application",
|
|
join(root, "must-not-be-read"),
|
|
"--detail",
|
|
"summary",
|
|
"--json",
|
|
],
|
|
});
|
|
expect(refused.exitCode).not.toBe(0);
|
|
expect(refused.json).toMatchObject({
|
|
code: "invalid_request",
|
|
category: "invalid_input",
|
|
details: {
|
|
operation: "inspect_desktop_application",
|
|
issues: [{ path: ["evidence_output"] }],
|
|
},
|
|
});
|
|
const response = await cli.run({
|
|
arguments: ["inspect-desktop-application", installation, "--json"],
|
|
});
|
|
expect(response.exitCode).toBe(0);
|
|
const evidence = parseEvidence(response.json);
|
|
const service = createDesktopApplicationService();
|
|
try {
|
|
const source = await service.inspect({ path: installation });
|
|
if (!source.ok) throw source.error;
|
|
expect(evidence).toEqual(source.value);
|
|
} finally {
|
|
await service.close();
|
|
}
|
|
const query = join(root, "view.json");
|
|
await writeFile(
|
|
query,
|
|
JSON.stringify({
|
|
source: { kind: "inline", evidence },
|
|
view: {
|
|
kind: "desktop-application",
|
|
collection: "candidates",
|
|
families: ["electron"],
|
|
fields: ["family"],
|
|
limit: 1,
|
|
},
|
|
}),
|
|
);
|
|
const page = await cli.run({
|
|
arguments: ["inspect-analysis-view", query, "--json"],
|
|
});
|
|
expect(page.exitCode).toBe(0);
|
|
expect(parseEvidence(page.json).normalized_result).toMatchObject({
|
|
items: [{ candidate_id: expect.any(String), family: "electron" }],
|
|
coverage: { total: 1, exhausted: true },
|
|
});
|
|
const bundlePath = join(root, "complete-evidence.json");
|
|
const compact = await cli.run({
|
|
arguments: [
|
|
"inspect-desktop-application",
|
|
installation,
|
|
"--detail",
|
|
"summary",
|
|
"--evidence_output",
|
|
bundlePath,
|
|
"--json",
|
|
],
|
|
});
|
|
expect(compact.exitCode).toBe(0);
|
|
expect(compact.json).toMatchObject({
|
|
evidence_bundle: { path: bundlePath, bytes: expect.any(Number) },
|
|
summary: {
|
|
normalized_result: {
|
|
kind: "summary",
|
|
parent_evidence_id: evidence.evidence_id,
|
|
},
|
|
},
|
|
});
|
|
const saved = await readEvidenceBundle(bundlePath);
|
|
if (!saved.ok) throw saved.error;
|
|
expect(saved.value.records).toEqual([evidence]);
|
|
const overwrite = await cli.run({
|
|
arguments: [
|
|
"inspect-desktop-application",
|
|
installation,
|
|
"--detail",
|
|
"summary",
|
|
"--evidence_output",
|
|
bundlePath,
|
|
"--json",
|
|
],
|
|
});
|
|
expect(overwrite.exitCode).not.toBe(0);
|
|
},
|
|
);
|
|
|
|
cliTest(
|
|
"refuses a non-directory or missing root as a target selection",
|
|
async ({ cli }) => {
|
|
const root = await createTestTempDirectory("rea-desktop-cli-root-");
|
|
const file = join(root, "regular-file");
|
|
await writeFile(file, "fixture\n");
|
|
const notDirectory = await cli.run({
|
|
arguments: ["inspect-desktop-application", file, "--json"],
|
|
});
|
|
expect(notDirectory.exitCode).toBe(1);
|
|
expect(notDirectory.json).toMatchObject({
|
|
code: "unsupported_target",
|
|
category: "unsupported_target",
|
|
details: { operation: "inspect_desktop_application", path: file },
|
|
});
|
|
const missingPath = join(root, "missing-directory");
|
|
const missing = await cli.run({
|
|
arguments: ["inspect-desktop-application", missingPath, "--json"],
|
|
});
|
|
expect(missing.exitCode).toBe(1);
|
|
expect(missing.json).toMatchObject({
|
|
code: "target_unavailable",
|
|
category: "unavailable",
|
|
details: { path: missingPath, reason: expect.stringContaining("ENOENT") },
|
|
});
|
|
},
|
|
);
|
|
|
|
cliTest.skipIf(process.platform === "win32" || process.getuid?.() === 0)(
|
|
"reports a read-denied root as host access denial with read-access recovery",
|
|
async ({ cli }) => {
|
|
const root = await createTestTempDirectory("rea-desktop-cli-denied-");
|
|
const locked = join(root, "locked-directory");
|
|
await mkdir(locked);
|
|
await chmod(locked, 0o000);
|
|
try {
|
|
const denied = await cli.run({
|
|
arguments: ["inspect-desktop-application", locked, "--json"],
|
|
});
|
|
expect(denied.exitCode).toBe(1);
|
|
expect(denied.json).toMatchObject({
|
|
code: "access_denied",
|
|
category: "unavailable",
|
|
remediation: { action: expect.stringContaining("read access") },
|
|
details: {
|
|
path: locked,
|
|
system_code: "EACCES",
|
|
boundary: "filesystem-read",
|
|
partial_observation: expect.any(Object),
|
|
},
|
|
});
|
|
} finally {
|
|
await chmod(locked, 0o700);
|
|
}
|
|
},
|
|
);
|
|
|
|
// Numeric coercion admits each spelling within the field's bounds:
|
|
// "0x1" as 1 entry, "1e1" as 10 entries and "0x1000" as 4096 bytes.
|
|
cliTest.for([
|
|
["max_entries", "0x1"],
|
|
["max_entries", "1e1"],
|
|
["max_probe_bytes", "0x1000"],
|
|
] as const)(
|
|
"rejects %s %s as a non-decimal desktop limit",
|
|
async ([field, value], { cli }) => {
|
|
const root = await createTestTempDirectory("rea-desktop-limit-");
|
|
const result = await cli.run({
|
|
arguments: [
|
|
"inspect-desktop-application",
|
|
root,
|
|
`--${field}=${value}`,
|
|
"--json",
|
|
],
|
|
});
|
|
expect(result.exitCode).toBe(1);
|
|
expect(result.json).toMatchObject({
|
|
code: "VALIDATION_ERROR",
|
|
fieldErrors: [expect.objectContaining({ path: field })],
|
|
});
|
|
},
|
|
);
|
|
|
|
cliTest("keeps a decimal desktop entry limit", async ({ cli }) => {
|
|
const root = await createTestTempDirectory("rea-desktop-limit-");
|
|
await writeFile(join(root, "a.txt"), "a");
|
|
await writeFile(join(root, "b.txt"), "b");
|
|
const result = await cli.run({
|
|
arguments: [
|
|
"inspect-desktop-application",
|
|
root,
|
|
"--max_entries=01",
|
|
"--json",
|
|
],
|
|
});
|
|
expect(result.exitCode, result.stderr).toBe(0);
|
|
expect(parseEvidence(result.json).normalized_result).toMatchObject({
|
|
coverage: {
|
|
status: "partial",
|
|
entries_examined: 1,
|
|
limits: { max_entries: 1 },
|
|
},
|
|
});
|
|
});
|