[PR #4053] [CLOSED] fix(reference): preserve imports with symlinks into unreadable subtrees #6023

Closed
opened 2026-10-31 01:11:15 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/4053
Author: @XY-code1
Created: 10/15/2026
Status: ❌ Closed

Base: main ← Head: fix/unreadable-symlink-targets


📝 Commits (4)

  • 2981097 fix(reference): keep unreadable symlink targets uncertain
  • 2f9093e fix(reference): bound unreadable target reconciliation
  • 6d04abf fix(reference): preserve reconciled exclusion facts
  • d20f452 fix(reference): preserve failed ancestor evidence

📊 Changes

5 files changed (+397 additions, -3 deletions)

View changed files

➕ src/reference/ReferenceSourceReader.test.ts (+212 -0)
📝 src/reference/ReferenceSourceReader.ts (+105 -0)
📝 src/reference/ReferenceSourceReaderEntries.ts (+8 -2)
📝 src/reference/ReferenceSourceReaderTypes.ts (+4 -0)
📝 tests/boundary/filesystem/referenceSourceUnreadableDirectories.test.ts (+68 -1)

📄 Description

Summary

Fixes #4013.

Preserve a successful partial reference-source import when a retained symlink
resolves inside a directory that the reader could not enumerate.

Problem and expected behavior

A searchable but non-enumerable directory can allow realpath to resolve a
symlink target even though the reader cannot inventory that target. The reader
previously labeled the target internal; graph validation then correctly
rejected it because no matching inventory entry or exclusion existed, causing
the whole import to fail and discarding readable siblings.

The symlink target should remain uncertain rather than being represented as an
inventoried internal target.

Change and scope

After traversal, the reader reconciles internal symlink observations with its
completed entry inventory. Failed ancestor lookup preserves the original failure code
and reason, including changed and symlink, and uses bounded parent lookup.

A symlink is converted to an unreadable observation only when:

  • its target is strictly below a recorded failed directory; and
  • no entry for that target was observed.

The existing failed-symlink projection produces target: null and
target_state: "unreadable".

Already inventoried internal targets retain their existing behavior. Similar
directory-name prefixes do not match.

checkSymlinks, root containment, no-follow traversal, and graph validation are
unchanged. The reader does not follow the symlink or read its target.

Evidence and regression coverage

Added:

  • a cross-platform reader reconciliation test covering:
    • unobserved targets below failed directories;
    • preservation of inventoried internal targets;
    • sibling-prefix path boundaries;
    • changed/symlink ancestor failures preserve their original code and reason;
    • canonically equivalent inventoried targets remain internal;
  • a POSIX-only filesystem regression with:
    • hidden/target.txt;
    • alias.txt -> hidden/target.txt;
    • hidden mode 0111;
    • a readable visible.txt sibling.

The POSIX regression asserts the EACCES directory diagnostic, hashed readable
sibling, successful partial import, and target: null / target_state: "unreadable" for the symlink.

Validation performed

  • npm run test:local -- src/reference/ReferenceSourceReader.test.ts
    — 7 passed.
  • Focused import projection — 1 passed, 17 skipped.
  • Focused graph contract — 1 passed, 26 skipped.
  • Windows filesystem boundary file — 1 baseline platform failure, 3 POSIX-only skips.
  • npm run check:fast — passed.
  • npm run verify:test-discovery
    — all 1330 test files discovered exactly once.
  • git diff --check — passed.
  • Requested focused suite on Windows:
    — 30 passed, 24 failed, 4 skipped.
  • The identical suite on an unmodified detached baseline:
    — 30 passed, the same 24 failed, 3 skipped.

All 24 failures are baseline Windows limitations: safe no-follow opens are
unavailable in this source checkout or symlink creation returns EPERM. The
additional skip is the new POSIX permission regression.

POSIX permission semantics were not executed locally because the registered
WSL2 Ubuntu instance cannot mount its missing VHD and no Docker Linux engine is
available. Linux/macOS CI must establish the native chmod 0111 result.

Compatibility and safety

  • No schema or CLI/MCP contract change.
  • No relaxation of internal symlink validation.
  • No new traversal or target read.
  • No user permission changes.
  • Tests modify and restore permissions only on their owned fixture.
  • No provider or package metadata impact.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/4053 **Author:** [@XY-code1](https://github.com/XY-code1) **Created:** 10/15/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/unreadable-symlink-targets` --- ### 📝 Commits (4) - [`2981097`](https://github.com/morluto/rea/commit/29810973b9fbe06ca5a022253bba9255b0d6db85) fix(reference): keep unreadable symlink targets uncertain - [`2f9093e`](https://github.com/morluto/rea/commit/2f9093ec8012af58e4a52c88d7b5632b16d8286b) fix(reference): bound unreadable target reconciliation - [`6d04abf`](https://github.com/morluto/rea/commit/6d04abf8b07c35cdc135a18a8654a7cb89c73c10) fix(reference): preserve reconciled exclusion facts - [`d20f452`](https://github.com/morluto/rea/commit/d20f4523183f89ca675102a9bb52a541e1c7ac67) fix(reference): preserve failed ancestor evidence ### 📊 Changes **5 files changed** (+397 additions, -3 deletions) <details> <summary>View changed files</summary> ➕ `src/reference/ReferenceSourceReader.test.ts` (+212 -0) 📝 `src/reference/ReferenceSourceReader.ts` (+105 -0) 📝 `src/reference/ReferenceSourceReaderEntries.ts` (+8 -2) 📝 `src/reference/ReferenceSourceReaderTypes.ts` (+4 -0) 📝 `tests/boundary/filesystem/referenceSourceUnreadableDirectories.test.ts` (+68 -1) </details> ### 📄 Description ## Summary Fixes #4013. Preserve a successful partial reference-source import when a retained symlink resolves inside a directory that the reader could not enumerate. ## Problem and expected behavior A searchable but non-enumerable directory can allow `realpath` to resolve a symlink target even though the reader cannot inventory that target. The reader previously labeled the target `internal`; graph validation then correctly rejected it because no matching inventory entry or exclusion existed, causing the whole import to fail and discarding readable siblings. The symlink target should remain uncertain rather than being represented as an inventoried internal target. ## Change and scope After traversal, the reader reconciles internal symlink observations with its completed entry inventory. Failed ancestor lookup preserves the original failure code and reason, including changed and symlink, and uses bounded parent lookup. A symlink is converted to an unreadable observation only when: - its target is strictly below a recorded failed directory; and - no entry for that target was observed. The existing failed-symlink projection produces `target: null` and `target_state: "unreadable"`. Already inventoried internal targets retain their existing behavior. Similar directory-name prefixes do not match. `checkSymlinks`, root containment, no-follow traversal, and graph validation are unchanged. The reader does not follow the symlink or read its target. ## Evidence and regression coverage Added: - a cross-platform reader reconciliation test covering: - unobserved targets below failed directories; - preservation of inventoried internal targets; - sibling-prefix path boundaries; - changed/symlink ancestor failures preserve their original code and reason; - canonically equivalent inventoried targets remain internal; - a POSIX-only filesystem regression with: - `hidden/target.txt`; - `alias.txt -> hidden/target.txt`; - `hidden` mode `0111`; - a readable `visible.txt` sibling. The POSIX regression asserts the `EACCES` directory diagnostic, hashed readable sibling, successful partial import, and `target: null / target_state: "unreadable"` for the symlink. ## Validation performed - `npm run test:local -- src/reference/ReferenceSourceReader.test.ts` — 7 passed. - Focused import projection — 1 passed, 17 skipped. - Focused graph contract — 1 passed, 26 skipped. - Windows filesystem boundary file — 1 baseline platform failure, 3 POSIX-only skips. - `npm run check:fast` — passed. - `npm run verify:test-discovery` — all 1330 test files discovered exactly once. - `git diff --check` — passed. - Requested focused suite on Windows: — 30 passed, 24 failed, 4 skipped. - The identical suite on an unmodified detached baseline: — 30 passed, the same 24 failed, 3 skipped. All 24 failures are baseline Windows limitations: safe no-follow opens are unavailable in this source checkout or symlink creation returns `EPERM`. The additional skip is the new POSIX permission regression. POSIX permission semantics were not executed locally because the registered WSL2 Ubuntu instance cannot mount its missing VHD and no Docker Linux engine is available. Linux/macOS CI must establish the native `chmod 0111` result. ## Compatibility and safety - No schema or CLI/MCP contract change. - No relaxation of internal symlink validation. - No new traversal or target read. - No user permission changes. - Tests modify and restore permissions only on their owned fixture. - No provider or package metadata impact. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:11:15 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#6023
No description provided.