Skip to content

Prepare 2.2.0: agent reach, directed boundaries, SARIF pentest profile, and the sibling-mitigation fix - #57

Merged
Animesh-Sri-bugb merged 6 commits into
mainfrom
fm/release-guardlink-2-2-0
Oct 7, 2026
Merged

Animesh-Sri-bugb merged 6 commits into
mainfrom
fm/release-guardlink-2-2-0

Conversation

@Animesh-Sri-bugb

@Animesh-Sri-bugb Animesh-Sri-bugb commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Prepares the 2.2.0 release. Nothing here publishes anything. It adds no tag, no GitHub Release, no registry push and no workflow run. .github/workflows/release.yml runs when a GitHub Release is published, so merging this sends nothing to npm until someone creates that Release.

What changed

test(readme): the D22 test gets a timeout sized to its work. tests/readme.test.ts › D22: the grammar examples do not register as real annotations parses the whole repository inside the test body. That puts it under vitest's 5000 ms test default, not the 10 s beforeAll default the other tests that parse this repository get. On CI it takes 3.1–3.8 s, and it timed out at 5000 ms on Node 18 in two recent ci.yml runs. The full scan is what the test needs: cwe:CWE-89 appears in grammar examples across src/, not only in the init template, so narrowing the scan would weaken the second assertion. It now has a 30 s timeout, following the convention in tests/paths-format.test.ts and tests/sidecar-handoff.test.ts. The global testTimeout is unchanged.

fix(deps): @modelcontextprotocol/sdk goes to ^1.31.0. This addresses GHSA-6qxp-vccf-f47h / CVE-2026-104850 (high; vulnerable >= 1.12.0, < 1.31.0). The flaw is in the SDK's OAuth client. guardlink-mcp is a server and uses only StdioServerTransport (src/mcp/index.ts), so this code cannot reach it. Even so, npm audit flags every install of guardlink until the version range excludes it. The lockfile resolves 1.32.1.

chore(release): 2.2.0. Changes package.json and the two root entries in package-lock.json. src/version.ts reads package.json at run time, so every surface that reports a version follows it (see CONTRIBUTING, Generated Files). The .guardlink/ artifact set is regenerated, and the only change in each file is the generator: stamp moving from guardlink@2.1.0 to guardlink@2.2.0. The annotation hash is byte-identical, ANNOTATION_HASH_VERSION (3) and ARTIFACT_SCHEMA_VERSION (2) are unchanged since v2.1.0, and guardlink sync . produces no diff.

docs(changelog,readme). [Unreleased] becomes [2.2.0] — 2026-10-07, covering #46–#55. No existing entry was reworded or dropped; I added a lead, an Upgrading list, a Security entry, and --state on hypothesis boundaries, which the Added entry left out. The lead covers the change most likely to turn a gate red: a @mitigates on one handler no longer clears the same asset and threat on sibling handlers, so validate, ci and sarif can report more open exposures. The Upgrading list covers:

  • more open exposures (above);
  • route_candidates replacing a guessed codegraph_reachability on ambiguous SARIF results;
  • regenerating artifacts once;
  • 2.1.0 being unable to write a hypothesis ledger that records a boundary outcome;
  • the new GitHub security-severity bands.

The README's status block is refreshed from a real guardlink status . run on this tree (169 files, 891 annotations).

On the version number: a minor, with one type change disclosed

I am not claiming "no breaking changes". No command, flag, library subpath, JSON field or SARIF result was removed, renamed or reordered, and new JSON fields and SARIF members are additive and optional. One TypeScript change is not purely additive. AnnotationVerb gained 'agents' | 'reaches' | 'effects' | 'gates', and the Annotation union gained ReachesAnnotation, EffectsAnnotation and GatesAnnotation. An exhaustive switch over verb with a never default stops compiling until it handles the four new verbs or adds a default branch. The 2.0.0 entry described the same kind of change for 'actor'/'entitles' as breaking. This release follows the precedent 2.1.0 set instead: 2.1.0 widened the exported DiagnosticCode union in a minor release. The changelog's On the version number paragraph states all of this.

Verification

Node v24.14.0 / npm 11.9.0, the same Node major release.yml pins.

Command Result
npm ci clean, lockfile in sync
npm run build clean
npm run lint exit 0
npm test 120 files, 2212 passed, 1 skipped (rerun after the dependency fixes: same)
guardlink validate . --artifacts ✓ Artifacts are current. ✓ Artifacts are drawable.
guardlink ci . exit 0
guardlink --version, guardlink-mcp --version 2.2.0
npm pack --dry-run version: 2.2.0, 796 files, conformance/ included

npm audit

after the SDK bump after fix(deps): take in-range fixes
all dependencies 25 (3 critical, 17 high, 3 moderate, 2 low) 6 (2 critical, 3 high, 1 moderate)
--omit=dev 14 (1 critical, 10 high, 2 moderate, 1 low) 3 (3 high)

The SDK advisory itself (GHSA-6qxp-vccf-f47h) is already gone in the first column.

How the transitive fixes were taken: npm audit fix without --force, plus npm update tsx (4.21.0 → 4.23.15, within the declared ^4.0.0). tsx's ~0.27 pin was holding esbuild below its fix (GHSA-g7r4-m6w7-qqqr). package.json does not change. Every move stays inside a declared range.

