depwire-cli 0.9.25 → 0.9.26

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/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  stashChanges,
18
18
  updateFileInGraph,
19
19
  watchProject
20
- } from "./chunk-ORGAO3HT.js";
20
+ } from "./chunk-B2KGFBZL.js";
21
21
  import {
22
22
  SimulationEngine,
23
23
  analyzeDeadCode,
@@ -29,14 +29,15 @@ import {
29
29
  getHealthTrend,
30
30
  getImpact,
31
31
  parseProject,
32
+ scanSecurity,
32
33
  searchSymbols
33
- } from "./chunk-QHVWDUSX.js";
34
+ } from "./chunk-YYY5TNG7.js";
34
35
 
35
36
  // src/index.ts
36
37
  import { Command } from "commander";
37
- import { resolve as resolve2, dirname as dirname3, join as join4 } from "path";
38
- import { writeFileSync, readFileSync as readFileSync2, existsSync } from "fs";
39
- import { fileURLToPath as fileURLToPath3 } from "url";
38
+ import { resolve as resolve3, dirname as dirname4, join as join5 } from "path";
39
+ import { writeFileSync, readFileSync as readFileSync3, existsSync } from "fs";
40
+ import { fileURLToPath as fileURLToPath4 } from "url";
40
41
 
41
42
  // src/graph/serializer.ts
42
43
  import { DirectedGraph } from "graphology";
