Repository navigation
fix(journey): on Windows the org scope reads a file id through a handle — on Node 22.16.x (libuv 1.49.2) acme read beta's file beside a workspace named through a share - #172
Merged
Conversation
…le — on Node 22.16.x (libuv 1.49.2) a local path beside a workspace named through a share was never placed, and acme read beta's file crawlScopeRefusal placed a local path in a workspace named through a share (\myhost\ws, a drive mapped to \localhost\C$\ws) by a file id read with statSync. libuv answers a stat of a local path by its name, and 1.49.0 to 1.50.x report there the upper half of the file's 128-bit id as the device, 0 on NTFS, while the workspace through its share is opened and reports the serial: no local directory was the workspace's own, so beta's C:\ws\orgs\beta\... read as outside the workspace, nobody's part, and an acme journey loaded it (fails open). A file id is now read through a handle (openSync, fstatSync, closeSync), as server/store/paths.mjs does since #165; the three are injectable in place of statSync. tools/test-journey-scope.mjs injects the ntfs fixture's handles, and a new test loops libuv 1.51.0 and 1.49.2; at the parent it fails on 1.49.2 alone. VENDOR-MANIFEST.json is unchanged (exports are). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #165:
crawlScopeRefusalintools/lib/journey.mjs, whichserver/store/paths.mjscalls its twin, read file ids withstatSync. On Windows they are now read through a handle.The bug: it failed open
While the workspace is named through a share this host serves (
OBSERVOGRAM_WORKSPACE=\myhost\ws, or a drive mapped to\localhost\C$\ws), a local path outside the workspace is placed by its nearest directory that has the workspace's file id. libuv 1.49.0 to 1.50.x (Node 22.16.x ships 1.49.2) stat a local path by name and report dev 0 on NTFS. The workspace, reached through its share, is opened instead and reports the volume serial. So no local directory ever matched the workspace,placed()returned null, and the path counted as "outside the workspace, on a local drive", which nobody owns, so it was read. Result: acme's journey read beta'sC:\ws\orgs\beta\packs\b1.pack.yaml. That is a fail-open, not the false refusal the original brief expected; I checked it on the ntfs fixture withfastDev: 0n.Fix
fileIdnow doesopenSync(p, 'r'), thenfstatSync(fd, { bigint: true }), withcloseSyncin afinally. That is whatpaths.mjsdoes since fix(store): on Windows the path comparison reads a path's volume through a handle — on Node 22.16.x (libuv 1.49.2) a path through a share of the workspace compared as outside it #165. A path that cannot be opened is skipped, the same way a path that could not be stat'd was skipped before.crawlScopeRefusal/crawlScopeTestnow takesopenSync,fstatSyncandcloseSyncwhere it used to takestatSync. This is named under## Unreleasedindocs/CHANGELOG.md(Suite total 1485 → 1486). Exports are unchanged, soVENDOR-MANIFEST.jsonstays in sync with no diff.Tests
tools/test-journey-scope.mjsnow passes the fixture's handles (onVolume(volume)) to every scope it builds.fastDev: null) and 1.49.2 (fastDev: 0n), with the workspace named\myhost\wsorZ:\. It checks that beta's file in every local spelling is refused to acme, that acme's own files andC:\repo\…are read, and that every handle is closed. The host also offers a by-namestatSync, so a regression back to a by-name read would fail. At the parent commit this test fails on the 1.49.2 iteration only.Gates (local, Windows, Node 22.16.0)
test:goldenandtest:golden:compile: byte-identicalvendor-manifest:check,sync-spec:check,tools/test-doc-test-totals.mjs: passtools/test-journey-scope.mjs: 11/11npm testlocally: failures in auth-local, authz, mcp-settings, smoke, store-boot and studio-bundle (/→ 404, boot-child timeouts). The same suites failed locally for fix(store): on Windows the path comparison reads a path's volume through a handle — on Node 22.16.x (libuv 1.49.2) a path through a share of the workspace compared as outside it #165, and its CI was green. They come from this worktree's environment (a root under.claude\, no localnode_modulesuntilnpm ci), not from this change. CI decides for those suites.🤖 Generated with Claude Code