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
|
@@ -3,7 +3,7 @@ import { AnalysisError, BrowserObservationError, ProviderAdapterError, } from ".
|
|
|
3
3
|
import { err, ok } from "../domain/result.js";
|
|
4
4
|
import { boundedText, numberValue, recordValue, stringValue, delayWithCancellation, } from "./CdpCaptureValues.js";
|
|
5
5
|
import { CdpConnection } from "./CdpConnection.js";
|
|
6
|
-
import {
|
|
6
|
+
import { authorizeRuntimeTargetLocation, canonicalRuntimeRoots, } from "./JavaScriptRuntimeScope.js";
|
|
7
7
|
import { createInspectorExclusionCounts, describeInspectorTargetLimitations, finalizeInspectorCapture, } from "./V8InspectorCaptureProjection.js";
|
|
8
8
|
import { discoverV8Inspector, } from "./V8InspectorEndpoint.js";
|
|
9
9
|
/** Public identity committed by passive V8 Inspector observations. */
|
|
@@ -24,7 +24,7 @@ export class V8InspectorProvider {
|
|
|
24
24
|
const allowed = [];
|
|
25
25
|
const excluded = createInspectorExclusionCounts();
|
|
26
26
|
for (const target of discovery.targets) {
|
|
27
|
-
const decision = await
|
|
27
|
+
const decision = await authorizeRuntimeTargetLocation(target.url, target.type, roots, input.allowed_origins);
|
|
28
28
|
if (!decision.allowed) {
|
|
29
29
|
excluded[decision.reason] += 1;
|
|
30
30
|
continue;
|
|
@@ -104,7 +104,7 @@ const authorizedTarget = async (targets, input, roots) => {
|
|
|
104
104
|
const target = targets.find(({ id }) => id === input.target_id);
|
|
105
105
|
if (target === undefined)
|
|
106
106
|
throw new BrowserObservationError("observe_javascript_runtime", "target_not_found");
|
|
107
|
-
const decision = await
|
|
107
|
+
const decision = await authorizeRuntimeTargetLocation(target.url, target.type, roots, input.allowed_origins);
|
|
108
108
|
if (target.attached ||
|
|
109
109
|
!decision.allowed ||
|
|
110
110
|
decision.location.kind === "builtin")
|
package/dist/catalogIdentity.js
CHANGED
|
@@ -12,12 +12,18 @@ const toolCatalog = TOOL_CONTRACTS.map((contract) => ({
|
|
|
12
12
|
description: contract.description,
|
|
13
13
|
effects: { ...contract.effects },
|
|
14
14
|
annotations: contract.annotations,
|
|
15
|
-
input_schema:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
15
|
+
input_schema: {
|
|
16
|
+
type: "object",
|
|
17
|
+
...z.toJSONSchema(contract.inputSchema, {
|
|
18
|
+
unrepresentable: "any",
|
|
19
|
+
}),
|
|
20
|
+
},
|
|
21
|
+
output_schema: {
|
|
22
|
+
type: "object",
|
|
23
|
+
...z.toJSONSchema(contract.outputSchema, {
|
|
24
|
+
unrepresentable: "any",
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
21
27
|
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
22
28
|
const promptCatalog = PROMPT_CONTRACTS.map((contract) => ({
|
|
23
29
|
name: contract.name,
|
|
@@ -29,7 +35,7 @@ const promptCatalog = PROMPT_CONTRACTS.map((contract) => ({
|
|
|
29
35
|
/** Canonical fixed resources exposed by every target-free MCP session. */
|
|
30
36
|
export const MCP_RESOURCE_CATALOG = [
|
|
31
37
|
{ name: "server-identity", uri: "rea://server/identity" },
|
|
32
|
-
{ name: "
|
|
38
|
+
{ name: "analysis-snapshot", uri: "rea://snapshot/current" },
|
|
33
39
|
];
|
|
34
40
|
/** Canonical resource templates exposed by every target-free MCP session. */
|
|
35
41
|
export const MCP_RESOURCE_TEMPLATE_CATALOG = [
|
|
@@ -40,8 +46,8 @@ export const MCP_RESOURCE_TEMPLATE_CATALOG = [
|
|
|
40
46
|
},
|
|
41
47
|
{ name: "residual-unknown", uri_template: "rea://unknown/{unknownId}" },
|
|
42
48
|
{
|
|
43
|
-
name: "
|
|
44
|
-
uri_template: "rea://
|
|
49
|
+
name: "evidence-bundle",
|
|
50
|
+
uri_template: "rea://evidence-bundle/{bundleDigest}",
|
|
45
51
|
},
|
|
46
52
|
{
|
|
47
53
|
name: "artifact-page",
|
|
@@ -73,17 +73,19 @@ const registerExtractionCommand = (cli, logger) => {
|
|
|
73
73
|
args: z.object({
|
|
74
74
|
path: z.string().describe("Application or package path"),
|
|
75
75
|
outputRoot: z.string().describe("Absent absolute output root"),
|
|
76
|
+
}),
|
|
77
|
+
options: z.object({
|
|
76
78
|
occurrenceIds: z
|
|
77
79
|
.array(z.string().regex(/^occ_[a-f0-9]{64}$/u))
|
|
78
80
|
.min(1)
|
|
79
81
|
.max(500)
|
|
80
82
|
.describe("Exact artifact occurrence IDs selected for extraction"),
|
|
81
83
|
}),
|
|
82
|
-
alias: {
|
|
83
|
-
run: ({ args }) => logCliCommand(logger, "extract-artifact", () => runProviderAnalysis(args.path, "extract_artifact", {
|
|
84
|
+
alias: { occurrenceIds: "occurrence-ids" },
|
|
85
|
+
run: ({ args, options }) => logCliCommand(logger, "extract-artifact", () => runProviderAnalysis(args.path, "extract_artifact", {
|
|
84
86
|
approved: true,
|
|
85
87
|
output_root: args.outputRoot,
|
|
86
|
-
occurrence_ids:
|
|
88
|
+
occurrence_ids: options.occurrenceIds,
|
|
87
89
|
}, logger)),
|
|
88
90
|
});
|
|
89
91
|
};
|
|
@@ -9,6 +9,7 @@ import { runCliJavaScriptApplicationAnalysis } from "./javascriptApplicationAnal
|
|
|
9
9
|
export const registerCoreAnalysisCommands = (cli, logger) => {
|
|
10
10
|
registerCoreCommands(cli, logger);
|
|
11
11
|
registerFunctionCommand(cli, logger);
|
|
12
|
+
registerNativeApiCommand(cli, logger);
|
|
12
13
|
registerInstructionsCommand(cli, logger);
|
|
13
14
|
registerSearchCommand(cli, logger);
|
|
14
15
|
registerXrefsCommand(cli, logger);
|
|
@@ -213,6 +214,46 @@ const registerFunctionCommand = (cli, logger) => {
|
|
|
213
214
|
}, directAnalysisOptions(logger, options.snapshot, options.provider))),
|
|
214
215
|
});
|
|
215
216
|
};
|
|
217
|
+
const registerNativeApiCommand = (cli, logger) => {
|
|
218
|
+
cli.command(CLI_COMMANDS.inspectNativeApi, {
|
|
219
|
+
description: "Reconstruct one native function API boundary with evidence",
|
|
220
|
+
args: z.object({
|
|
221
|
+
path: z.string().describe("App or program path"),
|
|
222
|
+
address: z.string().describe("Procedure name or address"),
|
|
223
|
+
}),
|
|
224
|
+
options: z.object({
|
|
225
|
+
maxPseudocodeChars: z
|
|
226
|
+
.number()
|
|
227
|
+
.int()
|
|
228
|
+
.min(1)
|
|
229
|
+
.max(100_000)
|
|
230
|
+
.default(20_000)
|
|
231
|
+
.describe("Maximum pseudocode characters to inspect"),
|
|
232
|
+
maxInstructions: z
|
|
233
|
+
.number()
|
|
234
|
+
.int()
|
|
235
|
+
.min(1)
|
|
236
|
+
.max(5_000)
|
|
237
|
+
.default(500)
|
|
238
|
+
.describe("Maximum assembly instructions to inspect"),
|
|
239
|
+
snapshot: z
|
|
240
|
+
.string()
|
|
241
|
+
.min(1)
|
|
242
|
+
.optional()
|
|
243
|
+
.describe("Load and update a local analysis snapshot"),
|
|
244
|
+
provider: providerSelectionOption,
|
|
245
|
+
}),
|
|
246
|
+
alias: {
|
|
247
|
+
maxPseudocodeChars: "max-pseudocode-chars",
|
|
248
|
+
maxInstructions: "max-instructions",
|
|
249
|
+
},
|
|
250
|
+
run: ({ args, options }) => logCliCommand(logger, "inspect-native-api", () => runDirectAnalysis(args.path, "inspect_native_api", {
|
|
251
|
+
procedure: args.address,
|
|
252
|
+
max_pseudocode_chars: options.maxPseudocodeChars,
|
|
253
|
+
max_instructions: options.maxInstructions,
|
|
254
|
+
}, directAnalysisOptions(logger, options.snapshot, options.provider))),
|
|
255
|
+
});
|
|
256
|
+
};
|
|
216
257
|
const registerInstructionsCommand = (cli, logger) => {
|
|
217
258
|
cli.command(CLI_COMMANDS.instructions, {
|
|
218
259
|
description: "Read one bounded raw-instruction window without decompiling",
|
|
@@ -388,7 +388,7 @@ const registerPlanManagedRuntimeCorrelation = (cli, logger) => {
|
|
|
388
388
|
if (!authority.ok)
|
|
389
389
|
return projectAnalysisError(authority.error);
|
|
390
390
|
const result = await planManagedRuntimeCorrelationEvidence({
|
|
391
|
-
policy: config.value.managedRuntimePolicy,
|
|
391
|
+
policy: () => config.value.managedRuntimePolicy,
|
|
392
392
|
authority: authority.value,
|
|
393
393
|
}, input.value);
|
|
394
394
|
return result.ok ? result.value : projectAnalysisError(result.error);
|
|
@@ -75,7 +75,7 @@ export const registerApplicationCommands = (cli, logger) => {
|
|
|
75
75
|
if (!authority.ok)
|
|
76
76
|
return projectAnalysisError(authority.error);
|
|
77
77
|
const result = await runControlledReplay({
|
|
78
|
-
policy: config.value.javascriptReplayPolicy,
|
|
78
|
+
policy: () => config.value.javascriptReplayPolicy,
|
|
79
79
|
host: new SystemJavaScriptReplayHost(),
|
|
80
80
|
runner: new LinuxJavaScriptReplayRunner(),
|
|
81
81
|
authority: authority.value,
|
|
@@ -193,7 +193,7 @@ const configuredAuthority = async () => {
|
|
|
193
193
|
: { ok: false, error: projectAnalysisError(configured.error) };
|
|
194
194
|
};
|
|
195
195
|
const replayDependencies = (config, authority) => ({
|
|
196
|
-
policy: config.javascriptReplayPolicy,
|
|
196
|
+
policy: () => config.javascriptReplayPolicy,
|
|
197
197
|
host: new SystemJavaScriptReplayHost(),
|
|
198
198
|
runner: new LinuxJavaScriptReplayRunner(),
|
|
199
199
|
authority,
|
|
@@ -4,7 +4,7 @@ import { loadConfiguredPermissionAuthority } from "./application/PermissionConfi
|
|
|
4
4
|
import { CdpBrowserProvider } from "./browser/CdpBrowserProvider.js";
|
|
5
5
|
import { logCliCommand } from "./cliLogging.js";
|
|
6
6
|
import { parseConfig } from "./config.js";
|
|
7
|
-
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
7
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, projectAnalysisError, } from "./domain/errors.js";
|
|
8
8
|
import { browserCaptureComparisonInputSchema } from "./domain/browserCaptureComparison.js";
|
|
9
9
|
import { discoverWebMcpToolsInputSchema } from "./domain/webMcpDiscovery.js";
|
|
10
10
|
import { captureWebScreenshotInputSchema, compareWebScreenshotsInputSchema, } from "./domain/webScreenshot.js";
|
|
@@ -69,7 +69,7 @@ const registerWebMcp = (cli, logger) => {
|
|
|
69
69
|
.describe("Maximum nesting depth in one declared tool schema"),
|
|
70
70
|
}),
|
|
71
71
|
run: ({ args, options }) => logCliCommand(logger, "discover-webmcp-tools", async () => {
|
|
72
|
-
const context = await browserContext();
|
|
72
|
+
const context = await browserContext("discover_webmcp_tools");
|
|
73
73
|
if (!context.ok)
|
|
74
74
|
return context.error;
|
|
75
75
|
const parsed = discoverWebMcpToolsInputSchema.safeParse({
|
|
@@ -155,7 +155,7 @@ const registerScreenshot = (cli, logger) => {
|
|
|
155
155
|
.describe("Maximum captured PNG size"),
|
|
156
156
|
}),
|
|
157
157
|
run: ({ args, options }) => logCliCommand(logger, "capture-web-screenshot", async () => {
|
|
158
|
-
const context = await browserContext();
|
|
158
|
+
const context = await browserContext("capture_web_screenshot");
|
|
159
159
|
if (!context.ok)
|
|
160
160
|
return context.error;
|
|
161
161
|
const parsed = captureWebScreenshotInputSchema.safeParse({
|
|
@@ -210,10 +210,16 @@ const registerScreenshotDiff = (cli, logger) => {
|
|
|
210
210
|
}),
|
|
211
211
|
});
|
|
212
212
|
};
|
|
213
|
-
const browserContext = async () => {
|
|
213
|
+
const browserContext = async (operation) => {
|
|
214
214
|
const config = parseConfig(process.env);
|
|
215
215
|
if (!config.ok)
|
|
216
216
|
return { ok: false, error: cliError(config.error) };
|
|
217
|
+
const policy = config.value.browserObservationPolicy;
|
|
218
|
+
if (policy.status === "disabled")
|
|
219
|
+
return {
|
|
220
|
+
ok: false,
|
|
221
|
+
error: cliError(new AnalysisCapabilityUnavailableError("rea-cdp-browser", operation, "browser observation is disabled; configure exact endpoints and origins before enabling it")),
|
|
222
|
+
};
|
|
217
223
|
const authority = await loadConfiguredPermissionAuthority(config.value);
|
|
218
224
|
if (!authority.ok)
|
|
219
225
|
return { ok: false, error: cliError(authority.error) };
|
|
@@ -221,7 +227,7 @@ const browserContext = async () => {
|
|
|
221
227
|
ok: true,
|
|
222
228
|
authority: authority.value,
|
|
223
229
|
provider: new CdpBrowserProvider(),
|
|
224
|
-
allowedBrowserOrigins:
|
|
230
|
+
allowedBrowserOrigins: policy.allowedOrigins,
|
|
225
231
|
};
|
|
226
232
|
};
|
|
227
233
|
const parseJson = (value) => {
|
|
@@ -7,7 +7,7 @@ import { parseConfig } from "./config.js";
|
|
|
7
7
|
import { inspectWebPageInputSchema, listBrowserTargetsInputSchema, } from "./domain/browserObservation.js";
|
|
8
8
|
import { analyzeWebBundleInputSchema } from "./domain/webBundleAnalysis.js";
|
|
9
9
|
import { observeWebSessionInputSchema } from "./domain/browserSession.js";
|
|
10
|
-
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
10
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, projectAnalysisError, } from "./domain/errors.js";
|
|
11
11
|
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
12
12
|
import { browserPageInspectionOptions } from "./cliObservationOptions.js";
|
|
13
13
|
const browserScopeOptions = {
|
|
@@ -49,7 +49,7 @@ const registerTargetList = (cli, logger) => {
|
|
|
49
49
|
limit: boundedCount("browser targets to return", 200, 100),
|
|
50
50
|
}),
|
|
51
51
|
run: ({ args, options }) => logCliCommand(logger, "list-browser-targets", async () => {
|
|
52
|
-
const context = await browserContext();
|
|
52
|
+
const context = await browserContext("list_browser_targets");
|
|
53
53
|
if (!context.ok)
|
|
54
54
|
return context.error;
|
|
55
55
|
const parsed = listBrowserTargetsInputSchema.safeParse({
|
|
@@ -75,7 +75,7 @@ const registerPageInspection = (cli, logger) => {
|
|
|
75
75
|
}),
|
|
76
76
|
options: browserPageInspectionOptions,
|
|
77
77
|
run: ({ args, options }) => logCliCommand(logger, "inspect-web-page", async () => {
|
|
78
|
-
const context = await browserContext();
|
|
78
|
+
const context = await browserContext("inspect_web_page");
|
|
79
79
|
if (!context.ok)
|
|
80
80
|
return context.error;
|
|
81
81
|
const parsed = inspectWebPageInputSchema.safeParse({
|
|
@@ -92,6 +92,7 @@ const registerPageInspection = (cli, logger) => {
|
|
|
92
92
|
include_websocket_shapes: options.includeWebsocketShapes,
|
|
93
93
|
websocket_shape_approved: options.websocketShapeApproved,
|
|
94
94
|
include_script_sources: options.includeScriptSources,
|
|
95
|
+
source_capture_approved: options.sourceCaptureApproved,
|
|
95
96
|
include_storage_keys: options.includeStorageKeys,
|
|
96
97
|
include_storage_fingerprints: options.includeStorageFingerprints,
|
|
97
98
|
limits: {
|
|
@@ -157,7 +158,7 @@ const registerBundleAnalysis = (cli, logger) => {
|
|
|
157
158
|
maxOriginalSources: boundedCount("original source files", 20_000, 2_000),
|
|
158
159
|
}),
|
|
159
160
|
run: ({ args, options }) => logCliCommand(logger, "analyze-web-bundle", async () => {
|
|
160
|
-
const context = await browserContext();
|
|
161
|
+
const context = await browserContext("analyze_web_bundle");
|
|
161
162
|
if (!context.ok)
|
|
162
163
|
return context.error;
|
|
163
164
|
const parsed = analyzeWebBundleInputSchema.safeParse({
|
|
@@ -200,7 +201,7 @@ const registerObservationSession = (cli, logger) => {
|
|
|
200
201
|
maxTimelineEvents: boundedCount("timeline events", 20_000, 2_000),
|
|
201
202
|
}),
|
|
202
203
|
run: ({ args, options }) => logCliCommand(logger, "observe-web-session", async () => {
|
|
203
|
-
const context = await browserContext();
|
|
204
|
+
const context = await browserContext("observe_web_session");
|
|
204
205
|
if (!context.ok)
|
|
205
206
|
return context.error;
|
|
206
207
|
const parsed = observeWebSessionInputSchema.safeParse({
|
|
@@ -218,10 +219,16 @@ const registerObservationSession = (cli, logger) => {
|
|
|
218
219
|
}),
|
|
219
220
|
});
|
|
220
221
|
};
|
|
221
|
-
const browserContext = async () => {
|
|
222
|
+
const browserContext = async (operation) => {
|
|
222
223
|
const config = parseConfig(process.env);
|
|
223
224
|
if (!config.ok)
|
|
224
225
|
return { ok: false, error: cliError(config.error) };
|
|
226
|
+
const policy = config.value.browserObservationPolicy;
|
|
227
|
+
if (policy.status === "disabled")
|
|
228
|
+
return {
|
|
229
|
+
ok: false,
|
|
230
|
+
error: cliError(new AnalysisCapabilityUnavailableError("rea-cdp-browser", operation, "browser observation is disabled; configure exact endpoints and origins before enabling it")),
|
|
231
|
+
};
|
|
225
232
|
const authority = await loadConfiguredPermissionAuthority(config.value);
|
|
226
233
|
if (!authority.ok)
|
|
227
234
|
return { ok: false, error: cliError(authority.error) };
|
|
@@ -229,7 +236,7 @@ const browserContext = async () => {
|
|
|
229
236
|
ok: true,
|
|
230
237
|
authority: authority.value,
|
|
231
238
|
provider: new CdpBrowserProvider(),
|
|
232
|
-
allowedBrowserOrigins:
|
|
239
|
+
allowedBrowserOrigins: policy.allowedOrigins,
|
|
233
240
|
};
|
|
234
241
|
};
|
|
235
242
|
const cliError = (error) => ({
|
package/dist/cliCommandNames.js
CHANGED
|
@@ -12,6 +12,7 @@ export const CLI_COMMANDS = Object.freeze({
|
|
|
12
12
|
capabilities: "capabilities",
|
|
13
13
|
providers: "providers",
|
|
14
14
|
function: "function",
|
|
15
|
+
inspectNativeApi: "inspect-native-api",
|
|
15
16
|
instructions: "instructions",
|
|
16
17
|
search: "search",
|
|
17
18
|
importReferenceSource: "import-reference-source",
|
|
@@ -49,6 +50,7 @@ export const CLI_COMMANDS = Object.freeze({
|
|
|
49
50
|
captureBrowserScenario: "capture-browser-scenario",
|
|
50
51
|
listElectronTargets: "list-electron-targets",
|
|
51
52
|
inspectElectronPage: "inspect-electron-page",
|
|
53
|
+
captureElectronScenario: "capture-electron-scenario",
|
|
52
54
|
listJavaScriptRuntimeTargets: "list-javascript-runtime-targets",
|
|
53
55
|
observeJavaScriptRuntime: "observe-javascript-runtime",
|
|
54
56
|
analyzeJavaScriptApplication: "analyze-javascript-application",
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { Cli, z } from "incur";
|
|
2
2
|
import { inspectElectronPage, listElectronTargets, } from "./application/ElectronObservationService.js";
|
|
3
|
+
import { captureElectronScenario } from "./application/ElectronActiveObservationService.js";
|
|
3
4
|
import { reconcileJavaScriptRuntimeEvidence } from "./application/JavaScriptRuntimeReconciliationService.js";
|
|
4
5
|
import { loadConfiguredPermissionAuthority } from "./application/PermissionConfiguration.js";
|
|
5
6
|
import { CdpElectronProvider } from "./browser/CdpElectronProvider.js";
|
|
7
|
+
import { PlaywrightElectronActiveProvider } from "./browser/PlaywrightElectronActiveProvider.js";
|
|
6
8
|
import { logCliCommand } from "./cliLogging.js";
|
|
7
9
|
import { parseConfig } from "./config.js";
|
|
8
10
|
import { inspectElectronPageInputSchema, listElectronTargetsInputSchema, } from "./domain/electronObservation.js";
|
|
9
|
-
import {
|
|
11
|
+
import { electronActiveObservationInputSchema } from "./domain/electronActiveObservation.js";
|
|
12
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, projectAnalysisError, } from "./domain/errors.js";
|
|
10
13
|
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
11
14
|
import { parseCliJsonInput } from "./cliJsonInput.js";
|
|
12
15
|
import { electronPageInspectionOptions, javascriptApplicationOptions, } from "./cliObservationOptions.js";
|
|
@@ -21,9 +24,33 @@ const scopeOptions = {
|
|
|
21
24
|
/** Register CLI equivalents of the Electron MCP tools. */
|
|
22
25
|
export const registerElectronCommands = (cli, logger) => {
|
|
23
26
|
registerElectronObservationCommands(cli, logger);
|
|
27
|
+
registerElectronActiveCommand(cli, logger);
|
|
24
28
|
registerJavaScriptApplicationCommand(cli, logger);
|
|
25
29
|
registerJavaScriptRuntimeReconciliationCommand(cli, logger);
|
|
26
30
|
};
|
|
31
|
+
const registerElectronActiveCommand = (cli, logger) => {
|
|
32
|
+
cli.command(CLI_COMMANDS.captureElectronScenario, {
|
|
33
|
+
description: "Run one approved, bounded owned Electron scenario",
|
|
34
|
+
args: z.object({
|
|
35
|
+
inputJson: z
|
|
36
|
+
.string()
|
|
37
|
+
.describe("Inline JSON or a JSON file matching capture_electron_scenario"),
|
|
38
|
+
}),
|
|
39
|
+
run: ({ args }) => logCliCommand(logger, CLI_COMMANDS.captureElectronScenario, async () => {
|
|
40
|
+
const input = await parseCliJsonInput(args.inputJson, "capture_electron_scenario");
|
|
41
|
+
if (!input.ok)
|
|
42
|
+
return input.error;
|
|
43
|
+
const parsed = electronActiveObservationInputSchema.safeParse(input.value);
|
|
44
|
+
if (!parsed.success)
|
|
45
|
+
return inputError("capture_electron_scenario");
|
|
46
|
+
const context = await electronContext();
|
|
47
|
+
if (!context.ok)
|
|
48
|
+
return context.error;
|
|
49
|
+
const result = await captureElectronScenario(context.activeProvider, context.authority, parsed.data);
|
|
50
|
+
return result.ok ? result.value : cliError(result.error);
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
};
|
|
27
54
|
const registerJavaScriptRuntimeReconciliationCommand = (cli, logger) => {
|
|
28
55
|
cli.command(CLI_COMMANDS.reconcileJavaScriptRuntime, {
|
|
29
56
|
description: "Reconcile static application and passive runtime Evidence JSON",
|
|
@@ -70,7 +97,7 @@ const registerElectronTargetList = (cli, logger) => {
|
|
|
70
97
|
.describe("Maximum Electron targets to return"),
|
|
71
98
|
}),
|
|
72
99
|
run: ({ args, options }) => logCliCommand(logger, "list-electron-targets", async () => {
|
|
73
|
-
const context = await
|
|
100
|
+
const context = await electronObservationContext("list_electron_targets");
|
|
74
101
|
if (!context.ok)
|
|
75
102
|
return context.error;
|
|
76
103
|
const parsed = listElectronTargetsInputSchema.safeParse({
|
|
@@ -98,7 +125,7 @@ const registerElectronPageInspection = (cli, logger) => {
|
|
|
98
125
|
}),
|
|
99
126
|
options: electronPageInspectionOptions,
|
|
100
127
|
run: ({ args, options }) => logCliCommand(logger, "inspect-electron-page", async () => {
|
|
101
|
-
const context = await
|
|
128
|
+
const context = await electronObservationContext("inspect_electron_page");
|
|
102
129
|
if (!context.ok)
|
|
103
130
|
return context.error;
|
|
104
131
|
const parsed = inspectElectronPageInputSchema.safeParse({
|
|
@@ -168,7 +195,22 @@ const electronContext = async () => {
|
|
|
168
195
|
ok: true,
|
|
169
196
|
authority: authority.value,
|
|
170
197
|
provider: new CdpElectronProvider(),
|
|
171
|
-
|
|
198
|
+
activeProvider: new PlaywrightElectronActiveProvider(),
|
|
199
|
+
observationPolicy: config.value.electronObservationPolicy,
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const electronObservationContext = async (operation) => {
|
|
203
|
+
const context = await electronContext();
|
|
204
|
+
if (!context.ok)
|
|
205
|
+
return context;
|
|
206
|
+
if (context.observationPolicy.status === "disabled")
|
|
207
|
+
return {
|
|
208
|
+
ok: false,
|
|
209
|
+
error: cliError(new AnalysisCapabilityUnavailableError("rea-cdp-electron", operation, "Electron observation is disabled; configure exact endpoints and file roots before enabling it")),
|
|
210
|
+
};
|
|
211
|
+
return {
|
|
212
|
+
...context,
|
|
213
|
+
allowedFileRoots: context.observationPolicy.fileRoots,
|
|
172
214
|
};
|
|
173
215
|
};
|
|
174
216
|
const inputError = (operation) => cliError(new AnalysisInputError(operation));
|
|
@@ -5,8 +5,9 @@ import { V8InspectorProvider } from "./browser/V8InspectorProvider.js";
|
|
|
5
5
|
import { CLI_COMMANDS } from "./cliCommandNames.js";
|
|
6
6
|
import { logCliCommand } from "./cliLogging.js";
|
|
7
7
|
import { parseConfig } from "./config.js";
|
|
8
|
+
import { v8InspectorLocationScopes } from "./config/passiveObservation.js";
|
|
8
9
|
import { javascriptRuntimeKindSchema, listJavaScriptRuntimeTargetsInputSchema, observeJavaScriptRuntimeInputSchema, } from "./domain/javascriptRuntimeObservation.js";
|
|
9
|
-
import { AnalysisInputError, projectAnalysisError } from "./domain/errors.js";
|
|
10
|
+
import { AnalysisCapabilityUnavailableError, AnalysisInputError, projectAnalysisError, } from "./domain/errors.js";
|
|
10
11
|
const scopeOptions = {
|
|
11
12
|
allowedFileRoots: z
|
|
12
13
|
.array(z.string().min(1))
|
|
@@ -89,7 +90,7 @@ export const registerJavaScriptRuntimeObservationCommands = (cli, logger) => {
|
|
|
89
90
|
}),
|
|
90
91
|
options: listOptionsSchema,
|
|
91
92
|
run: ({ args, options }) => logCliCommand(logger, CLI_COMMANDS.listJavaScriptRuntimeTargets, async () => {
|
|
92
|
-
const context = await runtimeContext();
|
|
93
|
+
const context = await runtimeContext("list_javascript_runtime_targets");
|
|
93
94
|
if (!context.ok)
|
|
94
95
|
return context.error;
|
|
95
96
|
const parsed = listJavaScriptRuntimeTargetsInputSchema.safeParse({
|
|
@@ -116,7 +117,7 @@ export const registerJavaScriptRuntimeObservationCommands = (cli, logger) => {
|
|
|
116
117
|
}),
|
|
117
118
|
options: observeOptionsSchema,
|
|
118
119
|
run: ({ args, options }) => logCliCommand(logger, CLI_COMMANDS.observeJavaScriptRuntime, async () => {
|
|
119
|
-
const context = await runtimeContext();
|
|
120
|
+
const context = await runtimeContext("observe_javascript_runtime");
|
|
120
121
|
if (!context.ok)
|
|
121
122
|
return context.error;
|
|
122
123
|
const parsed = observeJavaScriptRuntimeInputSchema.safeParse({
|
|
@@ -142,19 +143,26 @@ export const registerJavaScriptRuntimeObservationCommands = (cli, logger) => {
|
|
|
142
143
|
}),
|
|
143
144
|
});
|
|
144
145
|
};
|
|
145
|
-
const runtimeContext = async () => {
|
|
146
|
+
const runtimeContext = async (operation) => {
|
|
146
147
|
const config = parseConfig(process.env);
|
|
147
148
|
if (!config.ok)
|
|
148
149
|
return { ok: false, error: cliError(config.error) };
|
|
150
|
+
const policy = config.value.v8InspectorObservationPolicy;
|
|
151
|
+
if (policy.status === "disabled")
|
|
152
|
+
return {
|
|
153
|
+
ok: false,
|
|
154
|
+
error: cliError(new AnalysisCapabilityUnavailableError("rea-v8-inspector", operation, "V8 Inspector observation is disabled; configure exact endpoints and file or origin scopes before enabling it")),
|
|
155
|
+
};
|
|
149
156
|
const authority = await loadConfiguredPermissionAuthority(config.value);
|
|
150
157
|
if (!authority.ok)
|
|
151
158
|
return { ok: false, error: cliError(authority.error) };
|
|
159
|
+
const scopes = v8InspectorLocationScopes(policy.locations);
|
|
152
160
|
return {
|
|
153
161
|
ok: true,
|
|
154
162
|
authority: authority.value,
|
|
155
163
|
provider: new V8InspectorProvider(),
|
|
156
|
-
allowedFileRoots:
|
|
157
|
-
allowedOrigins:
|
|
164
|
+
allowedFileRoots: scopes.fileRoots,
|
|
165
|
+
allowedOrigins: scopes.allowedOrigins,
|
|
158
166
|
};
|
|
159
167
|
};
|
|
160
168
|
const inputError = (operation) => cliError(new AnalysisInputError(operation));
|
|
@@ -50,6 +50,10 @@ export const browserPageInspectionOptions = z.object({
|
|
|
50
50
|
.boolean()
|
|
51
51
|
.default(false)
|
|
52
52
|
.describe("Include bounded JavaScript source text"),
|
|
53
|
+
sourceCaptureApproved: z
|
|
54
|
+
.boolean()
|
|
55
|
+
.default(false)
|
|
56
|
+
.describe("Approve capturing bounded script source text"),
|
|
53
57
|
includeStorageKeys: z
|
|
54
58
|
.boolean()
|
|
55
59
|
.default(false)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ConfigurationError } from "../domain/errors.js";
|
|
2
|
+
import { err, ok } from "../domain/result.js";
|
|
3
|
+
import { browserEndpointSchema, browserOriginSchema, } from "../domain/browserObservation.js";
|
|
4
|
+
import { parseAbsoluteRoots, parseBrowserArray, parseStringArray, } from "./parsers.js";
|
|
5
|
+
import { browserNetworkScope, permissionScope } from "./permissions.js";
|
|
6
|
+
/** Parse controlled browser scenarios into a closed disabled or enabled policy. */
|
|
7
|
+
export const parseBrowserScenarioPolicy = (env) => {
|
|
8
|
+
const executableRoots = parseAbsoluteRoots(env.REA_BROWSER_SCENARIO_EXECUTABLE_ROOTS_JSON, "REA_BROWSER_SCENARIO_EXECUTABLE_ROOTS_JSON");
|
|
9
|
+
if (!executableRoots.ok)
|
|
10
|
+
return executableRoots;
|
|
11
|
+
const cdpEndpoints = parseBrowserArray(env.REA_BROWSER_SCENARIO_CDP_ENDPOINTS_JSON, "REA_BROWSER_SCENARIO_CDP_ENDPOINTS_JSON", browserEndpointSchema, 16);
|
|
12
|
+
if (!cdpEndpoints.ok)
|
|
13
|
+
return cdpEndpoints;
|
|
14
|
+
const allowedOrigins = parseBrowserArray(env.REA_BROWSER_SCENARIO_ALLOWED_ORIGINS_JSON, "REA_BROWSER_SCENARIO_ALLOWED_ORIGINS_JSON", browserOriginSchema, 32);
|
|
15
|
+
if (!allowedOrigins.ok)
|
|
16
|
+
return allowedOrigins;
|
|
17
|
+
const allowedEnvironment = parseStringArray(env.REA_BROWSER_SCENARIO_ALLOWED_ENV_JSON, "REA_BROWSER_SCENARIO_ALLOWED_ENV_JSON");
|
|
18
|
+
if (!allowedEnvironment.ok)
|
|
19
|
+
return allowedEnvironment;
|
|
20
|
+
if (env.REA_BROWSER_SCENARIO_ENABLED !== "true")
|
|
21
|
+
return ok({ status: "disabled" });
|
|
22
|
+
const [firstOrigin, ...remainingOrigins] = allowedOrigins.value;
|
|
23
|
+
if (firstOrigin === undefined)
|
|
24
|
+
return err(new ConfigurationError("REA_BROWSER_SCENARIO_ALLOWED_ORIGINS_JSON must encode at least one exact origin when browser scenarios are enabled"));
|
|
25
|
+
const target = parseTargetPolicy(executableRoots.value, cdpEndpoints.value);
|
|
26
|
+
if (!target.ok)
|
|
27
|
+
return target;
|
|
28
|
+
return ok({
|
|
29
|
+
status: "enabled",
|
|
30
|
+
target: target.value,
|
|
31
|
+
allowedOrigins: [firstOrigin, ...remainingOrigins],
|
|
32
|
+
allowedEnvironment: allowedEnvironment.value,
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
/** Add the separately permissioned controlled-browser ceiling. */
|
|
36
|
+
export const appendBrowserScenarioCeiling = (ceilings, policy) => {
|
|
37
|
+
if (policy.status === "disabled")
|
|
38
|
+
return;
|
|
39
|
+
const { executableRoots, cdpEndpoints } = targetScopes(policy.target);
|
|
40
|
+
ceilings.push(permissionScope("browser_automate", [], {
|
|
41
|
+
executables: executableRoots,
|
|
42
|
+
environment_names: policy.allowedEnvironment,
|
|
43
|
+
origins: [...cdpEndpoints, ...policy.allowedOrigins],
|
|
44
|
+
network: browserNetworkScope(policy.allowedOrigins),
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
const parseTargetPolicy = (executableRoots, cdpEndpoints) => {
|
|
48
|
+
const [firstExecutableRoot, ...remainingExecutableRoots] = executableRoots;
|
|
49
|
+
const [firstCdpEndpoint, ...remainingCdpEndpoints] = cdpEndpoints;
|
|
50
|
+
if (firstExecutableRoot !== undefined && firstCdpEndpoint !== undefined)
|
|
51
|
+
return ok({
|
|
52
|
+
access: "launch-or-attach",
|
|
53
|
+
executableRoots: [firstExecutableRoot, ...remainingExecutableRoots],
|
|
54
|
+
cdpEndpoints: [firstCdpEndpoint, ...remainingCdpEndpoints],
|
|
55
|
+
});
|
|
56
|
+
if (firstExecutableRoot !== undefined)
|
|
57
|
+
return ok({
|
|
58
|
+
access: "launch",
|
|
59
|
+
executableRoots: [firstExecutableRoot, ...remainingExecutableRoots],
|
|
60
|
+
});
|
|
61
|
+
if (firstCdpEndpoint !== undefined)
|
|
62
|
+
return ok({
|
|
63
|
+
access: "attach",
|
|
64
|
+
cdpEndpoints: [firstCdpEndpoint, ...remainingCdpEndpoints],
|
|
65
|
+
});
|
|
66
|
+
return err(new ConfigurationError("Browser scenarios require at least one executable root or loopback CDP endpoint when enabled"));
|
|
67
|
+
};
|
|
68
|
+
const targetScopes = (target) => {
|
|
69
|
+
switch (target.access) {
|
|
70
|
+
case "launch":
|
|
71
|
+
return { executableRoots: target.executableRoots, cdpEndpoints: [] };
|
|
72
|
+
case "attach":
|
|
73
|
+
return { executableRoots: [], cdpEndpoints: target.cdpEndpoints };
|
|
74
|
+
case "launch-or-attach":
|
|
75
|
+
return target;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ConfigurationError } from "../domain/errors.js";
|
|
2
|
+
import { err, ok } from "../domain/result.js";
|
|
3
|
+
import { permissionScope } from "./permissions.js";
|
|
4
|
+
import { parseAbsoluteRoots } from "./parsers.js";
|
|
5
|
+
/** Parse active Electron automation into a closed disabled or enabled policy. */
|
|
6
|
+
export const parseElectronAutomationPolicy = (env) => {
|
|
7
|
+
const executableRoots = parseAbsoluteRoots(env.REA_ELECTRON_AUTOMATE_EXECUTABLE_ROOTS_JSON, "REA_ELECTRON_AUTOMATE_EXECUTABLE_ROOTS_JSON");
|
|
8
|
+
if (!executableRoots.ok)
|
|
9
|
+
return executableRoots;
|
|
10
|
+
const applicationRoots = parseAbsoluteRoots(env.REA_ELECTRON_AUTOMATE_APPLICATION_ROOTS_JSON, "REA_ELECTRON_AUTOMATE_APPLICATION_ROOTS_JSON");
|
|
11
|
+
if (!applicationRoots.ok)
|
|
12
|
+
return applicationRoots;
|
|
13
|
+
if (env.REA_ELECTRON_AUTOMATE_ENABLED !== "true")
|
|
14
|
+
return ok({ status: "disabled" });
|
|
15
|
+
const [firstExecutableRoot, ...remainingExecutableRoots] = executableRoots.value;
|
|
16
|
+
if (firstExecutableRoot === undefined)
|
|
17
|
+
return err(new ConfigurationError("REA_ELECTRON_AUTOMATE_EXECUTABLE_ROOTS_JSON must encode at least one absolute root when Electron automation is enabled"));
|
|
18
|
+
const [firstApplicationRoot, ...remainingApplicationRoots] = applicationRoots.value;
|
|
19
|
+
if (firstApplicationRoot === undefined)
|
|
20
|
+
return err(new ConfigurationError("REA_ELECTRON_AUTOMATE_APPLICATION_ROOTS_JSON must encode at least one absolute root when Electron automation is enabled"));
|
|
21
|
+
return ok({
|
|
22
|
+
status: "enabled",
|
|
23
|
+
executableRoots: [firstExecutableRoot, ...remainingExecutableRoots],
|
|
24
|
+
applicationRoots: [firstApplicationRoot, ...remainingApplicationRoots],
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
/** Add the separately permissioned, no-network Electron automation ceiling. */
|
|
28
|
+
export const appendElectronAutomationCeiling = (ceilings, policy) => {
|
|
29
|
+
if (policy.status === "disabled")
|
|
30
|
+
return;
|
|
31
|
+
ceilings.push(permissionScope("electron_automate", policy.applicationRoots, {
|
|
32
|
+
executables: policy.executableRoots,
|
|
33
|
+
network: "external",
|
|
34
|
+
}));
|
|
35
|
+
};
|
|
@@ -61,6 +61,12 @@ const environmentSchema = z
|
|
|
61
61
|
REA_ELECTRON_OBSERVE_ENABLED: z.enum(["true", "false"]).default("false"),
|
|
62
62
|
REA_ELECTRON_CDP_ENDPOINTS_JSON: z.string().default("[]"),
|
|
63
63
|
REA_ELECTRON_FILE_ROOTS_JSON: z.string().default("[]"),
|
|
64
|
+
REA_ELECTRON_AUTOMATE_ENABLED: z.enum(["true", "false"]).default("false"),
|
|
65
|
+
REA_ELECTRON_AUTOMATE_AUTO_GRANT: z
|
|
66
|
+
.enum(["true", "false"])
|
|
67
|
+
.default("false"),
|
|
68
|
+
REA_ELECTRON_AUTOMATE_EXECUTABLE_ROOTS_JSON: z.string().default("[]"),
|
|
69
|
+
REA_ELECTRON_AUTOMATE_APPLICATION_ROOTS_JSON: z.string().default("[]"),
|
|
64
70
|
REA_V8_INSPECTOR_OBSERVE_ENABLED: z
|
|
65
71
|
.enum(["true", "false"])
|
|
66
72
|
.default("false"),
|