autoremediator 0.6.0 → 0.7.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.
@@ -1,14 +1,6 @@
1
+ import { J as JsonSchemaProperty } from '../options-schema-DfLBOsPI.js';
1
2
  import http from 'node:http';
2
- import { remediate, remediateFromScan, planRemediation } from '../index.js';
3
-
4
- /**
5
- * autoremediator OpenAPI HTTP server
6
- *
7
- * Exposes POST /remediate and POST /remediate-from-scan as a lightweight
8
- * HTTP server using Node.js built-in http module (no framework dependency).
9
- *
10
- * Start: node dist/openapi/server.js [--port 3000]
11
- */
3
+ import { r as remediate, l as remediateFromScan, p as planRemediation } from '../remediate-from-scan-C-E7gqxF.js';
12
4
 
13
5
  interface OpenApiServerDeps {
14
6
  remediateFn: typeof remediate;
@@ -44,9 +36,7 @@ declare const OPENAPI_SPEC: {
44
36
  options: {
45
37
  type: string;
46
38
  description: string;
47
- properties: Record<string, {
48
- [x: string]: unknown;
49
- }>;
39
+ properties: Record<string, JsonSchemaProperty>;
50
40
  };
51
41
  };
52
42
  };
@@ -102,9 +92,7 @@ declare const OPENAPI_SPEC: {
102
92
  options: {
103
93
  type: string;
104
94
  description: string;
105
- properties: Record<string, {
106
- [x: string]: unknown;
107
- }>;
95
+ properties: Record<string, JsonSchemaProperty>;
108
96
  };
109
97
  };
110
98
  };
@@ -159,9 +147,7 @@ declare const OPENAPI_SPEC: {
159
147
  options: {
160
148
  type: string;
161
149
  description: string;
162
- properties: Record<string, {
163
- [x: string]: unknown;
164
- }>;
150
+ properties: Record<string, JsonSchemaProperty>;
165
151
  };
166
152
  };
167
153
  };
@@ -175,9 +161,7 @@ declare const OPENAPI_SPEC: {
175
161
  "application/json": {
176
162
  schema: {
177
163
  type: string;
178
- properties: Record<string, {
179
- [x: string]: unknown;
180
- }>;
164
+ properties: Record<string, JsonSchemaProperty>;
181
165
  };
182
166
  };
183
167
  };
@@ -9,7 +9,7 @@ import {
9
9
  planRemediation,
10
10
  remediate,
11
11
  remediateFromScan
12
- } from "../chunk-ZXPLOIB7.js";
12
+ } from "../chunk-MUFP2DQX.js";
13
13
 
14
14
  // src/openapi/server.ts
15
15
  import http from "http";
@@ -205,7 +205,7 @@ var OPENAPI_SPEC = {
205
205
  options: {
206
206
  type: "object",
207
207
  description: "RemediateOptions",
208
- properties: createRemediateOptionSchemaProperties({ includeDryRun: false, includePreview: false })
208
+ properties: createRemediateOptionSchemaProperties({ includeDryRun: false, includePreview: false, includeEvidence: true })
209
209
  }
210
210
  }
211
211
  }
