@safebrowse/daemon 0.1.3 → 0.1.5

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.
@@ -0,0 +1,325 @@
1
+ const SUPPORTED_FEATURE_SCHEMA_VERSIONS = new Set(["recipe_v1", "v1"]);
2
+ const DECISION_LABELS = new Set([
3
+ "allow_read_only",
4
+ "require_shadow_replay",
5
+ "require_user_approval",
6
+ "deny"
7
+ ]);
8
+ const ENFORCEMENT_MODES = new Set(["off", "shadow", "tighten"]);
9
+ const MAX_REASON_CODES = 32;
10
+ const MAX_EVIDENCE_CHUNKS = 12;
11
+ const MAX_EVIDENCE_EXCERPT_CHARS = 1_000;
12
+ function normalizeBaseUrl(value) {
13
+ const trimmed = value?.trim();
14
+ if (!trimmed) {
15
+ return undefined;
16
+ }
17
+ let end = trimmed.length;
18
+ while (end > 0 && trimmed.charCodeAt(end - 1) === 47) {
19
+ end -= 1;
20
+ }
21
+ return trimmed.slice(0, end);
22
+ }
23
+ function defaultHealthSnapshot(configured, enforcementMode, validationError) {
24
+ return {
25
+ configured,
26
+ ready: false,
27
+ runtimeMode: "python_sidecar",
28
+ enforcementMode,
29
+ ...(validationError ? { validationError } : {})
30
+ };
31
+ }
32
+ function isRecord(value) {
33
+ return typeof value === "object" && value !== null && !Array.isArray(value);
34
+ }
35
+ function isFiniteProbability(value) {
36
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
37
+ }
38
+ function isFiniteNumber(value) {
39
+ return typeof value === "number" && Number.isFinite(value);
40
+ }
41
+ function requiredString(value, field) {
42
+ if (typeof value !== "string" || value.trim().length === 0) {
43
+ throw new Error(`invalid model guard ${field}`);
44
+ }
45
+ return value;
46
+ }
47
+ function optionalString(value, field) {
48
+ if (value === undefined) {
49
+ return undefined;
50
+ }
51
+ return requiredString(value, field);
52
+ }
53
+ function validateFeatureSchemaVersion(value) {
54
+ const version = requiredString(value, "feature schema version");
55
+ if (!SUPPORTED_FEATURE_SCHEMA_VERSIONS.has(version)) {
56
+ throw new Error(`unsupported model guard feature schema version: ${version}`);
57
+ }
58
+ return version;
59
+ }
60
+ function validateComponentDigests(value) {
61
+ if (value === undefined) {
62
+ return undefined;
63
+ }
64
+ if (!isRecord(value)) {
65
+ throw new Error("invalid model guard component digests");
66
+ }
67
+ const digests = {};
68
+ for (const [key, digest] of Object.entries(value)) {
69
+ if (!/^[A-Za-z0-9_.:-]{1,80}$/.test(key)) {
70
+ throw new Error("invalid model guard component digest key");
71
+ }
72
+ if (typeof digest !== "string" || !/^[A-Fa-f0-9]{32,128}$/.test(digest)) {
73
+ throw new Error("invalid model guard component digest value");
74
+ }
75
+ digests[key] = digest;
76
+ }
77
+ return digests;
78
+ }
79
+ function validateReasonCodes(value) {
80
+ if (!Array.isArray(value) || value.length > MAX_REASON_CODES) {
81
+ throw new Error("invalid model guard reason codes");
82
+ }
83
+ return value.map((entry) => {
84
+ if (typeof entry !== "string" || !/^[A-Z0-9_:-]{1,128}$/.test(entry)) {
85
+ throw new Error("invalid model guard reason code");
86
+ }
87
+ return entry;
88
+ });
89
+ }
90
+ function validateEvidenceChunkIds(value) {
91
+ if (!Array.isArray(value) || value.length > MAX_EVIDENCE_CHUNKS) {
92
+ throw new Error("invalid model guard evidence chunk ids");
93
+ }
94
+ return value.map((entry) => {
95
+ if (typeof entry !== "string" || entry.trim().length === 0 || entry.length > 128) {
96
+ throw new Error("invalid model guard evidence chunk id");
97
+ }
98
+ return entry;
99
+ });
100
+ }
101
+ function validateEvidenceChunks(value) {
102
+ if (value === undefined) {
103
+ return undefined;
104
+ }
105
+ if (!Array.isArray(value) || value.length > MAX_EVIDENCE_CHUNKS) {
106
+ throw new Error("invalid model guard evidence chunks");
107
+ }
108
+ return value.map((entry) => {
109
+ if (!isRecord(entry)) {
110
+ throw new Error("invalid model guard evidence chunk");
111
+ }
112
+ const chunkId = requiredString(entry.chunkId, "evidence chunk id");
113
+ const excerpt = requiredString(entry.excerpt, "evidence chunk excerpt").slice(0, MAX_EVIDENCE_EXCERPT_CHARS);
114
+ if (entry.score !== undefined && !isFiniteNumber(entry.score)) {
115
+ throw new Error("invalid model guard evidence chunk score");
116
+ }
117
+ return {
118
+ chunkId,
119
+ ...(typeof entry.score === "number" ? { score: entry.score } : {}),
120
+ excerpt
121
+ };
122
+ });
123
+ }
124
+ function validateHealthPayload(payload) {
125
+ if (!isRecord(payload)) {
126
+ throw new Error("invalid model guard health payload");
127
+ }
128
+ if (payload.status !== "ok" && payload.status !== "error") {
129
+ throw new Error("invalid model guard health status");
130
+ }
131
+ if (typeof payload.ready !== "boolean") {
132
+ throw new Error("invalid model guard health ready flag");
133
+ }
134
+ if (payload.runtimeMode !== "python_sidecar") {
135
+ throw new Error("invalid model guard runtime mode");
136
+ }
137
+ if (!ENFORCEMENT_MODES.has(payload.enforcementMode)) {
138
+ throw new Error("invalid model guard health enforcement mode");
139
+ }
140
+ const ready = payload.status === "ok" && payload.ready;
141
+ const bundleVersion = optionalString(payload.bundleVersion, "bundle version");
142
+ const featureSchemaVersion = ready
143
+ ? validateFeatureSchemaVersion(payload.featureSchemaVersion)
144
+ : optionalString(payload.featureSchemaVersion, "feature schema version");
145
+ const bundleDigest = optionalString(payload.bundleDigest, "bundle digest");
146
+ const componentDigests = validateComponentDigests(payload.componentDigests);
147
+ return {
148
+ status: payload.status,
149
+ ready,
150
+ runtimeMode: "python_sidecar",
151
+ enforcementMode: payload.enforcementMode,
152
+ ...(bundleVersion ? { bundleVersion } : {}),
153
+ ...(featureSchemaVersion ? { featureSchemaVersion } : {}),
154
+ ...(bundleDigest ? { bundleDigest } : {}),
155
+ ...(componentDigests ? { componentDigests } : {})
156
+ };
157
+ }
158
+ function validateObservationResponsePayload(payload, health, enforcementMode) {
159
+ if (!isRecord(payload) || !isRecord(payload.assessment)) {
160
+ throw new Error("invalid model guard observation response");
161
+ }
162
+ const assessment = payload.assessment;
163
+ const decisionLabel = assessment.decisionLabel;
164
+ const calibratedDecisionLabel = assessment.calibratedDecisionLabel;
165
+ if (!DECISION_LABELS.has(decisionLabel)) {
166
+ throw new Error("invalid model guard decision label");
167
+ }
168
+ if (!DECISION_LABELS.has(calibratedDecisionLabel)) {
169
+ throw new Error("invalid model guard calibrated decision label");
170
+ }
171
+ if (!isFiniteProbability(assessment.binaryThreatProbability)) {
172
+ throw new Error("invalid model guard probability");
173
+ }
174
+ if (!isRecord(assessment.pipeline)) {
175
+ throw new Error("invalid model guard pipeline metadata");
176
+ }
177
+ const pipeline = assessment.pipeline;
178
+ if (pipeline.runtimeMode !== "python_sidecar") {
179
+ throw new Error("invalid model guard assessment runtime mode");
180
+ }
181
+ if (typeof pipeline.scoredAt !== "string" || pipeline.scoredAt.trim().length === 0) {
182
+ throw new Error("invalid model guard scored timestamp");
183
+ }
184
+ const bundleVersion = requiredString(assessment.bundleVersion, "bundle version");
185
+ const featureSchemaVersion = validateFeatureSchemaVersion(assessment.featureSchemaVersion);
186
+ if (health.bundleVersion && health.bundleVersion !== bundleVersion) {
187
+ throw new Error("model guard bundle version changed after health check");
188
+ }
189
+ if (health.featureSchemaVersion && health.featureSchemaVersion !== featureSchemaVersion) {
190
+ throw new Error("model guard feature schema version changed after health check");
191
+ }
192
+ const bundleDigest = optionalString(assessment.bundleDigest, "bundle digest") ?? health.bundleDigest;
193
+ const componentDigests = validateComponentDigests(assessment.componentDigests) ?? health.componentDigests;
194
+ const evidenceChunks = validateEvidenceChunks(payload.evidenceChunks);
195
+ return {
196
+ assessment: {
197
+ assessmentId: requiredString(assessment.assessmentId, "assessment id"),
198
+ bundleVersion,
199
+ featureSchemaVersion,
200
+ ...(bundleDigest ? { bundleDigest } : {}),
201
+ ...(componentDigests ? { componentDigests } : {}),
202
+ binaryThreatProbability: assessment.binaryThreatProbability,
203
+ decisionLabel: decisionLabel,
204
+ calibratedDecisionLabel: calibratedDecisionLabel,
205
+ coarseReasonCodes: validateReasonCodes(assessment.coarseReasonCodes),
206
+ evidenceChunkIds: validateEvidenceChunkIds(assessment.evidenceChunkIds),
207
+ pipeline: {
208
+ runtimeMode: "python_sidecar",
209
+ enforcementMode,
210
+ scoredAt: pipeline.scoredAt,
211
+ ...(typeof pipeline.latencyMs === "number" && Number.isFinite(pipeline.latencyMs)
212
+ ? { latencyMs: pipeline.latencyMs }
213
+ : {}),
214
+ ...(typeof pipeline.sentinelVersion === "string"
215
+ ? { sentinelVersion: pipeline.sentinelVersion }
216
+ : {}),
217
+ ...(typeof pipeline.expertVersion === "string"
218
+ ? { expertVersion: pipeline.expertVersion }
219
+ : {}),
220
+ ...(typeof pipeline.stackerVersion === "string"
221
+ ? { stackerVersion: pipeline.stackerVersion }
222
+ : {})
223
+ }
224
+ },
225
+ ...(evidenceChunks ? { evidenceChunks } : {})
226
+ };
227
+ }
228
+ class DisabledModelGuardClient {
229
+ enforcementMode;
230
+ configured = false;
231
+ constructor(enforcementMode = "off") {
232
+ this.enforcementMode = enforcementMode;
233
+ }
234
+ async scoreObservation() {
235
+ throw new Error("model guard is not configured");
236
+ }
237
+ async getCachedHealth() {
238
+ return defaultHealthSnapshot(false, this.enforcementMode);
239
+ }
240
+ async refreshHealth() {
241
+ return defaultHealthSnapshot(false, this.enforcementMode);
242
+ }
243
+ async close() {
244
+ return;
245
+ }
246
+ }
247
+ class HttpModelGuardClient {
248
+ baseUrl;
249
+ timeoutMs;
250
+ enforcementMode;
251
+ configured = true;
252
+ cachedHealth;
253
+ constructor(baseUrl, timeoutMs, enforcementMode) {
254
+ this.baseUrl = baseUrl;
255
+ this.timeoutMs = timeoutMs;
256
+ this.enforcementMode = enforcementMode;
257
+ this.cachedHealth = defaultHealthSnapshot(true, enforcementMode);
258
+ }
259
+ async scoreObservation(request) {
260
+ if (this.enforcementMode === "off") {
261
+ throw new Error("model guard scoring is disabled");
262
+ }
263
+ if (!this.cachedHealth.ready) {
264
+ throw new Error("model guard is not ready");
265
+ }
266
+ const response = await fetch(`${this.baseUrl}/v1/score/observation`, {
267
+ method: "POST",
268
+ headers: {
269
+ "content-type": "application/json"
270
+ },
271
+ body: JSON.stringify(request),
272
+ signal: AbortSignal.timeout(this.timeoutMs)
273
+ });
274
+ if (!response.ok) {
275
+ throw new Error(`model guard returned ${response.status}`);
276
+ }
277
+ return validateObservationResponsePayload(await response.json(), this.cachedHealth, this.enforcementMode);
278
+ }
279
+ async getCachedHealth() {
280
+ return this.cachedHealth;
281
+ }
282
+ async refreshHealth() {
283
+ try {
284
+ const response = await fetch(`${this.baseUrl}/health`, {
285
+ method: "GET",
286
+ signal: AbortSignal.timeout(this.timeoutMs)
287
+ });
288
+ if (!response.ok) {
289
+ throw new Error(`model guard returned ${response.status}`);
290
+ }
291
+ const payload = validateHealthPayload(await response.json());
292
+ this.cachedHealth = {
293
+ configured: true,
294
+ ready: payload.ready,
295
+ runtimeMode: payload.runtimeMode,
296
+ enforcementMode: this.enforcementMode,
297
+ bundleVersion: payload.bundleVersion,
298
+ featureSchemaVersion: payload.featureSchemaVersion,
299
+ bundleDigest: payload.bundleDigest,
300
+ componentDigests: payload.componentDigests,
301
+ lastCheckedAt: new Date().toISOString()
302
+ };
303
+ }
304
+ catch (error) {
305
+ this.cachedHealth = {
306
+ ...defaultHealthSnapshot(true, this.enforcementMode, error instanceof Error ? error.message : "model guard health check failed"),
307
+ lastCheckedAt: new Date().toISOString()
308
+ };
309
+ }
310
+ return this.cachedHealth;
311
+ }
312
+ async close() {
313
+ return;
314
+ }
315
+ }
316
+ export function createModelGuardClient(options = {}) {
317
+ const baseUrl = normalizeBaseUrl(options.baseUrl);
318
+ const enforcementMode = options.enforcementMode ?? "off";
319
+ const timeoutMs = options.timeoutMs ?? 2_500;
320
+ if (!baseUrl) {
321
+ return new DisabledModelGuardClient(enforcementMode);
322
+ }
323
+ return new HttpModelGuardClient(baseUrl, timeoutMs, enforcementMode);
324
+ }
325
+ //# sourceMappingURL=modelGuard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelGuard.js","sourceRoot":"","sources":["../src/modelGuard.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,46 @@
1
- import type { CompiledObservation, ParserWorkerProbe, RuntimeContext, StructuredPlannerInput, SurfaceCapture } from "@safebrowse/core";
1
+ import type { CompiledObservationV6, ParserIsolationMode, ParserWorkerProbe, PlannerViewV6, RuntimeContext, SurfaceCapture } from "@safebrowse/core";
2
+ type ToolManifestDigests = {
3
+ manifestHash?: string;
4
+ schemaHash?: string;
5
+ };
6
+ export interface ParserIsolationProbeSnapshot {
7
+ probe: ParserWorkerProbe;
8
+ lastCheckedAt: string;
9
+ }
10
+ export interface ParserIsolationService {
11
+ compileObservation(input: {
12
+ capture: SurfaceCapture;
13
+ workflowHash?: string;
14
+ allowlistedEgress?: string[];
15
+ runtime?: Partial<RuntimeContext>;
16
+ compilerVersion?: "v6";
17
+ parserIsolationMode?: ParserIsolationMode;
18
+ }): Promise<{
19
+ compiledObservation: CompiledObservationV6;
20
+ plannerView?: PlannerViewV6;
21
+ toolManifestDigests?: ToolManifestDigests;
22
+ }>;
23
+ getCachedProbe(): Promise<ParserIsolationProbeSnapshot>;
24
+ refreshProbe(): Promise<ParserIsolationProbeSnapshot>;
25
+ close(): Promise<void>;
26
+ }
27
+ interface ParserIsolationServiceOptions {
28
+ allowlistedEgress?: string[];
29
+ runtime?: Partial<RuntimeContext>;
30
+ }
31
+ export declare function createParserIsolationService(parserIsolationMode?: ParserIsolationMode, options?: ParserIsolationServiceOptions): ParserIsolationService;
2
32
  export declare function compileObservationInIsolation(input: {
3
33
  capture: SurfaceCapture;
4
34
  workflowHash?: string;
5
35
  allowlistedEgress?: string[];
6
36
  runtime?: Partial<RuntimeContext>;
37
+ compilerVersion?: "v6";
38
+ parserIsolationMode?: ParserIsolationMode;
7
39
  }): Promise<{
8
- compiledObservation: CompiledObservation;
9
- plannerInput: StructuredPlannerInput;
40
+ compiledObservation: CompiledObservationV6;
41
+ plannerView?: PlannerViewV6;
42
+ toolManifestDigests?: ToolManifestDigests;
10
43
  }>;
