rea-agents 3.0.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 +14 -16
- package/dist/application/AnalysisContextQueries.js +21 -9
- 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 +14 -16
- package/dist/application/BinarySessionRecords.js +31 -5
- 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 +134 -63
- package/dist/application/CrossVersionInventory.js +7 -6
- 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 +22 -20
- package/dist/application/EvidenceBundleCommands.js +5 -1
- package/dist/application/EvidenceLedger.js +8 -1
- package/dist/application/JavaScriptReplayPermission.js +1 -1
- package/dist/application/JavaScriptReplayService.js +23 -15
- package/dist/application/ManagedRuntimeCorrelationService.js +9 -5
- 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/SetupClientConfiguration.js +6 -1
- package/dist/application/WindowsCapabilities.js +5 -4
- 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/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 +12 -6
- 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 +1 -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 +27 -34
- package/dist/contracts/browserToolContracts.js +2 -2
- package/dist/contracts/electronToolContracts.js +30 -1
- package/dist/contracts/enhancedInputs.js +13 -29
- package/dist/contracts/functionWorkflowToolContracts.js +2 -3
- 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/sessionToolSchemas.js +61 -0
- package/dist/contracts/toolContractExamples.js +1 -0
- package/dist/contracts/toolContractHelpers.js +23 -0
- package/dist/contracts/toolContracts.js +5 -77
- package/dist/contracts/toolEffects.js +15 -0
- package/dist/contracts/toolOutputSchemaGroups.js +17 -2
- package/dist/contracts/toolOutputSchemaPrimitives.js +76 -26
- package/dist/contracts/toolSchemaMetadata.js +128 -0
- package/dist/doctorRuntime.js +1 -1
- 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 +33 -35
- package/dist/domain/callPath.js +3 -2
- package/dist/domain/conformanceReplay.js +3 -3
- package/dist/domain/conformanceTrustGate.js +151 -16
- package/dist/domain/customProtocolCapture.js +3 -3
- 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 +82 -79
- package/dist/domain/functionComparisonNormalization.js +15 -8
- package/dist/domain/functionDossierEvidence.js +9 -4
- package/dist/domain/hopperValues.js +68 -71
- package/dist/domain/inputIssueProjection.js +4 -1
- 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/knownPageCoverage.js +15 -7
- package/dist/domain/nativeApiBoundary.js +15 -7
- package/dist/domain/nodeRuntimeCharacterization.js +14 -13
- 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 +8 -6
- 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/generatedMcpToolCatalog.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraClient.js +1 -1
- package/dist/ghidra/GhidraClientStartup.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +17 -15
- package/dist/ghidra/GhidraInventoryValues.js +57 -47
- package/dist/ghidra/GhidraProvider.js +18 -10
- package/dist/ghidra/GhidraProviderCapabilities.js +5 -1
- 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 +1 -1
- package/dist/hopper/HopperProvider.js +0 -14
- package/dist/hopper/LinuxPrivateDisplayProbe.js +16 -10
- package/dist/main/reload.js +1 -6
- package/dist/main/state.js +0 -14
- package/dist/main/transport.js +30 -37
- package/dist/main.js +17 -15
- package/dist/mcpDoctor.js +2 -24
- 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 +158 -94
- 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 +114 -122
- package/dist/server/registerEvidenceTools.js +5 -9
- package/dist/server/registerFunctionComparisonTool.js +11 -15
- package/dist/server/registerInvestigationTools.js +41 -57
- 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/registerReplayMachineTool.js +4 -10
- package/dist/server/registerSessionRecordTools.js +69 -40
- package/dist/server/registerSessionStatusTool.js +13 -28
- package/dist/server/registerSessionTools.js +36 -52
- package/dist/server/sessionAvailabilityPolicy.js +2 -1
- package/dist/server/sessionToolPolicies.js +1 -5
- package/dist/server/toolRegistrationOptions.js +4 -192
- package/dist/server/toolResult.js +2 -18
- package/package.json +22 -14
- package/scripts/electron-active-hook-boundaries.cjs +394 -0
- package/scripts/electron-active-hook.cjs +501 -0
- package/scripts/rea.mjs +1 -11
- package/skills/reverse-engineer-anything/SKILL.md +2 -2
- package/dist/server/DynamicToolAvailability.js +0 -70
- package/dist/server/LazyToolCatalog.js +0 -134
- package/dist/server/hydrateServerTools.js +0 -191
- package/dist/server/toolInputValidation.js +0 -77
- package/scripts/package-runner-bootstrap.mjs +0 -72
|
@@ -1,75 +1,27 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { browserScenarioDiffSchema, compareBrowserScenarios, compareBrowserScenariosInputSchema, } from "./browserScenarioDiff.js";
|
|
3
3
|
import { compareWebCaptures, captureSnapshotSchema, webCaptureDiffSchema, } from "./webCaptureDiff.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
.describe("
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.default(2_000)
|
|
26
|
-
.describe("Maximum normalized change records to retain."),
|
|
27
|
-
})
|
|
28
|
-
.superRefine((input, context) => {
|
|
29
|
-
const hasPassive = input.before !== undefined || input.after !== undefined;
|
|
30
|
-
const hasScenario = input.before_scenario !== undefined || input.after_scenario !== undefined;
|
|
31
|
-
if (hasPassive === hasScenario)
|
|
32
|
-
context.addIssue({
|
|
33
|
-
code: "custom",
|
|
34
|
-
message: "Provide exactly one complete pair: before/after or before_scenario/after_scenario",
|
|
35
|
-
});
|
|
36
|
-
if (hasPassive && (input.before === undefined || input.after === undefined))
|
|
37
|
-
context.addIssue({
|
|
38
|
-
code: "custom",
|
|
39
|
-
message: "Passive comparison requires both before and after",
|
|
40
|
-
});
|
|
41
|
-
if (hasScenario &&
|
|
42
|
-
(input.before_scenario === undefined ||
|
|
43
|
-
input.after_scenario === undefined))
|
|
44
|
-
context.addIssue({
|
|
45
|
-
code: "custom",
|
|
46
|
-
message: "Browser scenario comparison requires both before_scenario and after_scenario",
|
|
47
|
-
});
|
|
48
|
-
if (hasPassive && input.normalization.rules.length > 0)
|
|
49
|
-
context.addIssue({
|
|
50
|
-
code: "custom",
|
|
51
|
-
path: ["normalization"],
|
|
52
|
-
message: "Literal normalization rules apply only to browser scenario captures",
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
/** Parsed legacy page snapshots or step-indexed browser scenarios. */
|
|
56
|
-
export const browserCaptureComparisonInputSchema = browserCaptureComparisonWireSchema.transform((input) => {
|
|
57
|
-
if (input.before_scenario !== undefined &&
|
|
58
|
-
input.after_scenario !== undefined)
|
|
59
|
-
return {
|
|
60
|
-
before_scenario: input.before_scenario,
|
|
61
|
-
after_scenario: input.after_scenario,
|
|
62
|
-
normalization: input.normalization,
|
|
63
|
-
max_changes: input.max_changes,
|
|
64
|
-
};
|
|
65
|
-
if (input.before !== undefined && input.after !== undefined)
|
|
66
|
-
return {
|
|
67
|
-
before: input.before,
|
|
68
|
-
after: input.after,
|
|
69
|
-
max_changes: input.max_changes,
|
|
70
|
-
};
|
|
71
|
-
throw new TypeError("Capture comparison pair refinement failed");
|
|
72
|
-
});
|
|
4
|
+
const maxChangesSchema = z
|
|
5
|
+
.number()
|
|
6
|
+
.int()
|
|
7
|
+
.min(1)
|
|
8
|
+
.max(20_000)
|
|
9
|
+
.default(2_000)
|
|
10
|
+
.describe("Maximum normalized change records to retain.");
|
|
11
|
+
/** Top-level MCP shape for exactly one complete passive or scenario pair. */
|
|
12
|
+
export const browserCaptureComparisonInputSchema = z.union([
|
|
13
|
+
z.strictObject({
|
|
14
|
+
before: captureSnapshotSchema.describe("Earlier passive web-page capture."),
|
|
15
|
+
after: captureSnapshotSchema.describe("Later passive web-page capture."),
|
|
16
|
+
max_changes: maxChangesSchema,
|
|
17
|
+
}),
|
|
18
|
+
z.strictObject({
|
|
19
|
+
before_scenario: compareBrowserScenariosInputSchema.shape.before_scenario.describe("Earlier browser scenario capture."),
|
|
20
|
+
after_scenario: compareBrowserScenariosInputSchema.shape.after_scenario.describe("Later browser scenario capture."),
|
|
21
|
+
normalization: compareBrowserScenariosInputSchema.shape.normalization.describe("Exact-literal normalization policy."),
|
|
22
|
+
max_changes: maxChangesSchema,
|
|
23
|
+
}),
|
|
24
|
+
]);
|
|
73
25
|
/** Result from passive page or browser scenario comparison. */
|
|
74
26
|
export const browserCaptureComparisonSchema = z.union([
|
|
75
27
|
browserScenarioDiffSchema,
|
|
@@ -186,9 +186,7 @@ const DEFAULT_BROWSER_INSPECTION_LIMITS = {
|
|
|
186
186
|
max_websocket_shape_bytes: 64 * 1_024,
|
|
187
187
|
max_total_websocket_shape_bytes: 1_024 * 1_024,
|
|
188
188
|
};
|
|
189
|
-
|
|
190
|
-
export const inspectWebPageInputSchema = z
|
|
191
|
-
.object({
|
|
189
|
+
const inspectWebPageInputFacts = {
|
|
192
190
|
...approvedBrowserInput,
|
|
193
191
|
target_id: z.string().trim().min(1).max(256),
|
|
194
192
|
observation_ms: z.number().int().min(0).max(10_000).default(500),
|
|
@@ -199,12 +197,21 @@ export const inspectWebPageInputSchema = z
|
|
|
199
197
|
json_body_schema_approved: z.boolean().default(false),
|
|
200
198
|
include_websocket_shapes: z.boolean().default(false),
|
|
201
199
|
websocket_shape_approved: z.boolean().default(false),
|
|
202
|
-
include_script_sources: z.boolean().default(false),
|
|
203
200
|
include_storage_keys: z.boolean().default(false),
|
|
204
201
|
include_storage_fingerprints: z.boolean().default(false),
|
|
205
202
|
limits: browserInspectionLimitsSchema.default(DEFAULT_BROWSER_INSPECTION_LIMITS),
|
|
206
|
-
}
|
|
207
|
-
|
|
203
|
+
};
|
|
204
|
+
const inspectWebPageWithoutSourceSchema = z.strictObject({
|
|
205
|
+
...inspectWebPageInputFacts,
|
|
206
|
+
include_script_sources: z.literal(false).default(false),
|
|
207
|
+
source_capture_approved: z.literal(false).default(false),
|
|
208
|
+
});
|
|
209
|
+
const inspectWebPageWithSourceShapeSchema = z.strictObject({
|
|
210
|
+
...inspectWebPageInputFacts,
|
|
211
|
+
include_script_sources: z.literal(true).default(true),
|
|
212
|
+
source_capture_approved: z.literal(true),
|
|
213
|
+
});
|
|
214
|
+
const refineInspectWebPageInput = (input, context) => {
|
|
208
215
|
if (input.include_storage_fingerprints && !input.include_storage_keys)
|
|
209
216
|
context.addIssue({
|
|
210
217
|
code: "custom",
|
|
@@ -260,14 +267,20 @@ export const inspectWebPageInputSchema = z
|
|
|
260
267
|
path: ["limits", "max_websocket_shape_bytes"],
|
|
261
268
|
message: "Per-frame WebSocket limit cannot exceed the total frame limit",
|
|
262
269
|
});
|
|
263
|
-
if (input.limits.max_ax_text_field_bytes >
|
|
264
|
-
input.limits.max_total_ax_text_bytes)
|
|
270
|
+
if (input.limits.max_ax_text_field_bytes > input.limits.max_total_ax_text_bytes)
|
|
265
271
|
context.addIssue({
|
|
266
272
|
code: "custom",
|
|
267
273
|
path: ["limits", "max_ax_text_field_bytes"],
|
|
268
274
|
message: "Per-field accessibility text limit cannot exceed the total text limit",
|
|
269
275
|
});
|
|
270
|
-
}
|
|
276
|
+
};
|
|
277
|
+
/** Source-capturing inspection input, reusable by static bundle analysis. */
|
|
278
|
+
export const inspectWebPageWithSourceInputSchema = inspectWebPageWithSourceShapeSchema.superRefine(refineInspectWebPageInput);
|
|
279
|
+
/** Public input for one passive, bounded inspection of an existing page. */
|
|
280
|
+
export const inspectWebPageInputSchema = z.union([
|
|
281
|
+
inspectWebPageWithoutSourceSchema.superRefine(refineInspectWebPageInput),
|
|
282
|
+
inspectWebPageWithSourceInputSchema,
|
|
283
|
+
]);
|
|
271
284
|
export const sanitizedBrowserUrlSchema = z.object({
|
|
272
285
|
url: z.string().max(MAX_SANITIZED_BROWSER_URL_CHARS),
|
|
273
286
|
origin: z.string().max(2_048).nullable(),
|
|
@@ -109,48 +109,46 @@ export function detectArtifactFormat(path) {
|
|
|
109
109
|
return "zipapp";
|
|
110
110
|
return null;
|
|
111
111
|
}
|
|
112
|
+
const STANDARD_LIBRARY_PATH_MARKERS = [
|
|
113
|
+
"/stdlib/",
|
|
114
|
+
"/site-packages/",
|
|
115
|
+
"java/",
|
|
116
|
+
"javax/",
|
|
117
|
+
"sun/",
|
|
118
|
+
];
|
|
119
|
+
const STANDARD_LIBRARY_SYMBOL_MARKERS = ["java.", "javax.", "sun.", "__"];
|
|
120
|
+
const GENERATED_PATH_MARKERS = [
|
|
121
|
+
"/generated/",
|
|
122
|
+
"_generated",
|
|
123
|
+
"/build/",
|
|
124
|
+
"/target/",
|
|
125
|
+
"/dist-packages/",
|
|
126
|
+
"/__pycache__/",
|
|
127
|
+
];
|
|
128
|
+
const GENERATED_SYMBOL_MARKERS = ["Generated", "_generated"];
|
|
129
|
+
const VENDORED_PATH_MARKERS = [
|
|
130
|
+
"/vendor/",
|
|
131
|
+
"/vendored/",
|
|
132
|
+
"/third_party/",
|
|
133
|
+
"/3rdparty/",
|
|
134
|
+
"/node_modules/",
|
|
135
|
+
];
|
|
136
|
+
const BUNDLED_PATH_MARKERS = ["/bundle/", "/bundled/", ".jar!", ".war!"];
|
|
137
|
+
const includesAny = (value, markers) => markers.some((marker) => value.includes(marker));
|
|
138
|
+
const startsWithAny = (value, markers) => markers.some((marker) => value.startsWith(marker));
|
|
112
139
|
/** Classify bytecode symbol provenance. */
|
|
113
140
|
export function classifyProvenance(path, symbolName) {
|
|
114
141
|
const lower = path.toLowerCase();
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
lower.includes("/site-packages/") ||
|
|
118
|
-
lower.includes("java/") ||
|
|
119
|
-
lower.includes("javax/") ||
|
|
120
|
-
lower.includes("sun/") ||
|
|
121
|
-
symbolName.startsWith("java.") ||
|
|
122
|
-
symbolName.startsWith("javax.") ||
|
|
123
|
-
symbolName.startsWith("sun.") ||
|
|
124
|
-
symbolName.startsWith("__")) {
|
|
142
|
+
if (includesAny(lower, STANDARD_LIBRARY_PATH_MARKERS) ||
|
|
143
|
+
startsWithAny(symbolName, STANDARD_LIBRARY_SYMBOL_MARKERS))
|
|
125
144
|
return "standard_library";
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (lower.includes("/generated/") ||
|
|
129
|
-
lower.includes("_generated") ||
|
|
130
|
-
lower.includes("/build/") ||
|
|
131
|
-
lower.includes("/target/") ||
|
|
132
|
-
lower.includes("/dist-packages/") ||
|
|
133
|
-
lower.includes("/__pycache__/") ||
|
|
134
|
-
symbolName.includes("Generated") ||
|
|
135
|
-
symbolName.includes("_generated")) {
|
|
145
|
+
if (includesAny(lower, GENERATED_PATH_MARKERS) ||
|
|
146
|
+
includesAny(symbolName, GENERATED_SYMBOL_MARKERS))
|
|
136
147
|
return "generated";
|
|
137
|
-
|
|
138
|
-
// Vendored code
|
|
139
|
-
if (lower.includes("/vendor/") ||
|
|
140
|
-
lower.includes("/vendored/") ||
|
|
141
|
-
lower.includes("/third_party/") ||
|
|
142
|
-
lower.includes("/3rdparty/") ||
|
|
143
|
-
lower.includes("/node_modules/") ||
|
|
144
|
-
lower.includes("/vendor/")) {
|
|
148
|
+
if (includesAny(lower, VENDORED_PATH_MARKERS))
|
|
145
149
|
return "vendored";
|
|
146
|
-
|
|
147
|
-
// Bundled code
|
|
148
|
-
if (lower.includes("/bundle/") ||
|
|
149
|
-
lower.includes("/bundled/") ||
|
|
150
|
-
lower.includes(".jar!") ||
|
|
151
|
-
lower.includes(".war!")) {
|
|
150
|
+
if (includesAny(lower, BUNDLED_PATH_MARKERS))
|
|
152
151
|
return "bundled";
|
|
153
|
-
}
|
|
154
152
|
return "application";
|
|
155
153
|
}
|
|
156
154
|
/** Analyze a set of bytecode artifacts and produce a summary. */
|
package/dist/domain/callPath.js
CHANGED
|
@@ -178,9 +178,10 @@ const parseSnapshots = (groups) => {
|
|
|
178
178
|
return snapshots;
|
|
179
179
|
};
|
|
180
180
|
const assertCompatible = (snapshots) => {
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
181
|
+
const firstEntry = snapshots.values().next();
|
|
182
|
+
if (firstEntry.done)
|
|
183
183
|
return;
|
|
184
|
+
const first = firstEntry.value;
|
|
184
185
|
for (const snapshot of snapshots.values()) {
|
|
185
186
|
if (snapshot.subject.digest.sha256 !== first.subject.digest.sha256 ||
|
|
186
187
|
snapshot.subject.format !== first.subject.format ||
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { conformancePackageSchema, } from "./conformancePackage.js";
|
|
3
|
-
import { trustGateResultSchema } from "./conformanceTrustGate.js";
|
|
3
|
+
import { evaluatePackageTrustGates, trustGateResultSchema, } from "./conformanceTrustGate.js";
|
|
4
4
|
/** Result of a single scenario replay. */
|
|
5
5
|
export const scenarioReplayResultSchema = z.strictObject({
|
|
6
6
|
scenario_id: z.string().min(1),
|
|
@@ -25,6 +25,7 @@ export const packageReplayResultSchema = z.strictObject({
|
|
|
25
25
|
.strictObject({
|
|
26
26
|
scenario_id: z.string().min(1),
|
|
27
27
|
dimension: z.string().min(1),
|
|
28
|
+
evidence_id: z.string().min(1),
|
|
28
29
|
message: z.string(),
|
|
29
30
|
})
|
|
30
31
|
.nullable(),
|
|
@@ -84,6 +85,7 @@ export async function replayConformancePackage(packageInput, actualEvidence, run
|
|
|
84
85
|
? {
|
|
85
86
|
scenario_id: first_drift_gate.scenario_id,
|
|
86
87
|
dimension: first_drift_gate.first_divergence.dimension,
|
|
88
|
+
evidence_id: first_drift_gate.first_divergence.evidence_id,
|
|
87
89
|
message: first_drift_gate.first_divergence.message,
|
|
88
90
|
}
|
|
89
91
|
: null;
|
|
@@ -100,5 +102,3 @@ export async function replayConformancePackage(packageInput, actualEvidence, run
|
|
|
100
102
|
first_drift,
|
|
101
103
|
};
|
|
102
104
|
}
|
|
103
|
-
/** Import trust gate evaluator for replay. */
|
|
104
|
-
import { evaluatePackageTrustGates } from "./conformanceTrustGate.js";
|
|
@@ -35,11 +35,130 @@ const SEMANTIC_DIMENSIONS = new Set([
|
|
|
35
35
|
"stdout",
|
|
36
36
|
"stderr",
|
|
37
37
|
"filesystem",
|
|
38
|
+
"process",
|
|
38
39
|
"process_tree",
|
|
39
40
|
"shim_events",
|
|
40
41
|
"protocol_events",
|
|
41
42
|
"event_journal",
|
|
42
43
|
]);
|
|
44
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
45
|
+
const uniqueStrings = (values) => [
|
|
46
|
+
...new Set(values.filter((value) => value.length > 0)),
|
|
47
|
+
];
|
|
48
|
+
const stringValues = (value) => {
|
|
49
|
+
if (typeof value === "string")
|
|
50
|
+
return value.length > 0 ? [value] : [];
|
|
51
|
+
if (!Array.isArray(value))
|
|
52
|
+
return [];
|
|
53
|
+
return value.filter((item) => typeof item === "string" && item.length > 0);
|
|
54
|
+
};
|
|
55
|
+
const evidenceIds = (record) => uniqueStrings([
|
|
56
|
+
...stringValues(record["evidence_id"]),
|
|
57
|
+
...stringValues(record["evidence_ids"]),
|
|
58
|
+
...stringValues(record["evidence_links"]),
|
|
59
|
+
]);
|
|
60
|
+
const incompleteStatus = (value) => {
|
|
61
|
+
if (!isRecord(value))
|
|
62
|
+
return null;
|
|
63
|
+
const record = value;
|
|
64
|
+
if (record["truncated"] === true)
|
|
65
|
+
return "truncated";
|
|
66
|
+
const status = record["status"];
|
|
67
|
+
if (status === "truncated")
|
|
68
|
+
return "truncated";
|
|
69
|
+
if (status === "unknown" ||
|
|
70
|
+
status === "unavailable" ||
|
|
71
|
+
status === "partial" ||
|
|
72
|
+
status === "incomplete" ||
|
|
73
|
+
status === "unverifiable" ||
|
|
74
|
+
status === "failed" ||
|
|
75
|
+
status === "not_approved")
|
|
76
|
+
return "unknown";
|
|
77
|
+
for (const key of ["coverage", "completeness"]) {
|
|
78
|
+
const nested = record[key];
|
|
79
|
+
if (!isRecord(nested))
|
|
80
|
+
continue;
|
|
81
|
+
const nestedStatus = incompleteStatus(nested);
|
|
82
|
+
if (nestedStatus !== null)
|
|
83
|
+
return nestedStatus;
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
};
|
|
87
|
+
const hasResidualUnknowns = (value) => isRecord(value) &&
|
|
88
|
+
Array.isArray(value["residual_unknowns"]) &&
|
|
89
|
+
value["residual_unknowns"].length > 0;
|
|
90
|
+
const unknownScopes = (record) => {
|
|
91
|
+
const residualUnknowns = record["residual_unknowns"];
|
|
92
|
+
if (!Array.isArray(residualUnknowns))
|
|
93
|
+
return [];
|
|
94
|
+
return residualUnknowns.flatMap((item) => {
|
|
95
|
+
if (!isRecord(item) || typeof item["scope"] !== "string")
|
|
96
|
+
return [];
|
|
97
|
+
return [item["scope"]];
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
const evidenceView = (input) => {
|
|
101
|
+
if (!isRecord(input))
|
|
102
|
+
return {
|
|
103
|
+
values: {},
|
|
104
|
+
evidence_ids: [],
|
|
105
|
+
status: null,
|
|
106
|
+
unknown_scopes: [],
|
|
107
|
+
};
|
|
108
|
+
const normalized = input["normalized_result"];
|
|
109
|
+
const values = isRecord(normalized) ? normalized : input;
|
|
110
|
+
const normalizedStatus = isRecord(normalized)
|
|
111
|
+
? incompleteStatus(normalized)
|
|
112
|
+
: null;
|
|
113
|
+
return {
|
|
114
|
+
values,
|
|
115
|
+
evidence_ids: evidenceIds(input),
|
|
116
|
+
status: incompleteStatus(input) ?? normalizedStatus,
|
|
117
|
+
unknown_scopes: uniqueStrings([
|
|
118
|
+
...unknownScopes(input),
|
|
119
|
+
...(isRecord(normalized) ? unknownScopes(normalized) : []),
|
|
120
|
+
]),
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
const dimensionScope = (dimensionName) => {
|
|
124
|
+
if (dimensionName === "exit_code" || dimensionName === "exit")
|
|
125
|
+
return "exit";
|
|
126
|
+
if (dimensionName === "process" ||
|
|
127
|
+
dimensionName === "process_tree" ||
|
|
128
|
+
dimensionName === "event_journal")
|
|
129
|
+
return "process";
|
|
130
|
+
if (dimensionName === "stdout" || dimensionName === "stderr")
|
|
131
|
+
return "terminal";
|
|
132
|
+
if (dimensionName === "filesystem")
|
|
133
|
+
return "filesystem";
|
|
134
|
+
if (dimensionName === "shim_events")
|
|
135
|
+
return "shim";
|
|
136
|
+
if (dimensionName === "protocol_events")
|
|
137
|
+
return "protocol";
|
|
138
|
+
return null;
|
|
139
|
+
};
|
|
140
|
+
const statusForDimension = (view, dimensionName) => {
|
|
141
|
+
const valueStatus = incompleteStatus(view.values[dimensionName]);
|
|
142
|
+
if (valueStatus !== null)
|
|
143
|
+
return valueStatus;
|
|
144
|
+
if (hasResidualUnknowns(view.values[dimensionName]))
|
|
145
|
+
return "unknown";
|
|
146
|
+
const scope = dimensionScope(dimensionName);
|
|
147
|
+
return scope !== null && view.unknown_scopes.includes(scope)
|
|
148
|
+
? "unknown"
|
|
149
|
+
: view.status;
|
|
150
|
+
};
|
|
151
|
+
const comparisonIncompleteStatus = (expected, actual, options) => {
|
|
152
|
+
const expectedStatus = options.expected_status ?? incompleteStatus(expected);
|
|
153
|
+
const actualStatus = options.actual_status ?? incompleteStatus(actual);
|
|
154
|
+
if (options.truncated)
|
|
155
|
+
return "truncated";
|
|
156
|
+
if (expectedStatus === "truncated" || actualStatus === "truncated")
|
|
157
|
+
return "truncated";
|
|
158
|
+
if (expectedStatus === "unknown" || actualStatus === "unknown")
|
|
159
|
+
return "unknown";
|
|
160
|
+
return null;
|
|
161
|
+
};
|
|
43
162
|
/** Check if a dimension name is volatile (timing/normalization noise). */
|
|
44
163
|
export function isVolatileDimension(name) {
|
|
45
164
|
return VOLATILE_DIMENSIONS.has(name);
|
|
@@ -63,15 +182,19 @@ export function compareDimension(dimensionName, expected, actual, options = {})
|
|
|
63
182
|
name: dimensionName,
|
|
64
183
|
status: "match",
|
|
65
184
|
message: "volatile dimension ignored",
|
|
66
|
-
evidence_ids: [],
|
|
185
|
+
evidence_ids: uniqueStrings(options.evidence_ids ?? []),
|
|
67
186
|
};
|
|
68
187
|
}
|
|
69
|
-
|
|
188
|
+
const status = comparisonIncompleteStatus(expected, actual, options);
|
|
189
|
+
const resultEvidenceIds = uniqueStrings(options.evidence_ids ?? []);
|
|
190
|
+
if (status !== null) {
|
|
70
191
|
return {
|
|
71
192
|
name: dimensionName,
|
|
72
|
-
status
|
|
73
|
-
message:
|
|
74
|
-
|
|
193
|
+
status,
|
|
194
|
+
message: status === "truncated"
|
|
195
|
+
? "evidence was truncated"
|
|
196
|
+
: "evidence completeness is unknown",
|
|
197
|
+
evidence_ids: resultEvidenceIds,
|
|
75
198
|
};
|
|
76
199
|
}
|
|
77
200
|
if (expected === undefined && actual === undefined) {
|
|
@@ -79,15 +202,15 @@ export function compareDimension(dimensionName, expected, actual, options = {})
|
|
|
79
202
|
name: dimensionName,
|
|
80
203
|
status: "unknown",
|
|
81
204
|
message: "both expected and actual are undefined",
|
|
82
|
-
evidence_ids:
|
|
205
|
+
evidence_ids: resultEvidenceIds,
|
|
83
206
|
};
|
|
84
207
|
}
|
|
85
208
|
if (expected === undefined || actual === undefined) {
|
|
86
209
|
return {
|
|
87
210
|
name: dimensionName,
|
|
88
|
-
status: "
|
|
89
|
-
message:
|
|
90
|
-
evidence_ids:
|
|
211
|
+
status: "unknown",
|
|
212
|
+
message: "one side has no observed value",
|
|
213
|
+
evidence_ids: resultEvidenceIds,
|
|
91
214
|
};
|
|
92
215
|
}
|
|
93
216
|
// Semantic comparison for structured objects
|
|
@@ -99,14 +222,14 @@ export function compareDimension(dimensionName, expected, actual, options = {})
|
|
|
99
222
|
name: dimensionName,
|
|
100
223
|
status: "match",
|
|
101
224
|
message: "",
|
|
102
|
-
evidence_ids:
|
|
225
|
+
evidence_ids: resultEvidenceIds,
|
|
103
226
|
};
|
|
104
227
|
}
|
|
105
228
|
return {
|
|
106
229
|
name: dimensionName,
|
|
107
230
|
status: "mismatch",
|
|
108
231
|
message: "semantic content differs",
|
|
109
|
-
evidence_ids:
|
|
232
|
+
evidence_ids: resultEvidenceIds,
|
|
110
233
|
};
|
|
111
234
|
}
|
|
112
235
|
// Primitive comparison
|
|
@@ -115,14 +238,14 @@ export function compareDimension(dimensionName, expected, actual, options = {})
|
|
|
115
238
|
name: dimensionName,
|
|
116
239
|
status: "match",
|
|
117
240
|
message: "",
|
|
118
|
-
evidence_ids:
|
|
241
|
+
evidence_ids: resultEvidenceIds,
|
|
119
242
|
};
|
|
120
243
|
}
|
|
121
244
|
return {
|
|
122
245
|
name: dimensionName,
|
|
123
246
|
status: "mismatch",
|
|
124
247
|
message: `expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`,
|
|
125
|
-
evidence_ids:
|
|
248
|
+
evidence_ids: resultEvidenceIds,
|
|
126
249
|
};
|
|
127
250
|
}
|
|
128
251
|
/** Recursively sort object keys for deterministic comparison. */
|
|
@@ -131,6 +254,8 @@ function sortKeys(value) {
|
|
|
131
254
|
return value;
|
|
132
255
|
if (Array.isArray(value))
|
|
133
256
|
return value.map(sortKeys);
|
|
257
|
+
if (!isRecord(value))
|
|
258
|
+
return value;
|
|
134
259
|
const sorted = {};
|
|
135
260
|
for (const key of Object.keys(value).sort()) {
|
|
136
261
|
sorted[key] = sortKeys(value[key]);
|
|
@@ -144,12 +269,22 @@ function sortKeys(value) {
|
|
|
144
269
|
export function evaluateTrustGate(contract, expectedEvidence, actualEvidence, options = {}) {
|
|
145
270
|
const dimensionResults = [];
|
|
146
271
|
let firstDivergence = null;
|
|
272
|
+
const expectedView = evidenceView(expectedEvidence);
|
|
273
|
+
const actualView = evidenceView(actualEvidence);
|
|
147
274
|
for (const dim of contract.dimensions) {
|
|
148
275
|
if (!dim.required)
|
|
149
276
|
continue;
|
|
150
|
-
const expectedValue =
|
|
151
|
-
const actualValue =
|
|
152
|
-
const result = compareDimension(dim.name, expectedValue, actualValue,
|
|
277
|
+
const expectedValue = expectedView.values[dim.name];
|
|
278
|
+
const actualValue = actualView.values[dim.name];
|
|
279
|
+
const result = compareDimension(dim.name, expectedValue, actualValue, {
|
|
280
|
+
...options,
|
|
281
|
+
expected_status: statusForDimension(expectedView, dim.name),
|
|
282
|
+
actual_status: statusForDimension(actualView, dim.name),
|
|
283
|
+
evidence_ids: uniqueStrings([
|
|
284
|
+
...actualView.evidence_ids,
|
|
285
|
+
...expectedView.evidence_ids,
|
|
286
|
+
]),
|
|
287
|
+
});
|
|
153
288
|
dimensionResults.push(result);
|
|
154
289
|
if (result.status === "mismatch" && firstDivergence === null) {
|
|
155
290
|
firstDivergence = {
|
|
@@ -129,9 +129,9 @@ export function failedAuthEvents(events) {
|
|
|
129
129
|
}
|
|
130
130
|
/** Compute the duration of an authentication flow in milliseconds. */
|
|
131
131
|
export function authFlowDuration(events) {
|
|
132
|
-
|
|
132
|
+
const first = events.at(0);
|
|
133
|
+
const last = events.at(-1);
|
|
134
|
+
if (first === undefined || last === undefined)
|
|
133
135
|
return null;
|
|
134
|
-
const first = events[0];
|
|
135
|
-
const last = events[events.length - 1];
|
|
136
136
|
return last.at_ms - first.at_ms;
|
|
137
137
|
}
|