weavatrix 0.3.1 → 0.3.3

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 CHANGED
@@ -413,7 +413,22 @@ metrics are not persisted or transmitted by Weavatrix. If a source checkout's pa
413
413
  while an old daemon remains alive, `initialize`, `tools/list`, and tool calls fail loudly with
414
414
  `STALE_RUNTIME` until the client reconnects; the opt-out is reserved for deliberate development.
415
415
 
416
- ### 0.3.1 exact impact over oversized diffs
416
+ ### 0.3.3 parser supply-chain boundary
417
+
418
+ - Before compiling parser WASM, Core now requires the package-pinned `web-tree-sitter` runtime and
419
+ each selected `tree-sitter-wasms` grammar to resolve inside its dependency directory and match a
420
+ release-pinned SHA-256 allowlist. Repository paths, URLs, symlinks and custom parser locations are
421
+ rejected; a mismatch fails the graph build.
422
+ - This bounds the upstream Emscripten dynamic-module loader even though its generated code contains
423
+ `eval` glue for EM_ASM/EM_JS side modules. Weavatrix loads only its known local runtime and grammar
424
+ artifacts; it does not load a parser or grammar from the analyzed repository.
425
+ - Supply-chain documentation now distinguishes the Apache-2.0 license declared by
426
+ `typescript@5.9.3` from the W3C agreement reproduced for one specification in its third-party
427
+ notices. Conservative dependency scanners may still surface that component notice for review.
428
+
429
+ Full patch notes: [docs/releases/v0.3.3.md](docs/releases/v0.3.3.md).
430
+
431
+ ### 0.3.2 exact impact over oversized diffs
417
432
 
418
433
  - `change_impact` now recovers a bounded per-file unified diff when one large asset exceeds the
419
434
  aggregate diff budget. Normal source files retain line/symbol classification; only the files that
@@ -424,7 +439,7 @@ while an old daemon remains alive, `initialize`, `tools/list`, and tool calls fa
424
439
  - The global LSP overlay remains a bounded prewarm and can honestly be `PARTIAL`; `get_dependents`,
425
440
  `inspect_symbol`, and `change_impact` run revision-bound exact point/batch queries beyond that cap.
426
441
 
427
- Full patch notes: [docs/releases/v0.3.1.md](docs/releases/v0.3.1.md).
442
+ Full patch notes: [docs/releases/v0.3.2.md](docs/releases/v0.3.2.md).
428
443
 
429
444
  ### 0.3.0 network-free core and exact dependency evidence
430
445
 
package/SECURITY.md CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  | Version | Supported |
6
6
  |---|---|
7
- | `0.2.15.x` | Yes |
8
- | `0.2.14` and older | Upgrade to the latest release |
7
+ | `0.3.x` | Yes |
8
+ | `0.2.x` and older | Upgrade to the latest release |
9
9
 
10
10
  Security fixes are provided for the latest published version of Weavatrix. Upgrade before reporting
11
11
  an issue that may already be resolved.
@@ -56,6 +56,22 @@ bounded graph-work drain, and closes or tree-terminates TLS/tsserver before exit
56
56
  Set `WEAVATRIX_PRECISION=off` before server startup (or select `off` in the MCPB semantic-precision
57
57
  setting) to keep new graphs parser-only from their first build.
58
58
 
