weavatrix 0.2.15 → 0.2.16

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.
Files changed (46) hide show
  1. package/README.md +53 -13
  2. package/docs/releases/v0.2.16.md +53 -0
  3. package/package.json +6 -2
  4. package/src/analysis/cargo-dependency-evidence.js +111 -0
  5. package/src/analysis/cargo-manifests.js +74 -0
  6. package/src/analysis/dep-check-ecosystems.js +3 -0
  7. package/src/analysis/endpoints-java.js +2 -5
  8. package/src/analysis/findings.js +12 -0
  9. package/src/analysis/go-dependency-evidence.js +68 -0
  10. package/src/analysis/health-capabilities.js +1 -1
  11. package/src/analysis/http-contracts/analysis.js +2 -0
  12. package/src/analysis/http-contracts/client-call-detection.js +1 -0
  13. package/src/analysis/http-contracts/client-call-parser.js +18 -4
  14. package/src/analysis/internal-audit/dependency-health.js +15 -13
  15. package/src/analysis/internal-audit/python-manifests.js +18 -5
  16. package/src/analysis/internal-audit/supply-chain.js +2 -0
  17. package/src/analysis/internal-audit.run.js +12 -7
  18. package/src/analysis/jvm-dependency-evidence.js +102 -56
  19. package/src/analysis/jvm-manifests.js +114 -0
  20. package/src/analysis/source-correctness.js +2 -5
  21. package/src/analysis/transport-contracts.js +157 -0
  22. package/src/graph/builder/lang-go.js +4 -2
  23. package/src/graph/builder/lang-java.js +12 -3
  24. package/src/graph/builder/lang-rust.js +22 -3
  25. package/src/graph/freshness-probe.js +1 -1
  26. package/src/graph/internal-builder.build.js +2 -2
  27. package/src/graph/internal-builder.resolvers.js +18 -8
  28. package/src/mcp/actions/advisories.mjs +2 -3
  29. package/src/mcp/catalog.mjs +7 -4
  30. package/src/mcp/company-contract-verdict.mjs +42 -0
  31. package/src/mcp/tools-company.mjs +28 -53
  32. package/src/mcp/tools-impact-precision.mjs +89 -0
  33. package/src/mcp/tools-impact.mjs +52 -94
  34. package/src/precision/lsp-overlay/build.js +10 -0
  35. package/src/precision/lsp-overlay/contract.js +1 -1
  36. package/src/precision/symbol-query.js +39 -0
  37. package/src/precision/typescript-provider/client.js +16 -3
  38. package/src/precision/typescript-provider/discovery.js +1 -1
  39. package/src/precision/typescript-provider/isolated-runtime.js +39 -0
  40. package/src/precision/typescript-provider/project-host.js +11 -6
  41. package/src/precision/typescript-provider/project-safety.js +5 -0
  42. package/src/security/advisory-store.js +2 -2
  43. package/src/security/installed-jvm-rust.js +46 -0
  44. package/src/security/installed.js +21 -1
  45. package/src/util.js +8 -0
  46. package/docs/releases/v0.2.15.md +0 -37
