rea-agents 6.2.0 → 6.3.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 +18 -20
- package/bridge/hopper_bridge.py +2 -0
- package/dist/android/JadxProvider.js +8 -2
- package/dist/android/JadxSession.js +51 -9
- package/dist/application/BinaryTargetResolver.js +63 -17
- package/dist/application/BrowserScenarioEvidence.js +2 -2
- package/dist/application/ClientConfigurationDocument.js +28 -0
- package/dist/application/ClientRegistrationStatus.js +19 -6
- package/dist/application/DirectAnalysis.js +12 -6
- package/dist/application/DirectAnalysisCleanup.js +0 -1
- package/dist/application/DirectAnalysisStatus.js +2 -5
- package/dist/application/Doctor.js +25 -34
- package/dist/application/DoctorDiagnostics.js +1 -1
- package/dist/application/EvidenceBundleFiles.js +1 -1
- package/dist/application/InvestigationProviders.js +4 -4
- package/dist/application/JsonFiles.js +15 -15
- package/dist/application/LinuxHopper.js +2 -1
- package/dist/application/ReconstructionObligationCandidates.js +9 -2
- package/dist/application/ReconstructionObligationLedgerProjection.js +3 -1
- package/dist/application/RegularFileRead.js +17 -0
- package/dist/application/Setup.js +18 -7
- package/dist/application/SetupClientConfiguration.js +18 -7
- package/dist/application/SetupHost.js +6 -4
- package/dist/application/SetupPlan.js +19 -15
- package/dist/application/SetupSkill.js +57 -8
- package/dist/application/SupportedClients.js +43 -0
- package/dist/application/Uninstall.js +18 -2
- package/dist/application/UpdateMaintenance.js +6 -2
- package/dist/application/Utf8JsonInput.js +64 -0
- package/dist/application/WebScriptExportService.js +13 -6
- package/dist/application/android/AndroidAnalysisService.js +1 -1
- package/dist/application/binary/AnalysisSnapshotCache.js +5 -4
- package/dist/application/binary/BinarySession.js +16 -0
- package/dist/application/binary/BinarySessionOpen.js +9 -1
- package/dist/application/javascript/ElectronActiveEvidence.js +2 -2
- package/dist/application/javascript/ElectronBoundaryAnalysis.js +2 -2
- package/dist/application/javascript/ElectronBoundaryGraphNative.js +5 -1
- package/dist/application/javascript/JavaScriptApplicationEvidence.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationEvidenceGraph.js +107 -46
- package/dist/application/javascript/JavaScriptApplicationService.js +1 -0
- package/dist/application/javascript/JavaScriptApplicationWorkflowService.js +59 -45
- package/dist/application/javascript/JavaScriptArtifactAnalysis.js +0 -6
- package/dist/application/javascript/JavaScriptArtifactGraphBuilder.js +8 -18
- package/dist/application/javascript/JavaScriptArtifactGraphFindings.js +34 -26
- package/dist/application/javascript/JavaScriptArtifactPathResolution.js +44 -12
- package/dist/application/javascript/JavaScriptArtifactReconstruction.js +6 -3
- package/dist/application/javascript/JavaScriptArtifactReconstructionInput.js +1 -0
- package/dist/application/javascript/JavaScriptJsonModules.js +2 -2
- package/dist/application/javascript/JavaScriptModuleRelationships.js +5 -17
- package/dist/application/javascript/JavaScriptRuntimeReconciliationService.js +11 -27
- package/dist/application/javascript/JavaScriptSemanticGraphAsyncProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphBuilder.js +8 -6
- package/dist/application/javascript/JavaScriptSemanticGraphChildProcessProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphConstruction.js +7 -5
- package/dist/application/javascript/JavaScriptSemanticGraphDataProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphEvidence.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphFingerprintProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphFlowProjection.js +2 -2
- package/dist/application/javascript/JavaScriptSemanticGraphObjectProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphProjection.js +4 -4
- package/dist/application/javascript/JavaScriptSemanticGraphResourceProjection.js +1 -1
- package/dist/application/javascript/JavaScriptSemanticGraphValueProjection.js +10 -7
- package/dist/application/javascript/JavaScriptSemanticTraceService.js +15 -10
- package/dist/application/native/NativeCallRoutes.js +2 -4
- package/dist/artifacts/ArtifactProvider.js +14 -16
- package/dist/artifacts/ArtifactProviderMetadata.js +1 -4
- package/dist/artifacts/AsarArtifactReader.js +81 -17
- package/dist/artifacts/DirectoryArtifactReader.js +2 -2
- package/dist/artifacts/NativeDmgArtifactReader.js +152 -67
- package/dist/artifacts/NativeDmgOwnership.js +109 -0
- package/dist/artifacts/apple/KeyedArchiveReader.js +54 -46
- package/dist/artifacts/apple/MachoLoadCommandReader.js +36 -6
- package/dist/artifacts/extraction/ArtifactExtraction.js +29 -11
- package/dist/artifacts/inventory/ArtifactGraphConstruction.js +7 -8
- package/dist/artifacts/inventory/classify.js +33 -14
- package/dist/artifacts/inventory/hashStableRootArtifact.js +37 -0
- package/dist/artifacts/inventory/scanCanonical.js +28 -22
- package/dist/artifacts/inventory/scanReader.js +7 -11
- package/dist/artifacts/javascript/JavaScriptArtifactFiles.js +65 -27
- package/dist/browser/CdpBrowserProvider.js +4 -3
- package/dist/browser/CdpCaptureStorageFingerprints.js +3 -3
- package/dist/browser/CdpElectronInspection.js +2 -2
- package/dist/browser/CdpElectronProvider.js +4 -3
- package/dist/browser/CdpElectronScripts.js +2 -2
- package/dist/browser/CdpWebMcpDiscovery.js +16 -13
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +6 -6
- package/dist/browser/PlaywrightScenarioBrowser.js +145 -42
- package/dist/browser/PlaywrightScenarioSession.js +3 -11
- package/dist/browser/WebSourceMapFetcher.js +32 -6
- package/dist/browser/assets/ScenarioScriptCapture.js +8 -12
- package/dist/cli/coreAnalysisCommands.js +2 -2
- package/dist/cli/coreBinaryCommands.js +13 -9
- package/dist/cli/electronCommands.js +9 -10
- package/dist/cli/javascriptApplicationAnalysis.js +2 -12
- package/dist/cli/jsonOutput.js +3 -2
- package/dist/cli/streamedJsonOutput.js +83 -4
- package/dist/cli/utilityCommands.js +2 -4
- package/dist/cli.js +5 -2
- package/dist/cliJsonFile.js +179 -0
- package/dist/cliJsonInput.js +47 -34
- package/dist/cliObservationOptions.js +4 -0
- package/dist/composition/auxiliaryAnalysisProviders.js +5 -4
- package/dist/composition/browserScenario.js +2 -2
- package/dist/composition/directAnalysis.js +2 -3
- package/dist/contracts/artifactComparisonExample.js +5 -5
- package/dist/contracts/errorSchemas.js +3 -1
- package/dist/contracts/functionComparisonExample.js +8 -0
- package/dist/contracts/inputSchemaPresentation.js +94 -3
- package/dist/contracts/javascript/electronToolContracts.js +2 -1
- package/dist/contracts/javascript/javascriptApplicationWorkflowExamples.js +3 -2
- package/dist/contracts/javascript/javascriptExportShapeComparisonExample.js +6 -3
- package/dist/contracts/javascript/javascriptRuntimeReconciliationExample.js +8 -7
- package/dist/contracts/managed/managedToolContracts.js +3 -2
- package/dist/contracts/mobileApplicationGraphExamples.js +5 -5
- package/dist/contracts/native/nativeToolContracts.js +1 -1
- package/dist/contracts/sessionLifecycleInputs.js +4 -3
- package/dist/contracts/sessionStatusContract.js +3 -2
- package/dist/contracts/sessionToolContracts.js +3 -2
- package/dist/contracts/sessionToolSchemas.js +3 -2
- package/dist/contracts/toolOutputSchemaGroups.js +2 -2
- package/dist/contracts/toolOutputSchemaPrimitives.js +2 -5
- package/dist/domain/analysisErrorBase.js +5 -0
- package/dist/domain/analysisErrorPresentation.js +4 -2
- package/dist/domain/analysisSnapshot.js +3 -1
- package/dist/domain/analysisView/analysisView.js +1 -3
- package/dist/domain/android/androidPartialObservation.js +36 -0
- package/dist/domain/apple/dylibResolution.js +1 -1
- package/dist/domain/artifactComparison.js +4 -4
- package/dist/domain/artifactGraph.js +1 -1
- package/dist/domain/artifactIdentity.js +8 -8
- package/dist/domain/artifactInspection.js +8 -8
- package/dist/domain/artifactInventoryEvidence.js +5 -5
- package/dist/domain/browserCompleteness.js +3 -2
- package/dist/domain/browserScenarioCaptureValues.js +2 -2
- package/dist/domain/browserScenarioNormalization.js +3 -3
- package/dist/domain/browserScenarioValues.js +3 -2
- package/dist/domain/callPath.js +8 -10
- package/dist/domain/canonicalDigest.js +7 -1
- package/dist/domain/canonicalOrdering.js +1 -13
- package/dist/domain/changedBehavior.js +2 -3
- package/dist/domain/comparisonSemantics.js +0 -5
- package/dist/domain/digests.js +0 -3
- package/dist/domain/evidence.js +10 -5
- package/dist/domain/evidenceBundle.js +51 -33
- package/dist/domain/firmware/firmwareAnalysis.js +4 -3
- package/dist/domain/functionComparison.js +2 -1
- package/dist/domain/functionComparisonNormalization.js +4 -3
- package/dist/domain/functionComparisonResults.js +2 -2
- package/dist/domain/functionDossierEvidence.js +2 -1
- package/dist/domain/hopperValues.js +11 -15
- package/dist/domain/javascript/electronActiveObservation.js +4 -3
- package/dist/domain/javascript/electronStaticAnalysisBrowser.js +2 -2
- package/dist/domain/javascript/electronStaticAnalysisIpc.js +9 -1
- package/dist/domain/javascript/electronStaticAnalysisNative.js +5 -3
- package/dist/domain/javascript/electronStaticAnalysisValues.js +8 -4
- package/dist/domain/javascript/javascriptApplicationAnalysis.js +3 -1
- package/dist/domain/javascript/javascriptApplicationChangeGraph.js +12 -8
- package/dist/domain/javascript/javascriptApplicationEvidenceSchemas.js +4 -0
- package/dist/domain/javascript/javascriptApplicationGraph.js +15 -13
- package/dist/domain/javascript/javascriptApplicationVersionComparison.js +4 -4
- package/dist/domain/javascript/javascriptApplicationVersionComparisonSchemas.js +37 -22
- package/dist/domain/javascript/javascriptApplicationVersionItems.js +45 -34
- package/dist/domain/javascript/javascriptApplicationVersionKeys.js +7 -7
- package/dist/domain/javascript/javascriptAstFingerprint.js +2 -2
- package/dist/domain/javascript/javascriptAstValues.js +22 -0
- package/dist/domain/javascript/javascriptExportShapeComparison.js +3 -2
- package/dist/domain/javascript/javascriptExportShapeComparisonSchemas.js +31 -23
- package/dist/domain/javascript/javascriptExportShapeSelection.js +2 -2
- package/dist/domain/javascript/javascriptExportShapeVariants.js +3 -2
- package/dist/domain/javascript/javascriptFeatureSeed.js +5 -3
- package/dist/domain/javascript/javascriptFeatureTrace.js +7 -6
- package/dist/domain/javascript/javascriptFeatureTraceSchemas.js +17 -9
- package/dist/domain/javascript/javascriptFeatureTraversal.js +4 -4
- package/dist/domain/javascript/javascriptNativeHandoff.js +6 -6
- package/dist/domain/javascript/javascriptRuntimeObservation.js +8 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliation.js +12 -6
- package/dist/domain/javascript/javascriptRuntimeReconciliationActive.js +9 -8
- package/dist/domain/javascript/javascriptRuntimeReconciliationCaptureParsing.js +212 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationGraph.js +5 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationInputValidation.js +28 -0
- package/dist/domain/javascript/javascriptRuntimeReconciliationMatching.js +5 -5
- package/dist/domain/javascript/javascriptRuntimeReconciliationParsing.js +12 -223
- package/dist/domain/javascript/javascriptRuntimeReconciliationResult.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeReconciliationRuntime.js +15 -4
- package/dist/domain/javascript/javascriptRuntimeReconciliationSchemas.js +2 -2
- package/dist/domain/javascript/javascriptRuntimeStaticCandidates.js +7 -6
- package/dist/domain/javascript/javascriptSemanticAnalysis.js +200 -8
- package/dist/domain/javascript/javascriptSemanticCallResolution.js +9 -7
- package/dist/domain/javascript/javascriptSemanticChildProcesses.js +2 -2
- package/dist/domain/javascript/javascriptSemanticCoverage.js +20 -0
- package/dist/domain/javascript/javascriptSemanticDataEffectHelpers.js +7 -9
- package/dist/domain/javascript/javascriptSemanticDataEffects.js +4 -11
- package/dist/domain/javascript/javascriptSemanticFingerprints.js +2 -2
- package/dist/domain/javascript/javascriptSemanticGraph.js +142 -35
- package/dist/domain/javascript/javascriptSemanticGraphSchemas.js +19 -1
- package/dist/domain/javascript/javascriptSemanticIr.js +0 -4
- package/dist/domain/javascript/javascriptSemanticIterationSources.js +106 -0
- package/dist/domain/javascript/javascriptSemanticMemberMutations.js +497 -113
- package/dist/domain/javascript/javascriptSemanticMutationInitializers.js +190 -0
- package/dist/domain/javascript/javascriptSemanticMutationValues.js +41 -27
- package/dist/domain/javascript/javascriptSemanticObjects.js +2 -6
- package/dist/domain/javascript/javascriptSemanticPrimitives.js +7 -2
- package/dist/domain/javascript/javascriptSemanticProjection.js +20 -14
- package/dist/domain/javascript/javascriptSemanticPromises.js +15 -21
- package/dist/domain/javascript/javascriptSemanticPropertyPaths.js +23 -0
- package/dist/domain/javascript/javascriptSemanticProvenance.js +3 -3
- package/dist/domain/javascript/javascriptSemanticQuery.js +8 -2
- package/dist/domain/javascript/javascriptSemanticQueryIdentity.js +3 -2
- package/dist/domain/javascript/javascriptSemanticQuerySchemas.js +8 -9
- package/dist/domain/javascript/javascriptSemanticRequireOrigin.js +16 -10
- package/dist/domain/javascript/javascriptSemanticReturns.js +23 -27
- package/dist/domain/javascript/javascriptSemanticTraversal.js +6 -1
- package/dist/domain/javascript/javascriptSemanticValues.js +135 -24
- package/dist/domain/javascript/javascriptSourceMapPaths.js +11 -1
- package/dist/domain/javascript/javascriptSourceParser.js +34 -9
- package/dist/domain/javascript/javascriptStaticAnalysisBundler.js +5 -6
- package/dist/domain/javascript/javascriptStaticAnalysisHelpers.js +26 -15
- package/dist/domain/javascript/sourceToBundleComparison.js +7 -5
- package/dist/domain/javascript/sourceToBundleSignals.js +7 -7
- package/dist/domain/jsonSerialization.js +109 -55
- package/dist/domain/jsonShape.js +46 -19
- package/dist/domain/localPath.js +10 -4
- package/dist/domain/managed/managedApplicationGraph.js +10 -6
- package/dist/domain/managed/managedApplicationGraphNodes.js +82 -57
- package/dist/domain/managed/managedMemberComparisonMatch.js +6 -7
- package/dist/domain/native/nativeCallObservation.js +2 -4
- package/dist/domain/native/nativeValueFlow.js +5 -11
- package/dist/domain/native/objcSwiftMetadata.js +15 -17
- package/dist/domain/process/processCapture.js +11 -10
- package/dist/domain/process/processCaptureCoverage.js +8 -5
- package/dist/domain/process/processCaptureExample.js +43 -0
- package/dist/domain/process/processCaptureValidation.js +4 -3
- package/dist/domain/process/processComparison.js +0 -23
- package/dist/domain/process/processScenario.js +3 -3
- package/dist/domain/process/processTraceEvaluation.js +4 -4
- package/dist/domain/process/processTraceSpecification.js +1 -3
- package/dist/domain/providerCleanupError.js +6 -2
- package/dist/domain/reconstructionCoverage.js +2 -1
- package/dist/domain/reconstructionUnknowns.js +4 -3
- package/dist/domain/reconstructionVerification.js +3 -2
- package/dist/domain/referenceSourceGraph.js +7 -7
- package/dist/domain/referenceSourceImportParsing.js +34 -45
- package/dist/domain/residualUnknown.js +3 -2
- package/dist/domain/staticRuntimeCorrelation.js +2 -1
- package/dist/domain/swiftSymbolClassification.js +6 -1
- package/dist/domain/symbolAnalysis.js +17 -2
- package/dist/domain/unicodeCodePointOrder.js +6 -0
- package/dist/domain/webBundleAnalyzerInspection.js +9 -1
- package/dist/domain/webCaptureDiff.js +71 -29
- package/dist/domain/webCaptureDiffSchemas.js +2 -8
- package/dist/domain/webInventory.js +3 -2
- package/dist/domain/webMcpDiscovery.js +4 -3
- package/dist/domain/webScriptExport.js +1 -1
- package/dist/dotnet/ManagedMemberInstructionDecoder.js +1 -2
- package/dist/dotnet/ManagedStaticProvider.js +10 -7
- package/dist/dotnet/ManagedStaticProviderMetadata.js +1 -4
- package/dist/filesystem/RegularFile.js +41 -0
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +14 -4
- package/dist/ghidra/GhidraInstallation.js +111 -10
- package/dist/ghidra/GhidraLauncher.js +43 -19
- package/dist/hopper/HopperCleanup.js +1 -1
- package/dist/ida/IdaOperationRunner.js +2 -0
- package/dist/ida/IdaSessionClient.js +4 -2
- package/dist/inspector/JavaScriptRuntimeScope.js +9 -5
- package/dist/inspector/V8InspectorCaptureProjection.js +46 -13
- package/dist/inspector/V8InspectorProvider.js +60 -8
- package/dist/main/shutdown.js +76 -32
- package/dist/main/transport.js +1 -1
- package/dist/native/AppleObjcDispatchFacets.js +3 -3
- package/dist/native/AppleObjcProperties.js +17 -7
- package/dist/native/LldbCallTracer.js +241 -75
- package/dist/native/NativeMacOSProvider.js +10 -5
- package/dist/native/NativeMacOSProviderMetadata.js +1 -2
- package/dist/process/ProcessOwnershipObservation.js +9 -13
- package/dist/process/capture/FilesystemSnapshot.js +88 -18
- package/dist/process/capture/ProcessCaptureLifecycle.js +13 -27
- package/dist/process/capture/ProcessFilesystemEffects.js +19 -4
- package/dist/process/capture/ProcessHarness.js +8 -21
- package/dist/server/analysisAdmission.js +8 -0
- package/dist/server/createServer.js +22 -23
- package/dist/server/registerApplicationTools/compareExportShapes.js +2 -1
- package/dist/server/registerApplicationTools/helpers.js +3 -2
- package/dist/server/registerArtifactTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +6 -4
- package/dist/server/registerEnhancedTools.js +78 -73
- package/dist/server/registerEvidenceTools.js +54 -46
- package/dist/server/registerManagedTools.js +7 -4
- package/dist/server/registerOfficialTools.js +31 -25
- package/dist/server/registerSessionTools.js +9 -3
- package/native/windows/build/manifest.json +1 -1
- package/package.json +6 -3
- package/skills/reverse-engineer-anything/SKILL.md +5 -5
- package/skills/reverse-engineer-anything/references/native-and-artifacts.md +9 -0
- package/dist/artifacts/inventory/policy.js +0 -2
- package/dist/domain/managed/managedApplicationGraphNodeCoverage.js +0 -6
- package/dist/server/registerNativeTools.js +0 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { artifactInventoryResultSchema, } from "./artifactGraph.js";
|
|
3
|
-
import {
|
|
3
|
+
import { digestCanonicalValue } from "./canonicalDigest.js";
|
|
4
4
|
import { uniqueSorted } from "./canonicalOrdering.js";
|
|
5
5
|
import { evidenceSchema, parseEvidence } from "./evidence.js";
|
|
6
6
|
import { jsonValueSchema } from "./jsonValue.js";
|
|
@@ -137,7 +137,7 @@ export const createArtifactInspection = (inventoryInput) => {
|
|
|
137
137
|
},
|
|
138
138
|
substeps: [
|
|
139
139
|
{
|
|
140
|
-
substep_id: `ais_${
|
|
140
|
+
substep_id: `ais_${digestCanonicalValue({
|
|
141
141
|
operation: "inventory_artifact",
|
|
142
142
|
evidence_id: inventoryEvidence.evidence_id,
|
|
143
143
|
}, "Artifact inspection")}`,
|
|
@@ -175,7 +175,7 @@ export const createArtifactInspection = (inventoryInput) => {
|
|
|
175
175
|
};
|
|
176
176
|
return artifactInspectionResultSchema.parse({
|
|
177
177
|
...semantic,
|
|
178
|
-
inspection_id: `ai_${
|
|
178
|
+
inspection_id: `ai_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
|
179
179
|
});
|
|
180
180
|
};
|
|
181
181
|
const parseInventoryEvidence = (input) => {
|
|
@@ -198,7 +198,7 @@ const observation = (kind, subject, value, evidenceId) => {
|
|
|
198
198
|
evidence_id: evidenceId,
|
|
199
199
|
};
|
|
200
200
|
return {
|
|
201
|
-
observation_id: `aio_${
|
|
201
|
+
observation_id: `aio_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
|
202
202
|
...semantic,
|
|
203
203
|
};
|
|
204
204
|
};
|
|
@@ -212,7 +212,7 @@ const allRelationships = (inventory, evidenceId) => inventory.edges.map((edge) =
|
|
|
212
212
|
evidence_id: evidenceId,
|
|
213
213
|
};
|
|
214
214
|
return {
|
|
215
|
-
relationship_id: `air_${
|
|
215
|
+
relationship_id: `air_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
|
216
216
|
...semantic,
|
|
217
217
|
};
|
|
218
218
|
});
|
|
@@ -234,7 +234,7 @@ const allHypotheses = (inventory, evidenceId) => {
|
|
|
234
234
|
limitation: "Format classification proposes a bounded follow-up; it is not semantic proof.",
|
|
235
235
|
};
|
|
236
236
|
return {
|
|
237
|
-
hypothesis_id: `aih_${
|
|
237
|
+
hypothesis_id: `aih_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
|
238
238
|
...semantic,
|
|
239
239
|
};
|
|
240
240
|
});
|
|
@@ -248,7 +248,7 @@ const contradictions = (inventory, evidenceId) => inventory.integrity_contradict
|
|
|
248
248
|
evidence_id: evidenceId,
|
|
249
249
|
};
|
|
250
250
|
return {
|
|
251
|
-
contradiction_id: `aic_${
|
|
251
|
+
contradiction_id: `aic_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
|
252
252
|
...semantic,
|
|
253
253
|
};
|
|
254
254
|
});
|
|
@@ -308,7 +308,7 @@ const branch = (reason, detail, nextProbe, evidenceId) => {
|
|
|
308
308
|
evidence_id: evidenceId,
|
|
309
309
|
};
|
|
310
310
|
return {
|
|
311
|
-
branch_id: `aib_${
|
|
311
|
+
branch_id: `aib_${digestCanonicalValue(semantic, "Artifact inspection")}`,
|
|
312
312
|
...semantic,
|
|
313
313
|
};
|
|
314
314
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { artifactInventoryResultSchema, } from "./artifactGraph.js";
|
|
2
|
-
import {
|
|
2
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
3
3
|
import { canonicalJson } from "./comparisonSemantics.js";
|
|
4
4
|
import { artifactContradictionId, artifactEdgeId, artifactGraphDigest, artifactIdForContent, artifactManifestId, occurrenceIdForLocation, } from "./artifactIdentity.js";
|
|
5
5
|
import { parseEvidence } from "./evidence.js";
|
|
@@ -68,9 +68,9 @@ const assembleInventorySet = (pages) => {
|
|
|
68
68
|
return { evidence: pages.map(({ evidence }) => evidence), inventory };
|
|
69
69
|
};
|
|
70
70
|
const orderedInventory = (first, pages, values) => {
|
|
71
|
-
const nodes = [...values.nodes.values()].sort((left, right) =>
|
|
72
|
-
const occurrences = [...values.occurrences.values()].sort((left, right) =>
|
|
73
|
-
const edges = [...values.edges.values()].sort((left, right) =>
|
|
71
|
+
const nodes = [...values.nodes.values()].sort((left, right) => compareUnicodeCodePoints(left.artifact_id, right.artifact_id));
|
|
72
|
+
const occurrences = [...values.occurrences.values()].sort((left, right) => compareUnicodeCodePoints(left.logical_path, right.logical_path));
|
|
73
|
+
const edges = [...values.edges.values()].sort((left, right) => compareUnicodeCodePoints(left.edge_id, right.edge_id));
|
|
74
74
|
return {
|
|
75
75
|
manifest: first.manifest,
|
|
76
76
|
nodes,
|
|
@@ -79,7 +79,7 @@ const orderedInventory = (first, pages, values) => {
|
|
|
79
79
|
integrityContradictions: first.integrity_contradictions,
|
|
80
80
|
limitations: [
|
|
81
81
|
...new Set(pages.flatMap(({ inventory }) => inventory.limitations)),
|
|
82
|
-
].sort(
|
|
82
|
+
].sort(compareUnicodeCodePoints),
|
|
83
83
|
complete: nodes.length === first.manifest.node_count &&
|
|
84
84
|
occurrences.length === first.manifest.occurrence_count &&
|
|
85
85
|
edges.length === first.manifest.edge_count,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
2
3
|
/** Stable browser sections used by coverage and omission accounting. */
|
|
3
4
|
const browserSectionSchema = z.enum([
|
|
4
5
|
"frames",
|
|
@@ -98,5 +99,5 @@ export const classifyBrowserCompleteness = (input) => {
|
|
|
98
99
|
});
|
|
99
100
|
};
|
|
100
101
|
const sortedSections = (sections) => [...sections].sort();
|
|
101
|
-
const canonicalExclusions = (exclusions) => [...exclusions].sort((left, right) => left.section
|
|
102
|
-
left.reason
|
|
102
|
+
const canonicalExclusions = (exclusions) => [...exclusions].sort((left, right) => compareUnicodeCodePoints(left.section, right.section) ||
|
|
103
|
+
compareUnicodeCodePoints(left.reason, right.reason));
|
|
@@ -103,8 +103,8 @@ const eventBase = {
|
|
|
103
103
|
const eventUrl = sanitizedBrowserUrlSchema.nullable();
|
|
104
104
|
const networkEventShape = {
|
|
105
105
|
...eventBase,
|
|
106
|
-
transaction_id: z.string().min(1)
|
|
107
|
-
redirected_from_transaction_id: z.string().min(1).nullable()
|
|
106
|
+
transaction_id: z.string().min(1),
|
|
107
|
+
redirected_from_transaction_id: z.string().min(1).nullable(),
|
|
108
108
|
method: z.string().min(1),
|
|
109
109
|
url: sanitizedBrowserUrlSchema,
|
|
110
110
|
resource_type: z.string().min(1),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { digestCanonicalValue } from "./canonicalDigest.js";
|
|
2
2
|
const BUILT_IN_RULES = [
|
|
3
3
|
"ignore_step_elapsed_ms",
|
|
4
4
|
"ignore_event_sequence",
|
|
@@ -17,11 +17,11 @@ export const commitBrowserScenarioNormalization = (input) => {
|
|
|
17
17
|
const commitment = { built_in_rules: [...BUILT_IN_RULES], rules };
|
|
18
18
|
return {
|
|
19
19
|
...commitment,
|
|
20
|
-
sha256:
|
|
20
|
+
sha256: digestCanonicalValue(commitment, "Browser scenario"),
|
|
21
21
|
};
|
|
22
22
|
};
|
|
23
23
|
/** Digest one artifact after applying committed exact-literal rules. */
|
|
24
|
-
export const digestNormalizedScenarioValue = (value, artifact, rules) =>
|
|
24
|
+
export const digestNormalizedScenarioValue = (value, artifact, rules) => digestCanonicalValue(normalize(value, artifact, rules), "Browser scenario");
|
|
25
25
|
const normalize = (value, artifact, rules) => {
|
|
26
26
|
if (artifact === "screenshot")
|
|
27
27
|
return value;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
2
3
|
import { IDENTIFIER_PATTERN } from "./stringPatterns.js";
|
|
3
|
-
import {
|
|
4
|
+
import { localPathStringSchema } from "./localPath.js";
|
|
4
5
|
import { browserNetworkContentSelectionSchema } from "./browserNetworkEvidence.js";
|
|
5
6
|
import { browserEndpointSchema, browserOriginSchema, } from "./browserObservation.js";
|
|
6
7
|
export const scenarioIdentifierSchema = z.string().regex(IDENTIFIER_PATTERN);
|
|
7
|
-
const browserExecutablePathSchema = localPathStringSchema.refine(
|
|
8
|
+
const browserExecutablePathSchema = localPathStringSchema.refine(isAbsolute, {
|
|
8
9
|
message: "executable_path must be an absolute local filesystem path (for example /opt/chromium/chrome or C:\\chromium\\chrome.exe)",
|
|
9
10
|
});
|
|
10
11
|
const browserScenarioBaseUrlSchema = z
|
package/dist/domain/callPath.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { callPathInputSchema, callPathResultSchema, parseCallPathAddress, } from "./callPathSchemas.js";
|
|
2
2
|
import { parseFunctionEvidence, } from "./functionDossierEvidence.js";
|
|
3
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
3
4
|
/** Minimal directed caller-to-callee adjacency for call-path search. */
|
|
4
5
|
class CallGraph {
|
|
5
6
|
successors = new Map();
|
|
@@ -76,7 +77,7 @@ export const buildCallPath = (input) => {
|
|
|
76
77
|
goal: parsed.goal.address,
|
|
77
78
|
explored: summarizeSearch(graph, search.reached),
|
|
78
79
|
evidence_links: uniqueEvidence(snapshots.values()),
|
|
79
|
-
limitations: [...new Set(limitations)].sort(
|
|
80
|
+
limitations: [...new Set(limitations)].sort(compareUnicodeCodePoints),
|
|
80
81
|
};
|
|
81
82
|
const searchScope = { exhaustive };
|
|
82
83
|
if (found)
|
|
@@ -111,9 +112,9 @@ const parseSnapshots = (groups) => {
|
|
|
111
112
|
const snapshots = new Map();
|
|
112
113
|
for (const group of groups) {
|
|
113
114
|
const snapshot = parseFunctionEvidence(group);
|
|
114
|
-
const address =
|
|
115
|
+
const address = parseCallPathAddress(snapshot.dossier.procedure.address);
|
|
115
116
|
for (const callee of snapshot.dossier.callees)
|
|
116
|
-
|
|
117
|
+
parseCallPathAddress(callee.address);
|
|
117
118
|
if (snapshots.has(address))
|
|
118
119
|
throw new TypeError(`Duplicate function Evidence for ${address}`);
|
|
119
120
|
snapshots.set(address, snapshot);
|
|
@@ -141,7 +142,7 @@ const createGraph = (snapshots) => {
|
|
|
141
142
|
for (const [address, snapshot] of snapshots) {
|
|
142
143
|
graph.mergeNode(address);
|
|
143
144
|
for (const callee of snapshot.dossier.callees) {
|
|
144
|
-
const calleeAddress =
|
|
145
|
+
const calleeAddress = parseCallPathAddress(callee.address);
|
|
145
146
|
graph.mergeNode(calleeAddress);
|
|
146
147
|
graph.mergeDirectedEdge(address, calleeAddress);
|
|
147
148
|
}
|
|
@@ -174,9 +175,7 @@ const inspectSearch = ({ graph, snapshots, start, goal, }) => {
|
|
|
174
175
|
limitations.push(`No analyze_function Evidence covers reachable function ${node}`);
|
|
175
176
|
continue;
|
|
176
177
|
}
|
|
177
|
-
const neighbors = graph
|
|
178
|
-
.outNeighbors(node)
|
|
179
|
-
.sort((left, right) => left.localeCompare(right));
|
|
178
|
+
const neighbors = graph.outNeighbors(node).sort(compareUnicodeCodePoints);
|
|
180
179
|
for (const neighbor of neighbors)
|
|
181
180
|
if (!reached.has(neighbor)) {
|
|
182
181
|
reached.set(neighbor, depth + 1);
|
|
@@ -203,7 +202,7 @@ const enumeratePaths = ({ graph, start, goal, goalDistances, }) => {
|
|
|
203
202
|
.outNeighbors(node)
|
|
204
203
|
.filter((neighbor) => distance !== undefined &&
|
|
205
204
|
goalDistances.get(neighbor) === distance - 1)
|
|
206
|
-
.sort(
|
|
205
|
+
.sort(compareUnicodeCodePoints);
|
|
207
206
|
neighbors.set(node, candidates);
|
|
208
207
|
}
|
|
209
208
|
return { neighbors: candidates, nextIndex: 0 };
|
|
@@ -270,5 +269,4 @@ const snapshotLinks = (snapshot) => {
|
|
|
270
269
|
};
|
|
271
270
|
const uniqueEvidence = (snapshots) => [
|
|
272
271
|
...new Set([...snapshots].flatMap((snapshot) => snapshotLinks(snapshot))),
|
|
273
|
-
].sort(
|
|
274
|
-
const normalizeAddress = (input) => parseCallPathAddress(input);
|
|
272
|
+
].sort(compareUnicodeCodePoints);
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Streaming SHA-256 over canonical JSON. Hashing owner (avoids assembling
|
|
4
|
+
* aggregate strings); `comparisonSemantics.canonicalJson` (canonicalize lib)
|
|
5
|
+
* is the string-comparison owner. JSON object keys follow RFC 8785's UTF-16
|
|
6
|
+
* code-unit order in both; entity-list ordering is a separate concern.
|
|
7
|
+
*/
|
|
3
8
|
export const digestCanonicalValue = (value, context = "Comparison") => {
|
|
4
9
|
const hash = createHash("sha256");
|
|
5
10
|
// Batch small emitted parts to cut hash.update crossings.
|
|
@@ -54,6 +59,7 @@ const emitCanonical = (value, emit, ancestors) => {
|
|
|
54
59
|
else {
|
|
55
60
|
emit("{");
|
|
56
61
|
let first = true;
|
|
62
|
+
// Match canonicalize/RFC 8785, including supplementary-plane keys.
|
|
57
63
|
for (const key of Object.keys(value).sort()) {
|
|
58
64
|
if (Reflect.get(value, key) === undefined ||
|
|
59
65
|
typeof Reflect.get(value, key) === "symbol")
|
|
@@ -1,15 +1,3 @@
|
|
|
1
1
|
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
2
|
-
/**
|
|
3
|
-
* Canonical code-point ordering shared across domain and application layers.
|
|
4
|
-
*
|
|
5
|
-
* Compares strings by Unicode code point so graph ordering, fingerprints, and
|
|
6
|
-
* deterministic tie-breaks stay stable regardless of locale. Prefer this over
|
|
7
|
-
* `String.prototype.localeCompare`, which is locale-dependent.
|
|
8
|
-
*
|
|
9
|
-
* Ordering by code point differs from ordering by UTF-16 code unit for astral
|
|
10
|
-
* code points (above U+FFFF), whose lead surrogate is numerically below the
|
|
11
|
-
* BMP tail U+E000-U+FFFF.
|
|
12
|
-
*/
|
|
13
|
-
export const compareCodePoints = (left, right) => compareUnicodeCodePoints(left, right);
|
|
14
2
|
/** Deduplicate and sort strings with canonical code-point ordering. */
|
|
15
|
-
export const uniqueSorted = (values) => [...new Set(values)].sort(
|
|
3
|
+
export const uniqueSorted = (values) => [...new Set(values)].sort(compareUnicodeCodePoints);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { artifactComparisonResultSchema } from "./artifactComparison.js";
|
|
3
3
|
import { uniqueSorted } from "./canonicalOrdering.js";
|
|
4
|
+
import { compositeKey, compareUnicodeCodePoints, } from "./unicodeCodePointOrder.js";
|
|
4
5
|
import { comparisonSourceEvidenceIds } from "./comparisonSourceEvidence.js";
|
|
5
6
|
import { evidenceSchema, parseEvidence } from "./evidence.js";
|
|
6
7
|
import { functionComparisonResultSchema } from "./functionComparisonSchemas.js";
|
|
@@ -274,9 +275,7 @@ const behaviorStatus = (statuses) => {
|
|
|
274
275
|
const isChange = (status) => status === "added" || status === "removed" || status === "changed";
|
|
275
276
|
const count = (findings, classification) => findings.filter((finding) => finding.classification === classification)
|
|
276
277
|
.length;
|
|
277
|
-
const compareFindings = (left, right) => [left.scope, left.dimension, left.source_comparison_id]
|
|
278
|
-
.join("\0")
|
|
279
|
-
.localeCompare([right.scope, right.dimension, right.source_comparison_id].join("\0"), "en");
|
|
278
|
+
const compareFindings = (left, right) => compareUnicodeCodePoints(compositeKey([left.scope, left.dimension, left.source_comparison_id]), compositeKey([right.scope, right.dimension, right.source_comparison_id]));
|
|
280
279
|
const assertUnique = (values, label) => {
|
|
281
280
|
if (new Set(values).size !== values.length)
|
|
282
281
|
throw new TypeError(`Changed-behavior analysis rejects duplicate ${label}`);
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import canonicalize from "canonicalize";
|
|
2
|
-
import { digestCanonicalValue } from "./canonicalDigest.js";
|
|
3
2
|
/** Whether an inventory can support a claim that an item is absent. */
|
|
4
3
|
export const absenceClaimable = (coverage) => coverage.status === "complete" &&
|
|
5
4
|
coverage.truncated !== true &&
|
|
6
5
|
(coverage.omitted_count === undefined || coverage.omitted_count === 0);
|
|
7
|
-
/** SHA-256 of canonical JSON for stable, provider-neutral comparison IDs. */
|
|
8
|
-
export const canonicalDigest = (value, context = "Comparison") => {
|
|
9
|
-
return digestCanonicalValue(value, context);
|
|
10
|
-
};
|
|
11
6
|
/** Canonical JSON used for deterministic tie breaking and stable digests. */
|
|
12
7
|
export const canonicalJson = (value, context = "Comparison") => {
|
|
13
8
|
const encoded = canonicalize(value);
|
package/dist/domain/digests.js
CHANGED
|
@@ -25,6 +25,3 @@ export const prefixedDigestSchema = (prefix) => z
|
|
|
25
25
|
.regex(new RegExp(`^${prefix}_[a-f0-9]{64}$`, "u"), `Expected a ${prefix}_ prefixed lowercase sha256 digest`);
|
|
26
26
|
/** True when `value` is a bare digest. */
|
|
27
27
|
export const isDigest = (value) => typeof value === "string" && SHA256_PATTERN.test(value);
|
|
28
|
-
/** True when `value` is a digest carrying `prefix`. */
|
|
29
|
-
export const isPrefixedDigest = (value, prefix) => typeof value === "string" &&
|
|
30
|
-
prefixedDigestSchema(prefix).safeParse(value).success;
|
package/dist/domain/evidence.js
CHANGED
|
@@ -108,6 +108,15 @@ export const validateAnalysisProfileProvider = (evidence, context) => {
|
|
|
108
108
|
};
|
|
109
109
|
/** Strict, provider-neutral record for one successful public observation. */
|
|
110
110
|
export const evidenceSchema = evidenceBaseSchema.superRefine(validateAnalysisProfileProvider);
|
|
111
|
+
const authenticatedEvidenceSchema = evidenceSchema.superRefine((evidence, context) => {
|
|
112
|
+
const { evidence_id: evidenceId, ...withoutId } = evidence;
|
|
113
|
+
if (computeEvidenceId(withoutId) !== evidenceId)
|
|
114
|
+
context.addIssue({
|
|
115
|
+
code: "custom",
|
|
116
|
+
path: ["evidence_id"],
|
|
117
|
+
message: "Evidence semantic identifier does not match its record",
|
|
118
|
+
});
|
|
119
|
+
});
|
|
111
120
|
const immutableEvidenceSnapshots = new WeakMap();
|
|
112
121
|
const immutableResultSchema = z
|
|
113
122
|
.custom(isImmutableJsonSnapshot)
|
|
@@ -147,11 +156,7 @@ export const parseEvidence = (input) => {
|
|
|
147
156
|
: undefined;
|
|
148
157
|
if (immutable !== undefined)
|
|
149
158
|
return immutable;
|
|
150
|
-
|
|
151
|
-
const { evidence_id: evidenceId, ...withoutId } = evidence;
|
|
152
|
-
if (computeEvidenceId(withoutId) !== evidenceId)
|
|
153
|
-
throw new TypeError("Evidence semantic identifier does not match its record");
|
|
154
|
-
return evidence;
|
|
159
|
+
return authenticatedEvidenceSchema.parse(input);
|
|
155
160
|
};
|
|
156
161
|
/** Authenticate and seal a ledger-owned snapshot; external mutable values are copied first. */
|
|
157
162
|
export const immutableEvidence = (input) => rememberImmutableEvidence(parseEvidence(input));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import canonicalize from "canonicalize";
|
|
3
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
3
4
|
import { evidenceSchema, immutableEvidence, parseEvidence, providerSchema, } from "./evidence.js";
|
|
4
5
|
import { residualUnknownSchema, } from "./residualUnknown.js";
|
|
5
6
|
import { freezeJsonSnapshot } from "./immutableJson.js";
|
|
@@ -43,7 +44,7 @@ export const createImmutableEvidenceBundle = (records, unknowns = []) => {
|
|
|
43
44
|
};
|
|
44
45
|
/** Project records into a deterministic bundle whose order has no semantics. */
|
|
45
46
|
export const createEvidenceBundle = (records, unknowns = []) => {
|
|
46
|
-
const sortedRecords = [...records].sort((left, right) => left.evidence_id
|
|
47
|
+
const sortedRecords = [...records].sort((left, right) => compareUnicodeCodePoints(left.evidence_id, right.evidence_id));
|
|
47
48
|
return {
|
|
48
49
|
artifacts: uniqueSorted(sortedRecords.flatMap(({ subject }) => subject === null
|
|
49
50
|
? []
|
|
@@ -73,55 +74,60 @@ export const createEvidenceBundle = (records, unknowns = []) => {
|
|
|
73
74
|
},
|
|
74
75
|
]
|
|
75
76
|
: []),
|
|
76
|
-
unknowns: [...unknowns].sort((left, right) => left.unknown_id
|
|
77
|
+
unknowns: [...unknowns].sort((left, right) => compareUnicodeCodePoints(left.unknown_id, right.unknown_id) ||
|
|
77
78
|
left.revision - right.revision),
|
|
78
79
|
records: sortedRecords,
|
|
79
80
|
};
|
|
80
81
|
};
|
|
81
|
-
/**
|
|
82
|
+
/** Retain target records and eligible complete unknown histories with their mutation evidence. */
|
|
82
83
|
export const evidenceBundleForTarget = (bundle, sha256) => {
|
|
83
84
|
const recordsById = new Map(bundle.records.map((record) => [record.evidence_id, record]));
|
|
84
|
-
const
|
|
85
|
+
const histories = new Map();
|
|
86
|
+
for (const unknown of bundle.unknowns) {
|
|
87
|
+
const history = histories.get(unknown.unknown_id) ?? [];
|
|
88
|
+
history.push(unknown);
|
|
89
|
+
histories.set(unknown.unknown_id, history);
|
|
90
|
+
}
|
|
85
91
|
const retained = new Set();
|
|
86
|
-
const revisionsById = new Map();
|
|
87
92
|
const dependents = new Map();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
const relationships = new Map();
|
|
94
|
+
for (const [id, history] of histories) {
|
|
95
|
+
const eligible = history.every((unknown) => {
|
|
96
|
+
if (unknown.scope_digest !== sha256)
|
|
97
|
+
return false;
|
|
98
|
+
const mutationEvidenceIds = new Set(unknown.mutation_evidence_ids);
|
|
99
|
+
return referencedEvidenceIds(unknown).every((evidenceId) => {
|
|
100
|
+
const record = recordsById.get(evidenceId);
|
|
101
|
+
// Mutation subjects record the target active at the time of an edit,
|
|
102
|
+
// which need not be the question's immutable investigation scope.
|
|
103
|
+
return (record?.subject?.digest.sha256 === sha256 ||
|
|
104
|
+
(mutationEvidenceIds.has(evidenceId) &&
|
|
105
|
+
record?.predicate_type === "rea.residual-unknown-mutation"));
|
|
106
|
+
});
|
|
96
107
|
});
|
|
97
|
-
if (!
|
|
108
|
+
if (!eligible)
|
|
98
109
|
continue;
|
|
99
|
-
retained.add(
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
retained.add(id);
|
|
111
|
+
const relatedIds = new Set(history.flatMap((unknown) => unknown.relationships.map(({ unknown_id }) => unknown_id)));
|
|
112
|
+
relationships.set(id, relatedIds);
|
|
113
|
+
for (const relatedId of relatedIds) {
|
|
102
114
|
const references = dependents.get(relatedId) ?? new Set();
|
|
103
|
-
references.add(
|
|
115
|
+
references.add(id);
|
|
104
116
|
dependents.set(relatedId, references);
|
|
105
117
|
}
|
|
106
118
|
}
|
|
107
119
|
const pending = [];
|
|
108
|
-
for (const
|
|
109
|
-
if (
|
|
110
|
-
pending.push(
|
|
120
|
+
for (const [id, relatedIds] of relationships)
|
|
121
|
+
if ([...relatedIds].some((relatedId) => !retained.has(relatedId)))
|
|
122
|
+
pending.push(id);
|
|
111
123
|
for (let index = 0; index < pending.length; index += 1) {
|
|
112
|
-
const
|
|
113
|
-
if (
|
|
124
|
+
const id = pending[index];
|
|
125
|
+
if (id === undefined || !retained.delete(id))
|
|
114
126
|
continue;
|
|
115
|
-
const
|
|
116
|
-
if (remaining > 0) {
|
|
117
|
-
revisionsById.set(unknown.unknown_id, remaining);
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
revisionsById.delete(unknown.unknown_id);
|
|
121
|
-
for (const dependent of dependents.get(unknown.unknown_id) ?? [])
|
|
127
|
+
for (const dependent of dependents.get(id) ?? [])
|
|
122
128
|
pending.push(dependent);
|
|
123
129
|
}
|
|
124
|
-
const unknowns =
|
|
130
|
+
const unknowns = bundle.unknowns.filter((unknown) => retained.has(unknown.unknown_id));
|
|
125
131
|
const mutationIds = new Set(unknowns.flatMap(({ mutation_evidence_ids: ids }) => ids));
|
|
126
132
|
return createEvidenceBundle(bundle.records.filter((record) => record.subject?.digest.sha256 === sha256 ||
|
|
127
133
|
mutationIds.has(record.evidence_id)), unknowns);
|
|
@@ -166,7 +172,19 @@ export const parseEvidenceBundle = (input) => {
|
|
|
166
172
|
if (new Set(recordIds).size !== recordIds.length)
|
|
167
173
|
throw new TypeError("Evidence bundle contains duplicate record IDs");
|
|
168
174
|
validateUnknownGraph(parsed.unknowns, parsed.records);
|
|
169
|
-
const canonical = createEvidenceBundle(parsed.records.map(
|
|
175
|
+
const canonical = createEvidenceBundle(parsed.records.map((record, index) => {
|
|
176
|
+
try {
|
|
177
|
+
return parseEvidence(record);
|
|
178
|
+
}
|
|
179
|
+
catch (cause) {
|
|
180
|
+
if (cause instanceof z.ZodError)
|
|
181
|
+
throw new z.ZodError(cause.issues.map((issue) => ({
|
|
182
|
+
...issue,
|
|
183
|
+
path: ["records", index, ...issue.path],
|
|
184
|
+
})));
|
|
185
|
+
throw cause;
|
|
186
|
+
}
|
|
187
|
+
}), parsed.unknowns);
|
|
170
188
|
if (JSON.stringify(parsed) !== JSON.stringify(canonical))
|
|
171
189
|
throw new TypeError("Evidence bundle manifests are not canonical");
|
|
172
190
|
return canonical;
|
|
@@ -364,6 +382,6 @@ const uniqueSorted = (values) => {
|
|
|
364
382
|
for (const value of values)
|
|
365
383
|
unique.set(JSON.stringify(value), value);
|
|
366
384
|
return [...unique.entries()]
|
|
367
|
-
.sort(([left], [right]) => left
|
|
385
|
+
.sort(([left], [right]) => compareUnicodeCodePoints(left, right))
|
|
368
386
|
.map(([, value]) => value);
|
|
369
387
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
2
3
|
import { digestSchema } from "../digests.js";
|
|
3
4
|
import { jsonValueSchema } from "../jsonValue.js";
|
|
4
|
-
import {
|
|
5
|
+
import { localPathStringSchema } from "../localPath.js";
|
|
5
6
|
const bytes = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
6
7
|
const range = z.strictObject({ offset: bytes, length: bytes.positive() });
|
|
7
8
|
const target = {
|
|
8
9
|
path: localPathStringSchema
|
|
9
|
-
.refine(
|
|
10
|
+
.refine(isAbsolute, {
|
|
10
11
|
message: "path must be an absolute local filesystem path (for example /tmp/firmware.bin or C:\\firmware\\firmware.bin)",
|
|
11
12
|
})
|
|
12
13
|
.describe("Absolute local firmware file; never executed. Relative paths are rejected."),
|
|
@@ -17,7 +18,7 @@ export const firmwareInputSchemas = {
|
|
|
17
18
|
extract_firmware: z.strictObject({
|
|
18
19
|
...target,
|
|
19
20
|
output_directory: localPathStringSchema
|
|
20
|
-
.refine(
|
|
21
|
+
.refine(isAbsolute, {
|
|
21
22
|
message: "output_directory must be an absolute local filesystem path",
|
|
22
23
|
})
|
|
23
24
|
.describe("Absolute, absent output directory; parent must exist"),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { canonicalJson } from "./comparisonSemantics.js";
|
|
2
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
2
3
|
import { parseFunctionEvidence } from "./functionDossierEvidence.js";
|
|
3
4
|
import { functionMatch } from "./functionComparisonNormalization.js";
|
|
4
5
|
import { functionComparisonResultSchema, } from "./functionComparisonSchemas.js";
|
|
@@ -32,6 +33,6 @@ export const compareFunctions = (leftInput, rightInput) => {
|
|
|
32
33
|
]
|
|
33
34
|
: []),
|
|
34
35
|
]),
|
|
35
|
-
].sort((a, b) => a
|
|
36
|
+
].sort((a, b) => compareUnicodeCodePoints(a, b)),
|
|
36
37
|
});
|
|
37
38
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { canonicalJson } from "./comparisonSemantics.js";
|
|
2
|
-
import {
|
|
2
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
3
3
|
export const identityProjection = (snapshot) => ({
|
|
4
4
|
name: snapshot.dossier.procedure.name,
|
|
5
5
|
signature: snapshot.dossier.procedure.signature,
|
|
@@ -136,9 +136,10 @@ export const sorted = (values) => values
|
|
|
136
136
|
value,
|
|
137
137
|
json: canonicalJson(value, "Function normalization"),
|
|
138
138
|
}))
|
|
139
|
-
.sort((left, right) =>
|
|
139
|
+
.sort((left, right) => compareUnicodeCodePoints(left.json, right.json))
|
|
140
140
|
.map(({ value }) => value);
|
|
141
|
-
|
|
141
|
+
/** Recognize address-derived procedure names without excluding named FUN_ symbols. */
|
|
142
|
+
export const isAutoName = (name) => /^(?:sub_[0-9a-f]+|fcn\.[0-9a-f]+|FUN_[0-9a-f]+)$/iu.test(name);
|
|
142
143
|
const parseAddress = (value) => /^0x[0-9a-f]+$/iu.test(value) ? BigInt(value) : null;
|
|
143
144
|
const relativeAddress = (value, base) => {
|
|
144
145
|
const parsed = parseAddress(value);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { digestCanonicalValue } from "./canonicalDigest.js";
|
|
2
2
|
export const dimensionResult = (input) => {
|
|
3
3
|
const context = {
|
|
4
4
|
dimension: input.dimension,
|
|
@@ -51,4 +51,4 @@ export const summarize = (dimensions) => ({
|
|
|
51
51
|
changed: dimensions.filter(({ status }) => status === "changed").length,
|
|
52
52
|
unknown: dimensions.filter(({ status }) => status === "unknown").length,
|
|
53
53
|
});
|
|
54
|
-
const digest = (value) =>
|
|
54
|
+
const digest = (value) => digestCanonicalValue(value, "Function comparison");
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { parseEvidence } from "./evidence.js";
|
|
2
|
+
import { compareUnicodeCodePoints } from "./unicodeCodePointOrder.js";
|
|
2
3
|
import { functionDossierSchema } from "./hopperValues.js";
|
|
3
4
|
/** Parse one complete analyze_function Evidence record for comparison workflows. */
|
|
4
5
|
export const parseFunctionEvidence = (input) => {
|
|
@@ -14,6 +15,6 @@ export const parseFunctionEvidence = (input) => {
|
|
|
14
15
|
dossier,
|
|
15
16
|
limitations: [
|
|
16
17
|
...new Set([...evidence.limitations, ...dossier.limitations]),
|
|
17
|
-
].sort((left, right) => left
|
|
18
|
+
].sort((left, right) => compareUnicodeCodePoints(left, right)),
|
|
18
19
|
};
|
|
19
20
|
};
|
|
@@ -29,12 +29,12 @@ const procedureMapSchema = z.record(z.string(), z.string());
|
|
|
29
29
|
const addressedNamesSchema = z.array(z.object({ address: z.string(), name: z.string() }));
|
|
30
30
|
const addressedNameMapSchema = z.record(z.string(), z.string());
|
|
31
31
|
const segmentSchema = z.object({
|
|
32
|
-
name: z.string()
|
|
33
|
-
start: z.string()
|
|
34
|
-
end: z.string()
|
|
35
|
-
readable: z.boolean().nullable()
|
|
36
|
-
writable: z.boolean().nullable()
|
|
37
|
-
executable: z.boolean().nullable()
|
|
32
|
+
name: z.string(),
|
|
33
|
+
start: z.string(),
|
|
34
|
+
end: z.string(),
|
|
35
|
+
readable: z.boolean().nullable(),
|
|
36
|
+
writable: z.boolean().nullable(),
|
|
37
|
+
executable: z.boolean().nullable(),
|
|
38
38
|
});
|
|
39
39
|
const unavailableAnalysisFactSchema = z
|
|
40
40
|
.object({ available: z.literal(false), reason: z.string() })
|
|
@@ -142,10 +142,6 @@ export const functionBodySchema = z.discriminatedUnion("available", [
|
|
|
142
142
|
});
|
|
143
143
|
}),
|
|
144
144
|
]);
|
|
145
|
-
const unknownFunctionBody = () => functionBodySchema.default({
|
|
146
|
-
available: false,
|
|
147
|
-
reason: "The provider did not report complete function body ranges.",
|
|
148
|
-
});
|
|
149
145
|
/** Check the declared entry membership against complete, inclusive body ranges. */
|
|
150
146
|
export const functionBodyEntryAgrees = (body, address) => {
|
|
151
147
|
if (!body.available)
|
|
@@ -176,8 +172,8 @@ export const procedureIdentitySchema = z
|
|
|
176
172
|
.object({
|
|
177
173
|
address: z.string(),
|
|
178
174
|
name: z.string(),
|
|
179
|
-
classification: procedureClassificationSchema.nullable()
|
|
180
|
-
body:
|
|
175
|
+
classification: procedureClassificationSchema.nullable(),
|
|
176
|
+
body: functionBodySchema,
|
|
181
177
|
})
|
|
182
178
|
.strict()
|
|
183
179
|
.superRefine((identity, context) => {
|
|
@@ -289,9 +285,9 @@ export const functionDossierSchema = z
|
|
|
289
285
|
successors: z.array(z.string()),
|
|
290
286
|
})
|
|
291
287
|
.strict()),
|
|
292
|
-
native_api: nativeApiBoundarySchema.nullable()
|
|
293
|
-
native_value_flow: nativeValueFlowSchema.nullable()
|
|
294
|
-
limitations: z.array(z.string())
|
|
288
|
+
native_api: nativeApiBoundarySchema.nullable(),
|
|
289
|
+
native_value_flow: nativeValueFlowSchema.nullable(),
|
|
290
|
+
limitations: z.array(z.string()),
|
|
295
291
|
})
|
|
296
292
|
.strict();
|
|
297
293
|
/** Strictly parse a complete provider-neutral function dossier. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { isAbsolute } from "node:path";
|
|
3
|
+
import { localPathStringSchema } from "../localPath.js";
|
|
4
|
+
const pathInputSchema = localPathStringSchema.refine(isAbsolute, {
|
|
4
5
|
message: "Electron executable, application, and root paths must be absolute local filesystem paths (for example /Applications/Electron.app/Contents/MacOS/Electron)",
|
|
5
6
|
});
|
|
6
7
|
const absolutePathSchema = z
|
|
@@ -63,7 +64,7 @@ export const electronActiveObservationInputSchema = z.strictObject({
|
|
|
63
64
|
args: z
|
|
64
65
|
.array(z
|
|
65
66
|
.string()
|
|
66
|
-
.regex(/^[^\
|
|
67
|
+
.regex(/^[^\x00]*$/u, "Electron arguments must not contain NUL"))
|
|
67
68
|
.default([]),
|
|
68
69
|
actions: z.array(actionSchema).default([]),
|
|
69
70
|
});
|