One move held back by hand. npm audit fix took @hono/node-server from 1.19.9 to 2.1.3. The MCP SDK's range (^1.19.9 || ^2.0.5) allows that, but it is a major of that package and declares engines.node >= 20, while guardlink supports >= 18. The lockfile pins it at 1.19.17 instead, which is past every advisory against it (<= 1.19.14). No other runtime dependency's engines moved above Node 18.

Still open, and why:

Package Severity Scope Reason
braces (GHSA-vfj7-8cjw-p6xm) high runtime, via fast-glob → micromatch Every version is affected; no patched release exists
micromatch, fast-glob high runtime Flagged only through braces; no fix available
vitest, @vitest/mocker (GHSA-82fw-gwwq-j7x9) critical / moderate dev Fixed only in vitest 5, a major
tinypool (GHSA-5gmw-xhrv-c9v3, GHSA-85c8-ppgw-ccpr) critical dev, via vitest Same: needs vitest 5

The two critical advisories are in the test runner, which is not shipped in the package.

Note for review: rollup 4.64.1 (dev, via vite) adds an optional @napi-rs/lzma-linux-x64-gnu whose engines excludes Node 18 and 20. npm does not enforce engines by default, and this PR's CI on Node 18/20/22 is the check that it does no harm.

Release workflow

Nothing in release.yml blocks this version:

  • Trigger: release: published.
  • Permissions: id-token: write.
  • Provenance: Node 24's bundled npm 11 satisfies OIDC trusted publishing (>= 11.5.1), and repository.url matches this repository.
  • Version: npm publish takes the version from package.json. The registry's latest is 2.1.0.

Two things to watch when cutting the Release:

  1. Tag placement. The Release's tag must point at a commit that includes this PR. Otherwise the workflow tries to republish 2.1.0 and fails.
  2. Test order. The workflow runs npm test after the Release is already public, but only on Node 24, where D22 runs in about 0.7 s. The Node 18 timeouts happened in ci.yml.

For a reviewer

  • conformance/boundaries.json is included in the package, but package.json exports lists only ./conformance/flows.json. So import 'guardlink/conformance/boundaries.json' fails with ERR_PACKAGE_PATH_NOT_EXPORTED, even though the file is there. The changelog says it "ships in the npm package", which is true of the file. Adding the export is a one-line follow-up and is not done here.
  • docs/SPEC.md still shows "generator": "guardlink@2.1.0" in an example snippet (around line 1392). It's an illustration and the spec version is decoupled from the CLI's, so I left it alone.
  • A second test is close to its timeout. On the first CI run of the dependency commit, tests/paths.test.ts › findUnmitigatedPaths — against the live repo timed out on Node 20: its beforeAll parses the whole repository and hit the 10 s hook default. It passed on rerun. The dependency changes did not cause it. Locally that file and tests/readme.test.ts take 1.2 s with either lockfile, and the full suite 40.9 s after the change against 44.7 s before. On CI the same file already took 8.6 s on Node 18 in this PR's earlier green run. Several suites parse this repository in beforeAll (lookup, context, paths, subgraph, external-id, agent-block, graph-completeness), so they share the margin D22 had. The release workflow tests only on Node 24, where these run fastest. Sizing those hooks deserves its own change and is not done here.

…to it

The test parses this repository in its body, not in beforeAll, so it ran
under the 5000ms test default rather than the 10s hook default its
siblings get. On CI it takes 3.1-3.8s and has crossed 5000ms on Node 18.
The whole-repository scan is the assertion's point: cwe:CWE-89 is written
in grammar examples across src/, so narrowing the scan would weaken it.
The global testTimeout is unchanged.
GHSA-6qxp-vccf-f47h (CVE-2026-104850, high) is in the SDK's OAuth client.
guardlink-mcp only runs the SDK's stdio server, so it is not reachable
here, but npm audit flags every install of guardlink until the range
excludes the vulnerable versions. The lockfile resolves 1.32.1.
package.json and package-lock.json's two root entries, plus the
regenerated .guardlink/ artifact set. The only change in each artifact is
the generator stamp moving from guardlink@2.1.0 to guardlink@2.2.0; the
annotation hash is unchanged, and guardlink sync reports no change.
[Unreleased] becomes [2.2.0], led by the change that can turn a gate red
(a @mitigates no longer clears sibling handlers) and an Upgrading list:
more open exposures, route_candidates in place of a guessed route,
artifact regeneration, ledger compatibility with 2.1.0, and the
AnnotationVerb widening for exhaustive switches. Adds a Security entry
for the MCP SDK bump. The README status block is refreshed from a real
guardlink status . run on this tree.
npm audit fix, without --force, plus npm update tsx (4.21.0 -> 4.23.15,
inside the declared ^4.0.0), whose ~0.27 pin was holding esbuild below its
fix. package.json does not change; every move is inside a declared range.

One move is held back by hand: npm took @hono/node-server from 1.19.9 to
2.1.3, which the MCP SDK's range allows but is a major of that package and
requires Node >= 20, while guardlink supports Node >= 18. It is pinned at
1.19.17 instead, which is past every advisory against it.

npm audit: 25 -> 6 (14 -> 3 with --omit=dev). What remains has no fix in
range: braces (GHSA-vfj7-8cjw-p6xm, every version) and the micromatch and
fast-glob that depend on it have no patched release, and vitest, tinypool
and @vitest/mocker need vitest 5, a major.
@Animesh-Sri-bugb
Animesh-Sri-bugb merged commit 281992d into main Oct 7, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant