mirror of
https://github.com/morluto/rea.git
synced 2026-10-19 04:19:54 -05:00
fix(contracts): complete canonical mobile graph inventory examples (#4026)
* fix(contracts): complete canonical mobile graph inventory examples * test(contracts): place canonical graph CLI regression in acceptance * refactor(contracts): reuse artifact identity owners in mobile examples
This commit is contained in:
2 files changed
+134
-26
No files matched your search
@@ -1,18 +1,28 @@
|
||||
import { digestCanonicalValue } from "../domain/canonicalDigest.js";
|
||||
import { createEvidence } from "../domain/evidence.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import {
|
||||
artifactInventoryResultSchema,
|
||||
type ArtifactNode,
|
||||
type ArtifactOccurrence,
|
||||
} from "../domain/artifactGraph.js";
|
||||
import {
|
||||
artifactGraphDigest,
|
||||
artifactIdForContent,
|
||||
artifactManifestId,
|
||||
occurrenceIdForLocation,
|
||||
} from "../domain/artifactIdentity.js";
|
||||
|
||||
const inventory = (
|
||||
format: "apk" | "ipa" | "directory" | "hap",
|
||||
digit: string,
|
||||
) => {
|
||||
const sha = digit.repeat(64);
|
||||
const artifactId = `art_${digestCanonicalValue({ sha256: sha }, "Artifact inventory")}`;
|
||||
const occurrenceId = `occ_${digestCanonicalValue(
|
||||
{ root: artifactId },
|
||||
"Artifact inventory",
|
||||
)}`;
|
||||
const nodes = [
|
||||
const artifactId = artifactIdForContent(sha);
|
||||
const occurrenceId = occurrenceIdForLocation({
|
||||
rootArtifactId: artifactId,
|
||||
logicalPath: ".",
|
||||
entryKind: "file",
|
||||
});
|
||||
const nodes: ArtifactNode[] = [
|
||||
{
|
||||
artifact_id: artifactId,
|
||||
format: format === "directory" ? "directory" : "zip",
|
||||
@@ -24,7 +34,7 @@ const inventory = (
|
||||
limitations: [],
|
||||
},
|
||||
];
|
||||
const occurrences = [
|
||||
const occurrences: ArtifactOccurrence[] = [
|
||||
{
|
||||
occurrence_id: occurrenceId,
|
||||
artifact_id: artifactId,
|
||||
@@ -42,24 +52,15 @@ const inventory = (
|
||||
limitations: [],
|
||||
},
|
||||
];
|
||||
const graphSha256 = digestCanonicalValue(
|
||||
{
|
||||
nodes,
|
||||
occurrences,
|
||||
edges: [],
|
||||
integrity_contradictions: [],
|
||||
},
|
||||
"Artifact inventory",
|
||||
);
|
||||
return jsonValueSchema.parse({
|
||||
const graphSha256 = artifactGraphDigest({
|
||||
nodes,
|
||||
occurrences,
|
||||
edges: [],
|
||||
contradictions: [],
|
||||
});
|
||||
return artifactInventoryResultSchema.parse({
|
||||
manifest: {
|
||||
manifest_id: `agm_${digestCanonicalValue(
|
||||
{
|
||||
root_artifact_id: artifactId,
|
||||
graph_sha256: graphSha256,
|
||||
},
|
||||
"Artifact inventory",
|
||||
)}`,
|
||||
manifest_id: artifactManifestId(artifactId, graphSha256),
|
||||
root_artifact_id: artifactId,
|
||||
root_sha256: sha,
|
||||
root_format: format,
|
||||
@@ -72,6 +73,8 @@ const inventory = (
|
||||
occurrences,
|
||||
edges: [],
|
||||
provenance: [],
|
||||
integrity_contradictions: [],
|
||||
coverage: { scope: "root", status: "complete" },
|
||||
limitations: [],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
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";
|
||||
|
||||
cliTest.for([
|
||||
{
|
||||
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)(
|
||||
"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(
|
||||
"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);
|
||||
expect(result.json).toMatchObject({
|
||||
code: "invalid_request",
|
||||
details: {
|
||||
operation: "project_android_application_graph",
|
||||
issues: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
message: expect.stringContaining("coverage.status"),
|
||||
}),
|
||||
]),
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user