rea-agents 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -66
- package/bridge/ghidra/ReaGhidraBridge.java +2075 -0
- package/bridge/hopper_bridge.py +13 -3
- package/dist/application/AbortablePromise.js +25 -0
- package/dist/application/AnalysisProvider.js +3 -0
- package/dist/application/AnalysisProviderEvaluation.js +60 -0
- package/dist/application/AnalysisProviderRegistry.js +228 -0
- package/dist/application/AnalysisSnapshotCache.js +41 -21
- package/dist/application/AnalysisSnapshotFiles.js +5 -6
- package/dist/application/BinarySession.js +218 -101
- package/dist/application/CapabilityInventory.js +18 -0
- package/dist/application/CompositeProvider.js +20 -8
- package/dist/application/CrossVersionInvestigation.js +10 -6
- package/dist/application/DirectAnalysis.js +49 -35
- package/dist/application/Doctor.js +110 -8
- package/dist/application/ElectronBoundaryAnalysis.js +96 -0
- package/dist/application/ElectronBoundaryGraph.js +9 -0
- package/dist/application/ElectronBoundaryGraphContext.js +62 -0
- package/dist/application/ElectronBoundaryGraphIpc.js +242 -0
- package/dist/application/ElectronBoundaryGraphNative.js +86 -0
- package/dist/application/ElectronBoundaryGraphWindows.js +199 -0
- package/dist/application/EnhancedTools.js +39 -14
- package/dist/application/InvestigationProviders.js +41 -0
- package/dist/application/JavaScriptApplicationEvidence.js +26 -0
- package/dist/application/JavaScriptApplicationEvidenceGraph.js +89 -0
- package/dist/application/JavaScriptApplicationService.js +74 -0
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +29 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +90 -0
- package/dist/application/JavaScriptArtifactAnalysis.js +305 -0
- package/dist/application/JavaScriptArtifactAnalysisTypes.js +1 -0
- package/dist/application/JavaScriptArtifactFiles.js +231 -0
- package/dist/application/JavaScriptArtifactGraphAccumulator.js +54 -0
- package/dist/application/JavaScriptArtifactGraphBuilder.js +144 -0
- package/dist/application/JavaScriptArtifactGraphContext.js +205 -0
- package/dist/application/JavaScriptArtifactGraphDocuments.js +108 -0
- package/dist/application/JavaScriptArtifactGraphEvidence.js +99 -0
- package/dist/application/JavaScriptArtifactGraphFindings.js +271 -0
- package/dist/application/JavaScriptArtifactGraphStructure.js +409 -0
- package/dist/application/JavaScriptArtifactReconstruction.js +77 -0
- package/dist/application/JavaScriptArtifactReconstructionInput.js +18 -0
- package/dist/application/JavaScriptReplayPlanning.js +201 -0
- package/dist/application/JavaScriptReplayService.js +266 -0
- package/dist/application/JavaScriptRuntimeReconciliationEvidence.js +25 -0
- package/dist/application/JavaScriptRuntimeReconciliationService.js +27 -0
- package/dist/application/MacHopper.js +20 -4
- package/dist/application/ManagedApplicationGraphService.js +55 -0
- package/dist/application/ManagedMemberComparisonService.js +122 -0
- package/dist/application/ManagedNativeVerificationService.js +39 -0
- package/dist/application/ManagedReconstructionService.js +58 -0
- package/dist/application/ManagedRuntimeCorrelationService.js +103 -0
- package/dist/application/PermissionAuthority.js +1 -1
- package/dist/application/ProcessCaptureLifecycle.js +1 -1
- package/dist/application/ProcessHarness.js +1 -1
- package/dist/application/ProcessSampling.js +16 -12
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/SessionProviderRouter.js +219 -0
- package/dist/application/Setup.js +84 -60
- package/dist/application/SetupClients.js +1 -1
- package/dist/application/SetupPlan.js +9 -2
- package/dist/application/SupportedClients.js +40 -16
- package/dist/application/Upgrade.js +1 -1
- package/dist/application/runtime.js +11 -6
- package/dist/artifacts/AsarArtifactReader.js +23 -3
- package/dist/browser/CdpBrowserProvider.js +4 -2
- package/dist/browser/CdpCaptureEvents.js +49 -0
- package/dist/browser/CdpElectronInspection.js +106 -162
- package/dist/browser/CdpElectronProvider.js +9 -3
- package/dist/browser/CdpElectronScriptEvents.js +69 -0
- package/dist/browser/CdpElectronScripts.js +94 -0
- package/dist/browser/CdpElectronWorkers.js +56 -0
- package/dist/browser/CdpEndpoint.js +14 -1
- package/dist/browser/CdpPageCapture.js +8 -4
- package/dist/catalogIdentity.js +6 -42
- package/dist/cli.js +446 -34
- package/dist/cliApplicationCommands.js +62 -0
- package/dist/cliBrowserAdvancedCommands.js +5 -4
- package/dist/cliBrowserCommands.js +5 -4
- package/dist/cliCommandNames.js +56 -0
- package/dist/cliElectronCommands.js +106 -3
- package/dist/cliEvidenceCommands.js +4 -3
- package/dist/cliInvestigationCommands.js +2 -1
- package/dist/cliJsonInput.js +54 -0
- package/dist/cliPolicyCommands.js +2 -1
- package/dist/cliProcessCommands.js +3 -2
- package/dist/config.js +101 -2
- package/dist/contracts/applicationToolContracts.js +91 -0
- package/dist/contracts/artifactToolContracts.js +5 -9
- package/dist/contracts/browserToolContracts.js +14 -62
- package/dist/contracts/electronToolContracts.js +45 -19
- package/dist/contracts/enhancedInputs.js +2 -2
- package/dist/contracts/errorSchemas.js +1 -0
- package/dist/contracts/investigationExamples.js +0 -6
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +46 -0
- package/dist/contracts/javascriptRuntimeReconciliationExample.js +208 -0
- package/dist/contracts/managedToolContracts.js +153 -0
- package/dist/contracts/managedWorkflowExamples.js +346 -0
- package/dist/contracts/managedWorkflowToolContracts.js +203 -0
- package/dist/contracts/nativeToolContracts.js +2 -6
- package/dist/contracts/promptContracts.js +18 -2
- package/dist/contracts/providerSelection.js +28 -0
- package/dist/contracts/sessionLifecycleInputs.js +2 -0
- package/dist/contracts/toolContractExamples.js +10 -25
- package/dist/contracts/toolContracts.js +69 -65
- package/dist/contracts/toolEffects.js +160 -0
- package/dist/contracts/toolOutputSchemas.js +152 -42
- package/dist/doctorRuntime.js +47 -0
- package/dist/domain/analysisProfile.js +78 -0
- package/dist/domain/analysisSnapshot.js +92 -46
- package/dist/domain/artifactComparison.js +3 -4
- package/dist/domain/artifactGraph.js +1 -0
- package/dist/domain/binaryTarget.js +4 -29
- package/dist/domain/browserObservation.js +3 -0
- package/dist/domain/bundleComparison.js +4 -4
- package/dist/domain/electronObservation.js +13 -0
- package/dist/domain/electronStaticAnalysis.js +9 -0
- package/dist/domain/electronStaticAnalysisBrowser.js +194 -0
- package/dist/domain/electronStaticAnalysisIpc.js +171 -0
- package/dist/domain/electronStaticAnalysisNative.js +164 -0
- package/dist/domain/electronStaticAnalysisTypes.js +1 -0
- package/dist/domain/electronStaticAnalysisValues.js +103 -0
- package/dist/domain/errors.js +148 -7
- package/dist/domain/evidence.js +44 -5
- package/dist/domain/evidenceBundle.js +9 -7
- package/dist/domain/functionComparison.js +9 -3
- package/dist/domain/functionComparisonNormalization.js +37 -0
- package/dist/domain/functionComparisonSchemas.js +3 -8
- package/dist/domain/functionDossierEvidence.js +4 -1
- package/dist/domain/hopperValues.js +66 -9
- package/dist/domain/inputIssueProjection.js +52 -0
- package/dist/domain/investigationWorkspace.js +2 -1
- package/dist/domain/javascriptApplicationAnalysis.js +155 -0
- package/dist/domain/javascriptApplicationChangeGraph.js +231 -0
- package/dist/domain/javascriptApplicationEvidenceSchemas.js +379 -0
- package/dist/domain/javascriptApplicationGraph.js +282 -0
- package/dist/domain/javascriptApplicationGraphSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionComparison.js +116 -0
- package/dist/domain/javascriptApplicationVersionComparisonSchemas.js +139 -0
- package/dist/domain/javascriptApplicationVersionItems.js +221 -0
- package/dist/domain/javascriptApplicationVersionKeys.js +170 -0
- package/dist/domain/javascriptAstFingerprint.js +143 -0
- package/dist/domain/javascriptFeatureSeed.js +140 -0
- package/dist/domain/javascriptFeatureTrace.js +232 -0
- package/dist/domain/javascriptFeatureTraceSchemas.js +136 -0
- package/dist/domain/javascriptFeatureTraversal.js +88 -0
- package/dist/domain/javascriptNativeHandoff.js +85 -0
- package/dist/domain/javascriptReplay.js +361 -0
- package/dist/domain/javascriptRuntimeLoadState.js +106 -0
- package/dist/domain/javascriptRuntimeReconciliation.js +42 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +169 -0
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +247 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +160 -0
- package/dist/domain/javascriptRuntimeReconciliationResult.js +119 -0
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +316 -0
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +245 -0
- package/dist/domain/javascriptRuntimeStaticCandidates.js +191 -0
- package/dist/domain/javascriptStaticAnalysis.js +346 -0
- package/dist/domain/javascriptStaticAnalysisFindings.js +39 -0
- package/dist/domain/javascriptStaticAnalysisHelpers.js +274 -0
- package/dist/domain/javascriptStaticAnalysisState.js +23 -0
- package/dist/domain/javascriptStaticAnalysisTypes.js +1 -0
- package/dist/domain/managedApplicationGraph.js +556 -0
- package/dist/domain/managedArtifact.js +444 -0
- package/dist/domain/managedMemberComparison.js +565 -0
- package/dist/domain/managedNativeVerification.js +408 -0
- package/dist/domain/managedReconstruction.js +183 -0
- package/dist/domain/managedRuntimeCorrelation.js +175 -0
- package/dist/domain/reconstructionVerificationSchemas.js +1 -3
- package/dist/dotnet/ManagedArtifactInspector.js +318 -0
- package/dist/dotnet/ManagedMemberInspector.js +887 -0
- package/dist/dotnet/ManagedMetadataHeaps.js +131 -0
- package/dist/dotnet/ManagedMetadataInventory.js +368 -0
- package/dist/dotnet/ManagedMetadataLayout.js +322 -0
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +391 -0
- package/dist/dotnet/ManagedPeReader.js +157 -0
- package/dist/dotnet/ManagedReaderFailure.js +10 -0
- package/dist/dotnet/ManagedStaticProvider.js +203 -0
- package/dist/generatedPackageMetadata.js +2 -2
- package/dist/ghidra/GhidraAnalysisProfile.js +37 -0
- package/dist/ghidra/GhidraClient.js +400 -0
- package/dist/ghidra/GhidraClientTypes.js +1 -0
- package/dist/ghidra/GhidraDefaults.js +20 -0
- package/dist/ghidra/GhidraDiagnostics.js +43 -0
- package/dist/ghidra/GhidraDoctor.js +59 -0
- package/dist/ghidra/GhidraFunctionValues.js +264 -0
- package/dist/ghidra/GhidraInstallation.js +239 -0
- package/dist/ghidra/GhidraInventoryValues.js +217 -0
- package/dist/ghidra/GhidraLauncher.js +139 -0
- package/dist/ghidra/GhidraProvider.js +366 -0
- package/dist/ghidra/GhidraRequestQueue.js +98 -0
- package/dist/ghidra/GhidraResponseBuffer.js +31 -0
- package/dist/ghidra/GhidraResponseRouter.js +24 -0
- package/dist/ghidra/GhidraSessionError.js +39 -0
- package/dist/ghidra/GhidraSessionValues.js +62 -0
- package/dist/ghidra/GhidraSocketConnection.js +46 -0
- package/dist/ghidra/protocol.js +69 -0
- package/dist/hopper/BridgeLauncher.js +19 -54
- package/dist/hopper/HopperAnalysisProfile.js +106 -0
- package/dist/hopper/HopperClient.js +154 -162
- package/dist/hopper/HopperProvider.js +99 -7
- package/dist/hopper/HopperSessionValues.js +27 -0
- package/dist/hopper/HopperSocketConnection.js +31 -0
- package/dist/main.js +14 -0
- package/dist/native/NativeMacOSProvider.js +3 -1
- package/dist/process/PendingOperations.js +59 -0
- package/dist/process/PrivateRuntimeRoot.js +33 -0
- package/dist/process/ProviderDeadline.js +95 -0
- package/dist/process/ProviderProcess.js +275 -0
- package/dist/replay/JavaScriptReplayWorker.js +286 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +434 -0
- package/dist/replay/LinuxRuntimeClosure.js +46 -0
- package/dist/replay/LinuxSeccompPolicy.js +40 -0
- package/dist/replay/ReplayWorkerProtocol.js +55 -0
- package/dist/replay/SystemJavaScriptReplayHost.js +182 -0
- package/dist/server/createServer.js +53 -0
- package/dist/server/promptCompletion.js +9 -3
- package/dist/server/registerApplicationTools.js +115 -0
- package/dist/server/registerArtifactComparisonTool.js +16 -9
- package/dist/server/registerBrowserTools.js +33 -8
- package/dist/server/registerBundleComparisonTool.js +17 -20
- package/dist/server/registerElectronTools.js +45 -3
- package/dist/server/registerEnhancedTools.js +67 -19
- package/dist/server/registerEvidenceTools.js +5 -1
- package/dist/server/registerFunctionComparisonTool.js +14 -7
- package/dist/server/registerInvestigationTools.js +21 -17
- package/dist/server/registerManagedTools.js +6 -0
- package/dist/server/registerManagedWorkflowTools.js +277 -0
- package/dist/server/registerOfficialTools.js +11 -8
- package/dist/server/registerProcessComparisonTool.js +25 -47
- package/dist/server/registerSessionStatusTool.js +7 -7
- package/dist/server/registerSessionTools.js +57 -87
- package/dist/server/sessionEvidence.js +14 -19
- package/dist/server/toolInputValidation.js +77 -0
- package/dist/server/toolRegistrationOptions.js +79 -2
- package/dist/server/toolResult.js +25 -17
- package/package.json +17 -7
- package/scripts/rea.mjs +36 -2
- package/skills/rea-analysis/SKILL.md +59 -3
- /package/dist/{application → process}/ProcessOwnership.js +0 -0
package/dist/domain/errors.js
CHANGED
|
@@ -28,6 +28,7 @@ const ANALYSIS_ERROR_TAGS = [
|
|
|
28
28
|
"NoBinaryOpenError",
|
|
29
29
|
"BinaryTargetError",
|
|
30
30
|
"PermissionRequiredError",
|
|
31
|
+
"ReplayPlanStaleError",
|
|
31
32
|
];
|
|
32
33
|
/** Base class for expected analysis, provider, and session failures. */
|
|
33
34
|
export class AnalysisError extends Error {
|
|
@@ -46,10 +47,12 @@ export class AnalysisProtocolError extends AnalysisError {
|
|
|
46
47
|
/** Caller input failed provider-neutral application parsing. */
|
|
47
48
|
export class AnalysisInputError extends AnalysisError {
|
|
48
49
|
operation;
|
|
50
|
+
issues;
|
|
49
51
|
_tag = "AnalysisInputError";
|
|
50
|
-
constructor(operation, options) {
|
|
52
|
+
constructor(operation, options, issues = []) {
|
|
51
53
|
super(`Invalid analysis input for ${operation}`, options);
|
|
52
54
|
this.operation = operation;
|
|
55
|
+
this.issues = issues;
|
|
53
56
|
}
|
|
54
57
|
}
|
|
55
58
|
/** Provider output failed provider-neutral application parsing. */
|
|
@@ -96,24 +99,74 @@ export class AnalysisTimeoutError extends AnalysisError {
|
|
|
96
99
|
this.timeoutMs = timeoutMs;
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
|
-
/** No configured provider can satisfy a requested operation. */
|
|
102
|
+
/** No configured provider can satisfy a requested operation or target binding. */
|
|
100
103
|
export class ProviderSelectionError extends AnalysisError {
|
|
101
|
-
operation;
|
|
102
104
|
_tag = "ProviderSelectionError";
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
operation;
|
|
106
|
+
reason;
|
|
107
|
+
requestedProviderId;
|
|
108
|
+
candidateIds;
|
|
109
|
+
rejections;
|
|
110
|
+
userMessage;
|
|
111
|
+
constructor(input) {
|
|
112
|
+
const legacy = typeof input === "string";
|
|
113
|
+
const options = legacy
|
|
114
|
+
? {
|
|
115
|
+
operation: input,
|
|
116
|
+
reason: "provider_unavailable",
|
|
117
|
+
requestedProviderId: "auto",
|
|
118
|
+
candidateIds: [],
|
|
119
|
+
}
|
|
120
|
+
: input;
|
|
121
|
+
const operation = options.operation ?? "open_binary";
|
|
122
|
+
super(legacy
|
|
123
|
+
? `No configured provider can execute ${operation}`
|
|
124
|
+
: providerSelectionDiagnostic(options));
|
|
105
125
|
this.operation = operation;
|
|
126
|
+
this.reason = options.reason;
|
|
127
|
+
this.requestedProviderId = options.requestedProviderId;
|
|
128
|
+
this.candidateIds = [...options.candidateIds];
|
|
129
|
+
this.rejections = [...(options.rejections ?? [])].map((rejection) => ({
|
|
130
|
+
...rejection,
|
|
131
|
+
diagnostics: structuredClone(rejection.diagnostics),
|
|
132
|
+
}));
|
|
133
|
+
this.userMessage = providerSelectionUserMessage(options);
|
|
106
134
|
}
|
|
107
135
|
}
|
|
136
|
+
const providerSelectionDiagnostic = (options) => {
|
|
137
|
+
const candidates = options.candidateIds.length === 0
|
|
138
|
+
? "none"
|
|
139
|
+
: options.candidateIds.join(", ");
|
|
140
|
+
return `Analysis provider selection failed (${options.reason}) for ${options.requestedProviderId}; candidates: ${candidates}`;
|
|
141
|
+
};
|
|
142
|
+
const providerSelectionUserMessage = (options) => {
|
|
143
|
+
switch (options.reason) {
|
|
144
|
+
case "ambiguous":
|
|
145
|
+
return "Multiple analysis providers support this target. Choose one with provider_id, --provider, or REA_ANALYSIS_PROVIDER.";
|
|
146
|
+
case "unknown_provider":
|
|
147
|
+
return `The requested analysis provider is unknown. Choose one of: ${options.candidateIds.join(", ") || "no configured providers"}.`;
|
|
148
|
+
case "provider_unavailable":
|
|
149
|
+
return "The selected analysis provider is unavailable. Review the reported local diagnostics or run `rea doctor`, then retry.";
|
|
150
|
+
case "target_unsupported":
|
|
151
|
+
return "The selected analysis provider does not support this target. Choose another provider or open a supported extracted binary.";
|
|
152
|
+
case "invalid_options":
|
|
153
|
+
return "The analysis provider selection or open options are invalid. Correct them and try again.";
|
|
154
|
+
}
|
|
155
|
+
};
|
|
108
156
|
/** A provider adapter failed outside its more precise typed variants. */
|
|
109
157
|
export class ProviderAdapterError extends AnalysisError {
|
|
110
158
|
providerId;
|
|
111
159
|
operation;
|
|
112
160
|
_tag = "ProviderAdapterError";
|
|
113
|
-
|
|
161
|
+
diagnostics;
|
|
162
|
+
constructor(providerId, operation, options = {}) {
|
|
114
163
|
super(`Provider ${providerId} adapter failed during ${operation}`, options);
|
|
115
164
|
this.providerId = providerId;
|
|
116
165
|
this.operation = operation;
|
|
166
|
+
this.diagnostics =
|
|
167
|
+
options.diagnostics === undefined
|
|
168
|
+
? undefined
|
|
169
|
+
: structuredClone(options.diagnostics);
|
|
117
170
|
}
|
|
118
171
|
}
|
|
119
172
|
/** A bounded passive browser observation failed at its CDP boundary. */
|
|
@@ -146,6 +199,20 @@ export class ArtifactOperationError extends AnalysisError {
|
|
|
146
199
|
export class EvidenceIntegrityError extends AnalysisError {
|
|
147
200
|
_tag = "EvidenceIntegrityError";
|
|
148
201
|
}
|
|
202
|
+
/** A session Evidence reference is missing or has the wrong semantic identity. */
|
|
203
|
+
export class EvidenceReferenceError extends EvidenceIntegrityError {
|
|
204
|
+
evidenceId;
|
|
205
|
+
reason;
|
|
206
|
+
expected;
|
|
207
|
+
actual;
|
|
208
|
+
constructor(evidenceId, reason, expected, actual) {
|
|
209
|
+
super(`Evidence reference ${reason}: ${evidenceId}`);
|
|
210
|
+
this.evidenceId = evidenceId;
|
|
211
|
+
this.reason = reason;
|
|
212
|
+
this.expected = expected;
|
|
213
|
+
this.actual = actual;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
149
216
|
/** A bounded evidence ledger cannot accept more records or serialized bytes. */
|
|
150
217
|
export class EvidenceLimitError extends AnalysisError {
|
|
151
218
|
limit;
|
|
@@ -279,6 +346,17 @@ export class PermissionRequiredError extends AnalysisError {
|
|
|
279
346
|
this.restartRequired = restartRequired;
|
|
280
347
|
}
|
|
281
348
|
}
|
|
349
|
+
/** Approved replay commitment no longer matches the immediately rebuilt plan. */
|
|
350
|
+
export class ReplayPlanStaleError extends AnalysisError {
|
|
351
|
+
approvedDigest;
|
|
352
|
+
actualDigest;
|
|
353
|
+
_tag = "ReplayPlanStaleError";
|
|
354
|
+
constructor(approvedDigest, actualDigest) {
|
|
355
|
+
super("Controlled replay plan changed before execution");
|
|
356
|
+
this.approvedDigest = approvedDigest;
|
|
357
|
+
this.actualDigest = actualDigest;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
282
360
|
/** Project expected failures into exhaustive, secret-safe caller fields. */
|
|
283
361
|
export const projectAnalysisError = (error) => {
|
|
284
362
|
assertKnownTag(error._tag);
|
|
@@ -300,8 +378,13 @@ export const projectAnalysisError = (error) => {
|
|
|
300
378
|
};
|
|
301
379
|
};
|
|
302
380
|
const errorCode = (error) => {
|
|
381
|
+
if (error instanceof ReplayPlanStaleError)
|
|
382
|
+
return "plan_stale";
|
|
303
383
|
if (error instanceof PermissionRequiredError)
|
|
304
384
|
return "permission_required";
|
|
385
|
+
if (error instanceof ProviderSelectionError &&
|
|
386
|
+
error.reason === "provider_unavailable")
|
|
387
|
+
return "provider_unavailable";
|
|
305
388
|
if (error instanceof BrowserObservationError) {
|
|
306
389
|
if (error.reason === "payload_limit")
|
|
307
390
|
return "truncated";
|
|
@@ -400,9 +483,35 @@ const errorCode = (error) => {
|
|
|
400
483
|
case "UnknownRegistryError":
|
|
401
484
|
case "PermissionRequiredError":
|
|
402
485
|
throw new TypeError("Unhandled specialized analysis error");
|
|
486
|
+
case "ReplayPlanStaleError":
|
|
487
|
+
throw new TypeError("Unhandled specialized replay error");
|
|
403
488
|
}
|
|
404
489
|
};
|
|
405
490
|
const errorDetails = (error) => {
|
|
491
|
+
if (error instanceof AnalysisInputError && error.issues.length > 0)
|
|
492
|
+
return {
|
|
493
|
+
operation: error.operation,
|
|
494
|
+
issues: error.issues.map((issue) => ({
|
|
495
|
+
path: [...issue.path],
|
|
496
|
+
reason: issue.reason,
|
|
497
|
+
...(issue.expected === undefined ? {} : { expected: issue.expected }),
|
|
498
|
+
...(issue.minimum === undefined ? {} : { minimum: issue.minimum }),
|
|
499
|
+
...(issue.maximum === undefined ? {} : { maximum: issue.maximum }),
|
|
500
|
+
})),
|
|
501
|
+
};
|
|
502
|
+
if (error instanceof EvidenceReferenceError)
|
|
503
|
+
return {
|
|
504
|
+
evidence_id: error.evidenceId,
|
|
505
|
+
reason: error.reason,
|
|
506
|
+
expected: error.expected,
|
|
507
|
+
actual: error.actual,
|
|
508
|
+
};
|
|
509
|
+
if (error instanceof ReplayPlanStaleError)
|
|
510
|
+
return {
|
|
511
|
+
approved_plan_digest: error.approvedDigest,
|
|
512
|
+
actual_plan_digest: error.actualDigest,
|
|
513
|
+
application_code_admitted: false,
|
|
514
|
+
};
|
|
406
515
|
if (error instanceof PermissionRequiredError)
|
|
407
516
|
return {
|
|
408
517
|
capability: error.requested.capability,
|
|
@@ -441,8 +550,27 @@ const errorDetails = (error) => {
|
|
|
441
550
|
return { operation: error.operation, reason: error.reason };
|
|
442
551
|
if (error instanceof AnalysisCapabilityUnavailableError)
|
|
443
552
|
return { provider_id: error.providerId, operation: error.operation };
|
|
553
|
+
if (error instanceof ProviderSelectionError)
|
|
554
|
+
return {
|
|
555
|
+
operation: error.operation,
|
|
556
|
+
selection_reason: error.reason,
|
|
557
|
+
requested_provider_id: error.requestedProviderId,
|
|
558
|
+
candidate_ids: [...error.candidateIds],
|
|
559
|
+
rejections: error.rejections.map((rejection) => ({
|
|
560
|
+
provider_id: rejection.providerId,
|
|
561
|
+
code: rejection.code,
|
|
562
|
+
reason: rejection.reason,
|
|
563
|
+
diagnostics: rejection.diagnostics,
|
|
564
|
+
})),
|
|
565
|
+
};
|
|
444
566
|
if (error instanceof ProviderAdapterError)
|
|
445
|
-
return {
|
|
567
|
+
return {
|
|
568
|
+
provider_id: error.providerId,
|
|
569
|
+
operation: error.operation,
|
|
570
|
+
...(error.diagnostics === undefined
|
|
571
|
+
? {}
|
|
572
|
+
: { diagnostics: error.diagnostics }),
|
|
573
|
+
};
|
|
446
574
|
if (error instanceof BrowserObservationError)
|
|
447
575
|
return { operation: error.operation, reason: error.reason };
|
|
448
576
|
if (error instanceof HopperRemoteError)
|
|
@@ -483,12 +611,17 @@ const missingScopeDetails = (scope) => ({
|
|
|
483
611
|
...(scope.mount === undefined ? {} : { mount: scope.mount }),
|
|
484
612
|
});
|
|
485
613
|
const RETRYABLE_CODES = new Set([
|
|
614
|
+
"invalid_request",
|
|
486
615
|
"provider_timeout",
|
|
487
616
|
"cancelled",
|
|
488
617
|
"revision_conflict",
|
|
489
618
|
"provider_unavailable",
|
|
490
619
|
]);
|
|
491
620
|
const remediationAction = (error) => {
|
|
621
|
+
if (error instanceof AnalysisInputError)
|
|
622
|
+
return "Correct the listed arguments and retry.";
|
|
623
|
+
if (error instanceof ReplayPlanStaleError)
|
|
624
|
+
return "Review the rebuilt replay plan and explicitly approve its new digest.";
|
|
492
625
|
if (error instanceof PermissionRequiredError)
|
|
493
626
|
return error.elicitationSupported
|
|
494
627
|
? "Approve the exact missing scope, then retry the operation."
|
|
@@ -496,8 +629,13 @@ const remediationAction = (error) => {
|
|
|
496
629
|
return userMessage(error);
|
|
497
630
|
};
|
|
498
631
|
const errorCategory = (error) => {
|
|
632
|
+
if (error instanceof ReplayPlanStaleError)
|
|
633
|
+
return "integrity_mismatch";
|
|
499
634
|
if (error instanceof PermissionRequiredError)
|
|
500
635
|
return "permission_required";
|
|
636
|
+
if (error instanceof ProviderSelectionError &&
|
|
637
|
+
error.reason === "provider_unavailable")
|
|
638
|
+
return "unavailable";
|
|
501
639
|
if (error._tag === "ProcessCaptureError")
|
|
502
640
|
return error.userCategory ?? "execution_failure";
|
|
503
641
|
if (error instanceof BrowserObservationError) {
|
|
@@ -557,6 +695,8 @@ const STATIC_ERROR_CATEGORIES = {
|
|
|
557
695
|
BinaryTargetError: "unavailable",
|
|
558
696
|
};
|
|
559
697
|
const userMessage = (error) => {
|
|
698
|
+
if (error instanceof ReplayPlanStaleError)
|
|
699
|
+
return "The controlled replay plan changed before execution. Refresh the current state and try again.";
|
|
560
700
|
if (error instanceof PermissionRequiredError)
|
|
561
701
|
return "This operation needs additional local permission. Review the requested scope and remediation.";
|
|
562
702
|
if (error instanceof AnalysisInputError)
|
|
@@ -695,6 +835,7 @@ const KNOWN_ERROR_TAGS = {
|
|
|
695
835
|
NoBinaryOpenError: true,
|
|
696
836
|
BinaryTargetError: true,
|
|
697
837
|
PermissionRequiredError: true,
|
|
838
|
+
ReplayPlanStaleError: true,
|
|
698
839
|
};
|
|
699
840
|
const assertKnownTag = (tag) => {
|
|
700
841
|
if (KNOWN_ERROR_TAGS[tag] !== true)
|
package/dist/domain/evidence.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { analysisProfileSchema, } from "./analysisProfile.js";
|
|
4
5
|
import { jsonValueSchema } from "./jsonValue.js";
|
|
5
6
|
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
6
7
|
/** Provider identity schema shared by evidence-bearing persistence formats. */
|
|
@@ -14,6 +15,7 @@ const subjectSchema = z.object({
|
|
|
14
15
|
digest: z.object({ sha256: digestSchema }),
|
|
15
16
|
format: z.enum([
|
|
16
17
|
"hopper",
|
|
18
|
+
"analysis-database",
|
|
17
19
|
"mach-o",
|
|
18
20
|
"elf",
|
|
19
21
|
"pe",
|
|
@@ -66,8 +68,8 @@ const executionEnvironmentSchema = z.object({
|
|
|
66
68
|
architecture: z.string().min(1),
|
|
67
69
|
isolation: z.enum(["none", "process", "container", "virtual-machine"]),
|
|
68
70
|
});
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
const evidenceBaseSchema = z
|
|
72
|
+
.object({
|
|
71
73
|
schema_version: z.literal(2),
|
|
72
74
|
evidence_id: z.string().regex(/^ev_[a-f0-9]{64}$/u),
|
|
73
75
|
subject: subjectSchema.nullable(),
|
|
@@ -83,7 +85,34 @@ export const evidenceSchema = z.object({
|
|
|
83
85
|
limitations: z.array(z.string()),
|
|
84
86
|
locations: z.array(evidenceLocationSchema),
|
|
85
87
|
evidence_links: z.array(z.string().regex(/^ev_[a-f0-9]{64}$/u)),
|
|
88
|
+
})
|
|
89
|
+
.strict();
|
|
90
|
+
/** Object envelope used to specialize caller-visible Evidence result schemas. */
|
|
91
|
+
export const evidenceEnvelopeSchema = evidenceBaseSchema.extend({
|
|
92
|
+
analysis_profile: analysisProfileSchema.optional(),
|
|
86
93
|
});
|
|
94
|
+
const validateAnalysisProfileProvider = (evidence, context) => {
|
|
95
|
+
const profile = evidence.analysis_profile;
|
|
96
|
+
if (profile !== undefined &&
|
|
97
|
+
(profile.provider.id !== evidence.provider.id ||
|
|
98
|
+
profile.provider.name !== evidence.provider.name ||
|
|
99
|
+
profile.provider.version !== evidence.provider.version))
|
|
100
|
+
context.addIssue({
|
|
101
|
+
code: "custom",
|
|
102
|
+
path: ["analysis_profile", "provider"],
|
|
103
|
+
message: "Analysis profile provider does not match Evidence provider",
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
/** Strict, provider-neutral record for one successful public observation. */
|
|
107
|
+
export const evidenceSchema = evidenceEnvelopeSchema.superRefine(validateAnalysisProfileProvider);
|
|
108
|
+
const profiledEvidenceSchema = evidenceBaseSchema
|
|
109
|
+
.extend({ analysis_profile: analysisProfileSchema })
|
|
110
|
+
.superRefine(validateAnalysisProfileProvider);
|
|
111
|
+
/** JSON-exact union used where Evidence participates in larger schemas. */
|
|
112
|
+
export const evidenceRecordSchema = z.union([
|
|
113
|
+
profiledEvidenceSchema,
|
|
114
|
+
evidenceBaseSchema,
|
|
115
|
+
]);
|
|
87
116
|
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
|
88
117
|
/** Serialize JSON according to RFC 8785 JSON Canonicalization Scheme. */
|
|
89
118
|
const canonicalJson = (value) => {
|
|
@@ -102,6 +131,9 @@ const semanticProjection = (evidence) => ({
|
|
|
102
131
|
architecture: evidence.subject.architecture,
|
|
103
132
|
},
|
|
104
133
|
provider: evidence.provider,
|
|
134
|
+
...(!("analysis_profile" in evidence)
|
|
135
|
+
? {}
|
|
136
|
+
: { analysis_profile: evidence.analysis_profile }),
|
|
105
137
|
predicate_type: evidence.predicate_type,
|
|
106
138
|
operation: evidence.operation,
|
|
107
139
|
parameters: evidence.parameters,
|
|
@@ -123,7 +155,7 @@ export const parseEvidence = (input) => {
|
|
|
123
155
|
"schema_version" in input &&
|
|
124
156
|
input.schema_version !== 2)
|
|
125
157
|
throw new TypeError(`Unsupported evidence schema_version ${String(input.schema_version)}; Evidence v1 is not accepted. Produce Evidence v2.`);
|
|
126
|
-
const evidence =
|
|
158
|
+
const evidence = evidenceRecordSchema.parse(input);
|
|
127
159
|
const { evidence_id: evidenceId, ...withoutId } = evidence;
|
|
128
160
|
if (computeEvidenceId(withoutId) !== evidenceId)
|
|
129
161
|
throw new TypeError("Evidence semantic identifier does not match its record");
|
|
@@ -154,6 +186,9 @@ export const createEvidence = (target, provider, observation) => {
|
|
|
154
186
|
name: provider.name,
|
|
155
187
|
version: provider.version,
|
|
156
188
|
},
|
|
189
|
+
...(observation.analysisProfile === undefined
|
|
190
|
+
? {}
|
|
191
|
+
: { analysis_profile: observation.analysisProfile }),
|
|
157
192
|
predicate_type: observation.predicateType ?? "rea.analysis/v2",
|
|
158
193
|
operation: observation.operation,
|
|
159
194
|
parameters: observation.parameters,
|
|
@@ -171,9 +206,13 @@ export const createEvidence = (target, provider, observation) => {
|
|
|
171
206
|
locations: [...(observation.locations ?? [])],
|
|
172
207
|
evidence_links: [...(observation.evidenceLinks ?? [])],
|
|
173
208
|
};
|
|
174
|
-
|
|
209
|
+
const normalized = evidenceRecordSchema.parse({
|
|
175
210
|
...semantic,
|
|
176
|
-
evidence_id: `ev_${
|
|
211
|
+
evidence_id: `ev_${"0".repeat(64)}`,
|
|
177
212
|
subject,
|
|
178
213
|
});
|
|
214
|
+
return parseEvidence({
|
|
215
|
+
...normalized,
|
|
216
|
+
evidence_id: computeEvidenceId(normalized),
|
|
217
|
+
});
|
|
179
218
|
};
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
|
-
import {
|
|
3
|
+
import { evidenceEnvelopeSchema, evidenceRecordSchema, parseEvidence, providerSchema, } from "./evidence.js";
|
|
4
4
|
import { residualUnknownSchema, } from "./residualUnknown.js";
|
|
5
|
-
const artifactManifestSchema =
|
|
5
|
+
const artifactManifestSchema = evidenceEnvelopeSchema.shape.subject
|
|
6
|
+
.unwrap()
|
|
7
|
+
.pick({
|
|
6
8
|
digest: true,
|
|
7
9
|
format: true,
|
|
8
10
|
architecture: true,
|
|
9
11
|
});
|
|
10
|
-
const providerManifestSchema =
|
|
11
|
-
const environmentManifestSchema =
|
|
12
|
+
const providerManifestSchema = providerSchema;
|
|
13
|
+
const environmentManifestSchema = evidenceEnvelopeSchema.shape.environment.unwrap();
|
|
12
14
|
const scenarioManifestSchema = z.object({
|
|
13
|
-
evidence_id:
|
|
15
|
+
evidence_id: evidenceEnvelopeSchema.shape.evidence_id,
|
|
14
16
|
operation: z.string().min(1),
|
|
15
17
|
authority: z.literal("controlled-replay"),
|
|
16
18
|
});
|
|
17
19
|
const captureManifestSchema = z.object({
|
|
18
|
-
evidence_id:
|
|
20
|
+
evidence_id: evidenceEnvelopeSchema.shape.evidence_id,
|
|
19
21
|
predicate_type: z.string().min(1),
|
|
20
22
|
});
|
|
21
23
|
export const evidenceBundleSchema = z.object({
|
|
@@ -26,7 +28,7 @@ export const evidenceBundleSchema = z.object({
|
|
|
26
28
|
scenarios: z.array(scenarioManifestSchema),
|
|
27
29
|
captures: z.array(captureManifestSchema),
|
|
28
30
|
unknowns: z.array(residualUnknownSchema),
|
|
29
|
-
records: z.array(
|
|
31
|
+
records: z.array(evidenceRecordSchema),
|
|
30
32
|
});
|
|
31
33
|
/** Project records into a deterministic bundle whose order has no semantics. */
|
|
32
34
|
export const createEvidenceBundle = (records, unknowns = []) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { diffLines } from "diff";
|
|
2
2
|
import { parseFunctionEvidence, } from "./functionDossierEvidence.js";
|
|
3
|
-
import { commentProjection, combineCoverage, functionMatch, identityProjection, isAutoName, normalizeCfg, project, referenceProjection, sorted, stringAndNameProjection, } from "./functionComparisonNormalization.js";
|
|
3
|
+
import { commentProjection, combineCoverage, functionMatch, identityProjection, isAutoName, normalizeCfg, project, referenceKindProjection, referenceProjection, sorted, stringAndNameProjection, } from "./functionComparisonNormalization.js";
|
|
4
4
|
import { functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
5
5
|
import { canonicalJson, dimensionResult, overallStatus, summarize, unresolvedDimension as buildUnresolvedDimension, } from "./functionComparisonResults.js";
|
|
6
6
|
export { functionComparisonInputSchema, functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
@@ -141,10 +141,16 @@ const compareReferences = (left, right, links, providersDiffer) => {
|
|
|
141
141
|
rightCount: rightProjection.length,
|
|
142
142
|
textDelta: null,
|
|
143
143
|
limitations: [
|
|
144
|
-
"Reference endpoints differ
|
|
144
|
+
"Reference endpoints differ independently of provider reference-kind metadata.",
|
|
145
145
|
],
|
|
146
146
|
});
|
|
147
|
-
|
|
147
|
+
const leftKinds = referenceKindProjection(left);
|
|
148
|
+
const rightKinds = referenceKindProjection(right);
|
|
149
|
+
if (leftKinds !== null && rightKinds !== null)
|
|
150
|
+
return compareValues("references", leftKinds, rightKinds, links, true, true, providersDiffer);
|
|
151
|
+
return unresolvedDimension("references", "unknown", links, leftProjection.length, rightProjection.length, [
|
|
152
|
+
"At least one provider did not expose reference kinds, so equal endpoints do not prove equal edge semantics.",
|
|
153
|
+
]);
|
|
148
154
|
};
|
|
149
155
|
const compareIdentity = (left, right, links, providersDiffer) => {
|
|
150
156
|
if (isAutoName(left.procedure.name) || isAutoName(right.procedure.name))
|
|
@@ -60,6 +60,43 @@ export const referenceProjection = (snapshot) => sorted([
|
|
|
60
60
|
target: item.target_procedure?.name ?? null,
|
|
61
61
|
})),
|
|
62
62
|
]);
|
|
63
|
+
export const referenceKindProjection = (snapshot) => {
|
|
64
|
+
const edges = [
|
|
65
|
+
...snapshot.collections.incoming_references.items.map((edge) => ({
|
|
66
|
+
direction: "in",
|
|
67
|
+
edge,
|
|
68
|
+
})),
|
|
69
|
+
...snapshot.collections.outgoing_references.items.map((edge) => ({
|
|
70
|
+
direction: "out",
|
|
71
|
+
edge,
|
|
72
|
+
})),
|
|
73
|
+
];
|
|
74
|
+
if (edges.some(({ edge }) => !edge.kind.available))
|
|
75
|
+
return null;
|
|
76
|
+
return sorted(edges.map(({ direction, edge }) => {
|
|
77
|
+
if (!edge.kind.available)
|
|
78
|
+
throw new TypeError("Reference-kind availability changed during projection");
|
|
79
|
+
return {
|
|
80
|
+
direction,
|
|
81
|
+
source: edge.source_procedure?.name ?? null,
|
|
82
|
+
target: edge.target_procedure?.name ?? null,
|
|
83
|
+
type: edge.kind.type,
|
|
84
|
+
flow: edge.kind.flow,
|
|
85
|
+
call: edge.kind.call,
|
|
86
|
+
jump: edge.kind.jump,
|
|
87
|
+
data: edge.kind.data,
|
|
88
|
+
read: edge.kind.read,
|
|
89
|
+
write: edge.kind.write,
|
|
90
|
+
indirect: edge.kind.indirect,
|
|
91
|
+
computed: edge.kind.computed,
|
|
92
|
+
conditional: edge.kind.conditional,
|
|
93
|
+
terminal: edge.kind.terminal,
|
|
94
|
+
primary: edge.kind.primary,
|
|
95
|
+
operand_index: edge.kind.operand_index,
|
|
96
|
+
external: edge.kind.external,
|
|
97
|
+
};
|
|
98
|
+
}));
|
|
99
|
+
};
|
|
63
100
|
export const commentProjection = (snapshot) => {
|
|
64
101
|
const values = snapshot.collections.comments.items.map(({ address, kind, text }) => ({
|
|
65
102
|
offset: relativeAddress(address, snapshot.procedure.address),
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { evidenceSchema } from "./evidence.js";
|
|
3
|
-
const evidenceInput = z.union([
|
|
4
|
-
evidenceSchema,
|
|
5
|
-
z.array(evidenceSchema).min(1).max(100),
|
|
6
|
-
]);
|
|
7
2
|
const comparisonStatusSchema = z.enum([
|
|
8
3
|
"unchanged",
|
|
9
4
|
"added",
|
|
@@ -25,9 +20,9 @@ const dimensionNameSchema = z.enum([
|
|
|
25
20
|
const evidenceIdSchema = z.string().regex(/^ev_[a-f0-9]{64}$/u);
|
|
26
21
|
const digestSchema = z.string().regex(/^[a-f0-9]{64}$/u);
|
|
27
22
|
/** Strict bounded input for explicit function-to-function comparison. */
|
|
28
|
-
export const functionComparisonInputSchema = z.
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
export const functionComparisonInputSchema = z.strictObject({
|
|
24
|
+
left_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
|
|
25
|
+
right_evidence_ids: z.array(evidenceIdSchema).min(1).max(100),
|
|
31
26
|
offset: z.number().int().min(0).default(0),
|
|
32
27
|
limit: z.number().int().min(1).max(100).default(100),
|
|
33
28
|
unknown_registry_approved: z.literal(true).optional(),
|
|
@@ -47,7 +47,10 @@ export const parseFunctionEvidence = (input) => {
|
|
|
47
47
|
collections,
|
|
48
48
|
instructionScan: first.dossier.instruction_scan,
|
|
49
49
|
limitations: [
|
|
50
|
-
...new Set(pages.flatMap(({ evidence }) =>
|
|
50
|
+
...new Set(pages.flatMap(({ evidence, dossier }) => [
|
|
51
|
+
...evidence.limitations,
|
|
52
|
+
...dossier.limitations,
|
|
53
|
+
])),
|
|
51
54
|
].sort((left, right) => left.localeCompare(right)),
|
|
52
55
|
};
|
|
53
56
|
};
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { AnalysisOutputError, HopperProtocolError } from "./errors.js";
|
|
3
3
|
import { err, ok } from "./result.js";
|
|
4
|
-
/** Return
|
|
5
|
-
export const addressDistance = (start, end) =>
|
|
4
|
+
/** Return a bounded byte distance between canonical addresses in one space. */
|
|
5
|
+
export const addressDistance = (start, end) => {
|
|
6
|
+
const left = addressCoordinate(start);
|
|
7
|
+
const right = addressCoordinate(end);
|
|
8
|
+
if (left === null || right === null || left.space !== right.space)
|
|
9
|
+
return 0;
|
|
10
|
+
const distance = right.offset - left.offset;
|
|
11
|
+
if (distance <= 0n)
|
|
12
|
+
return 0;
|
|
13
|
+
return Number(distance > BigInt(Number.MAX_SAFE_INTEGER)
|
|
14
|
+
? BigInt(Number.MAX_SAFE_INTEGER)
|
|
15
|
+
: distance);
|
|
16
|
+
};
|
|
17
|
+
const addressCoordinate = (value) => {
|
|
18
|
+
const separator = value.lastIndexOf(":0x");
|
|
19
|
+
const space = separator < 0 ? "default" : value.slice(0, separator);
|
|
20
|
+
const offset = separator < 0 ? value : value.slice(separator + 1);
|
|
21
|
+
if (!/^0x[0-9a-f]+$/u.test(offset))
|
|
22
|
+
return null;
|
|
23
|
+
return { space, offset: BigInt(offset) };
|
|
24
|
+
};
|
|
6
25
|
const procedureMapSchema = z.record(z.string(), z.string());
|
|
7
26
|
const addressedNamesSchema = z.array(z.object({ address: z.string(), name: z.string() }));
|
|
8
27
|
const addressedNameMapSchema = z.record(z.string(), z.string());
|
|
@@ -39,16 +58,28 @@ const addressedPageSchema = z
|
|
|
39
58
|
});
|
|
40
59
|
}
|
|
41
60
|
});
|
|
42
|
-
const
|
|
61
|
+
const unavailableAnalysisFactSchema = z
|
|
43
62
|
.object({ available: z.literal(false), reason: z.string() })
|
|
44
63
|
.strict();
|
|
45
|
-
const
|
|
46
|
-
.object({
|
|
64
|
+
export const procedureClassificationSchema = z
|
|
65
|
+
.object({
|
|
66
|
+
external: z.boolean(),
|
|
67
|
+
thunk: z.boolean(),
|
|
68
|
+
thunk_target: z.string().nullable(),
|
|
69
|
+
provenance: z.string().min(1),
|
|
70
|
+
})
|
|
71
|
+
.strict();
|
|
72
|
+
export const procedureIdentitySchema = z
|
|
73
|
+
.object({
|
|
74
|
+
address: z.string(),
|
|
75
|
+
name: z.string(),
|
|
76
|
+
classification: procedureClassificationSchema.nullable().default(null),
|
|
77
|
+
})
|
|
47
78
|
.strict();
|
|
48
|
-
const localVariableSchema = z
|
|
79
|
+
export const localVariableSchema = z
|
|
49
80
|
.object({
|
|
50
81
|
description: z.string(),
|
|
51
|
-
provenance: z.
|
|
82
|
+
provenance: z.string().min(1),
|
|
52
83
|
})
|
|
53
84
|
.strict();
|
|
54
85
|
const boundedSchema = (item) => z
|
|
@@ -83,13 +114,37 @@ const boundedSchema = (item) => z
|
|
|
83
114
|
});
|
|
84
115
|
}
|
|
85
116
|
});
|
|
117
|
+
const availableReferenceKindSchema = z
|
|
118
|
+
.object({
|
|
119
|
+
available: z.literal(true),
|
|
120
|
+
provenance: z.string().min(1),
|
|
121
|
+
type: z.string(),
|
|
122
|
+
flow: z.boolean(),
|
|
123
|
+
call: z.boolean(),
|
|
124
|
+
jump: z.boolean(),
|
|
125
|
+
data: z.boolean(),
|
|
126
|
+
read: z.boolean(),
|
|
127
|
+
write: z.boolean(),
|
|
128
|
+
indirect: z.boolean(),
|
|
129
|
+
computed: z.boolean(),
|
|
130
|
+
conditional: z.boolean(),
|
|
131
|
+
terminal: z.boolean(),
|
|
132
|
+
primary: z.boolean(),
|
|
133
|
+
operand_index: z.number().int(),
|
|
134
|
+
external: z.boolean(),
|
|
135
|
+
})
|
|
136
|
+
.strict();
|
|
137
|
+
export const referenceKindSchema = z.discriminatedUnion("available", [
|
|
138
|
+
unavailableAnalysisFactSchema,
|
|
139
|
+
availableReferenceKindSchema,
|
|
140
|
+
]);
|
|
86
141
|
const referenceEdgeSchema = z
|
|
87
142
|
.object({
|
|
88
143
|
source_address: z.string(),
|
|
89
144
|
target_address: z.string(),
|
|
90
145
|
source_procedure: procedureIdentitySchema.nullable(),
|
|
91
146
|
target_procedure: procedureIdentitySchema.nullable(),
|
|
92
|
-
kind:
|
|
147
|
+
kind: referenceKindSchema,
|
|
93
148
|
})
|
|
94
149
|
.strict();
|
|
95
150
|
export const functionDossierSchema = z
|
|
@@ -98,6 +153,7 @@ export const functionDossierSchema = z
|
|
|
98
153
|
.object({
|
|
99
154
|
address: z.string(),
|
|
100
155
|
name: z.string(),
|
|
156
|
+
classification: procedureClassificationSchema.nullable().default(null),
|
|
101
157
|
signature: z.string().nullable(),
|
|
102
158
|
locals: z.array(localVariableSchema),
|
|
103
159
|
})
|
|
@@ -170,9 +226,10 @@ export const functionDossierSchema = z
|
|
|
170
226
|
instruction_scan: z
|
|
171
227
|
.object({ scanned: z.number().int().min(0), truncated: z.boolean() })
|
|
172
228
|
.strict(),
|
|
229
|
+
limitations: z.array(z.string()).default([]),
|
|
173
230
|
})
|
|
174
231
|
.strict();
|
|
175
|
-
/** Strictly parse a complete
|
|
232
|
+
/** Strictly parse a complete provider-neutral function dossier. */
|
|
176
233
|
export const parseFunctionDossier = (value) => {
|
|
177
234
|
const parsed = functionDossierSchema.safeParse(value);
|
|
178
235
|
return parsed.success
|