59
+ The parser runtime and language grammars are also exact package-pinned dependencies. Before compiling
60
+ WASM, Weavatrix requires the runtime and every selected grammar to resolve inside their dependency
61
+ directories and match a release-pinned SHA-256 allowlist. Repository paths, URLs, symlinks and custom
62
+ `runtimeWasm`/`wasmDir` overrides cannot enter this path. This specifically bounds the generated
63
+ Emscripten dynamic-module loader in `web-tree-sitter`: although upstream contains `eval` glue for
64
+ EM_ASM/EM_JS side-module exports, Weavatrix supplies only its known local runtime and grammar artifacts.
65
+ An integrity mismatch fails the graph build instead of silently falling back to an unverified parser.
66
+
67
+ Dependency scanners should distinguish a package's declared license from component notices.
68
+ `typescript@5.9.3` declares `Apache-2.0`; its `ThirdPartyNoticeText.txt` also reproduces the W3C Community
69
+ Final Specification Agreement for the Web Background Synchronization specification. That attribution
70
+ does not change the npm package's declared license, but conservative scanners may report the embedded
71
+ notice separately. `web-tree-sitter@0.25.10` declares MIT; its generated loader is covered by the
72
+ artifact boundary above. These observations are security evidence, not a request to suppress third-party
73
+ scanner warnings or legal advice.
74
+
59
75
  `verified_change` is read-only by default. Its optional targeted-test step can execute only an
60
76
  existing `package.json` script whose name matches the bounded test/check/verify allowlist. The call
61
77
  must set `run_tests:true` and the server operator must separately set
@@ -0,0 +1,15 @@
1
+ # Weavatrix 0.3.2
2
+
3
+ 0.3.2 carries the bounded large-diff recovery introduced in 0.3.1 and makes
4
+ its byte-limit detection consistent across supported Node.js platforms.
5
+
6
+ Some `spawnSync` implementations can return a successful process status while
7
+ the captured Git diff already exceeds the configured byte budget. Weavatrix now
8
+ checks the measured output length before accepting the aggregate diff, rather
9
+ than treating process status alone as proof that the evidence is complete.
10
+
11
+ The same fail-closed behavior remains in force: per-file diffs that fit keep
12
+ line/symbol classification, individually oversized files remain `unknown`, and
13
+ the overall result stays `PARTIAL/HIGH` until every changed file has bounded
14
+ textual evidence. Hosted dogfood continues to verify 16/16 selected changed
15
+ JS/TS symbols with exact LSP direct-reference evidence.
@@ -0,0 +1,25 @@
1
+ # Weavatrix 0.3.3
2
+
3
+ 0.3.3 hardens the portable parser boundary after reviewing two conservative
4
+ third-party supply-chain alerts.
5
+
6
+ `web-tree-sitter@0.25.10` is MIT-licensed, but its generated Emscripten loader
7
+ contains `eval` support for EM_ASM/EM_JS exports in dynamic side modules. The
8
+ same generated path remains in `web-tree-sitter@0.26.11`; changing the version
9
+ would not remove the signal. Weavatrix now verifies the exact SHA-256 of the
10
+ package-owned runtime and every selected `tree-sitter-wasms@0.1.13` grammar
11
+ before compilation. Parser artifacts must resolve inside their pinned package
12
+ directories. Repository paths, URLs, symlink escapes and custom runtime or
13
+ grammar locations are rejected, and an integrity mismatch fails closed.
14
+
15
+ The release also documents a separate license-classification alert.
16
+ `typescript@5.9.3` declares `Apache-2.0`. Its third-party notice reproduces the
17
+ W3C Community Final Specification Agreement for the Web Background
18
+ Synchronization specification; conservative scanners can identify that
19
+ component notice as non-permissive even though it is not the package's declared
20
+ license. Weavatrix keeps the notice visible and does not suppress the external
21
+ scanner finding.
22
+
23
+ The public site now presents the product boundary directly: the 34-tool MIT,
24
+ network-free Core and the separately licensed 39-tool Online overlay, including
25
+ managed Cloud and customer-hosted Enterprise availability.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "weavatrix",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "description": "Local repository intelligence MCP for AI coding agents: reusable architecture graph for fast application understanding, Health, dead code, clones, history, blast radius and architecture safeguards.",
6
6
  "author": "Sergii Ziborov <sergii.ziborov@gmail.com>",
@@ -35,6 +35,8 @@
35
35
  "docs/adr/0001-v0.3-offline-online-split.md",
36
36
  "docs/releases/v0.3.0.md",
37
37
  "docs/releases/v0.3.1.md",