@@ -57,6 +57,7 @@ export function typeScriptProjectSafety(repoRoot, relFiles = [], options = {}) {
57
57
 
58
58
  const configRecords = new Map()
59
59
  const projectFiles = new Set()
60
+ const configuredPlugins = new Set()
60
61
  const projects = {}
61
62
  for (let cursor = 0; cursor < queue.length; cursor++) {
62
63
  if (Date.now() >= budget.deadline) return {safe: false, reason: 'SAFETY_DEADLINE', fingerprint: null}
@@ -68,7 +69,9 @@ export function typeScriptProjectSafety(repoRoot, relFiles = [], options = {}) {
68
69
  projects[configRel] = {
69
70
  projectFiles: parsed.projectFiles,
70
71
  configFiles: [...parsed.configRecords.keys()].sort(),
72
+ configuredPlugins: parsed.plugins,
71
73
  }
74
+ for (const plugin of parsed.plugins || []) configuredPlugins.add(plugin)
72
75
  for (const [file, digest] of parsed.configRecords) {
73
76
  configRecords.set(file, digest)
74
77
  if (configRecords.size > MAX_CONFIG_FILES) {
@@ -133,6 +136,8 @@ export function typeScriptProjectSafety(repoRoot, relFiles = [], options = {}) {
133
136
  projectFiles: [...projectFiles].sort(),
134
137
  fileConfigs,
135
138
  projects,
139
+ configuredPlugins: [...configuredPlugins].sort(),
140
+ pluginsSuppressed: configuredPlugins.size,
136
141
  }
137
142
  }
138
143
 
@@ -17,7 +17,7 @@ export const DEFAULT_STORE = join(homedir(), ".weavatrix", "advisories.json");
17
17
  const OSV_BATCH_URL = "https://api.osv.dev/v1/querybatch";
18
18
  const OSV_VULN_URL = "https://api.osv.dev/v1/vulns/";
19
19
  const DEFAULT_FETCH_TIMEOUT_MS = Number(process.env.WEAVATRIX_OSV_TIMEOUT_MS || 20000);
20
- export const OSV_SUPPORTED_ECOSYSTEMS = new Set(["npm", "PyPI", "Go"]);
20
+ export const OSV_SUPPORTED_ECOSYSTEMS = new Set(["npm", "PyPI", "Go", "Maven", "crates.io"]);
21
21
 
22
22
  const keyOf = (ecosystem, name) => `${ecosystem}|${ecosystem === "PyPI" ? String(name).toLowerCase().replace(/[-_.]+/g, "-") : name}`;
23
23
 
@@ -121,7 +121,7 @@ export async function refreshAdvisories({ installed = [], storePath = DEFAULT_ST
121
121
  ok: false,
122
122
  queried: 0,
123
123
  unsupported,
124
- error: "No OSV-supported pinned package versions found to check. weavatrix currently queries OSV for npm, PyPI, and Go packages with concrete versions.",
124
+ error: "No OSV-supported pinned package versions found to check. Weavatrix queries OSV for npm, PyPI, Go, Maven/Gradle, and crates.io packages with concrete versions.",
125
125
  };
126
126
  }
127
127
  const store = loadStore(storePath);
@@ -0,0 +1,46 @@
1
+ import { createRepoBoundary } from "../repo-path.js";
2
+ import { listRepoFiles, readRepoText } from "../analysis/internal-audit/repo-files.js";
3
+ import { parseCargoLockPackages } from "../analysis/cargo-manifests.js";
4
+ import { parseGradleDependencies, parseGradleLockPackages, parseGradleVersionCatalog, parseMavenPom } from "../analysis/jvm-manifests.js";
5
+
6
+ const dedupe = (items) => {
7
+ const seen = new Set();
8
+ return items.filter((item) => {
9
+ const key = `${item.ecosystem}|${item.name}|${item.version}`;
10
+ if (!item.name || !item.version || seen.has(key)) return false;
11
+ seen.add(key); return true;
12
+ });
13
+ };
14
+ const concreteVersion = (value) => !!value && !/[\[\](),${}*+]/.test(String(value));
15
+
16
+ export function collectJvmRustInstalled(repoPath) {
17
+ const boundary = createRepoBoundary(repoPath);
18
+ if (!boundary.root) return [];
19
+ const files = listRepoFiles(repoPath);
20
+ const installed = [];
21
+ for (const file of files.filter((name) => /(^|\/)Cargo\.lock$/i.test(name))) {
22
+ installed.push(...parseCargoLockPackages(readRepoText(boundary, file)));
23
+ }
24
+ for (const file of files.filter((name) => /(^|\/)pom\.xml$/i.test(name))) {
25
+ const parsed = parseMavenPom(readRepoText(boundary, file));
26
+ installed.push(...parsed.dependencies.filter((item) => concreteVersion(item.version)).map((item) => ({
27
+ ecosystem: "Maven", name: item.name, version: item.version, dev: item.scope === "test",
28
+ integrity: "", source: "pom",
29
+ })));
30
+ }
31
+ const catalog = new Map();
32
+ for (const file of files.filter((name) => /(^|\/)libs\.versions\.toml$/i.test(name))) {
33
+ for (const [alias, entry] of parseGradleVersionCatalog(readRepoText(boundary, file))) catalog.set(alias, entry);
34
+ }
35
+ for (const file of files.filter((name) => /(^|\/)(?:build|settings|[^/]+)\.gradle(?:\.kts)?$/i.test(name))) {
36
+ const dependencies = parseGradleDependencies(readRepoText(boundary, file), catalog);
37
+ installed.push(...dependencies.filter((item) => concreteVersion(item.version)).map((item) => ({
38
+ ecosystem: "Maven", name: item.name, version: item.version,
39
+ dev: /test/i.test(item.scope || ""), integrity: "", source: "gradle-manifest",
40
+ })));
41
+ }
42
+ for (const file of files.filter((name) => /(^|\/)(?:gradle\.lockfile|dependency-locks\/[^/]+\.lockfile)$/i.test(name))) {
43
+ installed.push(...parseGradleLockPackages(readRepoText(boundary, file)));
44
+ }
45
+ return dedupe(installed);
46
+ }
@@ -7,6 +7,8 @@ import { join, relative } from "node:path";
7
7
  import { parseGoMod } from "../analysis/manifests.js";
8
8
  import { uniqueBy } from "../util.js";
9
9
  import { createRepoBoundary } from "../repo-path.js";
10
+ import { collectJvmRustInstalled } from "./installed-jvm-rust.js";
11
+ import { listRepoFiles, readRepoText } from "../analysis/internal-audit/repo-files.js";
10
12
 
11
13
  const pep503 = (name) => String(name).toLowerCase().replace(/[-_.]+/g, "-"); // PyPI canonical name
12
14
 
@@ -256,5 +258,23 @@ export function collectInstalled(repoPath) {
256
258
  if (!vers) merged.push(d);
257
259
  else if (!vers.has(d.version)) drift.push({ name: d.name, locked: locked.get(d.name).version, installed: d.version });
258
260
  }
259
- return { installed: dedupe([...merged, ...py, ...go]), drift };
261
+ const jvmRust = collectJvmRustInstalled(repoPath);
262
+ // The earlier fast path covers roots and immediate services. Complete the tracked repository
263
+ // universe so deeply nested Python/Go services are not silently omitted from advisory coverage.
264
+ const repositoryFiles = listRepoFiles(repoPath);
265
+ const allPython = repositoryFiles.flatMap((file) => {
266
+ const text = readRepoText(boundary, file);
267
+ if (/(^|\/)requirements[\w.-]*\.(?:txt|in)$/i.test(file) || /(^|\/)requirements\/[^/]+\.(?:txt|in)$/i.test(file)) return parseRequirements(text || "");
268
+ if (/(^|\/)poetry\.lock$/i.test(file)) return parseTomlLockPackages(text || "", "poetry-lock");
269
+ if (/(^|\/)uv\.lock$/i.test(file)) return parseTomlLockPackages(text || "", "uv-lock");
270
+ if (/(^|\/)Pipfile\.lock$/i.test(file)) { try { return parsePipfileLock(JSON.parse(text)); } catch { return []; } }
271
+ return [];
272
+ });
273
+ const allGo = repositoryFiles.flatMap((file) => {
274
+ const text = readRepoText(boundary, file) || "";
275
+ if (/(^|\/)go\.sum$/i.test(file)) return parseGoSum(text);
276
+ if (/(^|\/)go\.mod$/i.test(file)) return parseGoModPackages(text);
277
+ return [];
278
+ });
279
+ return { installed: dedupe([...merged, ...py, ...go, ...allPython, ...allGo, ...jvmRust]), drift };
260
280
  }
package/src/util.js CHANGED
@@ -16,6 +16,14 @@ export function uniqueBy(list, keyFn) {
16
16
  });
17
17
  }
18
18
 
19
+ export function lineNumberAt(text, index) {
20
+ let line = 1;
21
+ for (let offset = 0; offset < index && offset < text.length; offset++) {
22
+ if (text[offset] === "\n") line++;
23
+ }
24
+ return line;
25
+ }
26
+
19
27
  export function safeRead(path) {
20
28
  try {
21
29
  const st = statSync(path);
@@ -1,37 +0,0 @@
1
- # Weavatrix 0.2.15
2
-
3
- 0.2.15 is a focused self-audit precision release. It keeps the 38-tool MCP surface and all wire and
4
- security boundaries stable while removing false-positive dependency, dead-code, malware, and
5
- duplicate findings discovered by running Weavatrix against its own repository.
6
-
7
- ## Dependency and reachability precision
8
-
9
- - Dependency verification now respects the owning nested manifest before deciding whether an import
10
- is missing or a declaration is unused.
11
- - Framework peer dependencies and bounded package paths assembled from static string fragments are
12
- recognized without treating arbitrary runtime values as proof.
13
- - Source-owned HTML asset references participate in reachability, protecting maintained browser
14
- scripts and styles from false dead-file findings.
15
-
16
- ## Safer review queues
17
-
18
- - Malware scanning distinguishes placeholders, comments, documentation URLs, and ordinary Unicode
19
- text from executable registry/download behavior. Static heuristic evidence remains review-only and
20
- does not claim execution or compromise.
21
- - Duplicate detection suppresses policy-like numeric tables and stable ordered declarations where
22
- repeated structure carries meaning, while preserving clone evidence for executable code.
23
- - Reverse reachability, Git output parsing, ordered-member comparison, path terminology, task
24
- retrieval, and duplicate evidence now share focused owners instead of maintaining divergent copies.
25
-
26
- ## Compatibility and security
27
-
28
- - There are no MCP tool-schema, capability-profile, Hosted payload, sync-consent, or architecture
29
- contract changes in this release.
30
- - The default profile remains offline and local-first. Advisory and Hosted network capabilities
31
- remain explicit opt-ins.
32
-
33
- ## Verification
34
-
35
- The release is gated by the full Node suite, six-language fixture benchmark, six-repository semantic
36
- regression gate, release-manifest verification, packed npm and MCPB stdio checks, and npm audit. The
37
- exact counts and artifacts are recorded by the immutable GitHub release workflow.