mirror of
https://github.com/morluto/rea.git
synced 2026-10-22 22:02:27 -05:00
Authenticate inventory requests once before family projection, remove obsolete schema aliases and raw facades, and preserve unresolved occurrence references from partial pages without fabricating content identities.
156 lines
4.8 KiB
TypeScript
156 lines
4.8 KiB
TypeScript
import { writeFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
import { expect } from "vitest";
|
|
|
|
import {
|
|
ANDROID_APPLICATION_GRAPH_EXAMPLE,
|
|
APPLE_APPLICATION_GRAPH_EXAMPLE,
|
|
HARMONY_APPLICATION_GRAPH_EXAMPLE,
|
|
MACOS_APPLICATION_GRAPH_EXAMPLE,
|
|
} from "../../../src/contracts/mobileApplicationGraphExamples.js";
|
|
import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js";
|
|
import { artifactInventoryResultSchema } from "../../../src/domain/artifactGraph.js";
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
|
import { cliTest } from "../../support/cli/cliFixture.js";
|
|
|
|
const graphExamples = [
|
|
{
|
|
name: "Android",
|
|
command: "project-android-application-graph",
|
|
operation: "project_android_application_graph",
|
|
example: ANDROID_APPLICATION_GRAPH_EXAMPLE,
|
|
},
|
|
{
|
|
name: "IPA",
|
|
command: "project-apple-application-graph",
|
|
operation: "project_apple_application_graph",
|
|
example: APPLE_APPLICATION_GRAPH_EXAMPLE,
|
|
},
|
|
{
|
|
name: "macOS",
|
|
command: "project-apple-application-graph",
|
|
operation: "project_apple_application_graph",
|
|
example: MACOS_APPLICATION_GRAPH_EXAMPLE,
|
|
},
|
|
{
|
|
name: "Harmony",
|
|
command: "project-harmony-application-graph",
|
|
operation: "project_harmony_application_graph",
|
|
example: HARMONY_APPLICATION_GRAPH_EXAMPLE,
|
|
},
|
|
] as const;
|
|
|
|
cliTest.for(graphExamples)(
|
|
"CLI executes the canonical $name graph example without target files",
|
|
async ({ command, operation, example }, { cli }) => {
|
|
const root = await createTestTempDirectory("rea-mobile-graph-example-");
|
|
const input = JSON.stringify(example);
|
|
const path = join(root, "example.json");
|
|
await writeFile(path, input);
|
|
for (const argument of [input, path]) {
|
|
const result = await cli.run({
|
|
arguments: [command, argument, "--json"],
|
|
cwd: root,
|
|
});
|
|
expect(result.exitCode, result.stdout).toBe(0);
|
|
const evidence = parseEvidence(result.json);
|
|
expect(evidence.operation).toBe(operation);
|
|
expect(evidence.normalized_result).toMatchObject({
|
|
coverage: { status: "partial", inventory_complete: true },
|
|
});
|
|
}
|
|
},
|
|
);
|
|
|
|
cliTest.for(graphExamples)(
|
|
"CLI classifies malformed $name source Evidence separately from request errors",
|
|
async ({ command, example }, { cli }) => {
|
|
const source = example.inventory_evidence[0]!;
|
|
for (const { input, code } of [
|
|
{
|
|
input: {
|
|
inventory_evidence: [{ ...source, evidence_id: "not-a-digest" }],
|
|
},
|
|
code: "evidence_integrity_mismatch",
|
|
},
|
|
{
|
|
input: { inventory_evidence: [source], unexpected: true },
|
|
code: "invalid_request",
|
|
},
|
|
{ input: { inventory_evidence: [] }, code: "invalid_request" },
|
|
]) {
|
|
const result = await cli.run({
|
|
arguments: [command, JSON.stringify(input), "--json"],
|
|
});
|
|
expect(result.exitCode).toBe(1);
|
|
expect(result.json).toMatchObject({
|
|
code,
|
|
});
|
|
}
|
|
},
|
|
);
|
|
|
|
cliTest(
|
|
"CLI still rejects an unsupported inventory coverage status",
|
|
async ({ cli }) => {
|
|
const original = ANDROID_APPLICATION_GRAPH_EXAMPLE.inventory_evidence[0]!;
|
|
const inventory = artifactInventoryResultSchema.parse(
|
|
original.normalized_result,
|
|
);
|
|
const evidence = createEvidence(
|
|
{ path: "Fixture.apk", sha256: "a".repeat(64), format: "apk" },
|
|
original.provider,
|
|
{
|
|
operation: "inventory_artifact",
|
|
parameters: {},
|
|
result: {
|
|
...inventory,
|
|
coverage: { scope: "root", status: "invalid" },
|
|
},
|
|
confidence: "observed",
|
|
authority: "shipped-artifact",
|
|
},
|
|
);
|
|
const result = await cli.run({
|
|
arguments: [
|
|
"project-android-application-graph",
|
|
JSON.stringify({ inventory_evidence: [evidence] }),
|
|
"--json",
|
|
],
|
|
});
|
|
expect(result.exitCode).toBe(1);
|
|
const projected = result.json;
|
|
expect(projected).toMatchObject({
|
|
code: "evidence_integrity_mismatch",
|
|
category: "integrity_mismatch",
|
|
});
|
|
const reason = inventoryIntegrityReason(projected);
|
|
expect(JSON.parse(reason)).toMatchObject([
|
|
{
|
|
code: "invalid_value",
|
|
values: ["complete", "unknown"],
|
|
path: ["coverage", "status"],
|
|
},
|
|
]);
|
|
expect(projected).toMatchObject({
|
|
message: reason,
|
|
details: { reason },
|
|
});
|
|
},
|
|
);
|
|
|
|
const inventoryIntegrityReason = (projected: unknown): string => {
|
|
if (
|
|
projected === null ||
|
|
typeof projected !== "object" ||
|
|
!("details" in projected) ||
|
|
projected.details === null ||
|
|
typeof projected.details !== "object" ||
|
|
!("reason" in projected.details) ||
|
|
typeof projected.details.reason !== "string"
|
|
)
|
|
throw new Error("Inventory rejection omitted an integrity reason");
|
|
return projected.details.reason;
|
|
};
|