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.
- package/README.md +53 -13
- package/docs/releases/v0.2.16.md +53 -0
- package/package.json +6 -2
- package/src/analysis/cargo-dependency-evidence.js +111 -0
- package/src/analysis/cargo-manifests.js +74 -0
- package/src/analysis/dep-check-ecosystems.js +3 -0
- package/src/analysis/endpoints-java.js +2 -5
- package/src/analysis/findings.js +12 -0
- package/src/analysis/go-dependency-evidence.js +68 -0
- package/src/analysis/health-capabilities.js +1 -1
- package/src/analysis/http-contracts/analysis.js +2 -0
- package/src/analysis/http-contracts/client-call-detection.js +1 -0
- package/src/analysis/http-contracts/client-call-parser.js +18 -4
- package/src/analysis/internal-audit/dependency-health.js +15 -13
- package/src/analysis/internal-audit/python-manifests.js +18 -5
- package/src/analysis/internal-audit/supply-chain.js +2 -0
- package/src/analysis/internal-audit.run.js +12 -7
- package/src/analysis/jvm-dependency-evidence.js +102 -56
- package/src/analysis/jvm-manifests.js +114 -0
- package/src/analysis/source-correctness.js +2 -5
- package/src/analysis/transport-contracts.js +157 -0
- package/src/graph/builder/lang-go.js +4 -2
- package/src/graph/builder/lang-java.js +12 -3
- package/src/graph/builder/lang-rust.js +22 -3
- package/src/graph/freshness-probe.js +1 -1
- package/src/graph/internal-builder.build.js +2 -2
- package/src/graph/internal-builder.resolvers.js +18 -8
- package/src/mcp/actions/advisories.mjs +2 -3
- package/src/mcp/catalog.mjs +7 -4
- package/src/mcp/company-contract-verdict.mjs +42 -0
- package/src/mcp/tools-company.mjs +28 -53
- package/src/mcp/tools-impact-precision.mjs +89 -0
- package/src/mcp/tools-impact.mjs +52 -94
- package/src/precision/lsp-overlay/build.js +10 -0
- package/src/precision/lsp-overlay/contract.js +1 -1
- package/src/precision/symbol-query.js +39 -0
- package/src/precision/typescript-provider/client.js +16 -3
- package/src/precision/typescript-provider/discovery.js +1 -1
- package/src/precision/typescript-provider/isolated-runtime.js +39 -0
- package/src/precision/typescript-provider/project-host.js +11 -6
- package/src/precision/typescript-provider/project-safety.js +5 -0
- package/src/security/advisory-store.js +2 -2
- package/src/security/installed-jvm-rust.js +46 -0
- package/src/security/installed.js +21 -1
- package/src/util.js +8 -0
- 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.
|
|
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
|
-
|
|
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);
|
package/docs/releases/v0.2.15.md
DELETED
|
@@ -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.
|