mirror of
https://github.com/morluto/rea
synced 2026-10-26 22:28:27 -04:00
b4db35f092
* fix: bind identity and coverage to the producing rule Logical paths, container families, examined bytes, path-segment conventions, destination collisions, file-id leases, Mach-O CPU selection, and firmware cleanup now follow the observation that owns each rule. * fix: fail unmatched Mach-O slices and keep firmware roots independent A fat target whose architecture lipo did not list now stops before slice tools run. Chained fixups still count unread LC_DYLD_INFO rebase bytes, and a firmware cleanup failure no longer blocks the next workspace. * test: cover path identity and runtime families at the projection boundary NFC joins and segment conventions are now asserted by the path resolver, the Apple projection, and a real APK inventory instead of helper unit tests. * test: expect unread dyld rebase bytes in the Apple dispatch fixture The legacy LC_DYLD_INFO fixture keeps a rebase range this reader does not decode, so the public CLI and MCP check now requires that partial coverage beside the bind opcodes. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
115 lines
4.4 KiB
TypeScript
115 lines
4.4 KiB
TypeScript
/** Stable tags exposed by safe analysis-error projections. */
|
|
const ANALYSIS_ERROR_TAGS = [
|
|
"AnalysisProtocolError",
|
|
"AnalysisInputError",
|
|
"AnalysisAccessDeniedError",
|
|
"AnalysisArtifactChangedError",
|
|
"AnalysisOutputError",
|
|
"AnalysisCapabilityUnavailableError",
|
|
"AnalysisUnsupportedTargetError",
|
|
"AnalysisCancelledError",
|
|
"AnalysisTimeoutError",
|
|
"AnalysisResourceConstraintError",
|
|
"ProviderSelectionError",
|
|
"ProviderAdapterError",
|
|
"BrowserObservationError",
|
|
"ArtifactOperationError",
|
|
"ProcessCaptureError",
|
|
"EvidenceIntegrityError",
|
|
"EvidenceFileError",
|
|
"UnknownRegistryError",
|
|
"HopperTimeoutError",
|
|
"HopperCancelledError",
|
|
"HopperProtocolError",
|
|
"HopperRemoteError",
|
|
"HopperProcessError",
|
|
"HopperStartError",
|
|
"ConfigurationError",
|
|
"NoBinaryOpenError",
|
|
"BinaryTargetError",
|
|
] as const;
|
|
|
|
/** Stable tag for an expected analysis failure. */
|
|
export type AnalysisErrorTag = (typeof ANALYSIS_ERROR_TAGS)[number];
|
|
|
|
/** Retained command output associated with a typed failure; truncation stays explicit. */
|
|
export interface AnalysisCapturedOutput {
|
|
readonly stdout: string;
|
|
readonly stderr: string;
|
|
readonly truncated: boolean;
|
|
readonly stdout_bytes?: number;
|
|
readonly stderr_bytes?: number;
|
|
readonly exit_code?: number | null;
|
|
readonly signal?: string | null;
|
|
}
|
|
|
|
/** Cleanup uncertainty attached to the original typed analysis failure. */
|
|
export interface AnalysisCleanupObservation {
|
|
readonly reason: string;
|
|
readonly resources: readonly string[];
|
|
}
|
|
|
|
/** Optional provider-neutral context that must survive typed error projection. */
|
|
export interface AnalysisErrorOptions extends ErrorOptions {
|
|
readonly capturedOutput?: AnalysisCapturedOutput;
|
|
readonly cleanup?: AnalysisCleanupObservation;
|
|
readonly partialObservation?: AnalysisPartialObservation;
|
|
}
|
|
|
|
/** Base class for expected analysis, provider, and session failures. */
|
|
export abstract class AnalysisError extends Error {
|
|
readonly capturedOutput: AnalysisCapturedOutput | undefined;
|
|
readonly cleanup: AnalysisCleanupObservation | undefined;
|
|
readonly cleanupIncomplete: boolean;
|
|
readonly cleanupResources: readonly string[];
|
|
constructor(message: string, options?: AnalysisErrorOptions) {
|
|
super(message, options);
|
|
this.capturedOutput =
|
|
options?.capturedOutput === undefined
|
|
? undefined
|
|
: { ...options.capturedOutput };
|
|
this.cleanup = options?.cleanup;
|
|
this.cleanupIncomplete = options?.cleanup !== undefined;
|
|
this.cleanupResources = options?.cleanup?.resources ?? [];
|
|
this.partialObservation = options?.partialObservation;
|
|
}
|
|
abstract readonly _tag: AnalysisErrorTag;
|
|
readonly userMessage: string | undefined = undefined;
|
|
readonly userCategory: "cancelled" | undefined = undefined;
|
|
readonly executionFailure: string | undefined = undefined;
|
|
partialObservation: AnalysisPartialObservation | undefined;
|
|
readonly cleanupReport: ProcessCaptureCleanupReport | undefined = undefined;
|
|
|
|
/** Retain a completed observation when a later step fails. */
|
|
retainPartialObservation(observation: AnalysisPartialObservation): this {
|
|
this.partialObservation ??= observation;
|
|
return this;
|
|
}
|
|
}
|
|
import type {
|
|
PartialProcessCaptureObservation,
|
|
ProcessCaptureCleanupReport,
|
|
} from "./process/processCapture.js";
|
|
import type { FileOffsetPartialObservation } from "./native/fileOffsetPartialObservation.js";
|
|
import type { NativeCallPartialObservation } from "./native/nativeCallPartialObservation.js";
|
|
import type { ElectronActivePartialObservation } from "./javascript/electronActiveObservation.js";
|
|
import type { JavaScriptRuntimeObservation } from "./javascript/javascriptRuntimeObservation.js";
|
|
import type { ArtifactInventoryPartialObservation } from "./artifactPartialObservation.js";
|
|
import type { BrowserScenarioPartialObservation } from "./browserScenarioCapture.js";
|
|
import type { Evidence } from "./evidence.js";
|
|
import type { AndroidPartialObservation } from "./android/androidPartialObservation.js";
|
|
import type { FirmwarePartialObservation } from "./firmware/firmwareAnalysis.js";
|
|
|
|
/** Provider-neutral evidence collected before a typed analysis failure. */
|
|
export type AnalysisPartialObservation =
|
|
| PartialProcessCaptureObservation
|
|
| NativeCallPartialObservation
|
|
| FileOffsetPartialObservation
|
|
| ElectronActivePartialObservation
|
|
| BrowserScenarioPartialObservation
|
|
| JavaScriptRuntimeObservation
|
|
| ArtifactInventoryPartialObservation
|
|
| Evidence
|
|
| AndroidPartialObservation
|
|
| FirmwarePartialObservation;
|