Files
reverse-engineering-anything/src/application/InventoryProjectionEvidence.ts
T
morlutoandFelix 52fe342c73 fix(evidence): preserve subjects in derived workflows (#9492)
* fix(javascript): preserve verified trace evidence subjects

Co-authored-by: Felix <3937061056@qq.com>

* fix(evidence): preserve selected subject names in views

* fix(evidence): preserve subjects across related workflows

* fix(evidence): retain inventory projection subjects

* fix(managed): validate projected graph root identity

* style: format evidence and native command code

* fix(javascript): validate static graph root identity

* test(javascript): update feature trace graph expectations

---------

Co-authored-by: Felix <3937061056@qq.com>
2026-11-09 08:12:17 +08:00

90 lines
2.8 KiB
TypeScript

import {
resolveEvidenceRequest,
type EvidenceLookup,
} from "./EvidenceInputResolver.js";
import type { ExecutionOptions } from "./AnalysisProvider.js";
import type { AnalysisInputError } from "../domain/analysisErrorCore.js";
import type { AnalysisError } from "../domain/analysisErrorBase.js";
import {
createEvidence,
evidenceSubjectTarget,
type Evidence,
type EvidenceProvider,
} from "../domain/evidence.js";
import type { JsonValue } from "../domain/jsonValue.js";
import type { ParsedInventorySet } from "../domain/artifactInventoryEvidence.js";
import {
applicationInventoryProjectionInputSchema,
readApplicationInventoryProjection,
} from "../domain/mobileApplicationGraphProjection.js";
import { ok, type Result } from "../domain/result.js";
interface InventoryProjectionResult {
readonly root_sha256: string;
readonly source_evidence_ids: readonly string[];
readonly limitations: readonly string[];
}
export interface InventoryProjectionEvidenceResult {
readonly evidence: Evidence;
readonly sources: readonly Evidence[];
}
interface InventoryProjectionOptions<
Output extends InventoryProjectionResult & JsonValue,
> {
readonly rawInput: unknown;
readonly lookup?: EvidenceLookup;
readonly execution?: Pick<ExecutionOptions, "signal">;
readonly project: (
input: ParsedInventorySet,
) => Result<Output, AnalysisInputError>;
readonly operation: string;
readonly predicateType: string;
readonly provider: EvidenceProvider;
}
/** Resolve source inventory once, then wrap its family projection in Evidence. */
export const projectInventoryEvidence = <
Output extends InventoryProjectionResult & JsonValue,
>(
options: InventoryProjectionOptions<Output>,
): Result<InventoryProjectionEvidenceResult, AnalysisError> => {
const request = resolveEvidenceRequest(
options.operation,
options.rawInput,
applicationInventoryProjectionInputSchema,
options.lookup,
options.execution,
);
if (!request.ok) return request;
const source = readApplicationInventoryProjection(
request.value.input,
options.operation,
);
if (!source.ok) return source;
const projected = options.project(source.value);
if (!projected.ok) return projected;
const result = projected.value;
const first = source.value.evidence[0];
return ok({
evidence: createEvidence(
evidenceSubjectTarget(first?.subject ?? null),
options.provider,
{
predicateType: options.predicateType,
operation: options.operation,
parameters: { inventory_evidence_ids: [...result.source_evidence_ids] },
result,
rawResult: null,
confidence: "inferred",
authority: "analyst-inference",
environment: null,
limitations: result.limitations,
evidenceLinks: result.source_evidence_ids,
},
),
sources: source.value.evidence,
});
};