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
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { jsonValueSchema } from "./jsonValue.js";
|
|
3
|
+
/** Supported transport types for custom protocol capture. */
|
|
4
|
+
export const transportTypeSchema = z.enum([
|
|
5
|
+
"tcp",
|
|
6
|
+
"udp",
|
|
7
|
+
"ipc",
|
|
8
|
+
"unix-socket",
|
|
9
|
+
"named-pipe",
|
|
10
|
+
"xpc",
|
|
11
|
+
]);
|
|
12
|
+
/** Direction of a protocol frame. */
|
|
13
|
+
export const frameDirectionSchema = z.enum(["sent", "received", "intercepted"]);
|
|
14
|
+
/** A captured protocol frame. */
|
|
15
|
+
export const protocolFrameSchema = z.strictObject({
|
|
16
|
+
/** Monotonic sequence number. */
|
|
17
|
+
sequence: z.number().int().nonnegative(),
|
|
18
|
+
/** Timestamp in milliseconds. */
|
|
19
|
+
at_ms: z.number().int().nonnegative(),
|
|
20
|
+
/** Transport type. */
|
|
21
|
+
transport: transportTypeSchema,
|
|
22
|
+
/** Direction of the frame. */
|
|
23
|
+
direction: frameDirectionSchema,
|
|
24
|
+
/** Source process identity. */
|
|
25
|
+
source_pid: z.number().int().nullable(),
|
|
26
|
+
/** Destination process identity. */
|
|
27
|
+
dest_pid: z.number().int().nullable(),
|
|
28
|
+
/** Endpoint address (IP:port, socket path, pipe name). */
|
|
29
|
+
source_endpoint: z.string().nullable(),
|
|
30
|
+
/** Destination endpoint. */
|
|
31
|
+
dest_endpoint: z.string().nullable(),
|
|
32
|
+
/** Raw frame data as base64. */
|
|
33
|
+
raw_data: z.string().nullable(),
|
|
34
|
+
/** Decoded/parsed frame content if known. */
|
|
35
|
+
decoded_content: jsonValueSchema.nullable(),
|
|
36
|
+
/** Frame size in bytes. */
|
|
37
|
+
size: z.number().int().nonnegative(),
|
|
38
|
+
/** Whether the frame was truncated. */
|
|
39
|
+
truncated: z.boolean().default(false),
|
|
40
|
+
});
|
|
41
|
+
/** Authentication flow stage. */
|
|
42
|
+
export const authStageSchema = z.enum([
|
|
43
|
+
"init",
|
|
44
|
+
"challenge",
|
|
45
|
+
"response",
|
|
46
|
+
"token_exchange",
|
|
47
|
+
"renewal",
|
|
48
|
+
"revocation",
|
|
49
|
+
"failure",
|
|
50
|
+
"success",
|
|
51
|
+
]);
|
|
52
|
+
/** Token lifecycle event. */
|
|
53
|
+
export const tokenLifecycleEventSchema = z.enum([
|
|
54
|
+
"issued",
|
|
55
|
+
"refreshed",
|
|
56
|
+
"expired",
|
|
57
|
+
"revoked",
|
|
58
|
+
"renewed",
|
|
59
|
+
]);
|
|
60
|
+
/** A captured authentication flow event. */
|
|
61
|
+
export const authFlowEventSchema = z.strictObject({
|
|
62
|
+
/** Monotonic sequence number. */
|
|
63
|
+
sequence: z.number().int().nonnegative(),
|
|
64
|
+
/** Timestamp in milliseconds. */
|
|
65
|
+
at_ms: z.number().int().nonnegative(),
|
|
66
|
+
/** Authentication stage. */
|
|
67
|
+
stage: authStageSchema,
|
|
68
|
+
/** Protocol used. */
|
|
69
|
+
protocol: z.string().min(1),
|
|
70
|
+
/** Token type if applicable. */
|
|
71
|
+
token_type: z.string().nullable(),
|
|
72
|
+
/** Token lifecycle event. */
|
|
73
|
+
token_lifecycle: tokenLifecycleEventSchema.nullable(),
|
|
74
|
+
/** Correlation ID linking challenge-response pairs. */
|
|
75
|
+
correlation_id: z.string().nullable(),
|
|
76
|
+
/** Whether credentials were detected and redacted. */
|
|
77
|
+
credentials_redacted: z.boolean().default(false),
|
|
78
|
+
/** Whether the authentication succeeded. */
|
|
79
|
+
succeeded: z.boolean().default(false),
|
|
80
|
+
/** Error message if authentication failed. */
|
|
81
|
+
error: z.string().nullable(),
|
|
82
|
+
});
|
|
83
|
+
/** A captured protocol session. */
|
|
84
|
+
export const customProtocolCaptureSchema = z.strictObject({
|
|
85
|
+
/** Transport type for this session. */
|
|
86
|
+
transport: transportTypeSchema,
|
|
87
|
+
/** Captured frames in order. */
|
|
88
|
+
frames: z.array(protocolFrameSchema).min(0).max(100_000),
|
|
89
|
+
/** Authentication flow events. */
|
|
90
|
+
auth_events: z.array(authFlowEventSchema).default([]),
|
|
91
|
+
/** Whether any frame was truncated. */
|
|
92
|
+
has_truncated: z.boolean().default(false),
|
|
93
|
+
/** Whether credentials were detected. */
|
|
94
|
+
credentials_detected: z.boolean().default(false),
|
|
95
|
+
});
|
|
96
|
+
/** Correlate a frame with process identity. */
|
|
97
|
+
export function correlateProcessIdentity(frame, pid) {
|
|
98
|
+
return frame.source_pid === pid || frame.dest_pid === pid;
|
|
99
|
+
}
|
|
100
|
+
/** Check if a frame contains credential-like content. */
|
|
101
|
+
export function looksLikeCredentialFrame(frame) {
|
|
102
|
+
const patterns = [
|
|
103
|
+
"password",
|
|
104
|
+
"token",
|
|
105
|
+
"secret",
|
|
106
|
+
"api_key",
|
|
107
|
+
"apikey",
|
|
108
|
+
"authorization",
|
|
109
|
+
"credential",
|
|
110
|
+
];
|
|
111
|
+
const content = JSON.stringify(frame.decoded_content ?? "").toLowerCase();
|
|
112
|
+
return patterns.some((p) => content.includes(p));
|
|
113
|
+
}
|
|
114
|
+
/** Filter frames by transport type. */
|
|
115
|
+
export function framesByTransport(frames, transport) {
|
|
116
|
+
return frames.filter((f) => f.transport === transport);
|
|
117
|
+
}
|
|
118
|
+
/** Get all authentication flow events for a specific protocol. */
|
|
119
|
+
export function authEventsByProtocol(events, protocol) {
|
|
120
|
+
return events.filter((e) => e.protocol === protocol);
|
|
121
|
+
}
|
|
122
|
+
/** Get successful authentication events. */
|
|
123
|
+
export function successfulAuthEvents(events) {
|
|
124
|
+
return events.filter((e) => e.succeeded);
|
|
125
|
+
}
|
|
126
|
+
/** Get failed authentication events. */
|
|
127
|
+
export function failedAuthEvents(events) {
|
|
128
|
+
return events.filter((e) => !e.succeeded);
|
|
129
|
+
}
|
|
130
|
+
/** Compute the duration of an authentication flow in milliseconds. */
|
|
131
|
+
export function authFlowDuration(events) {
|
|
132
|
+
if (events.length === 0)
|
|
133
|
+
return null;
|
|
134
|
+
const first = events[0];
|
|
135
|
+
const last = events[events.length - 1];
|
|
136
|
+
return last.at_ms - first.at_ms;
|
|
137
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** Event types for event-backed process-tree capture. */
|
|
3
|
+
export const processEventTypeSchema = z.enum([
|
|
4
|
+
"spawn",
|
|
5
|
+
"exit",
|
|
6
|
+
"re_exec",
|
|
7
|
+
"reparent",
|
|
8
|
+
"signal",
|
|
9
|
+
"name_change",
|
|
10
|
+
"thread_create",
|
|
11
|
+
"thread_exit",
|
|
12
|
+
]);
|
|
13
|
+
/** A single event-backed process-tree event. */
|
|
14
|
+
export const processTreeEventSchema = z.strictObject({
|
|
15
|
+
/** Monotonic event sequence number. */
|
|
16
|
+
sequence: z.number().int().nonnegative(),
|
|
17
|
+
/** Event timestamp in milliseconds. */
|
|
18
|
+
at_ms: z.number().int().nonnegative(),
|
|
19
|
+
/** Event type. */
|
|
20
|
+
type: processEventTypeSchema,
|
|
21
|
+
/** Process ID. */
|
|
22
|
+
pid: z.number().int().positive(),
|
|
23
|
+
/** Parent process ID. */
|
|
24
|
+
ppid: z.number().int().nullable(),
|
|
25
|
+
/** Process name if known. */
|
|
26
|
+
process_name: z.string().nullable(),
|
|
27
|
+
/** Executable path if known. */
|
|
28
|
+
executable: z.string().nullable(),
|
|
29
|
+
/** Command line arguments. */
|
|
30
|
+
arguments: z.array(z.string()).default([]),
|
|
31
|
+
/** Previous PID (for reparent events). */
|
|
32
|
+
previous_pid: z.number().int().nullable(),
|
|
33
|
+
/** Previous PPID (for reparent events). */
|
|
34
|
+
previous_ppid: z.number().int().nullable(),
|
|
35
|
+
/** Exit code (for exit events). */
|
|
36
|
+
exit_code: z.number().int().nullable(),
|
|
37
|
+
/** Signal number (for signal events). */
|
|
38
|
+
signal: z.number().int().nullable(),
|
|
39
|
+
/** Thread ID (for thread events). */
|
|
40
|
+
tid: z.number().int().nullable(),
|
|
41
|
+
});
|
|
42
|
+
/** Process node in a reconstructed tree. */
|
|
43
|
+
export const processNodeSchema = z.strictObject({
|
|
44
|
+
pid: z.number().int().positive(),
|
|
45
|
+
ppid: z.number().int().nullable(),
|
|
46
|
+
process_name: z.string().nullable(),
|
|
47
|
+
executable: z.string().nullable(),
|
|
48
|
+
arguments: z.array(z.string()).default([]),
|
|
49
|
+
children: z.array(z.number().int()).default([]),
|
|
50
|
+
spawn_time_ms: z.number().int().nullable(),
|
|
51
|
+
exit_time_ms: z.number().int().nullable(),
|
|
52
|
+
exit_code: z.number().int().nullable(),
|
|
53
|
+
is_re_exec: z.boolean().default(false),
|
|
54
|
+
is_reparented: z.boolean().default(false),
|
|
55
|
+
previous_ppid: z.number().int().nullable(),
|
|
56
|
+
});
|
|
57
|
+
/** Result of event-backed process-tree reconstruction. */
|
|
58
|
+
export const processTreeReconstructionSchema = z.strictObject({
|
|
59
|
+
/** Root PID of the process tree. */
|
|
60
|
+
root_pid: z.number().int().positive(),
|
|
61
|
+
/** All reconstructed process nodes. */
|
|
62
|
+
processes: z.array(processNodeSchema).min(0).max(10_000),
|
|
63
|
+
/** Events that were consumed. */
|
|
64
|
+
events_consumed: z.number().int().nonnegative(),
|
|
65
|
+
/** Events that could not be matched. */
|
|
66
|
+
events_unmatched: z.number().int().nonnegative(),
|
|
67
|
+
/** Short-lived descendants that were missed by sampling. */
|
|
68
|
+
short_lived_descendants: z.number().int().nonnegative(),
|
|
69
|
+
/** Whether any re-exec was detected. */
|
|
70
|
+
has_re_exec: z.boolean().default(false),
|
|
71
|
+
/** Whether any reparenting was detected. */
|
|
72
|
+
has_reparenting: z.boolean().default(false),
|
|
73
|
+
});
|
|
74
|
+
/** Reconstruct a process tree from event-backed capture. */
|
|
75
|
+
export function reconstructProcessTree(events, rootPid) {
|
|
76
|
+
const nodes = new Map();
|
|
77
|
+
const children = new Map();
|
|
78
|
+
let eventsConsumed = 0;
|
|
79
|
+
let eventsUnmatched = 0;
|
|
80
|
+
let hasReExec = false;
|
|
81
|
+
let hasReparenting = false;
|
|
82
|
+
let shortLivedDescendants = 0;
|
|
83
|
+
const sorted = [...events].sort((a, b) => a.at_ms - b.at_ms);
|
|
84
|
+
for (const event of sorted) {
|
|
85
|
+
eventsConsumed++;
|
|
86
|
+
let node = nodes.get(event.pid);
|
|
87
|
+
switch (event.type) {
|
|
88
|
+
case "spawn": {
|
|
89
|
+
if (!node) {
|
|
90
|
+
node = {
|
|
91
|
+
pid: event.pid,
|
|
92
|
+
ppid: event.ppid,
|
|
93
|
+
process_name: event.process_name,
|
|
94
|
+
executable: event.executable,
|
|
95
|
+
arguments: event.arguments,
|
|
96
|
+
children: [],
|
|
97
|
+
spawn_time_ms: event.at_ms,
|
|
98
|
+
exit_time_ms: null,
|
|
99
|
+
exit_code: null,
|
|
100
|
+
is_re_exec: false,
|
|
101
|
+
is_reparented: false,
|
|
102
|
+
previous_ppid: null,
|
|
103
|
+
};
|
|
104
|
+
nodes.set(event.pid, node);
|
|
105
|
+
}
|
|
106
|
+
if (event.ppid !== null) {
|
|
107
|
+
const parentChildren = children.get(event.ppid) ?? [];
|
|
108
|
+
parentChildren.push(event.pid);
|
|
109
|
+
children.set(event.ppid, parentChildren);
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "exit": {
|
|
114
|
+
if (node) {
|
|
115
|
+
node.exit_time_ms = event.at_ms;
|
|
116
|
+
node.exit_code = event.exit_code;
|
|
117
|
+
if (node.spawn_time_ms !== null &&
|
|
118
|
+
event.at_ms - node.spawn_time_ms < 100)
|
|
119
|
+
shortLivedDescendants++;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
eventsUnmatched++;
|
|
123
|
+
}
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case "re_exec": {
|
|
127
|
+
if (node) {
|
|
128
|
+
node.is_re_exec = true;
|
|
129
|
+
node.executable = event.executable ?? node.executable;
|
|
130
|
+
node.arguments = event.arguments;
|
|
131
|
+
hasReExec = true;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
eventsUnmatched++;
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case "reparent": {
|
|
139
|
+
if (node) {
|
|
140
|
+
node.previous_ppid = node.ppid;
|
|
141
|
+
node.ppid = event.ppid;
|
|
142
|
+
node.is_reparented = true;
|
|
143
|
+
hasReparenting = true;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
eventsUnmatched++;
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "signal":
|
|
151
|
+
case "name_change":
|
|
152
|
+
case "thread_create":
|
|
153
|
+
case "thread_exit":
|
|
154
|
+
// These events are recorded but don't modify the tree structure
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Attach children to nodes
|
|
159
|
+
for (const [pid, childPids] of children) {
|
|
160
|
+
const node = nodes.get(pid);
|
|
161
|
+
if (node)
|
|
162
|
+
node.children = childPids;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
root_pid: rootPid,
|
|
166
|
+
processes: [...nodes.values()],
|
|
167
|
+
events_consumed: eventsConsumed,
|
|
168
|
+
events_unmatched: eventsUnmatched,
|
|
169
|
+
short_lived_descendants: shortLivedDescendants,
|
|
170
|
+
has_re_exec: hasReExec,
|
|
171
|
+
has_reparenting: hasReparenting,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** Get all descendant PIDs of a given root PID. */
|
|
175
|
+
export function getDescendants(processes, rootPid) {
|
|
176
|
+
const byPid = new Map(processes.map((p) => [p.pid, p]));
|
|
177
|
+
const visited = new Set();
|
|
178
|
+
const result = [];
|
|
179
|
+
const queue = [rootPid];
|
|
180
|
+
while (queue.length > 0) {
|
|
181
|
+
const pid = queue.shift();
|
|
182
|
+
if (visited.has(pid))
|
|
183
|
+
continue;
|
|
184
|
+
visited.add(pid);
|
|
185
|
+
const node = byPid.get(pid);
|
|
186
|
+
if (node) {
|
|
187
|
+
for (const child of node.children) {
|
|
188
|
+
if (!visited.has(child)) {
|
|
189
|
+
result.push(child);
|
|
190
|
+
queue.push(child);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
/** Check if a process tree contains a specific PID. */
|
|
198
|
+
export function containsProcess(processes, pid) {
|
|
199
|
+
return processes.some((p) => p.pid === pid);
|
|
200
|
+
}
|
|
201
|
+
/** Get the maximum tree depth from the root. */
|
|
202
|
+
export function maxTreeDepth(processes, rootPid) {
|
|
203
|
+
const byPid = new Map(processes.map((p) => [p.pid, p]));
|
|
204
|
+
function depth(pid, visited) {
|
|
205
|
+
if (visited.has(pid))
|
|
206
|
+
return 0;
|
|
207
|
+
visited.add(pid);
|
|
208
|
+
const node = byPid.get(pid);
|
|
209
|
+
if (!node || node.children.length === 0)
|
|
210
|
+
return 0;
|
|
211
|
+
return 1 + Math.max(...node.children.map((c) => depth(c, visited)));
|
|
212
|
+
}
|
|
213
|
+
return depth(rootPid, new Set());
|
|
214
|
+
}
|
|
@@ -163,6 +163,53 @@ const validateVerifiedResolution = (unknown, evidenceById) => {
|
|
|
163
163
|
if (qualifies !== true)
|
|
164
164
|
throw new TypeError(`Residual unknown ${unknown.unknown_id} has no qualifying resolution evidence`);
|
|
165
165
|
};
|
|
166
|
+
/**
|
|
167
|
+
* Validate one new residual-unknown revision against an already valid ledger.
|
|
168
|
+
* This keeps ordinary mutations proportional to the affected revision while
|
|
169
|
+
* full bundle imports continue to validate the complete graph.
|
|
170
|
+
*/
|
|
171
|
+
export const validateResidualUnknownAddition = (unknown, evidenceById, currentHeads) => {
|
|
172
|
+
const current = currentHeads.get(unknown.unknown_id);
|
|
173
|
+
if (current === undefined
|
|
174
|
+
? unknown.revision !== 1 || unknown.previous_revision_digest !== null
|
|
175
|
+
: unknown.revision !== current.revision + 1 ||
|
|
176
|
+
unknown.previous_revision_digest !== current.revision_digest)
|
|
177
|
+
throw new TypeError(`Residual unknown ${unknown.unknown_id} revision chain is broken`);
|
|
178
|
+
for (const evidenceId of referencedEvidenceIds(unknown))
|
|
179
|
+
if (!evidenceById.has(evidenceId))
|
|
180
|
+
throw new TypeError(`Residual unknown references missing evidence ${evidenceId}`);
|
|
181
|
+
for (const relationship of unknown.relationships)
|
|
182
|
+
if (relationship.unknown_id !== unknown.unknown_id &&
|
|
183
|
+
!currentHeads.has(relationship.unknown_id))
|
|
184
|
+
throw new TypeError(`Residual unknown references missing unknown ${relationship.unknown_id}`);
|
|
185
|
+
if (unknown.resolution?.disposition === "verified")
|
|
186
|
+
validateVerifiedResolution(unknown, evidenceById);
|
|
187
|
+
for (const relationship of unknown.relationships)
|
|
188
|
+
if (relationship.type === "depends-on" &&
|
|
189
|
+
reachesUnknown(relationship.unknown_id, unknown.unknown_id, currentHeads, unknown))
|
|
190
|
+
throw new TypeError("Residual unknown dependency graph contains a cycle");
|
|
191
|
+
};
|
|
192
|
+
const reachesUnknown = (start, goal, currentHeads, candidate) => {
|
|
193
|
+
const pending = [start];
|
|
194
|
+
const visited = new Set();
|
|
195
|
+
while (pending.length > 0) {
|
|
196
|
+
const id = pending.pop();
|
|
197
|
+
if (id === undefined)
|
|
198
|
+
break;
|
|
199
|
+
if (id === goal)
|
|
200
|
+
return true;
|
|
201
|
+
if (visited.has(id))
|
|
202
|
+
continue;
|
|
203
|
+
visited.add(id);
|
|
204
|
+
const unknown = id === candidate.unknown_id ? candidate : currentHeads.get(id);
|
|
205
|
+
if (unknown === undefined)
|
|
206
|
+
continue;
|
|
207
|
+
for (const relationship of unknown.relationships)
|
|
208
|
+
if (relationship.type === "depends-on")
|
|
209
|
+
pending.push(relationship.unknown_id);
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
212
|
+
};
|
|
166
213
|
const evidenceQualifies = (unknown, evidence) => {
|
|
167
214
|
if (unknown.required_authority !== null &&
|
|
168
215
|
evidence.authority !== unknown.required_authority)
|
|
@@ -27,7 +27,7 @@ const failures = [
|
|
|
27
27
|
[
|
|
28
28
|
75,
|
|
29
29
|
"hopper_exited_during_startup",
|
|
30
|
-
"Hopper exited before the REA bridge was ready.
|
|
30
|
+
"Hopper exited before the REA bridge was ready. In CI, run rea doctor --provider hopper --detail full --json; if Hopper showed a UI or license prompt, complete it in the runner user session, otherwise close stale Hopper sessions and retry.",
|
|
31
31
|
],
|
|
32
32
|
[
|
|
33
33
|
76,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { jsonValueSchema } from "./jsonValue.js";
|
|
2
3
|
import { AnalysisOutputError, HopperProtocolError } from "./errors.js";
|
|
3
4
|
import { err, ok } from "./result.js";
|
|
5
|
+
import { nativeApiBoundarySchema } from "./nativeApiBoundary.js";
|
|
4
6
|
/** Return a bounded byte distance between canonical addresses in one space. */
|
|
5
7
|
export const addressDistance = (start, end) => {
|
|
6
8
|
const left = addressCoordinate(start);
|
|
@@ -114,6 +116,16 @@ const boundedSchema = (item) => z
|
|
|
114
116
|
});
|
|
115
117
|
}
|
|
116
118
|
});
|
|
119
|
+
/** Provider-neutral bounded raw-instruction window for one analyzed function. */
|
|
120
|
+
export const functionInstructionWindowSchema = z
|
|
121
|
+
.object({
|
|
122
|
+
procedure: procedureIdentitySchema,
|
|
123
|
+
instructions: boundedSchema(z.string()),
|
|
124
|
+
instructions_scanned: z.number().int().min(0),
|
|
125
|
+
instruction_scan_truncated: z.boolean(),
|
|
126
|
+
limitations: z.array(z.string()),
|
|
127
|
+
})
|
|
128
|
+
.strict();
|
|
117
129
|
const availableReferenceKindSchema = z
|
|
118
130
|
.object({
|
|
119
131
|
available: z.literal(true),
|
|
@@ -226,6 +238,7 @@ export const functionDossierSchema = z
|
|
|
226
238
|
instruction_scan: z
|
|
227
239
|
.object({ scanned: z.number().int().min(0), truncated: z.boolean() })
|
|
228
240
|
.strict(),
|
|
241
|
+
native_api: nativeApiBoundarySchema.optional(),
|
|
229
242
|
limitations: z.array(z.string()).default([]),
|
|
230
243
|
})
|
|
231
244
|
.strict();
|
|
@@ -233,7 +246,7 @@ export const functionDossierSchema = z
|
|
|
233
246
|
export const parseFunctionDossier = (value) => {
|
|
234
247
|
const parsed = functionDossierSchema.safeParse(value);
|
|
235
248
|
return parsed.success
|
|
236
|
-
? ok(parsed.data)
|
|
249
|
+
? ok(jsonValueSchema.parse(parsed.data))
|
|
237
250
|
: err(new AnalysisOutputError("analyze_function", "provider output did not match the dossier contract", { cause: parsed.error }));
|
|
238
251
|
};
|
|
239
252
|
/** Parse page entries and continuation metadata returned by list operations. */
|
|
@@ -31,7 +31,13 @@ const projectIssue = (issue, input) => {
|
|
|
31
31
|
expected: issue.values.filter(isSafeExpected),
|
|
32
32
|
},
|
|
33
33
|
];
|
|
34
|
-
return [
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
path,
|
|
37
|
+
reason: "invalid_value",
|
|
38
|
+
...(issue.message.length > 0 ? { message: issue.message } : {}),
|
|
39
|
+
},
|
|
40
|
+
];
|
|
35
41
|
};
|
|
36
42
|
const valueAtPath = (input, path) => {
|
|
37
43
|
let current = input;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { browserEndpointSchema, browserOriginSchema, } from "./browserObservation.js";
|
|
4
|
+
const boundedTextSchema = z.string().min(1).max(4_096);
|
|
5
|
+
const runtimeFileRootsSchema = z
|
|
6
|
+
.array(z
|
|
7
|
+
.string()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(16_384)
|
|
10
|
+
.refine(isAbsolute, "Runtime file roots must be absolute paths")
|
|
11
|
+
.overwrite(resolve))
|
|
12
|
+
.max(32)
|
|
13
|
+
.overwrite((roots) => [...new Set(roots)].sort())
|
|
14
|
+
.default([]);
|
|
15
|
+
const runtimeOriginsSchema = z
|
|
16
|
+
.array(browserOriginSchema)
|
|
17
|
+
.max(32)
|
|
18
|
+
.overwrite((origins) => [...new Set(origins)].sort())
|
|
19
|
+
.default([]);
|
|
20
|
+
const approvedRuntimeScope = {
|
|
21
|
+
inspector_endpoint: browserEndpointSchema,
|
|
22
|
+
allowed_file_roots: runtimeFileRootsSchema,
|
|
23
|
+
allowed_origins: runtimeOriginsSchema,
|
|
24
|
+
approved: z.literal(true),
|
|
25
|
+
};
|
|
26
|
+
const requireRuntimeScope = (input, context) => {
|
|
27
|
+
if (input.allowed_file_roots.length === 0 &&
|
|
28
|
+
input.allowed_origins.length === 0)
|
|
29
|
+
context.addIssue({
|
|
30
|
+
code: "custom",
|
|
31
|
+
path: ["allowed_file_roots"],
|
|
32
|
+
message: "At least one exact file root or HTTP(S) origin is required",
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
/** Input for listing approved Node/Electron V8 Inspector targets. */
|
|
36
|
+
export const listJavaScriptRuntimeTargetsInputSchema = z
|
|
37
|
+
.strictObject({
|
|
38
|
+
...approvedRuntimeScope,
|
|
39
|
+
offset: z.number().int().min(0).default(0),
|
|
40
|
+
limit: z.number().int().min(1).max(200).default(100),
|
|
41
|
+
})
|
|
42
|
+
.superRefine(requireRuntimeScope);
|
|
43
|
+
export const javascriptRuntimeKindSchema = z.enum([
|
|
44
|
+
"node",
|
|
45
|
+
"electron-main",
|
|
46
|
+
"electron-preload",
|
|
47
|
+
"electron-renderer",
|
|
48
|
+
]);
|
|
49
|
+
export const javascriptRuntimeObservationLimitsSchema = z.strictObject({
|
|
50
|
+
max_events: z.number().int().min(1).max(50_000).default(10_000),
|
|
51
|
+
max_scripts: z.number().int().min(1).max(10_000).default(2_000),
|
|
52
|
+
max_execution_contexts: z.number().int().min(1).max(5_000).default(1_000),
|
|
53
|
+
max_location_bytes: z.number().int().min(64).max(65_536).default(16_384),
|
|
54
|
+
max_total_metadata_bytes: z
|
|
55
|
+
.number()
|
|
56
|
+
.int()
|
|
57
|
+
.min(1_024)
|
|
58
|
+
.max(32 * 1_024 * 1_024)
|
|
59
|
+
.default(4 * 1_024 * 1_024),
|
|
60
|
+
});
|
|
61
|
+
/** Input for one bounded, attach-only V8 Inspector observation. */
|
|
62
|
+
export const observeJavaScriptRuntimeInputSchema = z
|
|
63
|
+
.strictObject({
|
|
64
|
+
...approvedRuntimeScope,
|
|
65
|
+
target_id: z.string().trim().min(1).max(256),
|
|
66
|
+
runtime_kind: javascriptRuntimeKindSchema,
|
|
67
|
+
observation_ms: z.number().int().min(0).max(10_000).default(100),
|
|
68
|
+
limits: javascriptRuntimeObservationLimitsSchema.default({
|
|
69
|
+
max_events: 10_000,
|
|
70
|
+
max_scripts: 2_000,
|
|
71
|
+
max_execution_contexts: 1_000,
|
|
72
|
+
max_location_bytes: 16_384,
|
|
73
|
+
max_total_metadata_bytes: 4 * 1_024 * 1_024,
|
|
74
|
+
}),
|
|
75
|
+
})
|
|
76
|
+
.superRefine(requireRuntimeScope);
|
|
77
|
+
export const javascriptRuntimeVersionSchema = z.strictObject({
|
|
78
|
+
product: z.string().min(1).max(1_024),
|
|
79
|
+
protocol_version: z.string().min(1).max(100),
|
|
80
|
+
v8_version: z.string().max(1_024).nullable(),
|
|
81
|
+
});
|
|
82
|
+
export const javascriptRuntimeLocationSchema = z.discriminatedUnion("kind", [
|
|
83
|
+
z.strictObject({
|
|
84
|
+
kind: z.literal("file"),
|
|
85
|
+
file_path: z.string().min(1).max(16_384),
|
|
86
|
+
}),
|
|
87
|
+
z.strictObject({
|
|
88
|
+
kind: z.literal("url"),
|
|
89
|
+
origin: z.string().min(1).max(2_048),
|
|
90
|
+
sanitized_url: z.string().min(1).max(65_536),
|
|
91
|
+
}),
|
|
92
|
+
z.strictObject({
|
|
93
|
+
kind: z.literal("builtin"),
|
|
94
|
+
specifier: z.string().min(1).max(4_096),
|
|
95
|
+
}),
|
|
96
|
+
]);
|
|
97
|
+
const javascriptRuntimeTargetSchema = z.strictObject({
|
|
98
|
+
target_id: z.string().min(1).max(256),
|
|
99
|
+
protocol_type: z.string().min(1).max(100),
|
|
100
|
+
attached: z.boolean(),
|
|
101
|
+
location: javascriptRuntimeLocationSchema,
|
|
102
|
+
});
|
|
103
|
+
/** Root/origin-filtered V8 Inspector target inventory. */
|
|
104
|
+
export const javascriptRuntimeTargetListSchema = z.strictObject({
|
|
105
|
+
schema_version: z.literal(1),
|
|
106
|
+
runtime: javascriptRuntimeVersionSchema,
|
|
107
|
+
targets: z.strictObject({
|
|
108
|
+
items: z.array(javascriptRuntimeTargetSchema),
|
|
109
|
+
offset: z.number().int().min(0),
|
|
110
|
+
limit: z.number().int().min(1),
|
|
111
|
+
total: z.number().int().min(0),
|
|
112
|
+
next_offset: z.number().int().min(0).nullable(),
|
|
113
|
+
has_more: z.boolean(),
|
|
114
|
+
}),
|
|
115
|
+
excluded: z.strictObject({
|
|
116
|
+
outside_file_roots: z.number().int().min(0),
|
|
117
|
+
outside_origins: z.number().int().min(0),
|
|
118
|
+
unsupported_location: z.number().int().min(0),
|
|
119
|
+
unconnectable: z.number().int().min(0),
|
|
120
|
+
}),
|
|
121
|
+
limitations: z.array(boundedTextSchema).max(100),
|
|
122
|
+
});
|
|
123
|
+
const javascriptRuntimeScriptSchema = z.strictObject({
|
|
124
|
+
script_key: z.string().regex(/^v8_script_[a-f0-9]{64}$/u),
|
|
125
|
+
location: javascriptRuntimeLocationSchema,
|
|
126
|
+
execution_context_key: z.string().max(64).nullable(),
|
|
127
|
+
cdp_hash: z.string().max(512).nullable(),
|
|
128
|
+
length: z.number().int().min(0),
|
|
129
|
+
is_module: z.boolean(),
|
|
130
|
+
status: z.literal("observed-loaded"),
|
|
131
|
+
});
|
|
132
|
+
const javascriptRuntimeContextSchema = z.strictObject({
|
|
133
|
+
context_key: z.string().min(1).max(64),
|
|
134
|
+
state: z.enum(["created", "destroyed", "cleared"]),
|
|
135
|
+
name: z.string().max(1_024).nullable(),
|
|
136
|
+
origin: z.string().max(4_096).nullable(),
|
|
137
|
+
});
|
|
138
|
+
/** Deterministic passive script/context snapshot from one bounded window. */
|
|
139
|
+
export const javascriptRuntimeObservationSchema = z.strictObject({
|
|
140
|
+
schema_version: z.literal(1),
|
|
141
|
+
runtime: javascriptRuntimeVersionSchema,
|
|
142
|
+
target: javascriptRuntimeTargetSchema.extend({
|
|
143
|
+
runtime_kind: javascriptRuntimeKindSchema,
|
|
144
|
+
runtime_kind_authority: z.literal("caller-declared-unverified"),
|
|
145
|
+
}),
|
|
146
|
+
capture: z.strictObject({
|
|
147
|
+
observation_ms: z.number().int().min(0),
|
|
148
|
+
events_observed: z.number().int().min(0),
|
|
149
|
+
events_retained: z.number().int().min(0),
|
|
150
|
+
events_dropped: z.number().int().min(0),
|
|
151
|
+
metadata_bytes_retained: z.number().int().min(0),
|
|
152
|
+
truncated: z.boolean(),
|
|
153
|
+
truncation_reasons: z.array(boundedTextSchema).max(20),
|
|
154
|
+
}),
|
|
155
|
+
scripts: z.strictObject({
|
|
156
|
+
items: z.array(javascriptRuntimeScriptSchema),
|
|
157
|
+
observed_total: z.number().int().min(0),
|
|
158
|
+
excluded: z.strictObject({
|
|
159
|
+
outside_file_roots: z.number().int().min(0),
|
|
160
|
+
outside_origins: z.number().int().min(0),
|
|
161
|
+
unsupported_location: z.number().int().min(0),
|
|
162
|
+
invalid_protocol_value: z.number().int().min(0),
|
|
163
|
+
}),
|
|
164
|
+
}),
|
|
165
|
+
execution_contexts: z.array(javascriptRuntimeContextSchema),
|
|
166
|
+
directly_observed: z.array(boundedTextSchema).max(20),
|
|
167
|
+
unavailable_without_instrumentation: z.array(boundedTextSchema).max(20),
|
|
168
|
+
unknowns: z.array(boundedTextSchema).max(100),
|
|
169
|
+
limitations: z.array(boundedTextSchema).max(100),
|
|
170
|
+
});
|