mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
refactor(evidence): centralize analysis observation facts
This commit is contained in:
1 parent
7f9a03d6ab
commit
6dff37594c
14 files changed
+97
-101
No files matched your search
@@ -27,9 +27,9 @@ import type {
|
||||
import { providerConfigurationRefusal } from "../domain/providerConfigurationRefusal.js";
|
||||
import {
|
||||
createAnalysisExecution,
|
||||
createAnalysisExecutionEvidence,
|
||||
type AnalysisExecution,
|
||||
} from "../application/AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
import {
|
||||
apktoolResultSchemas,
|
||||
DEFAULT_APKTOOL_DECODE_TIMEOUT_MS,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
createAnalysisExecutionEvidence,
|
||||
type AnalysisExecution,
|
||||
type AnalysisOperationPort,
|
||||
import type {
|
||||
AnalysisExecution,
|
||||
AnalysisOperationPort,
|
||||
} from "./AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisCapabilityUnavailableError,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { EvidenceCreationOptions } from "../domain/evidence.js";
|
||||
import type { AnalysisObservation } from "../domain/analysisObservation.js";
|
||||
import type { ProviderInspectionScope } from "../providers/ProviderInspectionScope.js";
|
||||
import type { BinaryTarget } from "../domain/binaryTargetTypes.js";
|
||||
import type { OfficialToolName } from "../contracts/officialToolContracts.js";
|
||||
@@ -10,13 +10,11 @@ import type { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import type { AnalysisProfileCommitment } from "../domain/analysisProfile.js";
|
||||
import type { JsonValue } from "../domain/jsonValue.js";
|
||||
import type { Result } from "../domain/result.js";
|
||||
import {
|
||||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceLocation,
|
||||
type EvidenceSubjectTarget,
|
||||
import type {
|
||||
EvidenceLocation,
|
||||
EvidenceSubjectTarget,
|
||||
} from "../domain/evidence.js";
|
||||
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import type { ProgressReporter } from "./ProgressReporter.js";
|
||||
import type { ProviderRejectionCode } from "../contracts/providerSelection.js";
|
||||
import type { ProcessLineageObservation } from "../process/ProcessOwnership.js";
|
||||
@@ -51,16 +49,10 @@ export type AnalysisOperation =
|
||||
| "health";
|
||||
|
||||
/** Atomic successful provider observation with exact producing provenance. */
|
||||
export interface AnalysisExecution {
|
||||
readonly result: JsonValue;
|
||||
readonly rawResult: JsonValue | null;
|
||||
export interface AnalysisExecution extends AnalysisObservation {
|
||||
readonly provider: ProviderIdentity;
|
||||
readonly analysisProfile?: AnalysisProfileCommitment;
|
||||
/** Result-specific veto of snapshot replay; Evidence remains retainable. */
|
||||
readonly cachePolicy?: "live";
|
||||
readonly limitations: readonly string[];
|
||||
/** Provider-owned completeness assessment for caller/callee observations. */
|
||||
readonly relationshipCoverage?: RelationshipCoverage;
|
||||
/**
|
||||
* Whether the provider capped an `xrefs` read: true when it reported a
|
||||
* truncation, false when it explicitly reported none. Absent when it reports
|
||||
@@ -68,12 +60,6 @@ export interface AnalysisExecution {
|
||||
* output.
|
||||
*/
|
||||
readonly referencesTruncated?: boolean;
|
||||
readonly locations: readonly EvidenceLocation[];
|
||||
/**
|
||||
* Missing means the selected operation's default subject should be bound by
|
||||
* its caller. Explicit null means the observation has no file subject.
|
||||
*/
|
||||
readonly subject?: EvidenceSubjectTarget | null;
|
||||
}
|
||||
|
||||
interface CreateAnalysisExecutionOptions {
|
||||
@@ -138,40 +124,6 @@ export function createAnalysisExecution(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose one completed provider execution into its caller-visible Evidence,
|
||||
* so success and a late cancellation that retains it carry identical facts.
|
||||
*/
|
||||
export const createAnalysisExecutionEvidence = (
|
||||
operation: string,
|
||||
input: unknown,
|
||||
execution: AnalysisExecution,
|
||||
confidence: "observed" | "derived",
|
||||
options?: EvidenceCreationOptions,
|
||||
): Evidence =>
|
||||
createEvidence(
|
||||
execution.subject === undefined
|
||||
? undefined
|
||||
: (execution.subject ?? undefined),
|
||||
execution.provider,
|
||||
{
|
||||
operation,
|
||||
parameters: jsonObjectSchema.parse(input),
|
||||
result: execution.result,
|
||||
rawResult: execution.rawResult,
|
||||
limitations: execution.limitations,
|
||||
...(execution.analysisProfile === undefined
|
||||
? {}
|
||||
: { analysisProfile: execution.analysisProfile }),
|
||||
...(execution.relationshipCoverage === undefined
|
||||
? {}
|
||||
: { relationshipCoverage: execution.relationshipCoverage }),
|
||||
locations: execution.locations,
|
||||
confidence,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
/** Provider-neutral application capability for one analysis operation. */
|
||||
export interface AnalysisOperationPort {
|
||||
execute(
|
||||
|
||||
@@ -4,10 +4,8 @@ import { join } from "node:path";
|
||||
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import {
|
||||
createAnalysisExecution,
|
||||
createAnalysisExecutionEvidence,
|
||||
} from "./AnalysisProvider.js";
|
||||
import { createAnalysisExecution } from "./AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
import { resolveAppBundleResourceRoot } from "./AppBundleExecutable.js";
|
||||
import { bindExecutionTarget } from "./binary/BinarySessionExecution.js";
|
||||
import type { BinaryTarget } from "../domain/binaryTargetTypes.js";
|
||||
|
||||
@@ -47,7 +47,7 @@ import type {
|
||||
AnalysisExecution,
|
||||
ProviderIdentity,
|
||||
} from "./AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "./AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
import {
|
||||
REA_WORKFLOW_PROVIDER,
|
||||
workflowAnalysisProfile,
|
||||
|
||||
@@ -17,11 +17,11 @@ import {
|
||||
import { jsonValueSchema } from "../domain/jsonValue.js";
|
||||
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
||||
import { err, ok, type Result } from "../domain/result.js";
|
||||
import {
|
||||
createAnalysisExecutionEvidence,
|
||||
type AnalysisExecution,
|
||||
type ExecutionOptions,
|
||||
import type {
|
||||
AnalysisExecution,
|
||||
ExecutionOptions,
|
||||
} from "./AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
|
||||
/** Validated caller-selected request carrying its operation input. */
|
||||
export interface ProviderOperationRequest {
|
||||
|
||||
@@ -3,11 +3,11 @@ import {
|
||||
packetFieldsCatalogSchema,
|
||||
type InspectPacketFieldsInput,
|
||||
} from "../../domain/captures/packetFields.js";
|
||||
import {
|
||||
createAnalysisExecutionEvidence,
|
||||
type AnalysisExecution,
|
||||
type ExecutionOptions,
|
||||
import type {
|
||||
AnalysisExecution,
|
||||
ExecutionOptions,
|
||||
} from "../AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../../domain/analysisObservation.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {
|
||||
createAnalysisExecutionEvidence,
|
||||
type ExecutionOptions,
|
||||
} from "../AnalysisProvider.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../../domain/analysisObservation.js";
|
||||
import type { FirmwareAnalysisPort } from "./FirmwareAnalysisPort.js";
|
||||
import {
|
||||
firmwareRequestSchema,
|
||||
|
||||
@@ -3,11 +3,11 @@ import {
|
||||
signalDecodersSchema,
|
||||
type InspectSignalDecodersInput,
|
||||
} from "../../domain/signals/signalDecoders.js";
|
||||
import {
|
||||
createAnalysisExecutionEvidence,
|
||||
type AnalysisExecution,
|
||||
type ExecutionOptions,
|
||||
import type {
|
||||
AnalysisExecution,
|
||||
ExecutionOptions,
|
||||
} from "../AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../../domain/analysisObservation.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {
|
||||
createAnalysisExecutionEvidence,
|
||||
type ExecutionOptions,
|
||||
} from "../AnalysisProvider.js";
|
||||
import type { ExecutionOptions } from "../AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../../domain/analysisObservation.js";
|
||||
import type { WasmArtifactPort } from "./WasmArtifactPort.js";
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
createEvidence,
|
||||
type Evidence,
|
||||
type EvidenceCreationOptions,
|
||||
type EvidenceLocation,
|
||||
type EvidenceProvider,
|
||||
type EvidenceSubjectTarget,
|
||||
} from "./evidence.js";
|
||||
import type { AnalysisProfileCommitment } from "./analysisProfile.js";
|
||||
import { jsonObjectSchema, type JsonValue } from "./jsonValue.js";
|
||||
import type { RelationshipCoverage } from "./relationshipCoverage.js";
|
||||
|
||||
/** Provider observations that can be committed to Evidence. */
|
||||
export interface AnalysisObservation {
|
||||
readonly result: JsonValue;
|
||||
readonly rawResult: JsonValue | null;
|
||||
readonly provider: EvidenceProvider;
|
||||
readonly analysisProfile?: AnalysisProfileCommitment;
|
||||
readonly limitations: readonly string[];
|
||||
/** Provider-owned completeness assessment for caller/callee observations. */
|
||||
readonly relationshipCoverage?: RelationshipCoverage;
|
||||
readonly locations: readonly EvidenceLocation[];
|
||||
/**
|
||||
* Missing means the selected operation's default subject should be bound by
|
||||
* its caller. Explicit null means the observation has no file subject.
|
||||
*/
|
||||
readonly subject?: EvidenceSubjectTarget | null;
|
||||
}
|
||||
|
||||
/** Commit identical facts on success and when retaining a completed observation after cancellation. */
|
||||
export const createAnalysisExecutionEvidence = (
|
||||
operation: string,
|
||||
input: unknown,
|
||||
execution: AnalysisObservation,
|
||||
confidence: "observed" | "derived",
|
||||
options?: EvidenceCreationOptions,
|
||||
): Evidence =>
|
||||
createEvidence(
|
||||
execution.subject === undefined
|
||||
? undefined
|
||||
: (execution.subject ?? undefined),
|
||||
execution.provider,
|
||||
{
|
||||
operation,
|
||||
parameters: jsonObjectSchema.parse(input),
|
||||
result: execution.result,
|
||||
rawResult: execution.rawResult,
|
||||
limitations: execution.limitations,
|
||||
...(execution.analysisProfile === undefined
|
||||
? {}
|
||||
: { analysisProfile: execution.analysisProfile }),
|
||||
...(execution.relationshipCoverage === undefined
|
||||
? {}
|
||||
: { relationshipCoverage: execution.relationshipCoverage }),
|
||||
locations: execution.locations,
|
||||
confidence,
|
||||
},
|
||||
options,
|
||||
);
|
||||
@@ -227,11 +227,7 @@ export const rebindEvidenceSubjectTargetPath = (
|
||||
type EvidenceAuthority = z.infer<typeof evidenceAuthoritySchema>;
|
||||
type ExecutionEnvironment = z.infer<typeof executionEnvironmentSchema>;
|
||||
|
||||
export interface EvidenceProvider {
|
||||
readonly id: string;
|
||||
readonly name: string;
|
||||
readonly version: string | null;
|
||||
}
|
||||
export type EvidenceProvider = Readonly<z.output<typeof providerSchema>>;
|
||||
|
||||
export interface EvidenceObservation {
|
||||
readonly predicateType?: string;
|
||||
|
||||
@@ -12,9 +12,9 @@ import type {
|
||||
} from "../application/AnalysisProvider.js";
|
||||
import {
|
||||
createAnalysisExecution,
|
||||
createAnalysisExecutionEvidence,
|
||||
type AnalysisExecution,
|
||||
} from "../application/AnalysisProvider.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
import {
|
||||
MAX_FLUTTER_LIBRARY_PATH_BYTES,
|
||||
type FlutterRequest,
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
import { ProviderCleanupError } from "../domain/providerCleanupError.js";
|
||||
import { analysisErrorWithCleanupFailure } from "../domain/analysisErrorCleanup.js";
|
||||
import { createEvidence } from "../domain/evidence.js";
|
||||
import { createAnalysisExecutionEvidence } from "../domain/analysisObservation.js";
|
||||
import { projectAnalysisError } from "../domain/analysisErrorProjection.js";
|
||||
import {
|
||||
wasmArtifactSchema,
|
||||
@@ -478,17 +479,11 @@ export class WabtArtifactProvider implements WasmArtifactPort {
|
||||
result.ok &&
|
||||
(options?.signal?.aborted || cleanup.kind === "failed")
|
||||
) {
|
||||
partialObservation = createEvidence(
|
||||
result.value.subject ?? undefined,
|
||||
result.value.provider,
|
||||
{
|
||||
operation: OPERATION,
|
||||
parameters: input,
|
||||
result: result.value.result,
|
||||
confidence: "observed",
|
||||
locations: result.value.locations,
|
||||
limitations: result.value.limitations,
|
||||
},
|
||||
partialObservation = createAnalysisExecutionEvidence(
|
||||
OPERATION,
|
||||
input,
|
||||
result.value,
|
||||
"observed",
|
||||
);
|
||||
}
|
||||
if (result.ok && options?.signal?.aborted) {
|
||||
|
||||
Reference in new issue
Block a user