38
+ "docs/releases/v0.3.2.md",
39
+ "docs/releases/v0.3.3.md",
38
40
  "docs/releases/v0.2.19.md",
39
41
  "README.md",
40
42
  "SECURITY.md",
@@ -56,8 +56,9 @@ function runGitDiff(repoRoot, base, limits) {
56
56
  encoding: 'utf8', windowsHide: true, timeout: 12_000,
57
57
  maxBuffer: limits.maxDiffBytes + 1, env: childProcessEnv(),
58
58
  })
59
- if (result.status === 0) return {available: true, text: String(result.stdout || ''), error: null}
60
- const oversized = result.error?.code === 'ENOBUFS' || Buffer.byteLength(String(result.stdout || '')) > limits.maxDiffBytes
59
+ const output = String(result.stdout || '')
60
+ const oversized = result.error?.code === 'ENOBUFS' || Buffer.byteLength(output) > limits.maxDiffBytes
61
+ if (result.status === 0 && !oversized) return {available: true, text: output, error: null}
61
62
  let fallbackFiles = []
62
63
  let fallbackTruncated = false
63
64
  let recoveredText = ''
@@ -10,6 +10,7 @@ import { createRequire } from "node:module";
10
10
  import { isPathInside } from "../repo-path.js";
11
11
  import { childProcessEnv } from "../child-env.js";
12
12
  import { filterWeavatrixIgnored } from "../path-ignore.js";
13
+ import {trustedGrammarWasm, trustedRuntimeWasm} from './parser-artifact-boundary.js'
13
14
  import LANG_JS from "./builder/lang-js.js";
14
15
  import LANG_PY from "./builder/lang-python.js";
15
16
  import LANG_GO from "./builder/lang-go.js";
@@ -24,7 +25,6 @@ const { Parser, Language, Query } = require("web-tree-sitter");
24
25
 
25
26
  const WTS_DIR = dirname(require.resolve("web-tree-sitter"));
26
27
  const NODE_MODULES = dirname(WTS_DIR);
27
- const DEFAULT_RUNTIME_WASM = join(WTS_DIR, "tree-sitter.wasm");
28
28
  const DEFAULT_WASM_DIR = join(NODE_MODULES, "tree-sitter-wasms", "out");
29
29
 
30
30
  // ---- language registry (derived from the per-language modules) ----
@@ -61,11 +61,19 @@ const _langs = {};
61
61
  // in the repo get compiled. The heavy WASMs (rust ~3MB, c_sharp ~4MB) cost seconds to compile — a tax
62
62
  // a JS-only repo must never pay. Omit `wanted` to load everything (old behavior).
63
63
  async function ensureParser(opts = {}, wanted = null) {
64
- if (!_ready) _ready = Parser.init({ locateFile: () => opts.runtimeWasm || DEFAULT_RUNTIME_WASM });
64
+ if (opts.runtimeWasm != null || opts.wasmDir != null) {
65
+ throw new Error('custom parser artifacts are not supported; Weavatrix loads only pinned package-owned WASM')
66
+ }
67
+ if (!_ready) {
68
+ const runtimeWasm = trustedRuntimeWasm(WTS_DIR)
69
+ _ready = Parser.init({ locateFile: () => runtimeWasm });
70
+ }
65
71
  await _ready;
66
- const wasmDir = opts.wasmDir || DEFAULT_WASM_DIR;
67
72
  const list = wanted ? GRAMMARS.filter((g) => wanted.has(g)) : GRAMMARS;
68
- for (const g of list) if (!_langs[g]) { try { _langs[g] = await Language.load(join(wasmDir, `tree-sitter-${g}.wasm`)); } catch { _langs[g] = null; } }
73
+ for (const g of list) if (!_langs[g]) {
74
+ const grammarWasm = trustedGrammarWasm(DEFAULT_WASM_DIR, g)
75
+ try { _langs[g] = await Language.load(grammarWasm); } catch { _langs[g] = null; }
76
+ }
69
77
  return _langs;
70
78
  }
71
79
 