@@ -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.js\";\nimport type { RemediateOptions, ScanOptions } from \"../api.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 }),\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"],"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":[]}
@@ -0,0 +1,37 @@
1
+ type JsonSchemaProperty = Record<string, unknown>;
2
+ declare const PACKAGE_MANAGER_VALUES: readonly ["npm", "pnpm", "yarn"];
3
+ declare const LLM_PROVIDER_VALUES: readonly ["openai", "anthropic", "local"];
4
+ declare const PROVENANCE_SOURCE_VALUES: readonly ["cli", "sdk", "mcp", "openapi", "unknown"];
5
+ declare const OPTION_DESCRIPTIONS: {
6
+ readonly cveId: "CVE ID, e.g. CVE-2021-23337";
7
+ readonly inputPath: "Absolute path to the scanner output file";
8
+ readonly cwd: "Absolute path to the project root (default: process.cwd())";
9
+ readonly packageManager: "Package manager override (auto-detected by default)";
10
+ readonly dryRun: "If true, plan changes but write nothing";
11
+ readonly preview: "If true, enforce non-mutating preview mode";
12
+ readonly runTests: "Run package-manager test command after applying fix";
13
+ readonly llmProvider: "LLM provider override";
14
+ readonly patchesDir: "Directory to write .patch files (default: ./patches)";
15
+ readonly policy: "Optional path to .autoremediator policy file";
16
+ readonly requestId: "Request correlation ID";
17
+ readonly sessionId: "Session correlation ID";
18
+ readonly parentRunId: "Parent run correlation ID";
19
+ readonly idempotencyKey: "Idempotency key for replay-safe execution";
20
+ readonly resume: "Return cached result for matching idempotency key when available";
21
+ readonly actor: "Actor identity for evidence provenance";
22
+ readonly source: "Source system for provenance";
23
+ readonly format: "Scanner format (default: auto)";
24
+ readonly evidence: "Write evidence JSON to .autoremediator/evidence/ (default: true)";
25
+ readonly directDependenciesOnly: "Restrict remediation to direct dependencies only";
26
+ readonly preferVersionBump: "Reject override and patch remediation when version-bump-only policy is required";
27
+ };
28
+ declare function createConstraintSchemaProperties(): Record<string, JsonSchemaProperty>;
29
+ declare function createRemediateOptionSchemaProperties(options?: {
30
+ includeDryRun?: boolean;
31
+ includePreview?: boolean;
32
+ includeEvidence?: boolean;
33
+ }): Record<string, JsonSchemaProperty>;
34
+ declare function createScanOptionSchemaProperties(): Record<string, JsonSchemaProperty>;
35
+ declare function createScanReportSchemaProperties(): Record<string, JsonSchemaProperty>;
36
+
37
+ export { type JsonSchemaProperty as J, LLM_PROVIDER_VALUES as L, OPTION_DESCRIPTIONS as O, PACKAGE_MANAGER_VALUES as P, PROVENANCE_SOURCE_VALUES as a, createRemediateOptionSchemaProperties as b, createConstraintSchemaProperties as c, createScanOptionSchemaProperties as d, createScanReportSchemaProperties as e };
@@ -0,0 +1,211 @@
1
+ /** A resolved CVE entry with affected npm package info */
2
+ interface CveDetails {
3
+ id: string;
4
+ summary: string;
5
+ severity: "LOW" | "MEDIUM" | "HIGH" | "CRITICAL" | "UNKNOWN";
6
+ cvssScore?: number;
7
+ epss?: {
8
+ score: number;
9
+ percentile: number;
10
+ date?: string;
11
+ };
12
+ kev?: {
13
+ knownExploited: boolean;
14
+ dateAdded?: string;
15
+ dueDate?: string;
16
+ requiredAction?: string;
17
+ knownRansomwareCampaignUse?: string;
18
+ };
19
+ intelligence?: {
20
+ cveServicesEnriched?: boolean;
21
+ gitlabAdvisoryMatched?: boolean;
22
+ certCcMatched?: boolean;
23
+ depsDevEnrichedPackages?: number;
24
+ scorecardProjects?: number;
25
+ vendorAdvisories?: string[];
26
+ commercialFeeds?: string[];
27
+ sourceHealth?: Record<string, {
28
+ attempted: boolean;
29
+ changed: boolean;
30
+ error?: string;
31
+ }>;
32
+ };
33
+ references: string[];
34
+ affectedPackages: AffectedPackage[];
35
+ }
36
+ /** A single npm package affected by a CVE */
37
+ interface AffectedPackage {
38
+ name: string;
39
+ ecosystem: "npm";
40
+ /** Semver range string for the vulnerable version window, e.g. ">=0.0.0 <4.17.21" */
41
+ vulnerableRange: string;
42
+ /** The first version that is NOT vulnerable (the safe upgrade target) */
43
+ firstPatchedVersion?: string;
44
+ /** Source that provided this entry */
45
+ source: "osv" | "github-advisory";
46
+ }
47
+ /** A package found in the consumer's project */
48
+ interface InventoryPackage {
49
+ name: string;
50
+ version: string;
51
+ /** "direct" = listed in package.json; "indirect" = transitive dep */
52
+ type: "direct" | "indirect";
53
+ }
54
+ /** A package that is both installed and matches a vulnerable range */
55
+ interface VulnerablePackage {
56
+ installed: InventoryPackage;
57
+ affected: AffectedPackage;
58
+ /** The resolved safe upgrade version, if one exists on npm */
59
+ safeUpgradeVersion?: string;
60
+ }
61
+ /** The outcome of a single patch operation */
62
+ type PatchStrategy = "version-bump" | "override" | "patch-file" | "none";
63
+ type DependencyScope = "direct" | "transitive";
64
+ type UnresolvedReason = "constraint-blocked" | "indirect-dependency" | "install-failed" | "major-bump-required" | "no-safe-version" | "override-apply-failed" | "package-json-not-found" | "patch-apply-failed" | "patch-confidence-too-low" | "patch-generation-failed" | "patch-validation-failed" | "policy-blocked" | "requires-llm-fallback" | "source-fetch-failed" | "validation-failed";
65
+ type PatchStrategyCounts = Partial<Record<PatchStrategy, number>>;
66
+ type DependencyScopeCounts = Partial<Record<DependencyScope, number>>;
67
+ type UnresolvedReasonCounts = Partial<Record<UnresolvedReason, number>>;
68
+ interface PatchResult {
69
+ packageName: string;
70
+ strategy: PatchStrategy;
71
+ fromVersion: string;
72
+ toVersion?: string;
73
+ patchFilePath?: string;
74
+ applied: boolean;
75
+ dryRun: boolean;
76
+ message: string;
77
+ unresolvedReason?: UnresolvedReason;
78
+ validation?: {
79
+ passed: boolean;
80
+ error?: string;
81
+ };
82
+ }
83
+ interface CorrelationContext {
84
+ requestId?: string;
85
+ sessionId?: string;
86
+ parentRunId?: string;
87
+ }
88
+ interface RemediationConstraints {
89
+ directDependenciesOnly?: boolean;
90
+ preferVersionBump?: boolean;
91
+ }
92
+ interface ProvenanceContext {
93
+ actor?: string;
94
+ source?: "cli" | "sdk" | "mcp" | "openapi" | "unknown";
95
+ }
96
+ /** Top-level options for the remediate() API and CLI */
97
+ interface RemediateOptions extends CorrelationContext {
98
+ /** Working directory of the consumer's project (defaults to process.cwd()) */
99
+ cwd?: string;
100
+ /** Package manager to use (defaults to auto-detect from lockfile) */
101
+ packageManager?: "npm" | "pnpm" | "yarn";
102
+ /** If true, plan and report changes but do not write anything */
103
+ dryRun?: boolean;
104
+ /** If true, run package-manager tests after patching */
105
+ runTests?: boolean;
106
+ /** Override the LLM provider (falls back to env AUTOREMEDIATOR_LLM_PROVIDER) */
107
+ llmProvider?: "openai" | "anthropic" | "local";
108
+ /** Override the model name */
109
+ model?: string;
110
+ /** Optional path to a policy file (.autoremediator.json) */
111
+ policy?: string;
112
+ /** If false, do not write evidence JSON for this run (default: true). */
113
+ evidence?: boolean;
114
+ /** Directory to write .patch files (default: ./patches) */
115
+ patchesDir?: string;
116
+ /** If true, run a non-mutating remediation preview (forces dryRun behavior for mutation tools). */
117
+ preview?: boolean;
118
+ /** Optional deterministic idempotency key for request replay handling. */
119
+ idempotencyKey?: string;
120
+ /** If true, return cached report for matching idempotency key + CVE when available. */
121
+ resume?: boolean;
122
+ /** Optional caller provenance fields for evidence and reporting. */
123
+ actor?: string;
124
+ source?: "cli" | "sdk" | "mcp" | "openapi" | "unknown";
125
+ /** Optional orchestration constraints for result enforcement. */
126
+ constraints?: RemediationConstraints;
127
+ }
128
+ /** Final report returned by the remediation pipeline */
129
+ interface RemediationReport {
130
+ cveId: string;
131
+ cveDetails: CveDetails | null;
132
+ vulnerablePackages: VulnerablePackage[];
133
+ results: PatchResult[];
134
+ agentSteps: number;
135
+ summary: string;
136
+ evidenceFile?: string;
137
+ correlation?: CorrelationContext;
138
+ provenance?: ProvenanceContext;
139
+ constraints?: RemediationConstraints;
140
+ resumedFromCache?: boolean;
141
+ }
142
+
143
+ type ScanInputFormat = "npm-audit" | "yarn-audit" | "sarif" | "auto";
144
+
145
+ interface ScanOptions extends RemediateOptions {
146
+ format?: ScanInputFormat;
147
+ policy?: string;
148
+ }
149
+ interface ScanReport {
150
+ schemaVersion: "1.0";
151
+ status: "ok" | "partial" | "failed";
152
+ generatedAt: string;
153
+ cveIds: string[];
154
+ reports: RemediationReport[];
155
+ successCount: number;
156
+ failedCount: number;
157
+ errors: Array<{
158
+ cveId: string;
159
+ message: string;
160
+ }>;
161
+ evidenceFile?: string;
162
+ patchCount: number;
163
+ patchValidationFailures?: Array<{
164
+ packageName: string;
165
+ cveId: string;
166
+ error: string;
167
+ }>;
168
+ strategyCounts?: PatchStrategyCounts;
169
+ dependencyScopeCounts?: DependencyScopeCounts;
170
+ unresolvedByReason?: UnresolvedReasonCounts;
171
+ patchesDir?: string;
172
+ correlation?: CorrelationContext;
173
+ provenance?: ProvenanceContext;
174
+ constraints?: RemediationConstraints;
175
+ idempotencyKey?: string;
176
+ }
177
+ interface CiSummary {
178
+ schemaVersion: "1.0";
179
+ status: "ok" | "partial" | "failed";
180
+ generatedAt: string;
181
+ cveCount: number;
182
+ remediationCount: number;
183
+ successCount: number;
184
+ failedCount: number;
185
+ errors: Array<{
186
+ cveId: string;
187
+ message: string;
188
+ }>;
189
+ evidenceFile?: string;
190
+ patchCount?: number;
191
+ patchValidationFailures?: Array<{
192
+ packageName: string;
193
+ cveId: string;
194
+ error: string;
195
+ }>;
196
+ strategyCounts?: PatchStrategyCounts;
197
+ dependencyScopeCounts?: DependencyScopeCounts;
198
+ unresolvedByReason?: UnresolvedReasonCounts;
199
+ patchesDir?: string;
200
+ correlation?: CorrelationContext;
201
+ provenance?: ProvenanceContext;
202
+ constraints?: RemediationConstraints;
203
+ idempotencyKey?: string;
204
+ }
205
+
206
+ declare function remediate(cveId: string, options?: RemediateOptions): Promise<RemediationReport>;
207
+ declare function planRemediation(cveId: string, options?: RemediateOptions): Promise<RemediationReport>;
208
+
209
+ declare function remediateFromScan(inputPath: string, options?: ScanOptions): Promise<ScanReport>;
210
+
211
+ export { type AffectedPackage as A, type CiSummary as C, type DependencyScope as D, type InventoryPackage as I, type PatchResult as P, type RemediateOptions as R, type ScanReport as S, type UnresolvedReason as U, type VulnerablePackage as V, type RemediationReport as a, type CorrelationContext as b, type CveDetails as c, type DependencyScopeCounts as d, type PatchStrategy as e, type PatchStrategyCounts as f, type ProvenanceContext as g, type RemediationConstraints as h, type ScanInputFormat as i, type ScanOptions as j, type UnresolvedReasonCounts as k, remediateFromScan as l, planRemediation as p, remediate as r };
package/llms.txt CHANGED
@@ -44,7 +44,7 @@ autoremediator ./npm-audit.json --cwd ./my-project --ci
44
44
  autoremediator-mcp # stdio transport — register with any MCP host
