rea-agents 2.5.0 → 3.1.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 +20 -12
- package/bridge/ghidra/ReaGhidraBridge.java +477 -4
- package/bridge/hopper_bridge.py +54 -4
- package/dist/application/AnalysisContextQueries.js +142 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +19 -11
- package/dist/application/ArtifactInventory/policy.js +17 -0
- package/dist/application/ArtifactInventory/reader.js +1 -4
- package/dist/application/ArtifactInventory/scanCanonical.js +0 -3
- package/dist/application/ArtifactInventory/scanReader.js +7 -7
- package/dist/application/ArtifactInventory/types.js +1 -5
- package/dist/application/BinarySession.js +19 -20
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +106 -10
- package/dist/application/BinarySessionStatus.js +11 -5
- package/dist/application/BrowserEvidence.js +3 -5
- package/dist/application/CapabilityClientRequirements.js +26 -0
- package/dist/application/CapabilityInventory.js +140 -55
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CrossVersionInventory.js +7 -6
- package/dist/application/DirectAnalysis.js +6 -2
- package/dist/application/ElectronActiveEvidence.js +55 -0
- package/dist/application/ElectronActiveObservationPort.js +1 -0
- package/dist/application/ElectronActiveObservationService.js +81 -0
- package/dist/application/EnhancedTools.js +49 -17
- package/dist/application/EvidenceBundleCommands.js +5 -1
- package/dist/application/EvidenceLedger.js +53 -17
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- package/dist/application/JavaScriptReplayPermission.js +1 -1
- package/dist/application/JavaScriptReplayService.js +23 -15
- package/dist/application/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/NodeRuntimeCharacterizationService.js +8 -9
- package/dist/application/ProcessCaptureLifecycle.js +5 -0
- package/dist/application/ProcessCli.js +2 -1
- package/dist/application/ProcessHarness.js +8 -3
- package/dist/application/ProcessNormalization.js +2 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReferenceSourceImport.js +2 -2
- package/dist/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +10 -3
- package/dist/application/WindowsCapabilities.js +5 -4
- package/dist/application/runtime.js +26 -9
- package/dist/artifacts/ArtifactProvider.js +8 -10
- package/dist/artifacts/SafeOutputTree.js +7 -8
- package/dist/browser/CdpCaptureStorageFingerprints.js +10 -7
- package/dist/browser/CdpElectronInspection.js +3 -1
- package/dist/browser/JavaScriptRuntimeScope.js +5 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +8 -2
- package/dist/browser/PlaywrightElectronActiveActions.js +324 -0
- package/dist/browser/PlaywrightElectronActiveProvider.js +294 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +4 -4
- package/dist/browser/PlaywrightScenarioSession.js +4 -4
- package/dist/browser/SensitiveTextCapture.js +1 -1
- package/dist/browser/V8InspectorCaptureProjection.js +1 -0
- package/dist/browser/V8InspectorProvider.js +3 -3
- package/dist/catalogIdentity.js +15 -9
- package/dist/cli/artifactCommands.js +5 -3
- package/dist/cli/coreAnalysisCommands.js +41 -0
- package/dist/cli/managedCommands.js +1 -1
- package/dist/cliApplicationCommands.js +2 -2
- package/dist/cliBrowserAdvancedCommands.js +11 -5
- package/dist/cliBrowserCommands.js +14 -7
- package/dist/cliCommandNames.js +2 -0
- package/dist/cliElectronCommands.js +46 -4
- package/dist/cliJavaScriptRuntimeCommands.js +14 -6
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/browserScenario.js +77 -0
- package/dist/config/electronAutomation.js +35 -0
- package/dist/config/environment.js +6 -0
- package/dist/config/javascriptReplay.js +41 -0
- package/dist/config/managedRuntime.js +25 -0
- package/dist/config/parseConfig.js +56 -200
- package/dist/config/parsers.js +10 -1
- package/dist/config/passiveObservation.js +157 -0
- package/dist/config/processCapture.js +47 -0
- package/dist/contracts/applicationToolContracts.js +2 -5
- package/dist/contracts/applicationWorkflowInputContracts.js +86 -96
- package/dist/contracts/artifactToolContracts.js +35 -37
- package/dist/contracts/browserToolContracts.js +2 -2
- package/dist/contracts/electronToolContracts.js +30 -1
- package/dist/contracts/enhancedInputs.js +21 -27
- package/dist/contracts/functionWorkflowToolContracts.js +29 -0
- package/dist/contracts/managedToolContracts.js +4 -9
- package/dist/contracts/managedWorkflowExamples.js +12 -9
- package/dist/contracts/managedWorkflowToolContracts.js +30 -27
- package/dist/contracts/nativeToolContracts.js +2 -3
- package/dist/contracts/promptContracts.js +14 -15
- package/dist/contracts/sessionToolSchemas.js +61 -0
- package/dist/contracts/toolContractExamples.js +4 -0
- package/dist/contracts/toolContractHelpers.js +23 -0
- package/dist/contracts/toolContracts.js +12 -67
- package/dist/contracts/toolEffects.js +19 -0
- package/dist/contracts/toolOutputSchemaGroups.js +66 -11
- package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
- package/dist/contracts/toolSchemaMetadata.js +128 -0
- package/dist/doctorRuntime.js +1 -1
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +1 -0
- package/dist/domain/androidApplication.js +2 -0
- package/dist/domain/appleApplication.js +2 -0
- package/dist/domain/binaryTarget.js +7 -5
- package/dist/domain/binaryTargetTypes.js +1 -0
- package/dist/domain/browserCaptureComparison.js +21 -69
- package/dist/domain/browserObservation.js +22 -9
- package/dist/domain/bytecodeProvider.js +177 -0
- package/dist/domain/callPath.js +3 -2
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +328 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/electronActiveObservation.js +277 -0
- package/dist/domain/electronObservation.js +15 -11
- package/dist/domain/electronStaticAnalysisValues.js +4 -1
- package/dist/domain/eventProcessTree.js +217 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/functionComparisonNormalization.js +15 -8
- package/dist/domain/functionDossierEvidence.js +9 -4
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +68 -68
- package/dist/domain/inputIssueProjection.js +11 -2
- package/dist/domain/investigationWorkspace.js +16 -15
- package/dist/domain/javascriptExportShapeComparisonSchemas.js +2 -2
- package/dist/domain/javascriptReplay.js +79 -63
- package/dist/domain/javascriptRuntimeObservation.js +1 -0
- package/dist/domain/javascriptRuntimeReconciliationActive.js +89 -0
- package/dist/domain/javascriptRuntimeReconciliationGraph.js +11 -10
- package/dist/domain/javascriptRuntimeReconciliationMatching.js +57 -49
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +5 -1
- package/dist/domain/javascriptRuntimeReconciliationResult.js +21 -14
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +8 -12
- package/dist/domain/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +8 -12
- package/dist/domain/knownPageCoverage.js +15 -7
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +138 -0
- package/dist/domain/nodeRuntimeCharacterization.js +14 -13
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCaptureReactiveValidation.js +8 -3
- package/dist/domain/processCaptureValidation.js +7 -3
- package/dist/domain/processComparison.js +12 -7
- package/dist/domain/processObservation.js +5 -6
- package/dist/domain/processReactiveMatching.js +14 -7
- package/dist/domain/processReactiveTransition.js +9 -3
- package/dist/domain/processScenario.js +6 -3
- package/dist/domain/processTraceComparison.js +3 -2
- package/dist/domain/protocolCapture.js +245 -0
- package/dist/domain/reconstructionReadinessSchemas.js +30 -2
- package/dist/domain/referenceSourceImportParsing.js +2 -2
- package/dist/domain/replayMachineRuntime.js +5 -3
- package/dist/domain/sourceToBundleComparison.js +2 -2
- package/dist/domain/sourceToBundleComparisonSchemas.js +8 -8
- package/dist/domain/sourceToBundleSignals.js +7 -1
- package/dist/domain/staticRuntimeCorrelation.js +7 -5
- package/dist/domain/webBundleAnalysis.js +14 -14
- package/dist/domain/webCaptureDiff.js +15 -12
- package/dist/dotnet/ManagedNativeBoundaryInspector.js +2 -3
- package/dist/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraClient.js +1 -1
- package/dist/ghidra/GhidraClientStartup.js +1 -1
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +44 -16
- package/dist/ghidra/GhidraInventoryValues.js +57 -47
- package/dist/ghidra/GhidraProvider.js +18 -10
- package/dist/ghidra/GhidraProviderCapabilities.js +45 -39
- package/dist/ghidra/GhidraSocketConnection.js +1 -1
- package/dist/ghidra/protocol.js +19 -42
- package/dist/hopper/BridgeLauncher.js +3 -1
- package/dist/hopper/HopperAnalysisProfile.js +2 -4
- package/dist/hopper/HopperCleanup.js +5 -6
- package/dist/hopper/HopperClient.js +27 -3
- package/dist/hopper/HopperProvider.js +42 -44
- package/dist/hopper/HopperRequestQueue.js +32 -4
- package/dist/hopper/HopperResponseStream.js +2 -2
- package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
- package/dist/hopper/protocol.js +63 -21
- package/dist/main/reload.js +1 -6
- package/dist/main/state.js +0 -14
- package/dist/main/transport.js +31 -41
- package/dist/main.js +17 -13
- package/dist/mcpDoctor.js +4 -26
- package/dist/mcpStartupPolicy.js +14 -0
- package/dist/process/PrivateRuntimeRoot.js +17 -0
- package/dist/process/ProcessOwnership.js +64 -128
- package/dist/process/ProcessOwnershipIdentity.js +13 -0
- package/dist/process/ProcessOwnershipObservation.js +88 -0
- package/dist/process/ProcessOwnershipProcessTree.js +22 -0
- package/dist/process/ProviderDeadline.js +8 -12
- package/dist/process/WindowsAuthority.js +32 -0
- package/dist/reference/ReferenceSourceReader.js +3 -3
- package/dist/reference/ReferenceSourceReaderEntries.js +2 -2
- package/dist/replay/JavaScriptReplayWorker.js +95 -11
- package/dist/replay/JavaScriptReplayWorkerTypes.js +1 -0
- package/dist/replay/LinuxJavaScriptReplayRunner.js +10 -15
- package/dist/replay/ReplayOutcome.js +26 -15
- package/dist/replay/ReplayWorkerProtocol.js +34 -29
- package/dist/server/createServer.js +101 -144
- package/dist/server/mcpClientMetadata.js +32 -0
- package/dist/server/registerApplicationTools/characterization.js +6 -13
- package/dist/server/registerApplicationTools/compareExportShapes.js +2 -7
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +2 -7
- package/dist/server/registerApplicationTools/compareVersions.js +3 -8
- package/dist/server/registerApplicationTools/controlledReplay.js +6 -11
- package/dist/server/registerApplicationTools/coverage.js +13 -19
- package/dist/server/registerApplicationTools/obligationLedger.js +1 -6
- package/dist/server/registerApplicationTools/readiness.js +1 -6
- package/dist/server/registerApplicationTools/traceFeature.js +3 -8
- package/dist/server/registerApplicationTools/traceSemantics.js +1 -6
- package/dist/server/registerArtifactComparisonTool.js +12 -16
- package/dist/server/registerBrowserScenarioTool.js +1 -6
- package/dist/server/registerBrowserTools.js +37 -79
- package/dist/server/registerBundleComparisonTool.js +10 -14
- package/dist/server/registerCloseLifecycleTool.js +6 -14
- package/dist/server/registerElectronTools.js +30 -47
- package/dist/server/registerEnhancedTools.js +124 -122
- package/dist/server/registerEvidenceResources.js +50 -101
- package/dist/server/registerEvidenceTools.js +5 -9
- package/dist/server/registerFunctionComparisonTool.js +11 -15
- package/dist/server/registerInvestigationTools.js +42 -59
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +13 -27
- package/dist/server/registerManagedWorkflowTools/compareManagedMembers.js +4 -9
- package/dist/server/registerManagedWorkflowTools/contract.js +2 -3
- package/dist/server/registerManagedWorkflowTools/importManagedReconstruction.js +3 -8
- package/dist/server/registerManagedWorkflowTools/planManagedRuntimeCorrelation.js +3 -8
- package/dist/server/registerManagedWorkflowTools/projectManagedApplicationGraph.js +8 -13
- package/dist/server/registerManagedWorkflowTools/verifyManagedNativeBoundaries.js +4 -9
- package/dist/server/registerOfficialTools.js +8 -9
- package/dist/server/registerProcessComparisonTool.js +19 -24
- package/dist/server/registerReconstructionObligationLedgerResource.js +0 -7
- package/dist/server/registerReconstructionReadinessResource.js +0 -7
- package/dist/server/registerReplayMachineTool.js +4 -10
- package/dist/server/registerSessionRecordTools.js +146 -47
- package/dist/server/registerSessionStatusTool.js +14 -29
- package/dist/server/registerSessionTools.js +45 -41
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/sessionToolPolicies.js +1 -5
- package/dist/server/toolRegistrationOptions.js +4 -177
- package/dist/server/toolResult.js +14 -18
- package/package.json +35 -16
- package/scripts/electron-active-hook-boundaries.cjs +394 -0
- package/scripts/electron-active-hook.cjs +501 -0
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
- package/dist/server/DynamicToolAvailability.js +0 -70
- package/dist/server/toolInputValidation.js +0 -77
|
@@ -20,14 +20,16 @@ const reconcileEntity = (entity, index, layers) => {
|
|
|
20
20
|
const content = index.byCategoryDigest.get(categoryDigestKey(entity.staticKind, entity.sourceSha256)) ?? [];
|
|
21
21
|
const locatedKeys = new Set(locations.map(({ candidate }) => candidateKey(candidate)));
|
|
22
22
|
const combined = content.filter((candidate) => locatedKeys.has(candidateKey(candidate)));
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const combinedCandidate = combined.at(0);
|
|
24
|
+
if (combined.length === 1 && combinedCandidate !== undefined)
|
|
25
|
+
return matched(entity, combinedCandidate, {
|
|
25
26
|
basis: "content-and-location",
|
|
26
27
|
confidence: "high",
|
|
27
28
|
reason: "content-and-location-match",
|
|
28
29
|
});
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const contentCandidate = content.at(0);
|
|
31
|
+
if (content.length === 1 && contentCandidate !== undefined) {
|
|
32
|
+
const candidate = contentCandidate;
|
|
31
33
|
const digestBasis = candidate.digests.find(({ sha256 }) => sha256 === entity.sourceSha256)?.basis;
|
|
32
34
|
return matched(entity, candidate, {
|
|
33
35
|
basis: digestBasis ?? "content-sha256",
|
|
@@ -59,8 +61,9 @@ const reconcileEntity = (entity, index, layers) => {
|
|
|
59
61
|
candidates: [],
|
|
60
62
|
});
|
|
61
63
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
const location = locations.at(0);
|
|
65
|
+
if (locations.length === 1 && location !== undefined) {
|
|
66
|
+
const located = location;
|
|
64
67
|
return matched(entity, located.candidate, {
|
|
65
68
|
basis: located.mapping.basis,
|
|
66
69
|
confidence: "medium",
|
|
@@ -174,50 +177,55 @@ const createItem = (entity, input) => {
|
|
|
174
177
|
...semantic,
|
|
175
178
|
};
|
|
176
179
|
};
|
|
177
|
-
const reconciliationEvidence = (entity, layer, basis, confidence) =>
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
: {
|
|
203
|
-
status: "partial",
|
|
204
|
-
truncated: false,
|
|
205
|
-
omitted_count: null,
|
|
206
|
-
limits: [],
|
|
180
|
+
const reconciliationEvidence = (entity, layer, basis, confidence) => {
|
|
181
|
+
const observation = entity.node.observations.at(0);
|
|
182
|
+
if (observation === undefined)
|
|
183
|
+
throw new TypeError("Runtime reconciliation entity has no observation");
|
|
184
|
+
return {
|
|
185
|
+
authority: "cross-layer-reconciliation",
|
|
186
|
+
state: "inferred",
|
|
187
|
+
confidence: confidence === "medium" ? "medium" : "high",
|
|
188
|
+
artifact: entity.sourceSha256 === null
|
|
189
|
+
? {
|
|
190
|
+
available: false,
|
|
191
|
+
reason: "not-observed",
|
|
192
|
+
detail: "Runtime source bytes were not captured for this mapping.",
|
|
193
|
+
}
|
|
194
|
+
: {
|
|
195
|
+
available: true,
|
|
196
|
+
artifact_id: `art_${entity.sourceSha256}`,
|
|
197
|
+
sha256: entity.sourceSha256,
|
|
198
|
+
},
|
|
199
|
+
location: observation.evidence.location,
|
|
200
|
+
extractor: {
|
|
201
|
+
name: "rea-javascript-runtime-reconciliation",
|
|
202
|
+
version: "1",
|
|
203
|
+
operation: "reconcile_javascript_runtime",
|
|
204
|
+
executable_sha256: null,
|
|
207
205
|
},
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
206
|
+
coverage: layer.graph.coverage.status === "complete" &&
|
|
207
|
+
entity.capture.scriptsCompleteWithinScope
|
|
208
|
+
? { status: "complete", truncated: false, omitted_count: 0, limits: [] }
|
|
209
|
+
: {
|
|
210
|
+
status: "partial",
|
|
211
|
+
truncated: false,
|
|
212
|
+
omitted_count: null,
|
|
213
|
+
limits: [],
|
|
214
|
+
},
|
|
215
|
+
limitations: [
|
|
216
|
+
basis === "content-sha256" ||
|
|
217
|
+
basis === "module-source-sha256" ||
|
|
218
|
+
basis === "content-and-location"
|
|
219
|
+
? "Equal content digests establish byte identity, not execution causality."
|
|
220
|
+
: "Location correspondence is inferred from an artifact root or caller-declared mapping.",
|
|
221
|
+
"Passive script parsing or target presence does not prove feature execution.",
|
|
222
|
+
],
|
|
223
|
+
evidence_ids: [
|
|
224
|
+
layer.evidence.evidence_id,
|
|
225
|
+
entity.capture.evidence.evidence_id,
|
|
226
|
+
].sort(),
|
|
227
|
+
};
|
|
228
|
+
};
|
|
221
229
|
const strongestLocationBasis = (values) => {
|
|
222
230
|
const bases = new Set(values.map(({ mapping }) => mapping.basis));
|
|
223
231
|
if (bases.has("artifact-path"))
|
|
@@ -9,6 +9,7 @@ import { javascriptRuntimeObservationSchema, javascriptRuntimeKindSchema, } from
|
|
|
9
9
|
import { parseEvidence } from "./evidence.js";
|
|
10
10
|
import { javascriptApplicationAnalysisResultSchema, } from "./javascriptApplicationAnalysis.js";
|
|
11
11
|
import { compareCodePoints, } from "./javascriptApplicationGraph.js";
|
|
12
|
+
import { parseActiveElectronCapture } from "./javascriptRuntimeReconciliationActive.js";
|
|
12
13
|
/** Parse and semantically bind every static analysis Evidence layer. */
|
|
13
14
|
export const parseStaticLayers = (layers) => layers
|
|
14
15
|
.map((layer) => parseStaticLayer(layer))
|
|
@@ -133,7 +134,10 @@ const parseRuntimeCapture = (input) => {
|
|
|
133
134
|
scriptsCompleteWithinScope: false,
|
|
134
135
|
};
|
|
135
136
|
}
|
|
136
|
-
|
|
137
|
+
if (evidence.operation === "capture_electron_scenario") {
|
|
138
|
+
return parseActiveElectronCapture(evidence);
|
|
139
|
+
}
|
|
140
|
+
throw new TypeError("Runtime reconciliation requires inspect_web_page, inspect_electron_page, observe_javascript_runtime, or capture_electron_scenario Evidence");
|
|
137
141
|
};
|
|
138
142
|
const assertV8RuntimeParameters = (evidence, result) => {
|
|
139
143
|
const parameters = z
|
|
@@ -78,27 +78,34 @@ const sourceMapAuthority = (input) => ({
|
|
|
78
78
|
limitation: "Source-map declarations and approved original-source reads retain separate static authority and are not used as primary runtime byte matches.",
|
|
79
79
|
});
|
|
80
80
|
const reconciliationCoverage = (input, completion) => ({
|
|
81
|
-
status: completion.outputTruncated || completion.
|
|
81
|
+
status: completion.outputTruncated || completion.inputStatus === "truncated"
|
|
82
82
|
? "truncated"
|
|
83
|
-
: completion.
|
|
83
|
+
: completion.inputStatus === "partial"
|
|
84
84
|
? "partial"
|
|
85
85
|
: "complete-within-inputs",
|
|
86
|
-
truncated: completion.outputTruncated || completion.
|
|
86
|
+
truncated: completion.outputTruncated || completion.inputStatus === "truncated",
|
|
87
87
|
omitted_runtime_entities: input.runtime.omittedEntities,
|
|
88
88
|
omitted_reconciliation_items: input.matching.omittedItems,
|
|
89
89
|
omitted_static_load_states: input.loadStates.omittedStates,
|
|
90
90
|
omitted_graph_items: input.omittedGraphItems,
|
|
91
91
|
});
|
|
92
|
-
const completionFlags = (input) =>
|
|
93
|
-
|
|
94
|
-
input.
|
|
95
|
-
|
|
96
|
-
input.
|
|
97
|
-
|
|
98
|
-
input.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
const completionFlags = (input) => {
|
|
93
|
+
const inputTruncated = input.layers.some(({ graph }) => graph.coverage.truncated) ||
|
|
94
|
+
input.captures.some(({ inspection }) => inspection.completeness.conditions.includes("truncated"));
|
|
95
|
+
const inputPartial = input.layers.some(({ graph }) => graph.coverage.status !== "complete") ||
|
|
96
|
+
input.captures.some(({ inspection }) => inspection.completeness.status !== "complete_within_window");
|
|
97
|
+
return {
|
|
98
|
+
outputTruncated: input.runtime.omittedEntities > 0 ||
|
|
99
|
+
input.matching.omittedItems > 0 ||
|
|
100
|
+
input.loadStates.omittedStates > 0 ||
|
|
101
|
+
input.omittedGraphItems > 0,
|
|
102
|
+
inputStatus: inputTruncated
|
|
103
|
+
? "truncated"
|
|
104
|
+
: inputPartial
|
|
105
|
+
? "partial"
|
|
106
|
+
: "complete",
|
|
107
|
+
};
|
|
108
|
+
};
|
|
102
109
|
const reconciliationLimitations = (completion) => uniqueSorted([
|
|
103
110
|
"Only caller-supplied, semantically verified Evidence records were reconciled.",
|
|
104
111
|
"Digest equality establishes byte identity but not code reachability, module initialization, or feature execution.",
|
|
@@ -106,7 +113,7 @@ const reconciliationLimitations = (completion) => uniqueSorted([
|
|
|
106
113
|
"Not-observed means absent from the bounded captures in scope, never globally unloaded.",
|
|
107
114
|
"Caller-declared file and URL mappings are inference inputs and do not expand CDP origin or filesystem-root authority.",
|
|
108
115
|
"Source-map authority remains separate from passive runtime authority.",
|
|
109
|
-
...(completion.
|
|
116
|
+
...(completion.inputStatus !== "complete"
|
|
110
117
|
? ["One or more static graphs or passive captures were incomplete."]
|
|
111
118
|
: []),
|
|
112
119
|
...(completion.outputTruncated
|
|
@@ -133,7 +133,7 @@ const layerSummarySchema = z.strictObject({
|
|
|
133
133
|
const captureSummarySchema = z.strictObject({
|
|
134
134
|
evidence_id: evidenceIdSchema,
|
|
135
135
|
capture_sha256: digestSchema,
|
|
136
|
-
kind: z.enum(["browser", "electron", "v8-inspector"]),
|
|
136
|
+
kind: z.enum(["browser", "electron", "v8-inspector", "electron-active"]),
|
|
137
137
|
target_node_id: nodeIdSchema,
|
|
138
138
|
target_key: boundedTextSchema,
|
|
139
139
|
target_location: boundedTextSchema,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { parse } from "@babel/parser";
|
|
2
1
|
import * as t from "@babel/types";
|
|
3
2
|
import { DEFAULT_JAVASCRIPT_SEMANTIC_LIMITS, failedJavaScriptSemanticIr, } from "./javascriptSemanticIr.js";
|
|
4
3
|
import { collectSemanticModuleLink, collectSemanticCallable, collectSemanticReferences, immutableSemanticBindings, immutableSemanticScopes, reachSemanticLimit, semanticModuleOrigin, semanticStaticPropertyName, } from "./javascriptSemanticProjection.js";
|
|
@@ -7,20 +6,17 @@ import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
|
|
|
7
6
|
import { collectSemanticReturns, resolveSemanticModuleCallables, } from "./javascriptSemanticReturns.js";
|
|
8
7
|
import { collectJavaScriptDerivedSemantics } from "./javascriptSemanticDerivedAnalysis.js";
|
|
9
8
|
import { compareCodePoints, propertyName, range, } from "./javascriptStaticAnalysisHelpers.js";
|
|
9
|
+
import { parseJavaScriptSource, } from "./javascriptSourceParser.js";
|
|
10
10
|
/** Recover bounded lexical bindings, aliases, constants, and module links. */
|
|
11
11
|
export const analyzeJavaScriptSemantics = (source, inputLimits = {}) => {
|
|
12
|
+
const file = parseJavaScriptSource(source);
|
|
13
|
+
return file === null
|
|
14
|
+
? failedJavaScriptSemanticIr()
|
|
15
|
+
: analyzeParsedJavaScriptSemantics(file, inputLimits);
|
|
16
|
+
};
|
|
17
|
+
/** Recover semantics from an already parsed JavaScript artifact. */
|
|
18
|
+
export const analyzeParsedJavaScriptSemantics = (file, inputLimits = {}) => {
|
|
12
19
|
const limits = { ...DEFAULT_JAVASCRIPT_SEMANTIC_LIMITS, ...inputLimits };
|
|
13
|
-
let file;
|
|
14
|
-
try {
|
|
15
|
-
file = parse(source, {
|
|
16
|
-
sourceType: "unambiguous",
|
|
17
|
-
errorRecovery: true,
|
|
18
|
-
plugins: ["jsx", "typescript"],
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return failedJavaScriptSemanticIr();
|
|
23
|
-
}
|
|
24
20
|
const state = createState(file.program, limits);
|
|
25
21
|
collectDefinitions(file.program, state);
|
|
26
22
|
const references = collectSemanticReferences(file.program, state);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { parse } from "@babel/parser";
|
|
2
|
+
/** Parse JavaScript or TypeScript once without retaining unused comment nodes. */
|
|
3
|
+
export const parseJavaScriptSource = (source) => {
|
|
4
|
+
try {
|
|
5
|
+
return parse(source, {
|
|
6
|
+
sourceType: "unambiguous",
|
|
7
|
+
errorRecovery: true,
|
|
8
|
+
attachComment: false,
|
|
9
|
+
plugins: ["jsx", "typescript"],
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { parse } from "@babel/parser";
|
|
2
1
|
import * as t from "@babel/types";
|
|
3
2
|
import { inspectElectronStaticNode } from "./electronStaticAnalysis.js";
|
|
4
3
|
import { detectVendors, failedJavaScriptStaticAnalysis, registrationKey, sortedUnique, stringValue, } from "./javascriptStaticAnalysisHelpers.js";
|
|
@@ -6,19 +5,16 @@ import { addReference, addSourceMapDirectives, inspectCall, inspectRouteProperty
|
|
|
6
5
|
import { inspectBundlerRegistration, inspectEsbuildWrapper, } from "./javascriptStaticAnalysisBundler.js";
|
|
7
6
|
import { finalizeLocatedFindings } from "./javascriptStaticAnalysisFindings.js";
|
|
8
7
|
import { createJavaScriptAnalysisAccumulator, } from "./javascriptStaticAnalysisState.js";
|
|
8
|
+
import { parseJavaScriptSource, } from "./javascriptSourceParser.js";
|
|
9
9
|
/** Parse one bounded JavaScript artifact and recover static structure only. */
|
|
10
10
|
export const analyzeJavaScriptStaticSource = (source, limits) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return failedJavaScriptStaticAnalysis();
|
|
21
|
-
}
|
|
11
|
+
const file = parseJavaScriptSource(source);
|
|
12
|
+
return file === null
|
|
13
|
+
? failedJavaScriptStaticAnalysis()
|
|
14
|
+
: analyzeParsedJavaScriptStaticSource(source, file, limits);
|
|
15
|
+
};
|
|
16
|
+
/** Recover static structure from an already parsed JavaScript artifact. */
|
|
17
|
+
export const analyzeParsedJavaScriptStaticSource = (source, file, limits) => {
|
|
22
18
|
const accumulator = createJavaScriptAnalysisAccumulator();
|
|
23
19
|
traverseStaticSource(source, file, accumulator, limits);
|
|
24
20
|
addSourceMapDirectives(source, accumulator, limits.maxFindings);
|
|
@@ -11,11 +11,19 @@ export const assessKnownPageCoverage = (page, includedCount = page.items.length)
|
|
|
11
11
|
page.returned === page.total &&
|
|
12
12
|
sourceOmittedCount === 0;
|
|
13
13
|
const omittedCount = Math.max(0, page.total - retainedCount);
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
return sourceComplete && omittedCount === 0
|
|
15
|
+
? {
|
|
16
|
+
complete: true,
|
|
17
|
+
sourceComplete: true,
|
|
18
|
+
includedCount: retainedCount,
|
|
19
|
+
omittedCount: 0,
|
|
20
|
+
sourceOmittedCount: 0,
|
|
21
|
+
}
|
|
22
|
+
: {
|
|
23
|
+
complete: false,
|
|
24
|
+
sourceComplete,
|
|
25
|
+
includedCount: retainedCount,
|
|
26
|
+
omittedCount,
|
|
27
|
+
sourceOmittedCount,
|
|
28
|
+
};
|
|
21
29
|
};
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Supported mobile artifact formats. */
|
|
3
|
+
export const mobileArtifactFormatSchema = z.enum([
|
|
4
|
+
"apk",
|
|
5
|
+
"aab",
|
|
6
|
+
"ipa",
|
|
7
|
+
"dex",
|
|
8
|
+
"native_lib",
|
|
9
|
+
]);
|
|
10
|
+
/** Mobile platform. */
|
|
11
|
+
export const mobilePlatformSchema = z.enum([
|
|
12
|
+
"android",
|
|
13
|
+
"ios",
|
|
14
|
+
"cross_platform",
|
|
15
|
+
]);
|
|
16
|
+
/** Android manifest entry. */
|
|
17
|
+
export const androidManifestSchema = z.strictObject({
|
|
18
|
+
package_name: z.string().min(1),
|
|
19
|
+
version_name: z.string().nullable(),
|
|
20
|
+
version_code: z.number().int().nullable(),
|
|
21
|
+
min_sdk: z.number().int().nullable(),
|
|
22
|
+
target_sdk: z.number().int().nullable(),
|
|
23
|
+
permissions: z.array(z.string()).default([]),
|
|
24
|
+
activities: z.array(z.string()).default([]),
|
|
25
|
+
services: z.array(z.string()).default([]),
|
|
26
|
+
receivers: z.array(z.string()).default([]),
|
|
27
|
+
providers: z.array(z.string()).default([]),
|
|
28
|
+
});
|
|
29
|
+
/** iOS app manifest (Info.plist). */
|
|
30
|
+
export const iosManifestSchema = z.strictObject({
|
|
31
|
+
bundle_identifier: z.string().min(1),
|
|
32
|
+
bundle_version: z.string().nullable(),
|
|
33
|
+
short_version: z.string().nullable(),
|
|
34
|
+
minimum_os_version: z.string().nullable(),
|
|
35
|
+
supported_platforms: z.array(z.string()).default([]),
|
|
36
|
+
ui_required_device_capabilities: z.array(z.string()).default([]),
|
|
37
|
+
app_permissions: z.array(z.string()).default([]),
|
|
38
|
+
});
|
|
39
|
+
/** Signing information. */
|
|
40
|
+
export const signingInfoSchema = z.strictObject({
|
|
41
|
+
is_signed: z.boolean().default(false),
|
|
42
|
+
signer_identity: z.string().nullable(),
|
|
43
|
+
certificate_fingerprint: z.string().nullable(),
|
|
44
|
+
signature_scheme: z.string().nullable(),
|
|
45
|
+
is_debuggable: z.boolean().default(false),
|
|
46
|
+
});
|
|
47
|
+
/** Native library entry. */
|
|
48
|
+
export const nativeLibrarySchema = z.strictObject({
|
|
49
|
+
path: z.string().min(1),
|
|
50
|
+
architecture: z.string().nullable(),
|
|
51
|
+
size: z.number().int().nonnegative(),
|
|
52
|
+
digest: z
|
|
53
|
+
.string()
|
|
54
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
55
|
+
.nullable(),
|
|
56
|
+
});
|
|
57
|
+
/** Resource entry within a mobile artifact. */
|
|
58
|
+
export const mobileResourceSchema = z.strictObject({
|
|
59
|
+
path: z.string().min(1),
|
|
60
|
+
type: z.enum([
|
|
61
|
+
"layout",
|
|
62
|
+
"drawable",
|
|
63
|
+
"string",
|
|
64
|
+
"asset",
|
|
65
|
+
"raw",
|
|
66
|
+
"native_lib",
|
|
67
|
+
"manifest",
|
|
68
|
+
"entitlements",
|
|
69
|
+
"provisioning",
|
|
70
|
+
"other",
|
|
71
|
+
]),
|
|
72
|
+
size: z.number().int().nonnegative(),
|
|
73
|
+
});
|
|
74
|
+
/** Static analysis result for a mobile artifact. */
|
|
75
|
+
export const mobileArtifactManifestSchema = z.strictObject({
|
|
76
|
+
format: mobileArtifactFormatSchema,
|
|
77
|
+
platform: mobilePlatformSchema,
|
|
78
|
+
app_name: z.string().nullable(),
|
|
79
|
+
android_manifest: androidManifestSchema.nullable(),
|
|
80
|
+
ios_manifest: iosManifestSchema.nullable(),
|
|
81
|
+
signing: signingInfoSchema,
|
|
82
|
+
resources: z.array(mobileResourceSchema).default([]),
|
|
83
|
+
native_libraries: z.array(nativeLibrarySchema).default([]),
|
|
84
|
+
total_size: z.number().int().nonnegative(),
|
|
85
|
+
architectures: z.array(z.string()).default([]),
|
|
86
|
+
});
|
|
87
|
+
/** Detect mobile artifact format from file extension. */
|
|
88
|
+
export function detectMobileFormat(path) {
|
|
89
|
+
const lower = path.toLowerCase();
|
|
90
|
+
if (lower.endsWith(".apk"))
|
|
91
|
+
return "apk";
|
|
92
|
+
if (lower.endsWith(".aab"))
|
|
93
|
+
return "aab";
|
|
94
|
+
if (lower.endsWith(".ipa"))
|
|
95
|
+
return "ipa";
|
|
96
|
+
if (lower.endsWith(".dex"))
|
|
97
|
+
return "dex";
|
|
98
|
+
if (lower.endsWith(".so") || lower.endsWith(".dylib") || lower.endsWith(".a"))
|
|
99
|
+
return "native_lib";
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
/** Detect platform from format. */
|
|
103
|
+
export function detectPlatform(format) {
|
|
104
|
+
switch (format) {
|
|
105
|
+
case "apk":
|
|
106
|
+
case "aab":
|
|
107
|
+
case "dex":
|
|
108
|
+
return "android";
|
|
109
|
+
case "ipa":
|
|
110
|
+
return "ios";
|
|
111
|
+
case "native_lib":
|
|
112
|
+
return "cross_platform";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Classify a resource by its path. */
|
|
116
|
+
export function classifyMobileResource(path) {
|
|
117
|
+
const lower = path.toLowerCase();
|
|
118
|
+
if (lower.includes("androidmanifest.xml"))
|
|
119
|
+
return "manifest";
|
|
120
|
+
if (lower.includes(".entitlements"))
|
|
121
|
+
return "entitlements";
|
|
122
|
+
if (lower.includes("provisioning") || lower.includes(".mobileprovision"))
|
|
123
|
+
return "provisioning";
|
|
124
|
+
if (lower.includes("/layout/"))
|
|
125
|
+
return "layout";
|
|
126
|
+
if (lower.includes("/drawable/") || lower.includes("/mipmap/"))
|
|
127
|
+
return "drawable";
|
|
128
|
+
if (lower.includes("/values/"))
|
|
129
|
+
return "string";
|
|
130
|
+
if (lower.includes("assets/") || lower.includes("raw/"))
|
|
131
|
+
return "asset";
|
|
132
|
+
if (lower.endsWith(".so") || lower.endsWith(".dylib"))
|
|
133
|
+
return "native_lib";
|
|
134
|
+
if (lower.endsWith(".xml"))
|
|
135
|
+
return "layout";
|
|
136
|
+
return "other";
|
|
137
|
+
}
|
|
138
|
+
/** Get all native libraries for a specific architecture. */
|
|
139
|
+
export function nativeLibsByArchitecture(manifest, arch) {
|
|
140
|
+
return manifest.native_libraries.filter((l) => l.architecture === arch);
|
|
141
|
+
}
|
|
142
|
+
/** Check if an Android artifact has internet permission. */
|
|
143
|
+
export function hasInternetPermission(manifest) {
|
|
144
|
+
if (!manifest.android_manifest)
|
|
145
|
+
return false;
|
|
146
|
+
return manifest.android_manifest.permissions.some((p) => p.includes("INTERNET") || p.includes("android.permission.INTERNET"));
|
|
147
|
+
}
|
|
148
|
+
/** Get all unique architectures across native libraries. */
|
|
149
|
+
export function getAllArchitectures(manifest) {
|
|
150
|
+
const archs = new Set();
|
|
151
|
+
for (const lib of manifest.native_libraries) {
|
|
152
|
+
if (lib.architecture)
|
|
153
|
+
archs.add(lib.architecture);
|
|
154
|
+
}
|
|
155
|
+
for (const arch of manifest.architectures) {
|
|
156
|
+
archs.add(arch);
|
|
157
|
+
}
|
|
158
|
+
return [...archs];
|
|
159
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const inferenceConfidenceSchema = z.enum(["low", "medium", "high"]);
|
|
3
|
+
const inferenceEvidenceSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
kind: z.enum([
|
|
6
|
+
"signature-source",
|
|
7
|
+
"decompiler-type",
|
|
8
|
+
"type-lock",
|
|
9
|
+
"calling-convention",
|
|
10
|
+
"jump-table",
|
|
11
|
+
]),
|
|
12
|
+
source: z.string().min(1),
|
|
13
|
+
detail: z.string().min(1),
|
|
14
|
+
})
|
|
15
|
+
.strict();
|
|
16
|
+
const inferredBoundaryTypeFacts = {
|
|
17
|
+
ordinal: z.number().int().min(0).nullable(),
|
|
18
|
+
name: z.string().min(1).nullable(),
|
|
19
|
+
data_type: z.string().min(1),
|
|
20
|
+
size_bytes: z.number().int().min(0).nullable(),
|
|
21
|
+
storage: z.string().min(1).nullable(),
|
|
22
|
+
confidence: inferenceConfidenceSchema,
|
|
23
|
+
evidence: z.array(inferenceEvidenceSchema).min(1),
|
|
24
|
+
decompiler_artifacts: z.array(z.enum([
|
|
25
|
+
"recovered-signature",
|
|
26
|
+
"register-or-stack-storage",
|
|
27
|
+
"compiler-generated-variable",
|
|
28
|
+
])),
|
|
29
|
+
};
|
|
30
|
+
const inferredReturnTypeSchema = z.strictObject({
|
|
31
|
+
...inferredBoundaryTypeFacts,
|
|
32
|
+
role: z.literal("return"),
|
|
33
|
+
ordinal: z.null(),
|
|
34
|
+
name: z.null(),
|
|
35
|
+
});
|
|
36
|
+
const inferredParameterTypeSchema = z.strictObject({
|
|
37
|
+
...inferredBoundaryTypeFacts,
|
|
38
|
+
role: z.literal("parameter"),
|
|
39
|
+
ordinal: z.number().int().min(0),
|
|
40
|
+
});
|
|
41
|
+
const jumpTableDataSourceSchema = z
|
|
42
|
+
.object({
|
|
43
|
+
address: z.string().min(1),
|
|
44
|
+
provenance: z.enum([
|
|
45
|
+
"ghidra-decompiler-load-table",
|
|
46
|
+
"ghidra-dispatch-block-data-reference",
|
|
47
|
+
]),
|
|
48
|
+
entry_size_bytes: z.number().int().min(1).nullable(),
|
|
49
|
+
entry_count: z.number().int().min(0).nullable(),
|
|
50
|
+
confidence: inferenceConfidenceSchema,
|
|
51
|
+
evidence: z.array(inferenceEvidenceSchema).min(1),
|
|
52
|
+
})
|
|
53
|
+
.strict();
|
|
54
|
+
const jumpTableMappingSchema = z
|
|
55
|
+
.object({
|
|
56
|
+
case_value: z.number().int().nullable(),
|
|
57
|
+
target_address: z.string().min(1),
|
|
58
|
+
data_addresses: z.array(z.string().min(1)),
|
|
59
|
+
confidence: inferenceConfidenceSchema,
|
|
60
|
+
evidence: z.array(inferenceEvidenceSchema).min(1),
|
|
61
|
+
})
|
|
62
|
+
.strict();
|
|
63
|
+
const inferredJumpTableSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
dispatch_address: z.string().min(1),
|
|
66
|
+
data_sources: z.array(jumpTableDataSourceSchema),
|
|
67
|
+
data_sources_truncated: z.boolean(),
|
|
68
|
+
mappings: z.array(jumpTableMappingSchema),
|
|
69
|
+
mappings_truncated: z.boolean(),
|
|
70
|
+
limitations: z.array(z.string()),
|
|
71
|
+
})
|
|
72
|
+
.strict();
|
|
73
|
+
const availableNativeApiBoundarySchema = z
|
|
74
|
+
.object({
|
|
75
|
+
available: z.literal(true),
|
|
76
|
+
provenance: z.string().min(1),
|
|
77
|
+
signature_source: z.string().min(1),
|
|
78
|
+
calling_convention: z.string().min(1),
|
|
79
|
+
return_type: inferredReturnTypeSchema,
|
|
80
|
+
parameters: z.array(inferredParameterTypeSchema),
|
|
81
|
+
parameters_truncated: z.boolean(),
|
|
82
|
+
jump_tables: z.array(inferredJumpTableSchema),
|
|
83
|
+
jump_tables_truncated: z.boolean(),
|
|
84
|
+
pseudocode: z
|
|
85
|
+
.object({
|
|
86
|
+
classification: z.literal("decompiler-generated-non-source"),
|
|
87
|
+
compilable: z.literal(false),
|
|
88
|
+
})
|
|
89
|
+
.strict(),
|
|
90
|
+
decompiler_artifacts: z.array(z.enum([
|
|
91
|
+
"recovered-signature",
|
|
92
|
+
"register-and-stack-variables",
|
|
93
|
+
"compiler-generated-control-flow",
|
|
94
|
+
"pointer-arithmetic",
|
|
95
|
+
"pseudocode",
|
|
96
|
+
])),
|
|
97
|
+
limitations: z.array(z.string()),
|
|
98
|
+
})
|
|
99
|
+
.strict();
|
|
100
|
+
const unavailableNativeApiBoundarySchema = z
|
|
101
|
+
.object({
|
|
102
|
+
available: z.literal(false),
|
|
103
|
+
reason: z.string().min(1),
|
|
104
|
+
residual_unknowns: z.array(z.string().min(1)).min(1),
|
|
105
|
+
})
|
|
106
|
+
.strict();
|
|
107
|
+
/** Provider-neutral native API boundary observations attached to a function dossier. */
|
|
108
|
+
export const nativeApiBoundarySchema = z.discriminatedUnion("available", [
|
|
109
|
+
unavailableNativeApiBoundarySchema,
|
|
110
|
+
availableNativeApiBoundarySchema,
|
|
111
|
+
]);
|
|
112
|
+
const nativeApiInspectionSubstepSchema = z
|
|
113
|
+
.object({
|
|
114
|
+
operation: z.enum([
|
|
115
|
+
"analyze_function",
|
|
116
|
+
"project_native_api_boundary",
|
|
117
|
+
"preserve_residual_unknowns",
|
|
118
|
+
]),
|
|
119
|
+
status: z.enum(["completed", "unsupported"]),
|
|
120
|
+
observations: z.array(z.string().min(1)),
|
|
121
|
+
})
|
|
122
|
+
.strict();
|
|
123
|
+
/** Agent-facing projection of structured native API reconstruction substeps. */
|
|
124
|
+
export const nativeApiInspectionResultSchema = z
|
|
125
|
+
.object({
|
|
126
|
+
schema_version: z.literal(1),
|
|
127
|
+
procedure: z
|
|
128
|
+
.object({
|
|
129
|
+
address: z.string().min(1),
|
|
130
|
+
name: z.string().min(1),
|
|
131
|
+
})
|
|
132
|
+
.strict(),
|
|
133
|
+
boundary: nativeApiBoundarySchema,
|
|
134
|
+
substeps: z.array(nativeApiInspectionSubstepSchema).min(3).max(3),
|
|
135
|
+
unsupported_branches: z.array(z.string().min(1)),
|
|
136
|
+
residual_unknowns: z.array(z.string().min(1)),
|
|
137
|
+
})
|
|
138
|
+
.strict();
|