@@ -0,0 +1,56 @@
1
+ import {createHash} from 'node:crypto'
2
+ import {readFileSync, realpathSync, statSync} from 'node:fs'
3
+ import {join} from 'node:path'
4
+ import {isPathInside} from '../repo-path.js'
5
+
6
+ // Exact SHA-256 allowlist for the parser artifacts shipped by the package-pinned
7
+ // web-tree-sitter@0.25.10 and tree-sitter-wasms@0.1.13 dependencies. npm integrity
8
+ // protects installation; this second boundary detects replacement or redirection
9
+ // before Emscripten compiles a runtime or dynamic language module.
10
+ const RUNTIME_SHA256 = 'f38dcc4b43b818f9a0785bc1c6d5611a75ac4cdd428ff3f02757c34ca4e46d7f'
11
+ const GRAMMAR_SHA256 = Object.freeze({
12
+ javascript: '63812b9e275d26851264734868d27a1656bd44a2ef6eb3e85e6b03728c595ab5',
13
+ typescript: '8515404dceed38e1ed86aa34b09fcf3379fff1b4ff9dd3967bcd6d1eb5ac3d8f',
14
+ tsx: '6aa3b2c70e76f5d48eafef1093e9c4de383e13f2fdde2f4e9b98a378f6a8f1b6',
15
+ python: '9056d0fb0c337810d019fae350e8167786119da98f0f282aceae7ab89ee8253b',
16
+ go: '9963ca89b616eaf04b08a43bc1fb0f07b85395bec313330851f1f1ead2f755b6',
17
+ java: '637aac4415fb39a211a4f4292d63c66b5ce9c32fa2cd35464af4f681d91b9a1f',
18
+ c_sharp: '6266a7e32d68a3459104d994dc848df15d5672b0ea8e86d327274b694f8e6991',
19
+ rust: '4409921a70d0aa5bec7d1d7ce809a557a8ee1cf6ace901e3ac6a76e62cfea903',
20
+ html: '11b3405c1543fb012f5ed7f8ee73125076dce8b168301e1e787e4c717da6b456',
21
+ css: '5fc615467b1b98420ed7517e5bf9e1f88468132dd903d842dfb13714f6a1cb0c',
22
+ })
23
+
24
+ export function verifyParserArtifact({file, root, sha256, label = 'parser artifact'}) {
25
+ let rootReal, fileReal
26
+ try {
27
+ rootReal = realpathSync.native(root)
28
+ fileReal = realpathSync.native(file)
29
+ } catch {
30
+ throw new Error(`${label} is missing or cannot be resolved`)
31
+ }
32
+ if (!isPathInside(rootReal, fileReal) || !statSync(fileReal).isFile()) {
33
+ throw new Error(`${label} resolves outside its pinned package directory`)
34
+ }
35
+ const actual = createHash('sha256').update(readFileSync(fileReal)).digest('hex')
36
+ if (actual !== sha256) throw new Error(`${label} failed the pinned SHA-256 integrity check`)
37
+ return fileReal
38
+ }
39
+
40
+ export function trustedRuntimeWasm(wtsDir) {
41
+ return verifyParserArtifact({
42
+ file: join(wtsDir, 'tree-sitter.wasm'), root: wtsDir,
43
+ sha256: RUNTIME_SHA256, label: 'web-tree-sitter runtime',
44
+ })
45
+ }
46
+
47
+ export function trustedGrammarWasm(wasmDir, grammar) {
48
+ const sha256 = GRAMMAR_SHA256[grammar]
49
+ if (!sha256) throw new Error(`unsupported tree-sitter grammar: ${grammar}`)
50
+ return verifyParserArtifact({
51
+ file: join(wasmDir, `tree-sitter-${grammar}.wasm`), root: wasmDir,
52
+ sha256, label: `tree-sitter ${grammar} grammar`,
53
+ })
54
+ }
55
+
56
+ export const TRUSTED_GRAMMARS = Object.freeze(Object.keys(GRAMMAR_SHA256))