rea-agents 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -19
- package/bridge/ghidra/ReaGhidraBridge.java +524 -4
- package/bridge/hopper_bridge.py +313 -28
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/AnalysisContextQueries.js +130 -0
- package/dist/application/AnalysisSnapshotCache.js +4 -2
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/ArtifactInventory/scanCanonical.js +1 -1
- package/dist/application/BinarySession.js +20 -8
- package/dist/application/BinarySessionComposition.js +21 -0
- package/dist/application/BinarySessionRecords.js +79 -9
- package/dist/application/BinarySessionStatus.js +31 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +84 -14
- package/dist/application/ClientRegistrationStatus.js +4 -1
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +13 -4
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +71 -127
- package/dist/application/EvidenceLedger.js +45 -16
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptArtifactAnalysis.js +13 -4
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/LazyAnalysisProvider.js +77 -0
- package/dist/application/LoopbackReplay.js +1 -1
- package/dist/application/NativeApiInspection.js +80 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/application/SessionProviderRouter.js +6 -6
- package/dist/application/SetupClientConfiguration.js +4 -2
- package/dist/application/runtime.js +26 -9
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +259 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +11 -3
- package/dist/cli/artifactCommands.js +44 -3
- package/dist/cli/coreAnalysisCommands.js +78 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +9 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +29 -2
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +35 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/functionWorkflowToolContracts.js +30 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/promptContracts.js +14 -15
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +8 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +34 -25
- package/dist/contracts/toolEffects.js +25 -0
- package/dist/contracts/toolOutputSchemaGroups.js +120 -30
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorPresentation.js +8 -2
- package/dist/domain/analysisErrorProjection.js +9 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/bytecodeProvider.js +179 -0
- package/dist/domain/conformancePackage.js +169 -0
- package/dist/domain/conformanceReplay.js +104 -0
- package/dist/domain/conformanceTrustGate.js +193 -0
- package/dist/domain/customProtocolCapture.js +137 -0
- package/dist/domain/eventProcessTree.js +214 -0
- package/dist/domain/evidenceBundle.js +47 -0
- package/dist/domain/hopperStartupFailure.js +1 -1
- package/dist/domain/hopperValues.js +14 -1
- package/dist/domain/inputIssueProjection.js +7 -1
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +13 -16
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptSourceParser.js +15 -0
- package/dist/domain/javascriptStaticAnalysis.js +12 -15
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/mobileApplicationInvestigation.js +159 -0
- package/dist/domain/nativeApiBoundary.js +130 -0
- package/dist/domain/objcSwiftMetadata.js +150 -0
- package/dist/domain/packageAnalysis.js +123 -0
- package/dist/domain/peInspection.js +196 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/protocolCapture.js +243 -0
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/dotnet/ManagedStaticProvider.js +34 -5
- package/dist/generatedMcpToolCatalog.js +37 -0
- package/dist/generatedPackageMetadata.js +4 -4
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +40 -2
- package/dist/ghidra/GhidraProviderCapabilities.js +47 -38
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +93 -99
- package/dist/hopper/HopperProvider.js +61 -30
- package/dist/hopper/HopperRequestQueue.js +215 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +63 -20
- package/dist/main/transport.js +24 -27
- package/dist/main.js +14 -6
- package/dist/mcpDoctor.js +27 -4
- package/dist/mcpStartupPolicy.js +14 -0
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/LazyToolCatalog.js +134 -0
- package/dist/server/createServer.js +92 -154
- package/dist/server/hydrateServerTools.js +191 -0
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +28 -7
- package/dist/server/registerEvidenceResources.js +54 -101
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerInvestigationTools.js +1 -2
- package/dist/server/registerJavaScriptApplicationGraphResource.js +0 -4
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +32 -0
- package/dist/server/registerReconstructionReadinessResource.js +32 -0
- package/dist/server/registerSessionRecordTools.js +82 -12
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +32 -58
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/dist/server/toolRegistrationOptions.js +21 -6
- package/dist/server/toolResult.js +12 -0
- package/package.json +28 -11
- package/scripts/package-runner-bootstrap.mjs +72 -0
- package/scripts/rea.mjs +11 -1
- package/skills/reverse-engineer-anything/SKILL.md +10 -3
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { compareApplicationVersionsRequestSchema, compareJavaScriptExportShapesRequestSchema, traceApplicationFeatureRequestSchema, traceJavaScriptSemanticsRequestSchema, } from "../contracts/applicationWorkflowInputContracts.js";
|
|
2
|
+
import { compareApplicationVersionsRequestSchema, compareJavaScriptExportShapesRequestSchema, compareSourceToBundleRequestSchema, traceApplicationFeatureRequestSchema, traceJavaScriptSemanticsRequestSchema, } from "../contracts/applicationWorkflowInputContracts.js";
|
|
3
3
|
import { AnalysisInputError } from "../domain/errors.js";
|
|
4
4
|
import { projectInputIssues } from "../domain/inputIssueProjection.js";
|
|
5
5
|
import { compareApplicationVersionsInputSchema } from "../domain/javascriptApplicationVersionComparisonSchemas.js";
|
|
6
6
|
import { compareJavaScriptExportShapesInputSchema } from "../domain/javascriptExportShapeComparisonSchemas.js";
|
|
7
7
|
import { traceApplicationFeatureInputSchema } from "../domain/javascriptFeatureTraceSchemas.js";
|
|
8
8
|
import { traceJavaScriptSemanticsInputSchema } from "../domain/javascriptSemanticTraceSchemas.js";
|
|
9
|
+
import { compareSourceToBundleInputSchema } from "../domain/sourceToBundleComparisonSchemas.js";
|
|
9
10
|
import { err, ok } from "../domain/result.js";
|
|
10
11
|
import { resolveEvidenceReferences, } from "./EvidenceReferenceResolver.js";
|
|
11
12
|
const APPLICATION_GRAPH_IDENTITIES = [
|
|
@@ -35,18 +36,14 @@ export const resolveTraceApplicationFeatureRequest = (input, lookup) => {
|
|
|
35
36
|
};
|
|
36
37
|
/** Resolve a trace request already parsed by the caller-facing contract. */
|
|
37
38
|
export const resolveTraceApplicationFeatureRequestValidated = (input, lookup) => {
|
|
38
|
-
const application = input.application
|
|
39
|
-
? resolveEvidenceReferences(lookup, input.application_evidence_id === undefined
|
|
40
|
-
? []
|
|
41
|
-
: [input.application_evidence_id], APPLICATION_GRAPH_IDENTITIES)
|
|
42
|
-
: ok([input.application]);
|
|
39
|
+
const application = graphEvidence(input.application, input.application_evidence_id, lookup);
|
|
43
40
|
if (!application.ok)
|
|
44
41
|
return application;
|
|
45
42
|
const native = resolveEvidenceReferences(lookup, input.native_observation_evidence_ids);
|
|
46
43
|
if (!native.ok)
|
|
47
44
|
return native;
|
|
48
45
|
const raw = {
|
|
49
|
-
application: application.value
|
|
46
|
+
application: application.value,
|
|
50
47
|
native_observations: [...input.native_observations, ...native.value],
|
|
51
48
|
seed: input.seed,
|
|
52
49
|
direction: input.direction,
|
|
@@ -66,14 +63,10 @@ export const resolveTraceJavaScriptSemanticsRequest = (input, lookup) => {
|
|
|
66
63
|
};
|
|
67
64
|
/** Resolve a semantic trace request already parsed by its public contract. */
|
|
68
65
|
export const resolveTraceJavaScriptSemanticsRequestValidated = (input, lookup) => {
|
|
69
|
-
const application = input.application
|
|
70
|
-
? resolveEvidenceReferences(lookup, input.application_evidence_id === undefined
|
|
71
|
-
? []
|
|
72
|
-
: [input.application_evidence_id], APPLICATION_GRAPH_IDENTITIES)
|
|
73
|
-
: ok([input.application]);
|
|
66
|
+
const application = graphEvidence(input.application, input.application_evidence_id, lookup);
|
|
74
67
|
if (!application.ok)
|
|
75
68
|
return application;
|
|
76
|
-
const raw = { application: application.value
|
|
69
|
+
const raw = { application: application.value, query: input.query };
|
|
77
70
|
const parsed = traceJavaScriptSemanticsInputSchema.safeParse(raw);
|
|
78
71
|
return parsed.success
|
|
79
72
|
? ok(parsed.data)
|
|
@@ -121,6 +114,31 @@ export const resolveCompareApplicationVersionsRequestValidated = (input, lookup)
|
|
|
121
114
|
? ok(parsed.data)
|
|
122
115
|
: invalid("compare_application_versions", parsed.error, raw);
|
|
123
116
|
};
|
|
117
|
+
/** Parse and resolve one historical-source comparison adapter request. */
|
|
118
|
+
export const resolveCompareSourceToBundleRequest = (input, lookup) => {
|
|
119
|
+
const parsed = compareSourceToBundleRequestSchema.safeParse(input);
|
|
120
|
+
return parsed.success
|
|
121
|
+
? resolveCompareSourceToBundleRequestValidated(parsed.data, lookup)
|
|
122
|
+
: invalid("compare_source_to_bundle", parsed.error, input);
|
|
123
|
+
};
|
|
124
|
+
/** Resolve a historical-source comparison request parsed by its public contract. */
|
|
125
|
+
export const resolveCompareSourceToBundleRequestValidated = (input, lookup) => {
|
|
126
|
+
const application = graphEvidence(input.application, input.application_evidence_id, lookup);
|
|
127
|
+
if (!application.ok)
|
|
128
|
+
return application;
|
|
129
|
+
const raw = {
|
|
130
|
+
reference: input.reference,
|
|
131
|
+
application: application.value,
|
|
132
|
+
limits: input.limits,
|
|
133
|
+
...(input.unknown_registry_approved === undefined
|
|
134
|
+
? {}
|
|
135
|
+
: { unknown_registry_approved: input.unknown_registry_approved }),
|
|
136
|
+
};
|
|
137
|
+
const parsed = compareSourceToBundleInputSchema.safeParse(raw);
|
|
138
|
+
return parsed.success
|
|
139
|
+
? ok(parsed.data)
|
|
140
|
+
: invalid("compare_source_to_bundle", parsed.error, raw);
|
|
141
|
+
};
|
|
124
142
|
/** Parse and resolve an export-shape adapter request into canonical input. */
|
|
125
143
|
export const resolveCompareJavaScriptExportShapesRequest = (input, lookup) => {
|
|
126
144
|
const parsed = compareJavaScriptExportShapesRequestSchema.safeParse(input);
|
|
@@ -12,7 +12,7 @@ export const scanCanonicalArtifactInventory = async (path, limits, options = {})
|
|
|
12
12
|
const integrity = options.integrity ?? STRICT_INTEGRITY_POLICY;
|
|
13
13
|
if (integrity.mode === "record-and-continue" &&
|
|
14
14
|
(!integrity.approved || !integrity.enabled))
|
|
15
|
-
throw new ArtifactReaderFailure("
|
|
15
|
+
throw new ArtifactReaderFailure("policy", "Integrity continuation requires explicit approval and operator policy");
|
|
16
16
|
const metadata = await lstat(path);
|
|
17
17
|
const rootFormat = await classifyRoot(path, metadata.isDirectory());
|
|
18
18
|
const rootDigest = metadata.isDirectory()
|
|
@@ -2,14 +2,15 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { analysisProfilesEqual, } from "../domain/analysisProfile.js";
|
|
3
3
|
import { AnalysisCancelledError, ProviderAdapterError, } from "../domain/errors.js";
|
|
4
4
|
import { err, ok } from "../domain/result.js";
|
|
5
|
-
import {
|
|
6
|
-
import { OFFICIAL_TOOL_CONTRACTS } from "../contracts/toolContracts.js";
|
|
5
|
+
import { GENERATED_MCP_TOOL_CATALOG } from "../generatedMcpToolCatalog.js";
|
|
7
6
|
import { SessionProviderRouter, } from "./SessionProviderRouter.js";
|
|
8
7
|
import { BinarySessionRecords } from "./BinarySessionRecords.js";
|
|
9
8
|
import { binarySessionStatus } from "./BinarySessionStatus.js";
|
|
10
9
|
import { resolveSessionOpen, } from "./BinarySessionOpen.js";
|
|
11
10
|
import { prepareSessionExecution } from "./BinarySessionExecution.js";
|
|
12
|
-
|
|
11
|
+
import { closeAnalysisClient } from "./AnalysisClientCleanup.js";
|
|
12
|
+
const OFFICIAL_OPERATIONS = new Set(GENERATED_MCP_TOOL_CATALOG.filter(({ kind }) => kind === "official-proxy").map(({ name }) => name));
|
|
13
|
+
const ENHANCED_OPERATIONS = new Set(GENERATED_MCP_TOOL_CATALOG.filter(({ kind }) => kind === "enhanced").map(({ name }) => name));
|
|
13
14
|
/**
|
|
14
15
|
* Owns the single active target shared by CLI and MCP adapters.
|
|
15
16
|
*
|
|
@@ -41,7 +42,7 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
41
42
|
const exact = route.capabilities?.get(operation)?.provider;
|
|
42
43
|
if (exact !== undefined)
|
|
43
44
|
selected = exact;
|
|
44
|
-
else if (
|
|
45
|
+
else if (ENHANCED_OPERATIONS.has(operation)) {
|
|
45
46
|
const providers = new Map();
|
|
46
47
|
for (const descriptor of route.capabilities?.values() ?? [])
|
|
47
48
|
if (descriptor.available &&
|
|
@@ -111,12 +112,20 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
111
112
|
if (!imported.ok)
|
|
112
113
|
return imported;
|
|
113
114
|
}
|
|
115
|
+
this.resetSnapshotInvalidation();
|
|
114
116
|
return ok(target);
|
|
115
117
|
}
|
|
116
118
|
await this.#drainCalls();
|
|
117
119
|
const previous = this.#active;
|
|
118
120
|
this.#active = undefined;
|
|
119
|
-
|
|
121
|
+
if (previous !== undefined) {
|
|
122
|
+
const closed = await closeAnalysisClient(previous.client, previous.route.identity.id);
|
|
123
|
+
if (!closed.ok) {
|
|
124
|
+
this.clearSessionRecords();
|
|
125
|
+
this.#clearRuntimeAvailability();
|
|
126
|
+
return closed;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
120
129
|
const runId = randomUUID();
|
|
121
130
|
const client = route.createClient(target, { runId });
|
|
122
131
|
const started = await client.execute("health", {}, options);
|
|
@@ -157,15 +166,17 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
157
166
|
});
|
|
158
167
|
}
|
|
159
168
|
/** Close the active target, if any. */
|
|
160
|
-
close() {
|
|
169
|
+
close(options = {}) {
|
|
161
170
|
return this.#serialize(async () => {
|
|
162
171
|
const previous = this.#active;
|
|
163
172
|
this.#active = undefined;
|
|
164
173
|
await this.#drainCalls();
|
|
165
|
-
|
|
174
|
+
const closed = previous === undefined
|
|
175
|
+
? ok(null)
|
|
176
|
+
: await closeAnalysisClient(previous.client, previous.route.identity.id, options);
|
|
166
177
|
this.clearSessionRecords();
|
|
167
178
|
this.#clearRuntimeAvailability();
|
|
168
|
-
return
|
|
179
|
+
return closed;
|
|
169
180
|
});
|
|
170
181
|
}
|
|
171
182
|
/** Describe the active binary session. */
|
|
@@ -177,6 +188,7 @@ export class BinarySession extends BinarySessionRecords {
|
|
|
177
188
|
runtimeAvailability: this.#runtimeAvailability,
|
|
178
189
|
runId: this.#active?.runId,
|
|
179
190
|
runtimeLineageSnapshots: this.#active?.client.runtimeLineageSnapshots?.() ?? [],
|
|
191
|
+
requestActivitySnapshots: this.#active?.client.requestActivitySnapshots?.() ?? [],
|
|
180
192
|
});
|
|
181
193
|
}
|
|
182
194
|
/** Return the immutable artifact identity captured before its provider started. */
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AnalysisProviderRegistry } from "./AnalysisProviderRegistry.js";
|
|
2
|
+
import { BinarySession } from "./BinarySession.js";
|
|
3
|
+
import { SessionProviderRouter } from "./SessionProviderRouter.js";
|
|
4
|
+
const normalizeBinarySessionOptions = (optionsOrResolver) => typeof optionsOrResolver === "function"
|
|
5
|
+
? { resolveAnalysisProfile: optionsOrResolver }
|
|
6
|
+
: (optionsOrResolver ?? {});
|
|
7
|
+
/**
|
|
8
|
+
* Compose one provider-neutral session from deep-provider selection and
|
|
9
|
+
* disjoint auxiliary operation families.
|
|
10
|
+
*/
|
|
11
|
+
export const composeBinarySession = (registry, auxiliaryProviders = []) => new BinarySession(registry instanceof SessionProviderRouter
|
|
12
|
+
? registry
|
|
13
|
+
: SessionProviderRouter.selectable(registry, auxiliaryProviders));
|
|
14
|
+
/**
|
|
15
|
+
* Compose a session through the same internal seam for focused adapter tests.
|
|
16
|
+
* The constructor remains private to this composition module, so callers test
|
|
17
|
+
* provider behavior without coupling to BinarySession construction.
|
|
18
|
+
*/
|
|
19
|
+
export const composeBinarySessionFromFactory = (provider, optionsOrResolver) => new BinarySession(provider, normalizeBinarySessionOptions(optionsOrResolver));
|
|
20
|
+
/** Compose a focused session from any provider-shaped test seam. */
|
|
21
|
+
export const composeBinarySessionFromProvider = (provider, optionsOrResolver) => new BinarySession(provider, normalizeBinarySessionOptions(optionsOrResolver));
|
|
@@ -1,24 +1,37 @@
|
|
|
1
1
|
import { createEvidence } from "../domain/evidence.js";
|
|
2
|
-
import { evidenceBundleForTarget } from "../domain/evidenceBundle.js";
|
|
3
|
-
import { EvidenceIntegrityError, } from "../domain/errors.js";
|
|
2
|
+
import { evidenceBundleForTarget, serializeEvidenceBundle, } from "../domain/evidenceBundle.js";
|
|
3
|
+
import { EvidenceIntegrityError, EvidenceLimitError, } from "../domain/errors.js";
|
|
4
4
|
import { parseInvestigationWorkspace, } from "../domain/investigationWorkspace.js";
|
|
5
5
|
import { parseReconstructionCoverageWorkspace, } from "../domain/reconstructionCoverage.js";
|
|
6
|
-
import { err } from "../domain/result.js";
|
|
6
|
+
import { err, ok } from "../domain/result.js";
|
|
7
7
|
import { AnalysisSnapshotCache } from "./AnalysisSnapshotCache.js";
|
|
8
8
|
import { EvidenceLedger } from "./EvidenceLedger.js";
|
|
9
9
|
import { UNKNOWN_REGISTRY_PROVIDER, unknownEvidenceLinks, unknownMutationEvidence, } from "./UnknownEvidence.js";
|
|
10
10
|
/** Owns session evidence, snapshots, workspaces, and residual unknowns. */
|
|
11
11
|
export class BinarySessionRecords {
|
|
12
|
+
static MAX_RETAINED_BUNDLES = 16;
|
|
13
|
+
static MAX_RETAINED_BUNDLE_BYTES = 64 * 1024 * 1024;
|
|
12
14
|
#evidence = new EvidenceLedger({
|
|
13
15
|
maxRecords: 10_000,
|
|
14
16
|
maxBytes: 64 * 1024 * 1024,
|
|
15
17
|
});
|
|
16
18
|
#snapshot = new AnalysisSnapshotCache();
|
|
19
|
+
#retainedBundles = new Map();
|
|
20
|
+
#retainedBundleBytes = 0;
|
|
17
21
|
#investigationWorkspaces = new Map();
|
|
18
22
|
#coverageWorkspaces = new Map();
|
|
19
23
|
#snapshotInvalidated = false;
|
|
24
|
+
#snapshotListeners = new Set();
|
|
25
|
+
/** Observe changes to the mutable current analysis snapshot resource. */
|
|
26
|
+
onAnalysisSnapshotChanged(listener) {
|
|
27
|
+
this.#snapshotListeners.add(listener);
|
|
28
|
+
return () => this.#snapshotListeners.delete(listener);
|
|
29
|
+
}
|
|
20
30
|
recordEvidence(evidence) {
|
|
21
|
-
|
|
31
|
+
const recorded = this.#evidence.record(evidence);
|
|
32
|
+
if (recorded.ok && recorded.value === "added")
|
|
33
|
+
this.#emitSnapshotChanged();
|
|
34
|
+
return recorded;
|
|
22
35
|
}
|
|
23
36
|
hasEvidence(evidenceId) {
|
|
24
37
|
return this.#evidence.has(evidenceId);
|
|
@@ -29,8 +42,38 @@ export class BinarySessionRecords {
|
|
|
29
42
|
exportEvidenceBundle() {
|
|
30
43
|
return this.#evidence.export();
|
|
31
44
|
}
|
|
45
|
+
snapshotEvidenceBundle() {
|
|
46
|
+
const bundle = this.#evidence.export();
|
|
47
|
+
const encoded = serializeEvidenceBundle(bundle);
|
|
48
|
+
const digest = createHash("sha256").update(encoded).digest("hex");
|
|
49
|
+
const existing = this.#retainedBundles.get(digest);
|
|
50
|
+
if (existing === undefined) {
|
|
51
|
+
if (this.#retainedBundles.size >= BinarySessionRecords.MAX_RETAINED_BUNDLES)
|
|
52
|
+
return err(new EvidenceLimitError("records", BinarySessionRecords.MAX_RETAINED_BUNDLES));
|
|
53
|
+
const bytes = Buffer.byteLength(encoded);
|
|
54
|
+
if (this.#retainedBundleBytes + bytes >
|
|
55
|
+
BinarySessionRecords.MAX_RETAINED_BUNDLE_BYTES)
|
|
56
|
+
return err(new EvidenceLimitError("bytes", BinarySessionRecords.MAX_RETAINED_BUNDLE_BYTES));
|
|
57
|
+
this.#retainedBundles.set(digest, encoded);
|
|
58
|
+
this.#retainedBundleBytes += bytes;
|
|
59
|
+
}
|
|
60
|
+
return ok({
|
|
61
|
+
bundleDigest: digest,
|
|
62
|
+
bundleVersion: 2,
|
|
63
|
+
bytes: Buffer.byteLength(existing ?? encoded),
|
|
64
|
+
records: bundle.records.length,
|
|
65
|
+
unknowns: bundle.unknowns.length,
|
|
66
|
+
uri: `rea://evidence-bundle/${digest}`,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
retainedEvidenceBundle(digest) {
|
|
70
|
+
return this.#retainedBundles.get(digest);
|
|
71
|
+
}
|
|
32
72
|
importEvidenceBundle(bundle) {
|
|
33
|
-
|
|
73
|
+
const imported = this.#evidence.import(bundle);
|
|
74
|
+
if (imported.ok && imported.value > 0)
|
|
75
|
+
this.#emitSnapshotChanged();
|
|
76
|
+
return imported;
|
|
34
77
|
}
|
|
35
78
|
exportAnalysisSnapshot() {
|
|
36
79
|
const active = this.activeAnalysisBinding();
|
|
@@ -48,36 +91,53 @@ export class BinarySessionRecords {
|
|
|
48
91
|
const active = this.activeAnalysisBinding();
|
|
49
92
|
if (active?.profile === null)
|
|
50
93
|
return err(new EvidenceIntegrityError("Analysis snapshot profile_mismatch: the active target has no concrete analysis profile"));
|
|
51
|
-
|
|
94
|
+
const imported = this.#snapshot.import(snapshot, active === undefined
|
|
52
95
|
? undefined
|
|
53
96
|
: { target: active.target, profile: active.profile }, (bundle) => this.#evidence.import(bundle));
|
|
97
|
+
if (imported.ok)
|
|
98
|
+
this.#emitSnapshotChanged();
|
|
99
|
+
return imported;
|
|
54
100
|
}
|
|
55
101
|
matchesSnapshot(target, profile) {
|
|
56
102
|
return this.#snapshot.matches(target, profile ?? undefined);
|
|
57
103
|
}
|
|
58
104
|
selectSnapshot(target, profile) {
|
|
59
105
|
this.#snapshot.select(target, profile);
|
|
106
|
+
this.#emitSnapshotChanged();
|
|
60
107
|
}
|
|
61
108
|
lookupSnapshot(target, profile, operation, parameters) {
|
|
62
109
|
return this.#snapshot.lookup(target, profile, operation, parameters);
|
|
63
110
|
}
|
|
64
111
|
recordSnapshot(input) {
|
|
65
112
|
this.#snapshot.record(input);
|
|
113
|
+
this.#emitSnapshotChanged();
|
|
66
114
|
}
|
|
67
115
|
invalidateSnapshot() {
|
|
68
116
|
this.#snapshot.clear();
|
|
69
117
|
this.#snapshotInvalidated = true;
|
|
118
|
+
this.#emitSnapshotChanged();
|
|
70
119
|
}
|
|
71
120
|
resetSnapshotInvalidation() {
|
|
121
|
+
if (!this.#snapshotInvalidated)
|
|
122
|
+
return;
|
|
72
123
|
this.#snapshotInvalidated = false;
|
|
124
|
+
this.#emitSnapshotChanged();
|
|
73
125
|
}
|
|
74
126
|
clearSnapshot() {
|
|
75
127
|
this.#snapshot.clear();
|
|
128
|
+
this.#emitSnapshotChanged();
|
|
76
129
|
}
|
|
77
130
|
clearSessionRecords() {
|
|
78
131
|
this.#evidence.clear();
|
|
79
132
|
this.#snapshot.clear();
|
|
80
133
|
this.#snapshotInvalidated = false;
|
|
134
|
+
this.#retainedBundles.clear();
|
|
135
|
+
this.#retainedBundleBytes = 0;
|
|
136
|
+
this.#emitSnapshotChanged();
|
|
137
|
+
}
|
|
138
|
+
#emitSnapshotChanged() {
|
|
139
|
+
for (const listener of this.#snapshotListeners)
|
|
140
|
+
void listener();
|
|
81
141
|
}
|
|
82
142
|
retainInvestigationWorkspace(workspace) {
|
|
83
143
|
const parsed = parseInvestigationWorkspace(workspace);
|
|
@@ -111,10 +171,16 @@ export class BinarySessionRecords {
|
|
|
111
171
|
}
|
|
112
172
|
recordUnknown(input) {
|
|
113
173
|
const target = this.activeAnalysisBinding()?.target;
|
|
114
|
-
|
|
174
|
+
const recorded = this.#evidence.recordUnknown(input, unknownMutationEvidence(target, input));
|
|
175
|
+
if (recorded.ok)
|
|
176
|
+
this.#emitSnapshotChanged();
|
|
177
|
+
return recorded;
|
|
115
178
|
}
|
|
116
179
|
recordEvidenceWithUnknown(evidence, input) {
|
|
117
|
-
|
|
180
|
+
const recorded = this.#evidence.recordWithUnknown(evidence, input, unknownMutationEvidence(undefined, input));
|
|
181
|
+
if (recorded.ok)
|
|
182
|
+
this.#emitSnapshotChanged();
|
|
183
|
+
return recorded;
|
|
118
184
|
}
|
|
119
185
|
updateUnknown(input) {
|
|
120
186
|
const target = this.activeAnalysisBinding()?.target;
|
|
@@ -133,7 +199,10 @@ export class BinarySessionRecords {
|
|
|
133
199
|
"Registry mutation evidence records analyst intent, not proof of the answer.",
|
|
134
200
|
],
|
|
135
201
|
});
|
|
136
|
-
|
|
202
|
+
const updated = this.#evidence.updateUnknown(input, evidence);
|
|
203
|
+
if (updated.ok)
|
|
204
|
+
this.#emitSnapshotChanged();
|
|
205
|
+
return updated;
|
|
137
206
|
}
|
|
138
207
|
listUnknowns(filters = {}) {
|
|
139
208
|
return this.#evidence.listUnknowns(filters);
|
|
@@ -147,3 +216,4 @@ const sortedWorkspaces = (workspaces) => [...workspaces]
|
|
|
147
216
|
.sort((left, right) => left.workspace_id.localeCompare(right.workspace_id) ||
|
|
148
217
|
left.revision - right.revision)
|
|
149
218
|
.map((workspace) => structuredClone(workspace));
|
|
219
|
+
import { createHash } from "node:crypto";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Project internal provider routing state into the caller-visible session status. */
|
|
2
|
-
export const binarySessionStatus = ({ target, route, router, runtimeAvailability, runId, runtimeLineageSnapshots, }) => {
|
|
2
|
+
export const binarySessionStatus = ({ target, route, router, runtimeAvailability, runId, runtimeLineageSnapshots, requestActivitySnapshots, }) => {
|
|
3
3
|
const configuredProvider = router.configuredIdentity();
|
|
4
4
|
const provider = providerSummary(configuredProvider);
|
|
5
5
|
const providers = router.providerIdentities(route).map(providerSummary);
|
|
@@ -41,6 +41,7 @@ export const binarySessionStatus = ({ target, route, router, runtimeAvailability
|
|
|
41
41
|
run_id: runId,
|
|
42
42
|
process_lineage: processLineageStatus(runtimeLineageSnapshots),
|
|
43
43
|
},
|
|
44
|
+
analysis_activity: requestActivityStatus(requestActivitySnapshots),
|
|
44
45
|
};
|
|
45
46
|
return target === undefined
|
|
46
47
|
? { open: false, ...common }
|
|
@@ -54,6 +55,35 @@ export const binarySessionStatus = ({ target, route, router, runtimeAvailability
|
|
|
54
55
|
architecture: target.architecture ?? null,
|
|
55
56
|
};
|
|
56
57
|
};
|
|
58
|
+
const requestActivityStatus = (snapshots) => {
|
|
59
|
+
const providers = snapshots
|
|
60
|
+
.slice()
|
|
61
|
+
.sort((left, right) => left.provider.id.localeCompare(right.provider.id))
|
|
62
|
+
.map(({ provider, active, queuedRequests }) => ({
|
|
63
|
+
provider: providerSummary(provider),
|
|
64
|
+
active: active === null
|
|
65
|
+
? null
|
|
66
|
+
: {
|
|
67
|
+
request_id: active.requestId,
|
|
68
|
+
operation: active.operation,
|
|
69
|
+
elapsed_ms: active.elapsedMs,
|
|
70
|
+
timeout_ms: active.timeoutMs,
|
|
71
|
+
caller_state: active.callerState,
|
|
72
|
+
},
|
|
73
|
+
queued_requests: queuedRequests,
|
|
74
|
+
}));
|
|
75
|
+
const active = snapshots.flatMap((snapshot) => snapshot.active === null ? [] : [snapshot.active]);
|
|
76
|
+
return {
|
|
77
|
+
status: snapshots.length === 0
|
|
78
|
+
? "not_observed"
|
|
79
|
+
: active.some(({ callerState }) => callerState === "timed_out")
|
|
80
|
+
? "timed_out_busy"
|
|
81
|
+
: active.length > 0
|
|
82
|
+
? "busy"
|
|
83
|
+
: "idle",
|
|
84
|
+
providers,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
57
87
|
const providerSummary = ({ id, name, version, }) => ({ id, name, version });
|
|
58
88
|
const processLineageStatus = (snapshots) => snapshots.length === 0
|
|
59
89
|
? { status: "not_observed" }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createEvidence, } from "../domain/evidence.js";
|
|
2
2
|
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
3
|
+
import { commitBrowserScenarioNormalization } from "../domain/browserScenarioNormalization.js";
|
|
3
4
|
/** Create Evidence v2 for a policy-scoped external browser observation. */
|
|
4
5
|
export const createBrowserEvidence = (operation, input, result, provider) => createEvidence(undefined, provider, {
|
|
5
6
|
predicateType: browserPredicate(operation),
|
|
@@ -20,6 +21,18 @@ export const createBrowserEvidence = (operation, input, result, provider) => cre
|
|
|
20
21
|
});
|
|
21
22
|
const browserParameters = (input) => {
|
|
22
23
|
if (!("cdp_endpoint" in input)) {
|
|
24
|
+
if ("before_scenario" in input &&
|
|
25
|
+
input.before_scenario !== undefined &&
|
|
26
|
+
input.after_scenario !== undefined)
|
|
27
|
+
return {
|
|
28
|
+
comparison_kind: "browser_scenario",
|
|
29
|
+
before_browser: input.before_scenario.browser,
|
|
30
|
+
after_browser: input.after_scenario.browser,
|
|
31
|
+
before_start_origin: input.before_scenario.scenario.start_origin,
|
|
32
|
+
after_start_origin: input.after_scenario.scenario.start_origin,
|
|
33
|
+
max_changes: input.max_changes,
|
|
34
|
+
normalization_sha256: commitBrowserScenarioNormalization(input.normalization).sha256,
|
|
35
|
+
};
|
|
23
36
|
if ("max_changes" in input)
|
|
24
37
|
return {
|
|
25
38
|
before_target_id: input.before.inspection.target.target_id,
|
|
@@ -74,6 +87,7 @@ const browserParameters = (input) => {
|
|
|
74
87
|
include_websocket_shapes: input.include_websocket_shapes,
|
|
75
88
|
include_script_sources: input.include_script_sources,
|
|
76
89
|
include_storage_keys: input.include_storage_keys,
|
|
90
|
+
include_storage_fingerprints: input.include_storage_fingerprints,
|
|
77
91
|
limits: input.limits,
|
|
78
92
|
...(input.include_script_sources && "source_capture_approved" in input
|
|
79
93
|
? {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createBrowserScenarioEvidence } from "./BrowserScenarioEvidence.js";
|
|
2
|
+
import { digestJson } from "./JavaScriptReplayPlanning.js";
|
|
3
|
+
import { AnalysisCapabilityUnavailableError, AnalysisProtocolError, PermissionRequiredError, } from "../domain/errors.js";
|
|
4
|
+
import { isLiteralLoopbackHostname } from "../domain/browserObservation.js";
|
|
5
|
+
import { err } from "../domain/result.js";
|
|
6
|
+
const OPERATION = "capture_browser_scenario";
|
|
7
|
+
const PROVIDER_ID = "rea-playwright-browser-scenario";
|
|
8
|
+
const networkScope = (origins) => origins.every((origin) => isLiteralLoopbackHostname(new URL(origin).hostname))
|
|
9
|
+
? "loopback"
|
|
10
|
+
: "external";
|
|
11
|
+
const authorizeScenario = async (authority, scenario) => {
|
|
12
|
+
if (authority === undefined)
|
|
13
|
+
return err(new AnalysisCapabilityUnavailableError(PROVIDER_ID, OPERATION, "browser scenario permission policy is not configured"));
|
|
14
|
+
const authorized = await authority.authorize({
|
|
15
|
+
capability: "browser_automate",
|
|
16
|
+
roots: [],
|
|
17
|
+
executables: scenario.browser.mode === "launch"
|
|
18
|
+
? [scenario.browser.executable_path]
|
|
19
|
+
: [],
|
|
20
|
+
environment_names: scenario.secrets.map(({ environment_variable: name }) => name),
|
|
21
|
+
origins: [
|
|
22
|
+
...(scenario.browser.mode === "connect"
|
|
23
|
+
? [scenario.browser.cdp_endpoint]
|
|
24
|
+
: []),
|
|
25
|
+
...scenario.allowed_origins,
|
|
26
|
+
],
|
|
27
|
+
network: networkScope(scenario.allowed_origins),
|
|
28
|
+
mount: false,
|
|
29
|
+
operation_identity: `${OPERATION}:${digestJson(scenario)}`,
|
|
30
|
+
}, "write");
|
|
31
|
+
if (!authorized.ok)
|
|
32
|
+
return err(authorized.error instanceof PermissionRequiredError
|
|
33
|
+
? authorized.error
|
|
34
|
+
: new AnalysisProtocolError(authorized.error.message, {
|
|
35
|
+
cause: authorized.error,
|
|
36
|
+
}));
|
|
37
|
+
return { ok: true, value: true };
|
|
38
|
+
};
|
|
39
|
+
/** Authorize and execute one controlled browser scenario. */
|
|
40
|
+
export const captureBrowserScenario = async (provider, authority, scenario, options = {}) => {
|
|
41
|
+
const authorized = await authorizeScenario(authority, scenario);
|
|
42
|
+
if (!authorized.ok)
|
|
43
|
+
return authorized;
|
|
44
|
+
if (provider === undefined)
|
|
45
|
+
return err(new AnalysisCapabilityUnavailableError(PROVIDER_ID, OPERATION, "browser scenario provider is not configured"));
|
|
46
|
+
const captured = await provider.captureScenario(scenario, options);
|
|
47
|
+
return captured.ok
|
|
48
|
+
? {
|
|
49
|
+
ok: true,
|
|
50
|
+
value: createBrowserScenarioEvidence(scenario, captured.value, provider.identity()),
|
|
51
|
+
}
|
|
52
|
+
: captured;
|
|
53
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { sanitizeBrowserUrl } from "../domain/browserObservation.js";
|
|
2
|
+
import { createEvidence, } from "../domain/evidence.js";
|
|
3
|
+
import { jsonValueSchema } from "../domain/jsonValue.js";
|
|
4
|
+
import { digestJson } from "./JavaScriptReplayPlanning.js";
|
|
5
|
+
const browserScenarioParameters = (scenario) => ({
|
|
6
|
+
scenario_sha256: digestJson(scenario),
|
|
7
|
+
browser_mode: scenario.browser.mode,
|
|
8
|
+
start_url: sanitizeBrowserUrl(scenario.start_url.url),
|
|
9
|
+
allowed_origins: scenario.allowed_origins,
|
|
10
|
+
actions: scenario.actions.map(({ step_id, action }) => ({
|
|
11
|
+
step_id,
|
|
12
|
+
action,
|
|
13
|
+
})),
|
|
14
|
+
secret_declarations: scenario.secrets.map(({ secret_id, environment_variable, purpose, redaction }) => ({
|
|
15
|
+
secret_id,
|
|
16
|
+
environment_variable,
|
|
17
|
+
purpose,
|
|
18
|
+
redaction,
|
|
19
|
+
})),
|
|
20
|
+
capture: scenario.capture,
|
|
21
|
+
limits: scenario.limits,
|
|
22
|
+
});
|
|
23
|
+
/** Create Evidence v2 without retaining resolved scenario secret values. */
|
|
24
|
+
export const createBrowserScenarioEvidence = (scenario, capture, provider) => createEvidence(undefined, provider, {
|
|
25
|
+
predicateType: "rea.browser-scenario-capture/v1",
|
|
26
|
+
operation: "capture_browser_scenario",
|
|
27
|
+
parameters: browserScenarioParameters(scenario),
|
|
28
|
+
result: jsonValueSchema.parse(capture),
|
|
29
|
+
confidence: "observed",
|
|
30
|
+
authority: "controlled-replay",
|
|
31
|
+
environment: {
|
|
32
|
+
id: `${capture.browser.product}@${capture.browser.version}`,
|
|
33
|
+
platform: process.platform,
|
|
34
|
+
architecture: process.arch,
|
|
35
|
+
isolation: capture.browser.process_ownership === "provider-owned"
|
|
36
|
+
? "process"
|
|
37
|
+
: "none",
|
|
38
|
+
},
|
|
39
|
+
limitations: capture.limitations,
|
|
40
|
+
});
|