autoremediator 0.7.0 → 0.9.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 +92 -69
- package/dist/{chunk-MUFP2DQX.js → chunk-EDPCMRUW.js} +3510 -2170
- package/dist/chunk-EDPCMRUW.js.map +1 -0
- package/dist/cli.js +195 -8
- package/dist/cli.js.map +1 -1
- package/dist/index-Di8lB6CG.d.ts +401 -0
- package/dist/index.d.ts +4 -6
- package/dist/index.js +9 -5
- package/dist/mcp/server.d.ts +75 -2
- package/dist/mcp/server.js +72 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/openapi/server.d.ts +444 -137
- package/dist/openapi/server.js +358 -147
- package/dist/openapi/server.js.map +1 -1
- package/dist/{options-schema-DfLBOsPI.d.ts → options-schema-CH5GjZY1.d.ts} +18 -2
- package/llms.txt +36 -7
- package/package.json +10 -5
- package/dist/chunk-MUFP2DQX.js.map +0 -1
- package/dist/remediate-from-scan-C-E7gqxF.d.ts +0 -211
package/dist/openapi/server.js
CHANGED
|
@@ -6,139 +6,53 @@ import {
|
|
|
6
6
|
createRemediateOptionSchemaProperties,
|
|
7
7
|
createScanOptionSchemaProperties,
|
|
8
8
|
createScanReportSchemaProperties,
|
|
9
|
+
inspectPatchArtifact,
|
|
10
|
+
listPatchArtifacts,
|
|
9
11
|
planRemediation,
|
|
10
12
|
remediate,
|
|
11
|
-
remediateFromScan
|
|
12
|
-
|
|
13
|
+
remediateFromScan,
|
|
14
|
+
validatePatchArtifact
|
|
15
|
+
} from "../chunk-EDPCMRUW.js";
|
|
13
16
|
|
|
14
17
|
// src/openapi/server.ts
|
|
15
18
|
import http from "http";
|
|
16
19
|
import { fileURLToPath } from "url";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
// src/openapi/spec/schemas.ts
|
|
22
|
+
var PATCH_ARTIFACT_OPTION_PROPERTIES = {
|
|
23
|
+
cwd: { type: "string", description: OPTION_DESCRIPTIONS.cwd },
|
|
24
|
+
patchesDir: { type: "string", description: OPTION_DESCRIPTIONS.patchesDir },
|
|
25
|
+
packageManager: {
|
|
26
|
+
type: "string",
|
|
27
|
+
enum: ["npm", "pnpm", "yarn"],
|
|
28
|
+
description: OPTION_DESCRIPTIONS.packageManager
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
};
|
|
31
|
+
var REMEDIATION_REPORT_SCHEMA = {
|
|
32
|
+
type: "object",
|
|
33
|
+
properties: {
|
|
34
|
+
cveId: { type: "string" },
|
|
35
|
+
cveDetails: { type: ["object", "null"] },
|
|
36
|
+
vulnerablePackages: { type: "array", items: { type: "object" } },
|
|
37
|
+
results: { type: "array", items: { type: "object" } },
|
|
38
|
+
agentSteps: { type: "number" },
|
|
39
|
+
summary: { type: "string" },
|
|
40
|
+
evidenceFile: { type: "string" },
|
|
41
|
+
llmUsage: { type: "array", items: { type: "object" } },
|
|
42
|
+
correlation: { type: "object" },
|
|
43
|
+
provenance: { type: "object" },
|
|
44
|
+
constraints: { type: "object" },
|
|
45
|
+
resumedFromCache: { type: "boolean" }
|
|
27
46
|
}
|
|
28
|
-
return DEFAULT_PORT;
|
|
29
|
-
}
|
|
30
|
-
function readBody(req) {
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
let raw = "";
|
|
33
|
-
req.setEncoding("utf8");
|
|
34
|
-
req.on("data", (chunk) => {
|
|
35
|
-
raw += chunk;
|
|
36
|
-
});
|
|
37
|
-
req.on("end", () => {
|
|
38
|
-
try {
|
|
39
|
-
resolve(raw ? JSON.parse(raw) : {});
|
|
40
|
-
} catch {
|
|
41
|
-
reject(new Error("Invalid JSON body"));
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
req.on("error", reject);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
function send(res, status, body) {
|
|
48
|
-
const payload = JSON.stringify(body);
|
|
49
|
-
res.writeHead(status, {
|
|
50
|
-
"Content-Type": "application/json",
|
|
51
|
-
"Content-Length": Buffer.byteLength(payload)
|
|
52
|
-
});
|
|
53
|
-
res.end(payload);
|
|
54
|
-
}
|
|
55
|
-
function withOpenApiSource(options) {
|
|
56
|
-
const normalized = typeof options === "object" && options !== null ? options : {};
|
|
57
|
-
return {
|
|
58
|
-
...normalized,
|
|
59
|
-
source: typeof normalized.source === "string" ? normalized.source : "openapi"
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
var defaultDeps = {
|
|
63
|
-
remediateFn: remediate,
|
|
64
|
-
remediateFromScanFn: remediateFromScan,
|
|
65
|
-
planRemediationFn: planRemediation
|
|
66
47
|
};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return send(res, 200, OPENAPI_SPEC);
|
|
76
|
-
}
|
|
77
|
-
if (method === "POST" && url.pathname === "/remediate") {
|
|
78
|
-
let body;
|
|
79
|
-
try {
|
|
80
|
-
body = await readBody(req);
|
|
81
|
-
} catch {
|
|
82
|
-
return send(res, 400, { error: "Invalid JSON body" });
|
|
83
|
-
}
|
|
84
|
-
if (typeof body.cveId !== "string" || !body.cveId) {
|
|
85
|
-
return send(res, 400, { error: "cveId is required (string)" });
|
|
86
|
-
}
|
|
87
|
-
try {
|
|
88
|
-
const report = await deps.remediateFn(body.cveId, withOpenApiSource(body.options));
|
|
89
|
-
return send(res, 200, report);
|
|
90
|
-
} catch (err) {
|
|
91
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
92
|
-
return send(res, 400, { error: message });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (method === "POST" && url.pathname === "/plan-remediation") {
|
|
96
|
-
let body;
|
|
97
|
-
try {
|
|
98
|
-
body = await readBody(req);
|
|
99
|
-
} catch {
|
|
100
|
-
return send(res, 400, { error: "Invalid JSON body" });
|
|
101
|
-
}
|
|
102
|
-
if (typeof body.cveId !== "string" || !body.cveId) {
|
|
103
|
-
return send(res, 400, { error: "cveId is required (string)" });
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
const report = await deps.planRemediationFn(body.cveId, withOpenApiSource(body.options));
|
|
107
|
-
return send(res, 200, report);
|
|
108
|
-
} catch (err) {
|
|
109
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
110
|
-
return send(res, 400, { error: message });
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (method === "POST" && url.pathname === "/remediate-from-scan") {
|
|
114
|
-
let body;
|
|
115
|
-
try {
|
|
116
|
-
body = await readBody(req);
|
|
117
|
-
} catch {
|
|
118
|
-
return send(res, 400, { error: "Invalid JSON body" });
|
|
119
|
-
}
|
|
120
|
-
if (typeof body.inputPath !== "string" || !body.inputPath) {
|
|
121
|
-
return send(res, 400, { error: "inputPath is required (string)" });
|
|
122
|
-
}
|
|
123
|
-
try {
|
|
124
|
-
const report = await deps.remediateFromScanFn(body.inputPath, withOpenApiSource(body.options));
|
|
125
|
-
return send(res, 200, report);
|
|
126
|
-
} catch (err) {
|
|
127
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
128
|
-
return send(res, 400, { error: message });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return send(res, 404, { error: "Not found" });
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
var OPENAPI_SPEC = {
|
|
135
|
-
openapi: "3.1.0",
|
|
136
|
-
info: {
|
|
137
|
-
title: "autoremediator",
|
|
138
|
-
version: PACKAGE_VERSION,
|
|
139
|
-
description: "Agentic CVE remediation for Node.js dependency projects"
|
|
140
|
-
},
|
|
141
|
-
paths: {
|
|
48
|
+
var ERROR_RESPONSE_SCHEMA = {
|
|
49
|
+
type: "object",
|
|
50
|
+
properties: { error: { type: "string" } }
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// src/openapi/spec/paths.ts
|
|
54
|
+
function createOpenApiPaths() {
|
|
55
|
+
return {
|
|
142
56
|
"/remediate": {
|
|
143
57
|
post: {
|
|
144
58
|
operationId: "remediate",
|
|
@@ -169,18 +83,11 @@ var OPENAPI_SPEC = {
|
|
|
169
83
|
responses: {
|
|
170
84
|
"200": {
|
|
171
85
|
description: "RemediationReport",
|
|
172
|
-
content: { "application/json": { schema:
|
|
86
|
+
content: { "application/json": { schema: REMEDIATION_REPORT_SCHEMA } }
|
|
173
87
|
},
|
|
174
88
|
"400": {
|
|
175
89
|
description: "Invalid input or remediation error",
|
|
176
|
-
content: {
|
|
177
|
-
"application/json": {
|
|
178
|
-
schema: {
|
|
179
|
-
type: "object",
|
|
180
|
-
properties: { error: { type: "string" } }
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
90
|
+
content: { "application/json": { schema: ERROR_RESPONSE_SCHEMA } }
|
|
184
91
|
}
|
|
185
92
|
}
|
|
186
93
|
}
|
|
@@ -205,7 +112,11 @@ var OPENAPI_SPEC = {
|
|
|
205
112
|
options: {
|
|
206
113
|
type: "object",
|
|
207
114
|
description: "RemediateOptions",
|
|
208
|
-
properties: createRemediateOptionSchemaProperties({
|
|
115
|
+
properties: createRemediateOptionSchemaProperties({
|
|
116
|
+
includeDryRun: false,
|
|
117
|
+
includePreview: false,
|
|
118
|
+
includeEvidence: true
|
|
119
|
+
})
|
|
209
120
|
}
|
|
210
121
|
}
|
|
211
122
|
}
|
|
@@ -215,18 +126,11 @@ var OPENAPI_SPEC = {
|
|
|
215
126
|
responses: {
|
|
216
127
|
"200": {
|
|
217
128
|
description: "RemediationReport",
|
|
218
|
-
content: { "application/json": { schema:
|
|
129
|
+
content: { "application/json": { schema: REMEDIATION_REPORT_SCHEMA } }
|
|
219
130
|
},
|
|
220
131
|
"400": {
|
|
221
132
|
description: "Invalid input or remediation error",
|
|
222
|
-
content: {
|
|
223
|
-
"application/json": {
|
|
224
|
-
schema: {
|
|
225
|
-
type: "object",
|
|
226
|
-
properties: { error: { type: "string" } }
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
133
|
+
content: { "application/json": { schema: ERROR_RESPONSE_SCHEMA } }
|
|
230
134
|
}
|
|
231
135
|
}
|
|
232
136
|
}
|
|
@@ -271,15 +175,115 @@ var OPENAPI_SPEC = {
|
|
|
271
175
|
},
|
|
272
176
|
"400": {
|
|
273
177
|
description: "Invalid input or remediation error",
|
|
178
|
+
content: { "application/json": { schema: ERROR_RESPONSE_SCHEMA } }
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"/patches/list": {
|
|
184
|
+
post: {
|
|
185
|
+
operationId: "listPatchArtifacts",
|
|
186
|
+
summary: "List stored patch artifacts",
|
|
187
|
+
requestBody: {
|
|
188
|
+
required: false,
|
|
189
|
+
content: {
|
|
190
|
+
"application/json": {
|
|
191
|
+
schema: {
|
|
192
|
+
type: "object",
|
|
193
|
+
properties: {
|
|
194
|
+
options: {
|
|
195
|
+
type: "object",
|
|
196
|
+
description: "PatchArtifactQueryOptions",
|
|
197
|
+
properties: PATCH_ARTIFACT_OPTION_PROPERTIES
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
responses: {
|
|
205
|
+
"200": {
|
|
206
|
+
description: "Patch artifact summaries",
|
|
274
207
|
content: {
|
|
275
|
-
"application/json": {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
208
|
+
"application/json": { schema: { type: "array", items: { type: "object" } } }
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"400": {
|
|
212
|
+
description: "Invalid input",
|
|
213
|
+
content: { "application/json": { schema: ERROR_RESPONSE_SCHEMA } }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"/patches/inspect": {
|
|
219
|
+
post: {
|
|
220
|
+
operationId: "inspectPatchArtifact",
|
|
221
|
+
summary: "Inspect a stored patch artifact",
|
|
222
|
+
requestBody: {
|
|
223
|
+
required: true,
|
|
224
|
+
content: {
|
|
225
|
+
"application/json": {
|
|
226
|
+
schema: {
|
|
227
|
+
type: "object",
|
|
228
|
+
required: ["patchFilePath"],
|
|
229
|
+
properties: {
|
|
230
|
+
patchFilePath: { type: "string" },
|
|
231
|
+
options: {
|
|
232
|
+
type: "object",
|
|
233
|
+
description: "PatchArtifactQueryOptions",
|
|
234
|
+
properties: {
|
|
235
|
+
cwd: PATCH_ARTIFACT_OPTION_PROPERTIES.cwd
|
|
236
|
+
}
|
|
237
|
+
}
|
|
279
238
|
}
|
|
280
239
|
}
|
|
281
240
|
}
|
|
282
241
|
}
|
|
242
|
+
},
|
|
243
|
+
responses: {
|
|
244
|
+
"200": {
|
|
245
|
+
description: "Patch artifact inspection",
|
|
246
|
+
content: { "application/json": { schema: { type: "object" } } }
|
|
247
|
+
},
|
|
248
|
+
"400": {
|
|
249
|
+
description: "Invalid input",
|
|
250
|
+
content: { "application/json": { schema: ERROR_RESPONSE_SCHEMA } }
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"/patches/validate": {
|
|
256
|
+
post: {
|
|
257
|
+
operationId: "validatePatchArtifact",
|
|
258
|
+
summary: "Validate a stored patch artifact",
|
|
259
|
+
requestBody: {
|
|
260
|
+
required: true,
|
|
261
|
+
content: {
|
|
262
|
+
"application/json": {
|
|
263
|
+
schema: {
|
|
264
|
+
type: "object",
|
|
265
|
+
required: ["patchFilePath"],
|
|
266
|
+
properties: {
|
|
267
|
+
patchFilePath: { type: "string" },
|
|
268
|
+
options: {
|
|
269
|
+
type: "object",
|
|
270
|
+
description: "PatchArtifactQueryOptions",
|
|
271
|
+
properties: PATCH_ARTIFACT_OPTION_PROPERTIES
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
responses: {
|
|
279
|
+
"200": {
|
|
280
|
+
description: "Patch artifact validation report",
|
|
281
|
+
content: { "application/json": { schema: { type: "object" } } }
|
|
282
|
+
},
|
|
283
|
+
"400": {
|
|
284
|
+
description: "Invalid input",
|
|
285
|
+
content: { "application/json": { schema: ERROR_RESPONSE_SCHEMA } }
|
|
286
|
+
}
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
289
|
},
|
|
@@ -302,8 +306,215 @@ var OPENAPI_SPEC = {
|
|
|
302
306
|
}
|
|
303
307
|
}
|
|
304
308
|
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/openapi/spec/index.ts
|
|
313
|
+
var OPENAPI_SPEC = {
|
|
314
|
+
openapi: "3.1.0",
|
|
315
|
+
info: {
|
|
316
|
+
title: "autoremediator",
|
|
317
|
+
version: PACKAGE_VERSION,
|
|
318
|
+
description: "Agentic CVE remediation for Node.js dependency projects"
|
|
319
|
+
},
|
|
320
|
+
servers: [
|
|
321
|
+
{
|
|
322
|
+
url: "http://localhost:3000",
|
|
323
|
+
description: "Local development server"
|
|
324
|
+
}
|
|
325
|
+
],
|
|
326
|
+
"x-agent-compatible": true,
|
|
327
|
+
"x-agent-use-cases": [
|
|
328
|
+
"plan-first remediation",
|
|
329
|
+
"scanner-driven batch remediation",
|
|
330
|
+
"patch lifecycle validation"
|
|
331
|
+
],
|
|
332
|
+
paths: createOpenApiPaths()
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
// src/openapi/http-utils.ts
|
|
336
|
+
var DEFAULT_PORT = 3e3;
|
|
337
|
+
function parsePort() {
|
|
338
|
+
const idx = process.argv.indexOf("--port");
|
|
339
|
+
if (idx !== -1 && process.argv[idx + 1]) {
|
|
340
|
+
const p = parseInt(process.argv[idx + 1], 10);
|
|
341
|
+
if (!isNaN(p)) return p;
|
|
342
|
+
}
|
|
343
|
+
if (process.env.PORT) {
|
|
344
|
+
const p = parseInt(process.env.PORT, 10);
|
|
345
|
+
if (!isNaN(p)) return p;
|
|
305
346
|
}
|
|
347
|
+
return DEFAULT_PORT;
|
|
348
|
+
}
|
|
349
|
+
function readBody(req) {
|
|
350
|
+
return new Promise((resolve, reject) => {
|
|
351
|
+
let raw = "";
|
|
352
|
+
req.setEncoding("utf8");
|
|
353
|
+
req.on("data", (chunk) => {
|
|
354
|
+
raw += chunk;
|
|
355
|
+
});
|
|
356
|
+
req.on("end", () => {
|
|
357
|
+
try {
|
|
358
|
+
resolve(raw ? JSON.parse(raw) : {});
|
|
359
|
+
} catch {
|
|
360
|
+
reject(new Error("Invalid JSON body"));
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
req.on("error", reject);
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
function sendJson(res, status, body) {
|
|
367
|
+
const payload = JSON.stringify(body);
|
|
368
|
+
res.writeHead(status, {
|
|
369
|
+
"Content-Type": "application/json",
|
|
370
|
+
"Content-Length": Buffer.byteLength(payload)
|
|
371
|
+
});
|
|
372
|
+
res.end(payload);
|
|
373
|
+
}
|
|
374
|
+
function withOpenApiSource(options) {
|
|
375
|
+
const normalized = typeof options === "object" && options !== null ? options : {};
|
|
376
|
+
return {
|
|
377
|
+
...normalized,
|
|
378
|
+
source: typeof normalized.source === "string" ? normalized.source : "openapi"
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// src/openapi/handlers/validators.ts
|
|
383
|
+
function toMessage(error) {
|
|
384
|
+
return error instanceof Error ? error.message : String(error);
|
|
385
|
+
}
|
|
386
|
+
async function readJsonBody(req, res) {
|
|
387
|
+
try {
|
|
388
|
+
return await readBody(req);
|
|
389
|
+
} catch {
|
|
390
|
+
sendJson(res, 400, { error: "Invalid JSON body" });
|
|
391
|
+
return void 0;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async function runRequest(res, action) {
|
|
395
|
+
try {
|
|
396
|
+
const report = await action();
|
|
397
|
+
sendJson(res, 200, report);
|
|
398
|
+
} catch (error) {
|
|
399
|
+
sendJson(res, 400, { error: toMessage(error) });
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
function requireStringField(body, field, res, errorMessage) {
|
|
403
|
+
if (!body || typeof body[field] !== "string" || !body[field]) {
|
|
404
|
+
sendJson(res, 400, { error: errorMessage });
|
|
405
|
+
return void 0;
|
|
406
|
+
}
|
|
407
|
+
return body[field];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/openapi/handlers/routes.ts
|
|
411
|
+
function createOpenApiRouteHandlers(deps) {
|
|
412
|
+
const routes = /* @__PURE__ */ new Map();
|
|
413
|
+
routes.set("GET /health", async (_req, res) => {
|
|
414
|
+
sendJson(res, 200, { status: "ok" });
|
|
415
|
+
});
|
|
416
|
+
routes.set("GET /openapi.json", async (_req, res) => {
|
|
417
|
+
sendJson(res, 200, OPENAPI_SPEC);
|
|
418
|
+
});
|
|
419
|
+
routes.set("POST /remediate", async (req, res) => {
|
|
420
|
+
const body = await readJsonBody(req, res);
|
|
421
|
+
const cveId = requireStringField(body, "cveId", res, "cveId is required (string)");
|
|
422
|
+
if (!cveId) return;
|
|
423
|
+
await runRequest(
|
|
424
|
+
res,
|
|
425
|
+
() => deps.remediateFn(cveId, withOpenApiSource(body?.options))
|
|
426
|
+
);
|
|
427
|
+
});
|
|
428
|
+
routes.set("POST /plan-remediation", async (req, res) => {
|
|
429
|
+
const body = await readJsonBody(req, res);
|
|
430
|
+
const cveId = requireStringField(body, "cveId", res, "cveId is required (string)");
|
|
431
|
+
if (!cveId) return;
|
|
432
|
+
await runRequest(
|
|
433
|
+
res,
|
|
434
|
+
() => deps.planRemediationFn(cveId, withOpenApiSource(body?.options))
|
|
435
|
+
);
|
|
436
|
+
});
|
|
437
|
+
routes.set("POST /remediate-from-scan", async (req, res) => {
|
|
438
|
+
const body = await readJsonBody(req, res);
|
|
439
|
+
const inputPath = requireStringField(
|
|
440
|
+
body,
|
|
441
|
+
"inputPath",
|
|
442
|
+
res,
|
|
443
|
+
"inputPath is required (string)"
|
|
444
|
+
);
|
|
445
|
+
if (!inputPath) return;
|
|
446
|
+
await runRequest(
|
|
447
|
+
res,
|
|
448
|
+
() => deps.remediateFromScanFn(inputPath, withOpenApiSource(body?.options))
|
|
449
|
+
);
|
|
450
|
+
});
|
|
451
|
+
routes.set("POST /patches/list", async (req, res) => {
|
|
452
|
+
const body = await readJsonBody(req, res);
|
|
453
|
+
if (!body) return;
|
|
454
|
+
await runRequest(res, () => deps.listPatchArtifactsFn(body.options));
|
|
455
|
+
});
|
|
456
|
+
routes.set("POST /patches/inspect", async (req, res) => {
|
|
457
|
+
const body = await readJsonBody(req, res);
|
|
458
|
+
const patchFilePath = requireStringField(
|
|
459
|
+
body,
|
|
460
|
+
"patchFilePath",
|
|
461
|
+
res,
|
|
462
|
+
"patchFilePath is required (string)"
|
|
463
|
+
);
|
|
464
|
+
if (!patchFilePath) return;
|
|
465
|
+
await runRequest(
|
|
466
|
+
res,
|
|
467
|
+
() => deps.inspectPatchArtifactFn(patchFilePath, body?.options)
|
|
468
|
+
);
|
|
469
|
+
});
|
|
470
|
+
routes.set("POST /patches/validate", async (req, res) => {
|
|
471
|
+
const body = await readJsonBody(req, res);
|
|
472
|
+
const patchFilePath = requireStringField(
|
|
473
|
+
body,
|
|
474
|
+
"patchFilePath",
|
|
475
|
+
res,
|
|
476
|
+
"patchFilePath is required (string)"
|
|
477
|
+
);
|
|
478
|
+
if (!patchFilePath) return;
|
|
479
|
+
await runRequest(
|
|
480
|
+
res,
|
|
481
|
+
() => deps.validatePatchArtifactFn(patchFilePath, body?.options)
|
|
482
|
+
);
|
|
483
|
+
});
|
|
484
|
+
return routes;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// src/openapi/handlers/index.ts
|
|
488
|
+
async function handleOpenApiRequest(req, res, deps) {
|
|
489
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
490
|
+
const method = req.method?.toUpperCase() ?? "GET";
|
|
491
|
+
const key = `${method} ${url.pathname}`;
|
|
492
|
+
const routes = createOpenApiRouteHandlers(deps);
|
|
493
|
+
const handler = routes.get(key);
|
|
494
|
+
if (!handler) {
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
await handler(req, res);
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/openapi/server.ts
|
|
502
|
+
var defaultDeps = {
|
|
503
|
+
remediateFn: remediate,
|
|
504
|
+
remediateFromScanFn: remediateFromScan,
|
|
505
|
+
planRemediationFn: planRemediation,
|
|
506
|
+
listPatchArtifactsFn: listPatchArtifacts,
|
|
507
|
+
inspectPatchArtifactFn: inspectPatchArtifact,
|
|
508
|
+
validatePatchArtifactFn: validatePatchArtifact
|
|
306
509
|
};
|
|
510
|
+
function createOpenApiServer(deps = defaultDeps) {
|
|
511
|
+
return http.createServer(async (req, res) => {
|
|
512
|
+
if (await handleOpenApiRequest(req, res, deps)) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
return sendJson(res, 404, { error: "Not found" });
|
|
516
|
+
});
|
|
517
|
+
}
|
|
307
518
|
function isMainModule() {
|
|
308
519
|
if (!process.argv[1]) return false;
|
|
309
520
|
return fileURLToPath(import.meta.url) === process.argv[1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/openapi/server.ts"],"sourcesContent":["/**\n * autoremediator OpenAPI HTTP server\n *\n * Exposes POST /remediate and POST /remediate-from-scan as a lightweight\n * HTTP server using Node.js built-in http module (no framework dependency).\n *\n * Start: node dist/openapi/server.js [--port 3000]\n */\nimport http from \"node:http\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n createRemediateOptionSchemaProperties,\n createScanOptionSchemaProperties,\n createScanReportSchemaProperties,\n OPTION_DESCRIPTIONS,\n planRemediation,\n remediate,\n remediateFromScan,\n} from \"../api/index.js\";\nimport type { RemediateOptions, ScanOptions } from \"../api/index.js\";\nimport { PACKAGE_VERSION } from \"../version\";\n\nconst DEFAULT_PORT = 3000;\n\nfunction parsePort(): number {\n const idx = process.argv.indexOf(\"--port\");\n if (idx !== -1 && process.argv[idx + 1]) {\n const p = parseInt(process.argv[idx + 1], 10);\n if (!isNaN(p)) return p;\n }\n if (process.env.PORT) {\n const p = parseInt(process.env.PORT, 10);\n if (!isNaN(p)) return p;\n }\n return DEFAULT_PORT;\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let raw = \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk: string) => { raw += chunk; });\n req.on(\"end\", () => {\n try {\n resolve(raw ? JSON.parse(raw) : {});\n } catch {\n reject(new Error(\"Invalid JSON body\"));\n }\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction send(res: http.ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(payload),\n });\n res.end(payload);\n}\n\nfunction withOpenApiSource(options: unknown): Record<string, unknown> {\n const normalized = typeof options === \"object\" && options !== null\n ? (options as Record<string, unknown>)\n : {};\n return {\n ...normalized,\n source: typeof normalized.source === \"string\" ? normalized.source : \"openapi\",\n };\n}\n\ninterface OpenApiServerDeps {\n remediateFn: typeof remediate;\n remediateFromScanFn: typeof remediateFromScan;\n planRemediationFn: typeof planRemediation;\n}\n\nconst defaultDeps: OpenApiServerDeps = {\n remediateFn: remediate,\n remediateFromScanFn: remediateFromScan,\n planRemediationFn: planRemediation,\n};\n\nexport function createOpenApiServer(deps: OpenApiServerDeps = defaultDeps): http.Server {\n return http.createServer(async (req, res) => {\n const url = new URL(req.url ?? \"/\", `http://localhost`);\n const method = req.method?.toUpperCase();\n\n // Health check\n if (method === \"GET\" && url.pathname === \"/health\") {\n return send(res, 200, { status: \"ok\" });\n }\n\n // OpenAPI spec\n if (method === \"GET\" && url.pathname === \"/openapi.json\") {\n return send(res, 200, OPENAPI_SPEC);\n }\n\n if (method === \"POST\" && url.pathname === \"/remediate\") {\n let body: { cveId?: unknown; options?: unknown };\n try {\n body = (await readBody(req)) as typeof body;\n } catch {\n return send(res, 400, { error: \"Invalid JSON body\" });\n }\n if (typeof body.cveId !== \"string\" || !body.cveId) {\n return send(res, 400, { error: \"cveId is required (string)\" });\n }\n try {\n const report = await deps.remediateFn(body.cveId, withOpenApiSource(body.options) as RemediateOptions);\n return send(res, 200, report);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return send(res, 400, { error: message });\n }\n }\n\n if (method === \"POST\" && url.pathname === \"/plan-remediation\") {\n let body: { cveId?: unknown; options?: unknown };\n try {\n body = (await readBody(req)) as typeof body;\n } catch {\n return send(res, 400, { error: \"Invalid JSON body\" });\n }\n if (typeof body.cveId !== \"string\" || !body.cveId) {\n return send(res, 400, { error: \"cveId is required (string)\" });\n }\n try {\n const report = await deps.planRemediationFn(body.cveId, withOpenApiSource(body.options) as RemediateOptions);\n return send(res, 200, report);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return send(res, 400, { error: message });\n }\n }\n\n if (method === \"POST\" && url.pathname === \"/remediate-from-scan\") {\n let body: { inputPath?: unknown; options?: unknown };\n try {\n body = (await readBody(req)) as typeof body;\n } catch {\n return send(res, 400, { error: \"Invalid JSON body\" });\n }\n if (typeof body.inputPath !== \"string\" || !body.inputPath) {\n return send(res, 400, { error: \"inputPath is required (string)\" });\n }\n try {\n const report = await deps.remediateFromScanFn(body.inputPath, withOpenApiSource(body.options) as ScanOptions);\n return send(res, 200, report);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return send(res, 400, { error: message });\n }\n }\n\n return send(res, 404, { error: \"Not found\" });\n });\n}\n\nexport const OPENAPI_SPEC = {\n openapi: \"3.1.0\",\n info: {\n title: \"autoremediator\",\n version: PACKAGE_VERSION,\n description: \"Agentic CVE remediation for Node.js dependency projects\",\n },\n paths: {\n \"/remediate\": {\n post: {\n operationId: \"remediate\",\n summary: \"Remediate a single CVE\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"cveId\"],\n properties: {\n cveId: {\n type: \"string\",\n description: OPTION_DESCRIPTIONS.cveId,\n pattern: \"^CVE-\\\\d{4}-\\\\d+$\",\n },\n options: {\n type: \"object\",\n description: \"RemediateOptions\",\n properties: createRemediateOptionSchemaProperties(),\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"RemediationReport\",\n content: { \"application/json\": { schema: { type: \"object\" } } },\n },\n \"400\": {\n description: \"Invalid input or remediation error\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: { error: { type: \"string\" } },\n },\n },\n },\n },\n },\n },\n },\n \"/plan-remediation\": {\n post: {\n operationId: \"planRemediation\",\n summary: \"Generate a non-mutating remediation preview\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"cveId\"],\n properties: {\n cveId: {\n type: \"string\",\n description: OPTION_DESCRIPTIONS.cveId,\n pattern: \"^CVE-\\\\d{4}-\\\\d+$\",\n },\n options: {\n type: \"object\",\n description: \"RemediateOptions\",\n properties: createRemediateOptionSchemaProperties({ includeDryRun: false, includePreview: false, includeEvidence: true }),\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"RemediationReport\",\n content: { \"application/json\": { schema: { type: \"object\" } } },\n },\n \"400\": {\n description: \"Invalid input or remediation error\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: { error: { type: \"string\" } },\n },\n },\n },\n },\n },\n },\n },\n \"/remediate-from-scan\": {\n post: {\n operationId: \"remediateFromScan\",\n summary: \"Parse a scanner file and remediate all found CVEs\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"inputPath\"],\n properties: {\n inputPath: {\n type: \"string\",\n description: OPTION_DESCRIPTIONS.inputPath,\n },\n options: {\n type: \"object\",\n description: \"ScanOptions\",\n properties: createScanOptionSchemaProperties(),\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"ScanReport\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: createScanReportSchemaProperties(),\n },\n },\n },\n },\n \"400\": {\n description: \"Invalid input or remediation error\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: { error: { type: \"string\" } },\n },\n },\n },\n },\n },\n },\n },\n \"/health\": {\n get: {\n operationId: \"health\",\n summary: \"Health check\",\n responses: {\n \"200\": {\n description: \"Server is healthy\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: { status: { type: \"string\" } },\n },\n },\n },\n },\n },\n },\n },\n },\n};\n\nfunction isMainModule(): boolean {\n if (!process.argv[1]) return false;\n return fileURLToPath(import.meta.url) === process.argv[1];\n}\n\nif (isMainModule()) {\n const port = parsePort();\n const server = createOpenApiServer();\n server.listen(port, () => {\n console.log(`autoremediator OpenAPI server listening on http://localhost:${port}`);\n console.log(` OpenAPI spec: http://localhost:${port}/openapi.json`);\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/openapi/server.ts","../../src/openapi/spec/schemas.ts","../../src/openapi/spec/paths.ts","../../src/openapi/spec/index.ts","../../src/openapi/http-utils.ts","../../src/openapi/handlers/validators.ts","../../src/openapi/handlers/routes.ts","../../src/openapi/handlers/index.ts"],"sourcesContent":["/**\n * autoremediator OpenAPI HTTP server\n *\n * Exposes POST /remediate and POST /remediate-from-scan as a lightweight\n * HTTP server using Node.js built-in http module (no framework dependency).\n *\n * Start: node dist/openapi/server.js [--port 3000]\n */\nimport http from \"node:http\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n inspectPatchArtifact,\n listPatchArtifacts,\n planRemediation,\n remediate,\n remediateFromScan,\n validatePatchArtifact,\n} from \"../api/index.js\";\nimport { OPENAPI_SPEC } from \"./spec/index.js\";\nimport { handleOpenApiRequest } from \"./handlers/index.js\";\nimport { parsePort, sendJson } from \"./http-utils.js\";\n\nexport { OPENAPI_SPEC } from \"./spec/index.js\";\n\nexport interface OpenApiServerDeps {\n remediateFn: typeof remediate;\n remediateFromScanFn: typeof remediateFromScan;\n planRemediationFn: typeof planRemediation;\n listPatchArtifactsFn: typeof listPatchArtifacts;\n inspectPatchArtifactFn: typeof inspectPatchArtifact;\n validatePatchArtifactFn: typeof validatePatchArtifact;\n}\n\nconst defaultDeps: OpenApiServerDeps = {\n remediateFn: remediate,\n remediateFromScanFn: remediateFromScan,\n planRemediationFn: planRemediation,\n listPatchArtifactsFn: listPatchArtifacts,\n inspectPatchArtifactFn: inspectPatchArtifact,\n validatePatchArtifactFn: validatePatchArtifact,\n};\n\nexport function createOpenApiServer(deps: OpenApiServerDeps = defaultDeps): http.Server {\n return http.createServer(async (req, res) => {\n if (await handleOpenApiRequest(req, res, deps)) {\n return;\n }\n return sendJson(res, 404, { error: \"Not found\" });\n });\n}\n\nfunction isMainModule(): boolean {\n if (!process.argv[1]) return false;\n return fileURLToPath(import.meta.url) === process.argv[1];\n}\n\nif (isMainModule()) {\n const port = parsePort();\n const server = createOpenApiServer();\n server.listen(port, () => {\n console.log(`autoremediator OpenAPI server listening on http://localhost:${port}`);\n console.log(` OpenAPI spec: http://localhost:${port}/openapi.json`);\n });\n}\n","import { OPTION_DESCRIPTIONS } from \"../../api/index.js\";\n\nexport const PATCH_ARTIFACT_OPTION_PROPERTIES = {\n cwd: { type: \"string\", description: OPTION_DESCRIPTIONS.cwd },\n patchesDir: { type: \"string\", description: OPTION_DESCRIPTIONS.patchesDir },\n packageManager: {\n type: \"string\",\n enum: [\"npm\", \"pnpm\", \"yarn\"],\n description: OPTION_DESCRIPTIONS.packageManager,\n },\n} as const;\n\nexport const REMEDIATION_REPORT_SCHEMA = {\n type: \"object\",\n properties: {\n cveId: { type: \"string\" },\n cveDetails: { type: [\"object\", \"null\"] },\n vulnerablePackages: { type: \"array\", items: { type: \"object\" } },\n results: { type: \"array\", items: { type: \"object\" } },\n agentSteps: { type: \"number\" },\n summary: { type: \"string\" },\n evidenceFile: { type: \"string\" },\n llmUsage: { type: \"array\", items: { type: \"object\" } },\n correlation: { type: \"object\" },\n provenance: { type: \"object\" },\n constraints: { type: \"object\" },\n resumedFromCache: { type: \"boolean\" },\n },\n} as const;\n\nexport const ERROR_RESPONSE_SCHEMA = {\n type: \"object\",\n properties: { error: { type: \"string\" } },\n} as const;","import {\n createRemediateOptionSchemaProperties,\n createScanOptionSchemaProperties,\n createScanReportSchemaProperties,\n OPTION_DESCRIPTIONS,\n} from \"../../api/index.js\";\nimport {\n ERROR_RESPONSE_SCHEMA,\n PATCH_ARTIFACT_OPTION_PROPERTIES,\n REMEDIATION_REPORT_SCHEMA,\n} from \"./schemas.js\";\n\nexport function createOpenApiPaths() {\n return {\n \"/remediate\": {\n post: {\n operationId: \"remediate\",\n summary: \"Remediate a single CVE\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"cveId\"],\n properties: {\n cveId: {\n type: \"string\",\n description: OPTION_DESCRIPTIONS.cveId,\n pattern: \"^CVE-\\\\d{4}-\\\\d+$\",\n },\n options: {\n type: \"object\",\n description: \"RemediateOptions\",\n properties: createRemediateOptionSchemaProperties(),\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"RemediationReport\",\n content: { \"application/json\": { schema: REMEDIATION_REPORT_SCHEMA } },\n },\n \"400\": {\n description: \"Invalid input or remediation error\",\n content: { \"application/json\": { schema: ERROR_RESPONSE_SCHEMA } },\n },\n },\n },\n },\n \"/plan-remediation\": {\n post: {\n operationId: \"planRemediation\",\n summary: \"Generate a non-mutating remediation preview\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"cveId\"],\n properties: {\n cveId: {\n type: \"string\",\n description: OPTION_DESCRIPTIONS.cveId,\n pattern: \"^CVE-\\\\d{4}-\\\\d+$\",\n },\n options: {\n type: \"object\",\n description: \"RemediateOptions\",\n properties: createRemediateOptionSchemaProperties({\n includeDryRun: false,\n includePreview: false,\n includeEvidence: true,\n }),\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"RemediationReport\",\n content: { \"application/json\": { schema: REMEDIATION_REPORT_SCHEMA } },\n },\n \"400\": {\n description: \"Invalid input or remediation error\",\n content: { \"application/json\": { schema: ERROR_RESPONSE_SCHEMA } },\n },\n },\n },\n },\n \"/remediate-from-scan\": {\n post: {\n operationId: \"remediateFromScan\",\n summary: \"Parse a scanner file and remediate all found CVEs\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"inputPath\"],\n properties: {\n inputPath: {\n type: \"string\",\n description: OPTION_DESCRIPTIONS.inputPath,\n },\n options: {\n type: \"object\",\n description: \"ScanOptions\",\n properties: createScanOptionSchemaProperties(),\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"ScanReport\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: createScanReportSchemaProperties(),\n },\n },\n },\n },\n \"400\": {\n description: \"Invalid input or remediation error\",\n content: { \"application/json\": { schema: ERROR_RESPONSE_SCHEMA } },\n },\n },\n },\n },\n \"/patches/list\": {\n post: {\n operationId: \"listPatchArtifacts\",\n summary: \"List stored patch artifacts\",\n requestBody: {\n required: false,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: {\n options: {\n type: \"object\",\n description: \"PatchArtifactQueryOptions\",\n properties: PATCH_ARTIFACT_OPTION_PROPERTIES,\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"Patch artifact summaries\",\n content: {\n \"application/json\": { schema: { type: \"array\", items: { type: \"object\" } } },\n },\n },\n \"400\": {\n description: \"Invalid input\",\n content: { \"application/json\": { schema: ERROR_RESPONSE_SCHEMA } },\n },\n },\n },\n },\n \"/patches/inspect\": {\n post: {\n operationId: \"inspectPatchArtifact\",\n summary: \"Inspect a stored patch artifact\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"patchFilePath\"],\n properties: {\n patchFilePath: { type: \"string\" },\n options: {\n type: \"object\",\n description: \"PatchArtifactQueryOptions\",\n properties: {\n cwd: PATCH_ARTIFACT_OPTION_PROPERTIES.cwd,\n },\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"Patch artifact inspection\",\n content: { \"application/json\": { schema: { type: \"object\" } } },\n },\n \"400\": {\n description: \"Invalid input\",\n content: { \"application/json\": { schema: ERROR_RESPONSE_SCHEMA } },\n },\n },\n },\n },\n \"/patches/validate\": {\n post: {\n operationId: \"validatePatchArtifact\",\n summary: \"Validate a stored patch artifact\",\n requestBody: {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n required: [\"patchFilePath\"],\n properties: {\n patchFilePath: { type: \"string\" },\n options: {\n type: \"object\",\n description: \"PatchArtifactQueryOptions\",\n properties: PATCH_ARTIFACT_OPTION_PROPERTIES,\n },\n },\n },\n },\n },\n },\n responses: {\n \"200\": {\n description: \"Patch artifact validation report\",\n content: { \"application/json\": { schema: { type: \"object\" } } },\n },\n \"400\": {\n description: \"Invalid input\",\n content: { \"application/json\": { schema: ERROR_RESPONSE_SCHEMA } },\n },\n },\n },\n },\n \"/health\": {\n get: {\n operationId: \"health\",\n summary: \"Health check\",\n responses: {\n \"200\": {\n description: \"Server is healthy\",\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n properties: { status: { type: \"string\" } },\n },\n },\n },\n },\n },\n },\n },\n } as const;\n}","import { PACKAGE_VERSION } from \"../../version.js\";\nimport { createOpenApiPaths } from \"./paths.js\";\n\nexport const OPENAPI_SPEC = {\n openapi: \"3.1.0\",\n info: {\n title: \"autoremediator\",\n version: PACKAGE_VERSION,\n description: \"Agentic CVE remediation for Node.js dependency projects\",\n },\n servers: [\n {\n url: \"http://localhost:3000\",\n description: \"Local development server\",\n },\n ],\n \"x-agent-compatible\": true,\n \"x-agent-use-cases\": [\n \"plan-first remediation\",\n \"scanner-driven batch remediation\",\n \"patch lifecycle validation\",\n ],\n paths: createOpenApiPaths(),\n} as const;","import http from \"node:http\";\n\nconst DEFAULT_PORT = 3000;\n\nexport function parsePort(): number {\n const idx = process.argv.indexOf(\"--port\");\n if (idx !== -1 && process.argv[idx + 1]) {\n const p = parseInt(process.argv[idx + 1], 10);\n if (!isNaN(p)) return p;\n }\n if (process.env.PORT) {\n const p = parseInt(process.env.PORT, 10);\n if (!isNaN(p)) return p;\n }\n return DEFAULT_PORT;\n}\n\nexport function readBody(req: http.IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let raw = \"\";\n req.setEncoding(\"utf8\");\n req.on(\"data\", (chunk: string) => {\n raw += chunk;\n });\n req.on(\"end\", () => {\n try {\n resolve(raw ? JSON.parse(raw) : {});\n } catch {\n reject(new Error(\"Invalid JSON body\"));\n }\n });\n req.on(\"error\", reject);\n });\n}\n\nexport function sendJson(res: http.ServerResponse, status: number, body: unknown): void {\n const payload = JSON.stringify(body);\n res.writeHead(status, {\n \"Content-Type\": \"application/json\",\n \"Content-Length\": Buffer.byteLength(payload),\n });\n res.end(payload);\n}\n\nexport function withOpenApiSource(options: unknown): Record<string, unknown> {\n const normalized =\n typeof options === \"object\" && options !== null\n ? (options as Record<string, unknown>)\n : {};\n return {\n ...normalized,\n source: typeof normalized.source === \"string\" ? normalized.source : \"openapi\",\n };\n}","import http from \"node:http\";\nimport { readBody, sendJson } from \"../http-utils.js\";\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport async function readJsonBody<T>(\n req: http.IncomingMessage,\n res: http.ServerResponse\n): Promise<T | undefined> {\n try {\n return (await readBody(req)) as T;\n } catch {\n sendJson(res, 400, { error: \"Invalid JSON body\" });\n return undefined;\n }\n}\n\nexport async function runRequest<T>(\n res: http.ServerResponse,\n action: () => Promise<T>\n): Promise<void> {\n try {\n const report = await action();\n sendJson(res, 200, report);\n } catch (error) {\n sendJson(res, 400, { error: toMessage(error) });\n }\n}\n\nexport function requireStringField(\n body: Record<string, unknown> | undefined,\n field: string,\n res: http.ServerResponse,\n errorMessage: string\n): string | undefined {\n if (!body || typeof body[field] !== \"string\" || !(body[field] as string)) {\n sendJson(res, 400, { error: errorMessage });\n return undefined;\n }\n return body[field] as string;\n}","import http from \"node:http\";\nimport type { PatchArtifactQueryOptions, RemediateOptions, ScanOptions } from \"../../api/index.js\";\nimport { OPENAPI_SPEC } from \"../spec/index.js\";\nimport { sendJson, withOpenApiSource } from \"../http-utils.js\";\nimport type { OpenApiServerDeps } from \"../server.js\";\nimport { readJsonBody, requireStringField, runRequest } from \"./validators.js\";\n\ntype RouteHandler = (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;\n\nexport function createOpenApiRouteHandlers(deps: OpenApiServerDeps): Map<string, RouteHandler> {\n const routes = new Map<string, RouteHandler>();\n\n routes.set(\"GET /health\", async (_req, res) => {\n sendJson(res, 200, { status: \"ok\" });\n });\n\n routes.set(\"GET /openapi.json\", async (_req, res) => {\n sendJson(res, 200, OPENAPI_SPEC);\n });\n\n routes.set(\"POST /remediate\", async (req, res) => {\n const body = await readJsonBody<{ cveId?: unknown; options?: unknown }>(req, res);\n const cveId = requireStringField(body as Record<string, unknown> | undefined, \"cveId\", res, \"cveId is required (string)\");\n if (!cveId) return;\n\n await runRequest(res, () =>\n deps.remediateFn(cveId, withOpenApiSource(body?.options) as RemediateOptions)\n );\n });\n\n routes.set(\"POST /plan-remediation\", async (req, res) => {\n const body = await readJsonBody<{ cveId?: unknown; options?: unknown }>(req, res);\n const cveId = requireStringField(body as Record<string, unknown> | undefined, \"cveId\", res, \"cveId is required (string)\");\n if (!cveId) return;\n\n await runRequest(res, () =>\n deps.planRemediationFn(cveId, withOpenApiSource(body?.options) as RemediateOptions)\n );\n });\n\n routes.set(\"POST /remediate-from-scan\", async (req, res) => {\n const body = await readJsonBody<{ inputPath?: unknown; options?: unknown }>(req, res);\n const inputPath = requireStringField(\n body as Record<string, unknown> | undefined,\n \"inputPath\",\n res,\n \"inputPath is required (string)\"\n );\n if (!inputPath) return;\n\n await runRequest(res, () =>\n deps.remediateFromScanFn(inputPath, withOpenApiSource(body?.options) as ScanOptions)\n );\n });\n\n routes.set(\"POST /patches/list\", async (req, res) => {\n const body = await readJsonBody<{ options?: unknown }>(req, res);\n if (!body) return;\n await runRequest(res, () => deps.listPatchArtifactsFn(body.options as PatchArtifactQueryOptions));\n });\n\n routes.set(\"POST /patches/inspect\", async (req, res) => {\n const body = await readJsonBody<{ patchFilePath?: unknown; options?: unknown }>(req, res);\n const patchFilePath = requireStringField(\n body as Record<string, unknown> | undefined,\n \"patchFilePath\",\n res,\n \"patchFilePath is required (string)\"\n );\n if (!patchFilePath) return;\n await runRequest(res, () =>\n deps.inspectPatchArtifactFn(patchFilePath, body?.options as PatchArtifactQueryOptions)\n );\n });\n\n routes.set(\"POST /patches/validate\", async (req, res) => {\n const body = await readJsonBody<{ patchFilePath?: unknown; options?: unknown }>(req, res);\n const patchFilePath = requireStringField(\n body as Record<string, unknown> | undefined,\n \"patchFilePath\",\n res,\n \"patchFilePath is required (string)\"\n );\n if (!patchFilePath) return;\n await runRequest(res, () =>\n deps.validatePatchArtifactFn(patchFilePath, body?.options as PatchArtifactQueryOptions)\n );\n });\n\n return routes;\n}","import http from \"node:http\";\nimport type { OpenApiServerDeps } from \"../server.js\";\nimport { createOpenApiRouteHandlers } from \"./routes.js\";\n\nexport async function handleOpenApiRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n deps: OpenApiServerDeps\n): Promise<boolean> {\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n const method = req.method?.toUpperCase() ?? \"GET\";\n const key = `${method} ${url.pathname}`;\n\n const routes = createOpenApiRouteHandlers(deps);\n const handler = routes.get(key);\n if (!handler) {\n return false;\n }\n\n await handler(req, res);\n return true;\n}"],"mappings":"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","names":[]}
|