11
- export declare function probeParserIsolation(): Promise<ParserWorkerProbe>;
44
+ export declare function probeParserIsolation(parserIsolationMode?: ParserIsolationMode): Promise<ParserWorkerProbe>;
45
+ export {};
12
46
  //# sourceMappingURL=parserIsolation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parserIsolation.d.ts","sourceRoot":"","sources":["../src/parserIsolation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,cAAc,EACf,MAAM,kBAAkB,CAAC;AAwE1B,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACnC,GAAG,OAAO,CAAC;IACV,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,YAAY,EAAE,sBAAsB,CAAC;CACtC,CAAC,CAQD;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAIjE"}
1
+ {"version":3,"file":"parserIsolation.d.ts","sourceRoot":"","sources":["../src/parserIsolation.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,cAAc,EACf,MAAM,kBAAkB,CAAC;AAgC1B,KAAK,mBAAmB,GAAG;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAmBF,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,iBAAiB,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,kBAAkB,CAAC,KAAK,EAAE;QACxB,OAAO,EAAE,cAAc,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;QAClC,eAAe,CAAC,EAAE,IAAI,CAAC;QACvB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;KAC3C,GAAG,OAAO,CAAC;QACV,mBAAmB,EAAE,qBAAqB,CAAC;QAC3C,WAAW,CAAC,EAAE,aAAa,CAAC;QAC5B,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;KAC3C,CAAC,CAAC;IACH,cAAc,IAAI,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACxD,YAAY,IAAI,OAAO,CAAC,4BAA4B,CAAC,CAAC;IACtD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,6BAA6B;IACrC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CACnC;AAoPD,wBAAgB,4BAA4B,CAC1C,mBAAmB,GAAE,mBAAwC,EAC7D,OAAO,GAAE,6BAAkC,GAC1C,sBAAsB,CAExB;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,OAAO,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C,GAAG,OAAO,CAAC;IACV,mBAAmB,EAAE,qBAAqB,CAAC;IAC3C,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C,CAAC,CAMD;AAED,wBAAgB,oBAAoB,CAClC,mBAAmB,GAAE,mBAAwC,GAC5D,OAAO,CAAC,iBAAiB,CAAC,CAI5B"}
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import { existsSync } from "node:fs";
2
3
  import { fork } from "node:child_process";
3
4
  import { fileURLToPath } from "node:url";
@@ -6,52 +7,201 @@ const moduleDir = dirname(fileURLToPath(import.meta.url));
6
7
  const compiledWorkerPath = resolve(moduleDir, "parserWorker.js");
7
8
  const sourceWorkerPath = resolve(moduleDir, "parserWorker.ts");
8
9
  const workerPath = existsSync(compiledWorkerPath) ? compiledWorkerPath : sourceWorkerPath;
9
- function runWorker(payload) {
10
- return new Promise((resolvePromise, rejectPromise) => {
11
- const child = fork(workerPath, [], {
12
- env: {},
13
- stdio: ["ignore", "ignore", "ignore", "ipc"],
14
- execArgv: workerPath.endsWith(".ts")
15
- ? [...process.execArgv, "--import", "tsx"]
16
- : process.execArgv
10
+ function parserReadRoots() {
11
+ return [...new Set([resolve(process.cwd()), resolve(dirname(workerPath), "..", "..")])];
12
+ }
13
+ function buildExecArgv(mode) {
14
+ const baseArgs = workerPath.endsWith(".ts")
15
+ ? mode === "node_permission_process"
16
+ ? ["--experimental-strip-types"]
17
+ : ["--import", "tsx"]
18
+ : [];
19
+ if (mode !== "node_permission_process") {
20
+ return baseArgs;
21
+ }
22
+ return [
23
+ "--permission",
24
+ ...parserReadRoots().map((root) => `--allow-fs-read=${root}`),
25
+ ...baseArgs
26
+ ];
27
+ }
28
+ class ParserIsolationServiceImpl {
29
+ mode;
30
+ options;
31
+ child;
32
+ closed = false;
33
+ cachedProbe;
34
+ startup;
35
+ pending = new Map();
36
+ constructor(mode, options = {}) {
37
+ this.mode = mode;
38
+ this.options = options;
39
+ }
40
+ async compileObservation(input) {
41
+ const result = await this.sendRequest({
42
+ kind: "parse",
43
+ compilerVersion: input.compilerVersion,
44
+ parserIsolationMode: input.parserIsolationMode ?? this.mode,
45
+ capture: input.capture,
46
+ workflowHash: input.workflowHash,
47
+ allowlistedEgress: input.allowlistedEgress ?? this.options.allowlistedEgress,
48
+ runtime: input.runtime ?? this.options.runtime
17
49
  });
18
- const finish = (error, value) => {
19
- child.removeAllListeners();
20
- child.kill();
21
- if (error) {
22
- rejectPromise(error);
23
- return;
24
- }
25
- resolvePromise(value);
50
+ return result;
51
+ }
52
+ async getCachedProbe() {
53
+ if (this.cachedProbe) {
54
+ return this.cachedProbe;
55
+ }
56
+ return this.refreshProbe();
57
+ }
58
+ async refreshProbe() {
59
+ const probe = await this.sendRequest({
60
+ kind: "probe"
61
+ });
62
+ this.cachedProbe = {
63
+ probe,
64
+ lastCheckedAt: new Date().toISOString()
26
65
  };
27
- child.once("error", (error) => finish(error));
28
- child.once("message", (message) => {
29
- if (!message.ok) {
30
- finish(new Error(message.error));
31
- return;
66
+ return this.cachedProbe;
67
+ }
68
+ async close() {
69
+ this.closed = true;
70
+ this.cachedProbe = undefined;
71
+ const pendingError = new Error("parser isolation service closed");
72
+ for (const [requestId, pending] of this.pending.entries()) {
73
+ this.pending.delete(requestId);
74
+ pending.reject(pendingError);
75
+ }
76
+ this.startup = undefined;
77
+ const child = this.child;
78
+ this.child = undefined;
79
+ if (!child) {
80
+ return;
81
+ }
82
+ await new Promise((resolvePromise) => {
83
+ child.once("close", () => resolvePromise());
84
+ child.kill();
85
+ });
86
+ }
87
+ async ensureWorker() {
88
+ if (this.closed) {
89
+ throw new Error("parser isolation service closed");
90
+ }
91
+ if (this.child?.connected) {
92
+ return;
93
+ }
94
+ if (this.startup) {
95
+ return this.startup;
96
+ }
97
+ this.startup = (async () => {
98
+ const child = fork(workerPath, [], {
99
+ env: workerPath.endsWith(".ts") && this.mode !== "node_permission_process"
100
+ ? { TSX_DISABLE_CACHE: "1" }
101
+ : {},
102
+ stdio: ["ignore", "ignore", "ignore", "ipc"],
103
+ execArgv: buildExecArgv(this.mode)
104
+ });
105
+ child.unref();
106
+ child.on("message", (message) => this.handleMessage(message));
107
+ child.on("error", (error) => this.handleWorkerFailure(error));
108
+ child.on("exit", (code, signal) => {
109
+ const suffix = signal ? ` (${signal})` : "";
110
+ this.handleWorkerFailure(code && code !== 0 ? new Error(`parser worker exited with code ${code}${suffix}`) : undefined);
111
+ });
112
+ this.child = child;
113
+ if (this.options.allowlistedEgress || this.options.runtime) {
114
+ await this.sendRequest({
115
+ kind: "configure",
116
+ parserIsolationMode: this.mode,
117
+ allowlistedEgress: this.options.allowlistedEgress,
118
+ runtime: this.options.runtime
119
+ });
32
120
  }
33
- finish(undefined, (message.probe ?? message.result));
121
+ })().finally(() => {
122
+ this.startup = undefined;
34
123
  });
35
- child.once("exit", (code) => {
36
- if (code && code !== 0) {
37
- finish(new Error(`parser worker exited with code ${code}`));
124
+ return this.startup;
125
+ }
126
+ handleMessage(message) {
127
+ if (!message || typeof message !== "object" || !("requestId" in message)) {
128
+ return;
129
+ }
130
+ const response = message;
131
+ const pending = this.pending.get(response.requestId);
132
+ if (!pending) {
133
+ return;
134
+ }
135
+ this.pending.delete(response.requestId);
136
+ if (!response.ok) {
137
+ pending.reject(new Error(response.error));
138
+ return;
139
+ }
140
+ pending.resolve((response.probe ?? response.result));
141
+ }
142
+ handleWorkerFailure(error) {
143
+ this.cachedProbe = undefined;
144
+ const child = this.child;
145
+ this.child = undefined;
146
+ if (child) {
147
+ child.removeAllListeners();
148
+ }
149
+ if (this.closed && this.pending.size === 0) {
150
+ return;
151
+ }
152
+ const failure = error ?? new Error("parser worker exited unexpectedly");
153
+ for (const [requestId, pending] of this.pending.entries()) {
154
+ this.pending.delete(requestId);
155
+ pending.reject(failure);
156
+ }
157
+ }
158
+ async sendRequest(payload) {
159
+ await this.ensureWorker();
160
+ const child = this.child;
161
+ if (!child?.connected) {
162
+ throw new Error("parser worker is not connected");
163
+ }
164
+ return new Promise((resolvePromise, rejectPromise) => {
165
+ const requestId = randomUUID();
166
+ this.pending.set(requestId, {
167
+ resolve: (value) => resolvePromise(value),
168
+ reject: rejectPromise
169
+ });
170
+ try {
171
+ child.send({
172
+ requestId,
173
+ payload
174
+ });
175
+ }
176
+ catch (error) {
177
+ this.pending.delete(requestId);
178
+ rejectPromise(error instanceof Error ? error : new Error(String(error)));
38
179
  }
39
180
  });
40
- child.send(payload);
41
- });
181
+ }
182
+ }
183
+ const defaultServices = new Map();
184
+ function defaultServiceForMode(mode) {
185
+ let service = defaultServices.get(mode);
186
+ if (!service) {
187
+ service = createParserIsolationService(mode);
188
+ defaultServices.set(mode, service);
189
+ }
190
+ return service;
191
+ }
192
+ export function createParserIsolationService(parserIsolationMode = "scrubbed_process", options = {}) {
193
+ return new ParserIsolationServiceImpl(parserIsolationMode, options);
42
194
  }
43
195
  export function compileObservationInIsolation(input) {
44
- return runWorker({
45
- kind: "parse",
46
- capture: input.capture,
47
- workflowHash: input.workflowHash,
48
- allowlistedEgress: input.allowlistedEgress,
49
- runtime: input.runtime
196
+ const mode = input.parserIsolationMode ?? "scrubbed_process";
197
+ return defaultServiceForMode(mode).compileObservation({
198
+ ...input,
199
+ parserIsolationMode: mode
50
200
  });
51
201
  }
52
- export function probeParserIsolation() {
53
- return runWorker({
54
- kind: "probe"
55
- });
202
+ export function probeParserIsolation(parserIsolationMode = "scrubbed_process") {
203
+ return defaultServiceForMode(parserIsolationMode)
204
+ .refreshProbe()
205
+ .then((snapshot) => snapshot.probe);
56
206
  }
57
207
  //# sourceMappingURL=parserIsolation.js.map