45
45
  ```
46
46
 
47
- Available MCP tools: `remediate`, `remediateFromScan`
47
+ Available MCP tools: `remediate`, `planRemediation`, `remediateFromScan`
48
48
 
49
49
  ## Tools (agent / MCP)
50
50
 
@@ -55,6 +55,7 @@ Available MCP tools: `remediate`, `remediateFromScan`
55
55
  | `check-version-match` | Cross-reference inventory against vulnerable ranges |
56
56
  | `find-fixed-version` | Query npm registry for lowest safe upgrade |
57
57
  | `apply-version-bump` | Update package.json and run package-manager install |
58
+ | `apply-package-override` | Apply package-manager-native override for vulnerable transitive dependencies |
58
59
  | `fetch-package-source`| Download package tarball for patch generation |
59
60
  | `generate-patch` | Generate unified diff patch via LLM |
60
61
  | `apply-patch-file` | Write/apply patch file via native or compatibility patch flow |
@@ -63,6 +64,7 @@ Available MCP tools: `remediate`, `remediateFromScan`
63
64
 
64
65
  ```
65
66
  lookup-cve → check-inventory → check-version-match → find-fixed-version → apply-version-bump
67
+ └─ transitive path: apply-package-override
66
68
  └─ fallback: fetch-package-source → generate-patch → apply-patch-file
67
69
  ```
68
70
 
@@ -72,11 +74,20 @@ lookup-cve → check-inventory → check-version-match → find-fixed-version
72
74
  |--------|------|---------|-------------|
73
75
  | `cwd` | string | `process.cwd()` | Project root |
74
76
  | `dryRun` | boolean | `false` | Plan only, write nothing |
75
- | `skipTests` | boolean | `true` | Skip package-manager test command after fix |
77
+ | `runTests` | boolean | `false` | Run package-manager test command after fix |
76
78
  | `packageManager` | `npm\|pnpm\|yarn` | auto-detect | Override package manager selection |
77
- | `llmProvider` | `openai\|anthropic\|local` | `openai` | LLM backend (`local` = deterministic, no API key needed) |
79
+ | `llmProvider` | `openai\|anthropic\|local` | `openai` | LLM backend (`local` = deterministic primary path; fallback patch generation may require model credentials) |
78
80
  | `patchesDir` | string | `./patches` | Directory for .patch files |
79
- | `policyPath` | string | `.autoremediator.json` | Policy file path |
81
+ | `policy` | string | `.autoremediator.json` | Policy file path |
82
+ | `preview` | boolean | `false` | Non-mutating remediation preview (forces dry-run behavior) |
83
+ | `evidence` | boolean | `true` | Write evidence JSON output |
84
+ | `requestId` | string | auto-generated | Request correlation ID |
85
+ | `sessionId` | string | unset | Session correlation ID |
86
+ | `parentRunId` | string | unset | Parent run correlation ID |
87
+ | `idempotencyKey` | string | unset | Replay-safe idempotency key |
88
+ | `resume` | boolean | `false` | Return cached result for matching idempotency key when available |
89
+ | `constraints.directDependenciesOnly` | boolean | `false` | Restrict remediation to direct dependencies |
90
+ | `constraints.preferVersionBump` | boolean | `false` | Reject override and patch remediation |
80
91
 
81
92
  ## Policy File (`.autoremediator.json`)
82
93
 
@@ -114,6 +125,7 @@ lookup-cve → check-inventory → check-version-match → find-fixed-version
114
125
  results: PatchResult[]; // strategy: "version-bump" | "patch-file" | "none"
115
126
  agentSteps: number;
116
127
  summary: string;
128
+ evidenceFile?: string;
117
129
  }
118
130
  ```
119
131
 
@@ -129,8 +141,11 @@ lookup-cve → check-inventory → check-version-match → find-fixed-version
129
141
  failedCount: number;
130
142
  errors: Array<{ cveId: string; message: string }>;
131
143
  evidenceFile?: string; // path to .autoremediator/evidence/<runId>.json
132
- patchFileCount: number;
144
+ patchCount: number;
133
145
  patchValidationFailures?: Array<{ packageName: string; cveId: string; error: string }>;
134
- patchStorageDir?: string;
146
+ strategyCounts?: Record<string, number>;
147
+ dependencyScopeCounts?: Record<string, number>;
148
+ unresolvedByReason?: Record<string, number>;
149
+ patchesDir?: string;
135
150
  }
136
151
  ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "autoremediator",
3
3
  "private": false,
4
- "version": "0.6.0",
4
+ "version": "0.7.0",
5
5
  "description": "Risk-aware, agentic CVE remediation for Node.js using OSV, CISA KEV, and FIRST EPSS intelligence with policy and evidence controls.",
6
6
  "keywords": [
7
7
  "security-remediation",