@@ -305,10 +306,10 @@ async function findAvailablePort(startPort) {
305
306
  const net = await import("net");
306
307
  for (let attempt = 0; attempt < 10; attempt++) {
307
308
  const testPort = startPort + attempt;
308
- const isAvailable = await new Promise((resolve3) => {
309
- const server = net.createServer().once("error", () => resolve3(false)).once("listening", () => {
309
+ const isAvailable = await new Promise((resolve4) => {
310
+ const server = net.createServer().once("error", () => resolve4(false)).once("listening", () => {
310
311
  server.close();
311
- resolve3(true);
312
+ resolve4(true);
312
313
  }).listen(testPort, "127.0.0.1");
313
314
  });
314
315
  if (isAvailable) {
@@ -349,13 +350,13 @@ async function startTemporalServer(snapshots, projectRoot, preferredPort = 3334)
349
350
  console.log(" (Could not open browser automatically)");
350
351
  });
351
352
  });
352
- await new Promise((resolve3, reject) => {
353
+ await new Promise((resolve4, reject) => {
353
354
  server.on("error", reject);
354
355
  process.on("SIGINT", () => {
355
356
  console.log("\n\nShutting down temporal server...");
356
357
  server.close(() => {
357
358
  console.log("Server stopped");
358
- resolve3();
359
+ resolve4();
359
360
  process.exit(0);
360
361
  });
361
362
  });
@@ -689,14 +690,14 @@ async function findAvailablePort2(startPort, maxAttempts = 10) {
689
690
  const net = await import("net");
690
691
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
691
692
  const testPort = startPort + attempt;
692
- const isAvailable = await new Promise((resolve3) => {
693
+ const isAvailable = await new Promise((resolve4) => {
693
694
  const server = net.createServer();
694
695
  server.once("error", () => {
695
- resolve3(false);
696
+ resolve4(false);
696
697
  });
697
698
  server.once("listening", () => {
698
699
  server.close();
699
- resolve3(true);
700
+ resolve4(true);
700
701
  });
701
702
  server.listen(testPort, "127.0.0.1");
702
703
  });
@@ -887,18 +888,198 @@ function formatAction(action) {
887
888
  }
888
889
  }
889
890
 
890
- // src/index.ts
891
+ // src/commands/security.ts
892
+ import { resolve as resolve2, dirname as dirname3, join as join4 } from "path";
893
+ import { readFileSync as readFileSync2 } from "fs";
894
+ import { fileURLToPath as fileURLToPath3 } from "url";
895
+
896
+ // src/security/reporter.ts
897
+ import chalk2 from "chalk";
898
+ var SEVERITY_COLORS = {
899
+ critical: chalk2.red.bold,
900
+ high: chalk2.red,
901
+ medium: chalk2.yellow,
902
+ low: chalk2.blue,
903
+ info: chalk2.dim
904
+ };
905
+ var SEVERITY_LABELS = {
906
+ critical: "CRITICAL",
907
+ high: "HIGH",
908
+ medium: "MEDIUM",
909
+ low: "LOW",
910
+ info: "INFO"
911
+ };
912
+ function formatTable(result, elapsedMs) {
913
+ const lines = [];
914
+ const sep = "\u2500".repeat(62);
915
+ lines.push("");
916
+ lines.push(chalk2.bold("Depwire Security Scan"));
917
+ lines.push("");
918
+ const summaryParts = [
919
+ result.summary.critical > 0 ? chalk2.red.bold(`${result.summary.critical} Critical`) : null,
920
+ result.summary.high > 0 ? chalk2.red(`${result.summary.high} High`) : null,
921
+ result.summary.medium > 0 ? chalk2.yellow(`${result.summary.medium} Medium`) : null,
922
+ result.summary.low > 0 ? chalk2.blue(`${result.summary.low} Low`) : null,
923
+ result.summary.info > 0 ? chalk2.dim(`${result.summary.info} Info`) : null
924
+ ].filter(Boolean);
925
+ if (summaryParts.length > 0) {
926
+ lines.push(`\u250C${sep}\u2510`);
927
+ lines.push(`\u2502 ${summaryParts.join(" \u2502 ")} \u2502`);
928
+ lines.push(`\u2514${sep}\u2518`);
929
+ } else {
930
+ lines.push(chalk2.green.bold(" No security findings detected."));
931
+ }
932
+ lines.push("");
933
+ const severityOrder = ["critical", "high", "medium", "low", "info"];
934
+ for (const severity of severityOrder) {
935
+ const group = result.findings.filter((f) => f.severity === severity);
936
+ if (group.length === 0) continue;
937
+ const colorFn = SEVERITY_COLORS[severity];
938
+ lines.push(colorFn(SEVERITY_LABELS[severity]));
939
+ for (const finding of group) {
940
+ lines.push(` ${colorFn(`[${finding.id}]`)} ${finding.title}`);
941
+ lines.push(` File: ${finding.file}${finding.line ? `:${finding.line}` : ""}`);
942
+ lines.push(` ${chalk2.dim(finding.description)}`);
943
+ lines.push(` ${chalk2.dim("Fix:")} ${finding.suggestedFix}`);
944
+ if (finding.graphReachability?.elevatedBy) {
945
+ lines.push(` ${chalk2.magenta("\u2191 Elevated:")} ${finding.graphReachability.elevatedBy}`);
946
+ }
947
+ lines.push("");
948
+ }
949
+ }
950
+ const elapsed = (elapsedMs / 1e3).toFixed(1);
951
+ lines.push(chalk2.dim(`Scanned ${result.filesScanned} files in ${elapsed}s`));
952
+ lines.push(chalk2.dim("Run with --format json for machine output"));
953
+ lines.push(chalk2.dim("Run with --format sarif for GitHub Security integration"));
954
+ lines.push("");
955
+ return lines.join("\n");
956
+ }
957
+ function formatJSON(result) {
958
+ return JSON.stringify(result, null, 2);
959
+ }
960
+ function formatSARIF(result, version) {
961
+ const rules = result.findings.map((f) => ({
962
+ id: f.id,
963
+ shortDescription: { text: f.title },
964
+ fullDescription: { text: f.description },
965
+ help: { text: f.suggestedFix },
966
+ properties: {
967
+ severity: f.severity,
968
+ vulnerabilityClass: f.vulnerabilityClass
969
+ }
970
+ }));
971
+ const uniqueRules = Array.from(
972
+ new Map(rules.map((r) => [r.id, r])).values()
973
+ );
974
+ const results = result.findings.map((f) => {
975
+ let level;
976
+ if (f.severity === "critical" || f.severity === "high") level = "error";
977
+ else if (f.severity === "medium") level = "warning";
978
+ else level = "note";
979
+ const sarifResult = {
980
+ ruleId: f.id,
981
+ level,
982
+ message: { text: `${f.title}: ${f.description}` },
983
+ locations: [
984
+ {
985
+ physicalLocation: {
986
+ artifactLocation: { uri: f.file },
987
+ region: f.line ? { startLine: f.line } : void 0
988
+ }
989
+ }
990
+ ]
991
+ };
992
+ return sarifResult;
993
+ });
994
+ const sarif = {
995
+ $schema: "https://json.schemastore.org/sarif-2.1.0.json",
996
+ version: "2.1.0",
997
+ runs: [
998
+ {
999
+ tool: {
1000
+ driver: {
1001
+ name: "depwire",
1002
+ version,
1003
+ rules: uniqueRules
1004
+ }
1005
+ },
1006
+ results
1007
+ }
1008
+ ]
1009
+ };
1010
+ return JSON.stringify(sarif, null, 2);
1011
+ }
1012
+
1013
+ // src/commands/security.ts
891
1014
  var __filename3 = fileURLToPath3(import.meta.url);
892
1015
  var __dirname3 = dirname3(__filename3);
893
- var packageJsonPath = join4(__dirname3, "../package.json");
894
- var packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
1016
+ function getVersion() {
1017
+ try {
1018
+ let dir = __dirname3;
1019
+ for (let i = 0; i < 5; i++) {
1020
+ const pkgPath = join4(dir, "package.json");
1021
+ try {
1022
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
1023
+ if (pkg.name === "depwire-cli") return pkg.version;
1024
+ } catch {
1025
+ }
1026
+ dir = dirname3(dir);
1027
+ }
1028
+ } catch {
1029
+ }
1030
+ return "0.0.0";
1031
+ }
1032
+ var SEVERITY_ORDER = ["critical", "high", "medium", "low", "info"];
1033
+ async function securityCommand(dir, options) {
1034
+ const projectRoot = dir === "." ? findProjectRoot() : resolve2(dir);
1035
+ console.error(`Scanning: ${projectRoot}`);
1036
+ const startTime = Date.now();
1037
+ const parsedFiles = await parseProject(projectRoot);
1038
+ console.error(`Parsed ${parsedFiles.length} files`);
1039
+ const graph = buildGraph(parsedFiles);
1040
+ console.error(`Built graph: ${graph.order} symbols, ${graph.size} edges`);
1041
+ const result = await scanSecurity(projectRoot, graph, {
1042
+ target: options.target,
1043
+ classes: options.class,
1044
+ format: options.format || "table",
1045
+ graphAware: true
1046
+ });
1047
+ const elapsedMs = Date.now() - startTime;
1048
+ const format = options.format || "table";
1049
+ if (format === "json") {
1050
+ console.log(formatJSON(result));
1051
+ } else if (format === "sarif") {
1052
+ console.log(formatSARIF(result, getVersion()));
1053
+ } else {
1054
+ console.log(formatTable(result, elapsedMs));
1055
+ }
1056
+ if (options.failOn) {
1057
+ const threshold = options.failOn;
1058
+ const thresholdIdx = SEVERITY_ORDER.indexOf(threshold);
1059
+ if (thresholdIdx >= 0) {
1060
+ const hasFindings = result.findings.some(
1061
+ (f) => SEVERITY_ORDER.indexOf(f.severity) <= thresholdIdx
1062
+ );
1063
+ if (hasFindings) {
1064
+ console.error(`Findings at or above ${threshold} severity detected \u2014 exiting with code 1`);
1065
+ process.exit(1);
1066
+ }
1067
+ }
1068
+ }
1069
+ }
1070
+
1071
+ // src/index.ts
1072
+ var __filename4 = fileURLToPath4(import.meta.url);
1073
+ var __dirname4 = dirname4(__filename4);
1074
+ var packageJsonPath = join5(__dirname4, "../package.json");
1075
+ var packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
895
1076
  var program = new Command();
896
1077
  program.name("depwire").description("Code cross-reference graph builder for TypeScript projects").version(packageJson.version);
897
1078
  program.command("parse").description("Parse a TypeScript project and build dependency graph").argument("[directory]", "Project directory to parse (defaults to current directory or auto-detected project root)").option("-o, --output <path>", "Output JSON file path", "depwire-output.json").option("--pretty", "Pretty-print JSON output").option("--stats", "Print summary statistics").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').option("--verbose", "Show detailed parsing progress").action(async (directory, options) => {
898
1079
  trackCommand("parse", packageJson.version);
899
1080
  const startTime = Date.now();
900
1081
  try {
901
- const projectRoot = directory ? resolve2(directory) : findProjectRoot();
1082
+ const projectRoot = directory ? resolve3(directory) : findProjectRoot();
902
1083
  console.log(`Parsing project: ${projectRoot}`);
903
1084
  const parsedFiles = await parseProject(projectRoot, {
904
1085
  exclude: options.exclude,
@@ -937,12 +1118,12 @@ Orphan Files (no cross-references): ${summary.orphanFiles.length}`);
937
1118
  program.command("query").description("Query impact analysis for a symbol").argument("<directory>", "Project directory").argument("<symbol-name>", "Symbol name to query").action(async (directory, symbolName) => {
938
1119
  trackCommand("query", packageJson.version);
939
1120
  try {
940
- const projectRoot = resolve2(directory);
1121
+ const projectRoot = resolve3(directory);
941
1122
  const cacheFile = "depwire-output.json";
942
1123
  let graph;
943
1124
  if (existsSync(cacheFile)) {
944
1125
  console.log("Loading from cache...");
945
- const json = JSON.parse(readFileSync2(cacheFile, "utf-8"));
1126
+ const json = JSON.parse(readFileSync3(cacheFile, "utf-8"));
946
1127
  graph = importFromJSON(json);
947
1128
  } else {
948
1129
  console.log("Parsing project...");
@@ -986,7 +1167,7 @@ Total Transitive Dependents: ${impact.transitiveDependents.length}`);
986
1167
  program.command("viz").description("Launch interactive arc diagram visualization").argument("[directory]", "Project directory to visualize (defaults to current directory or auto-detected project root)").option("-p, --port <number>", "Server port", "3333").option("--no-open", "Don't auto-open browser").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').option("--verbose", "Show detailed parsing progress").action(async (directory, options) => {
987
1168
  trackCommand("viz", packageJson.version);
988
1169
  try {
989
- const projectRoot = directory ? resolve2(directory) : findProjectRoot();
1170
+ const projectRoot = directory ? resolve3(directory) : findProjectRoot();
990
1171
  console.log(`Parsing project: ${projectRoot}`);
991
1172
  const parsedFiles = await parseProject(projectRoot, {
992
1173
  exclude: options.exclude,
@@ -1009,7 +1190,7 @@ program.command("viz").description("Launch interactive arc diagram visualization
1009
1190
  program.command("temporal").description("Visualize how the dependency graph evolved over git history").argument("[directory]", "Project directory to analyze (defaults to current directory or auto-detected project root)").option("--commits <number>", "Number of commits to sample", "20").option("--strategy <type>", "Sampling strategy: even, weekly, monthly", "even").option("-p, --port <number>", "Server port", "3334").option("--output <path>", "Save snapshots to custom path (default: .depwire/temporal/)").option("--verbose", "Show progress for each commit being parsed").option("--stats", "Show summary statistics at end").action(async (directory, options) => {
1010
1191
  trackCommand("temporal", packageJson.version);
1011
1192
  try {
1012
- const projectRoot = directory ? resolve2(directory) : findProjectRoot();
1193
+ const projectRoot = directory ? resolve3(directory) : findProjectRoot();
1013
1194
  await runTemporalAnalysis(projectRoot, {
1014
1195
  commits: parseInt(options.commits, 10),
1015
1196
  strategy: options.strategy,
@@ -1029,11 +1210,11 @@ program.command("mcp").description("Start MCP server for AI coding tools").argum
1029
1210
  const state = createEmptyState();
1030
1211
  let projectRootToConnect = null;
1031
1212
  if (directory) {
1032
- projectRootToConnect = resolve2(directory);
1213
+ projectRootToConnect = resolve3(directory);
1033
1214
  } else {
1034
1215
  const detectedRoot = findProjectRoot();
1035
1216
  const cwd = process.cwd();
1036
- if (detectedRoot !== cwd || existsSync(join4(cwd, "package.json")) || existsSync(join4(cwd, "tsconfig.json")) || existsSync(join4(cwd, "go.mod")) || existsSync(join4(cwd, "pyproject.toml")) || existsSync(join4(cwd, "setup.py")) || existsSync(join4(cwd, ".git"))) {
1217
+ if (detectedRoot !== cwd || existsSync(join5(cwd, "package.json")) || existsSync(join5(cwd, "tsconfig.json")) || existsSync(join5(cwd, "go.mod")) || existsSync(join5(cwd, "pyproject.toml")) || existsSync(join5(cwd, "setup.py")) || existsSync(join5(cwd, ".git"))) {
1037
1218
  projectRootToConnect = detectedRoot;
1038
1219
  }
1039
1220
  }
@@ -1090,8 +1271,8 @@ program.command("docs").description("Generate comprehensive codebase documentati
1090
1271
  trackCommand("docs", packageJson.version);
1091
1272
  const startTime = Date.now();
1092
1273
  try {
1093
- const projectRoot = directory ? resolve2(directory) : findProjectRoot();
1094
- const outputDir = options.output ? resolve2(options.output) : join4(projectRoot, ".depwire");
1274
+ const projectRoot = directory ? resolve3(directory) : findProjectRoot();
1275
+ const outputDir = options.output ? resolve3(options.output) : join5(projectRoot, ".depwire");
1095
1276
  const includeList = options.include.split(",").map((s) => s.trim());
1096
1277
  const onlyList = options.only ? options.only.split(",").map((s) => s.trim()) : void 0;
1097
1278
  if (options.gitignore === void 0 && !existsSyncNode(outputDir)) {
@@ -1153,16 +1334,16 @@ async function promptGitignore() {
1153
1334
  input: process.stdin,
1154
1335
  output: process.stdout
1155
1336
  });
1156
- return new Promise((resolve3) => {
1337
+ return new Promise((resolve4) => {
1157
1338
  rl.question("Add .depwire/ to .gitignore? [Y/n] ", (answer) => {
1158
1339
  rl.close();
1159
1340
  const normalized = answer.trim().toLowerCase();
1160
- resolve3(normalized === "" || normalized === "y" || normalized === "yes");
1341
+ resolve4(normalized === "" || normalized === "y" || normalized === "yes");
1161
1342
  });
1162
1343
  });
1163
1344
  }
1164
1345
  function addToGitignore(projectRoot, pattern) {
1165
- const gitignorePath = join4(projectRoot, ".gitignore");
1346
+ const gitignorePath = join5(projectRoot, ".gitignore");
1166
1347
  try {
1167
1348
  let content = "";
1168
1349
  if (existsSyncNode(gitignorePath)) {
@@ -1187,7 +1368,7 @@ ${pattern}
1187
1368
  program.command("health").description("Analyze dependency architecture health (0-100 score)").argument("[directory]", "Project directory to analyze (defaults to current directory or auto-detected project root)").option("--json", "Output as JSON").option("--verbose", "Show detailed breakdown").action(async (directory, options) => {
1188
1369
  trackCommand("health", packageJson.version);
1189
1370
  try {
1190
- const projectRoot = directory ? resolve2(directory) : findProjectRoot();
1371
+ const projectRoot = directory ? resolve3(directory) : findProjectRoot();
1191
1372
  const startTime = Date.now();
1192
1373
  const parsedFiles = await parseProject(projectRoot);
1193
1374
  const graph = buildGraph(parsedFiles);
@@ -1211,7 +1392,7 @@ program.command("health").description("Analyze dependency architecture health (0
1211
1392
  program.command("dead-code").description("Identify dead code - symbols defined but never referenced").argument("[directory]", "Project directory to analyze (defaults to current directory or auto-detected project root)").option("--confidence <level>", "Minimum confidence level to show: high, medium, low (default: medium)", "medium").option("--json", "Output as JSON (for CI/automation)").option("--verbose", "Show detailed info for each dead symbol").option("--stats", "Show summary statistics").option("--include-tests", "Include test files in analysis").option("--include-low", "Shortcut for --confidence low").option("--debug", "Show debug information (exclusion stats)").action(async (directory, options) => {
1212
1393
  trackCommand("dead-code", packageJson.version);
1213
1394
  try {
1214
- const projectRoot = directory ? resolve2(directory) : findProjectRoot();
1395
+ const projectRoot = directory ? resolve3(directory) : findProjectRoot();
1215
1396
  const startTime = Date.now();
1216
1397
  const parsedFiles = await parseProject(projectRoot);
1217
1398
  const graph = buildGraph(parsedFiles);
@@ -1247,4 +1428,13 @@ program.command("whatif").description("Simulate architectural changes before tou
1247
1428
  process.exit(1);
1248
1429
  }
1249
1430
  });
1431
+ program.command("security").description("Scan codebase for security vulnerabilities (deterministic, no API key required)").argument("[directory]", "Project directory to scan (defaults to current directory or auto-detected project root)").option("--target <file>", "Scan a single file instead of the whole repo").option("--class <classes...>", "Only run specific vulnerability class checks").option("--format <format>", "Output format: table (default), json, sarif", "table").option("--fail-on <level>", "Exit with code 1 if findings at this severity or above").action(async (directory, options) => {
1432
+ trackCommand("security", packageJson.version);
1433
+ try {
1434
+ await securityCommand(directory || ".", options);
1435
+ } catch (err) {
1436
+ console.error("Error running security scan:", err);
1437
+ process.exit(1);
1438
+ }
1439
+ });
1250
1440
  program.parse();
@@ -4,11 +4,11 @@ import {
4
4
  startMcpServer,
5
5
  updateFileInGraph,
6
6
  watchProject
7
- } from "./chunk-ORGAO3HT.js";
7
+ } from "./chunk-B2KGFBZL.js";
8
8
  import {
9
9
  buildGraph,
10
10
  parseProject
11
- } from "./chunk-QHVWDUSX.js";
11
+ } from "./chunk-YYY5TNG7.js";
12
12
 
13
13
  // src/mcpb-entry.ts
14
14
  import { resolve } from "path";
package/dist/sdk.d.ts CHANGED
@@ -222,6 +222,54 @@ declare class SimulationEngine {
222
222
  private computeHealthScore;
223
223
  }
224
224
 
225
+ type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
226
+ type VulnerabilityClass = 'dependency-cve' | 'shell-injection' | 'code-injection' | 'secrets' | 'path-traversal' | 'auth' | 'input-validation' | 'information-disclosure' | 'architecture' | 'cryptography' | 'supply-chain' | 'frontend-xss';
227
+ interface SecurityFinding {
228
+ id: string;
229
+ severity: Severity;
230
+ vulnerabilityClass: VulnerabilityClass;
231
+ file: string;
232
+ line?: number;
233
+ symbol?: string;
234
+ title: string;
235
+ description: string;
236
+ attackScenario: string;
237
+ suggestedFix: string;
238
+ graphReachability?: {
239
+ entryPoints: string[];
240
+ reachableFrom: number;
241
+ elevatedBy: string;
242
+ };
243
+ }
244
+ interface SecurityScanResult {
245
+ scannedAt: string;
246
+ projectRoot: string;
247
+ filesScanned: number;
248
+ findings: SecurityFinding[];
249
+ summary: {
250
+ critical: number;
251
+ high: number;
252
+ medium: number;
253
+ low: number;
254
+ info: number;
255
+ total: number;
256
+ };
257
+ dependencyAudit: {
258
+ ran: boolean;
259
+ packageManager: string | null;
260
+ rawOutput: string;
261
+ };
262
+ }
263
+ interface SecurityScanOptions {
264
+ target?: string;
265
+ classes?: VulnerabilityClass[];
266
+ format?: 'table' | 'json' | 'sarif';
267
+ failOn?: Severity;
268
+ graphAware?: boolean;
269
+ }
270
+
271
+ declare function scanSecurity(projectRoot: string, graph: DirectedGraph, options?: SecurityScanOptions): Promise<SecurityScanResult>;
272
+
225
273
  /**
226
274
  * depwire-cli SDK — Public API Surface
227
275
  *
@@ -234,4 +282,4 @@ declare class SimulationEngine {
234
282
  /** Current SDK version — matches depwire-cli npm version */
235
283
  declare const DepwireSDKVersion: string;
236
284
 
237
- export { type BrokenImport, DepwireSDKVersion, type GraphDiff, type HealthDelta, type SimulationAction, SimulationEngine, type SimulationResult, analyzeDeadCode, buildGraph, calculateHealthScore, generateDocs, getArchitectureSummary, getImpact, parseProject, searchSymbols };
285
+ export { type BrokenImport, DepwireSDKVersion, type GraphDiff, type HealthDelta, type SecurityFinding, type SecurityScanOptions, type SecurityScanResult, type Severity, type SimulationAction, SimulationEngine, type SimulationResult, type VulnerabilityClass, analyzeDeadCode, buildGraph, calculateHealthScore, generateDocs, getArchitectureSummary, getImpact, parseProject, scanSecurity, searchSymbols };
package/dist/sdk.js CHANGED
@@ -7,8 +7,9 @@ import {
7
7
  getArchitectureSummary,
8
8
  getImpact,
9
9
  parseProject,
10
+ scanSecurity,
10
11
  searchSymbols
11
- } from "./chunk-QHVWDUSX.js";
12
+ } from "./chunk-YYY5TNG7.js";
12
13
 
13
14
  // src/sdk.ts
14
15
  import { readFileSync } from "fs";
@@ -28,5 +29,6 @@ export {
28
29
  getArchitectureSummary,
29
30
  getImpact,
30
31
  parseProject,
32
+ scanSecurity,
31
33
  searchSymbols
32
34
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "depwire-cli",
3
- "version": "0.9.25",
3
+ "version": "0.9.26",
4
4
  "description": "Dependency graph + 16 MCP tools for AI coding assistants. Impact analysis, health scoring, visualization.",
5
5
  "type": "module",
6
6
  "bin": {