Skip to content

Conversation

@luxass
Copy link
Member

@luxass luxass commented Jan 6, 2026

🔗 Linked issue

📚 Description

This PR is a combination of changes related to fs-bridge, but also playgrounds from #440.

This will help close #420.

Summary by CodeRabbit

  • New Features

    • Directory listing (listdir) for the Node file-system bridge
    • Detection utility for the built-in HTTP bridge
    • Public "./errors" export and new local playground scripts (node & http)
  • Improvements

    • Enhanced HTTP bridge request/schema validation and verbose logging
    • Unified error normalization and improved error cause propagation
  • Tests

    • Expanded HTTP/schema/security tests; many test suites converted to todo/placeholders

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 6, 2026

⚠️ No Changeset found

Latest commit: 5334e8c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

📝 Walkthrough

Walkthrough

Adds Node listdir API; exports an errors entry; tags HTTP bridges with a runtime symbol and adds an isBuiltinHttpBridge guard; strengthens HTTP bridge URL/schema, logging, and schema checks; refactors BridgeGenericError to accept ErrorOptions; adds playground scripts and test/fixture updates; updates build/config files.

Changes

Cohort / File(s) Summary
Packaging & Config
packages/fs-bridge/eslint.config.js, packages/fs-bridge/tsdown.config.ts, packages/fs-bridge/package.json, pnpm-workspace.yaml
ESLint ignores now include playgrounds/**; tsdown adds ./src/errors.ts and marks @luxass/msw-utils noExternal; package.json adds ./errors export, two playground scripts, and @luxass/msw-utils devDependency; workspace bumps msw-utils to 0.6.0.
Playgrounds
packages/fs-bridge/playgrounds/http-playground.ts, packages/fs-bridge/playgrounds/node-playground.ts
New standalone test/playground scripts exercising HTTP and Node bridges across read/exists/listdir/write/mkdir/rm scenarios and asserting expected outcomes.
HTTP Bridge
packages/fs-bridge/src/bridges/http.ts
Adds and exports kHttpBridgeSymbol; replaces URL schema with stricter z.url handling; extensive debug logging for read/listdir/exists; clearer HTTP-status handling and fetch diagnostics; bridge exposes the symbol.
Node Bridge
packages/fs-bridge/src/bridges/node.ts
Adds public listdir(path, recursive = false) API; centralizes path formatting (ensure leading slash, trailing slash for directories), normalizes keys for entry maps and parent-child wiring.
Bridge Factory & Types
packages/fs-bridge/src/define.ts, packages/fs-bridge/src/types.ts, packages/fs-bridge/src/index.ts
defineFileSystemBridge accepts optional symbol and attaches it at runtime; new FileSystemBridgeArgs<T> type and updated FileSystemBridgeFactory signature; exports updated to include isBuiltinHttpBridge and FileSystemBridgeArgs.
Errors & Utilities
packages/fs-bridge/src/errors.ts, packages/fs-bridge/src/utils.ts, packages/fs-bridge/src/guards.ts
BridgeGenericError constructor changed to (message, options?: ErrorOptions) and removed originalError property; utils.handleError normalizes errors and specially handles MSW errors; new isBuiltinHttpBridge(fs) guard checks kHttpBridgeSymbol.
Tests — Bridges & HTTP
packages/fs-bridge/test/bridges/http/*.test.ts, packages/fs-bridge/test/bridges/node/node.test.ts, packages/fs-bridge/test/bridge-methods.test.ts
Fixtures and expectations updated to require leading slashes and trailing directory slashes; added Zod schema validation tests for listdir payloads; added listdir shape and error-wrapping tests; minor test comment cleanup.
Tests — Security
packages/fs-bridge/test/security/http/*, packages/fs-bridge/test/security/node/*, packages/fs-bridge/test/security/node/path-traversal.test.ts
Tests updated/added for URL-encoded traversal, excessive-encoding expectations, and recursive listdir traversal protections; titles normalized to "URL-encoded".
Store Tests Marked TODO
packages/ucd-store/test/**/*
Many ucd-store test suites converted from active describe to describe.todo, marking them pending/skipped.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant HTTPBridge as HTTP Bridge
  participant RemoteAPI as Remote API
  participant Zod as Schema Validator

  rect rgba(99,102,241,0.06)
  Client->>HTTPBridge: listdir(path, recursive?)
  end

  HTTPBridge->>RemoteAPI: GET /list?path=... (fetch)
  RemoteAPI-->>HTTPBridge: 200 JSON / 404 / 500
  alt 200
    HTTPBridge->>Zod: validate(listResponse)
    Zod-->>HTTPBridge: ok / error
    alt ok
      HTTPBridge-->>Client: FSEntry[] (normalized paths, dirs with trailing '/')
    else error
      HTTPBridge-->>Client: throw BridgeGenericError("Invalid response schema")
    end
  else 404/403/500
    HTTPBridge-->>Client: map status -> empty/list or throw (logged)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🐰 I hopped in code with tiny feet,
listdir trimmed and paths made neat,
symbols whispered, errors re‑styled,
playgrounds sprinted, tests compiled—
carrots shared for every passing suite! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Multiple out-of-scope changes detected: ucd-store test suites converted to describe.todo throughout packages/ucd-store, and analyze.test.ts converted to todos. These test changes are unrelated to the fs-bridge improvements stated in the PR objectives. Remove or separate the ucd-store test conversions to describe.todo/it.todo blocks into a dedicated test infrastructure PR. Keep only fs-bridge and playground-related changes in this PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'refactor: modify fs-bridge to work better' is vague and does not clearly convey the specific changes made. The phrase 'work better' is non-descriptive and fails to highlight the main improvements such as HTTP bridge enhancements, playground additions, or error handling updates. Use a more specific title that describes the primary changes, such as 'refactor: add fs-bridge HTTP and Node playgrounds with symbol-based bridge detection and improved error handling' or break into separate commits with more precise titles.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR addresses issue #420's fs-bridge improvements through multiple changes including HTTP bridge enhancements, playground scripts, path formatting, error handling updates, and symbol-based bridge detection. Core coding requirements around bridge functionality appear to be met.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the pkg: fs-bridge Changes related to the FS Bridge package. label Jan 6, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 6, 2026

📋 OpenAPI Schema Analysis

No changes detected - The OpenAPI schema is identical to the main branch.

🤖 This comment is automatically updated when you push new commits.

@codecov
Copy link

codecov bot commented Jan 7, 2026

Codecov Report

❌ Patch coverage is 89.74359% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/fs-bridge/src/bridges/http.ts 88.88% 2 Missing ⚠️
packages/fs-bridge/src/guards.ts 0.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@luxass luxass changed the base branch from feat/improve-wildcard-api to main January 7, 2026 06:16
@github-actions github-actions bot added pkg: ucd-store Changes related to the UCD Store package. apps: api Changes related to the API. pkg: schemas Changes related to the FS Bridge package. labels Jan 7, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 7, 2026

🌏 Preview Deployments

Note

No deployable apps affected by changes in this PR.

Built from commit: 5334e8cb4698ae11565b13a235cba9b8f36bb1a6


🤖 This comment will be updated automatically when you push new commits to this PR.

@luxass luxass force-pushed the bridge-improvements branch from 5866646 to 21748cc Compare January 7, 2026 06:36
@luxass luxass marked this pull request as ready for review January 7, 2026 06:37
Copilot AI review requested due to automatic review settings January 7, 2026 06:37
@greptile-apps
Copy link

greptile-apps bot commented Jan 7, 2026

Greptile Summary

  • Refactors fs-bridge package to improve path handling consistency between HTTP and Node bridges, with enhanced error propagation and symbol-based bridge type detection
  • Adds playground scripts and exports error types for better debugging/testing capabilities while temporarily disabling many ucd-store tests via describe.todo
  • Updates path formatting to ensure FileEntry schema compliance with leading slashes for files and trailing slashes for directories across both bridge implementations

Important Files Changed

Filename Overview
packages/fs-bridge/src/bridges/http.ts Enhanced HTTP bridge with symbol-based detection, comprehensive debug logging, improved schema validation, and path normalization
packages/fs-bridge/src/bridges/node.ts Refactored Node bridge to align path formatting with FileEntry schema requirements using new path utilities
packages/fs-bridge/src/utils.ts Improved error handling with MSW error detection and enhanced error cause propagation
packages/fs-bridge/test/bridges/http/http.test.ts Added comprehensive schema validation, fetch error handling, and content handling test suites
packages/fs-bridge/test/bridges/node/node.test.ts Updated path format expectations and added shape consistency and error surface tests

Confidence score: 4/5

  • This PR requires careful review due to extensive path handling changes across critical fs-bridge infrastructure
  • Score reflects comprehensive testing additions and systematic approach, but deducted one point due to the complexity of path normalization changes and potential for subtle edge cases in bridge behavior
  • Pay close attention to path handling logic in both HTTP and Node bridges, particularly the resolveSafePath usage and FileEntry schema compliance

Sequence Diagram

sequenceDiagram
    participant User
    participant HTTPBridge as "HTTP Bridge"
    participant PathUtils as "Path Utils"
    participant RemoteAPI as "Remote API"
    participant Schema as "Zod Schema"

    User->>HTTPBridge: "HTTPFileSystemBridge({ baseUrl })"
    HTTPBridge->>HTTPBridge: "Validate baseUrl with Zod"
    HTTPBridge-->>User: "Bridge instance"

    User->>HTTPBridge: "read(path)"
    HTTPBridge->>HTTPBridge: "Validate path (reject trailing /)"
    HTTPBridge->>PathUtils: "resolveSafePath(baseUrl.pathname, path)"
    PathUtils-->>HTTPBridge: "Safe resolved path"
    HTTPBridge->>RemoteAPI: "GET request to resolved URL"
    RemoteAPI-->>HTTPBridge: "Response with file content"
    HTTPBridge->>HTTPBridge: "response.text()"
    HTTPBridge-->>User: "File content string"

    User->>HTTPBridge: "exists(path)"
    HTTPBridge->>PathUtils: "resolveSafePath(baseUrl.pathname, path)"
    PathUtils-->>HTTPBridge: "Safe resolved path"
    HTTPBridge->>RemoteAPI: "HEAD request to resolved URL"
    RemoteAPI-->>HTTPBridge: "Response status"
    HTTPBridge-->>User: "Boolean exists result"

    User->>HTTPBridge: "listdir(path, recursive)"
    HTTPBridge->>PathUtils: "resolveSafePath(baseUrl.pathname, path)"
    PathUtils-->>HTTPBridge: "Safe resolved path"
    HTTPBridge->>RemoteAPI: "GET request with Accept: application/json"
    RemoteAPI-->>HTTPBridge: "JSON directory listing"
    HTTPBridge->>Schema: "Validate with FileEntrySchema"
    Schema-->>HTTPBridge: "Validated entries array"
    alt recursive = true
        loop For each directory entry
            HTTPBridge->>HTTPBridge: "Recursive listdir call for subdirectories"
        end
    end
    HTTPBridge-->>User: "FSEntry[] with file/directory structure"
Loading

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the fs-bridge package to improve error handling, add playgrounds for manual testing, and enhance schema validation. The changes support work from PR #440 (playgrounds) and help close PR #420 (comprehensive refactoring).

Key changes:

  • Updated @luxass/msw-utils from 0.5.0 to 0.6.0 for better MSW error detection
  • Added Node.js and HTTP playgrounds for manual testing and verification
  • Improved error handling with MSW error detection in the error flow
  • Enhanced HTTP bridge with Zod schema validation for file entries
  • Updated test expectations for path format consistency (directory paths now require leading/trailing slashes)

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pnpm-workspace.yaml Bumped @luxass/msw-utils from 0.5.0 to 0.6.0
pnpm-lock.yaml Updated lockfile to reflect dependency version changes
packages/ucd-store/test/maintenance/analyze.test.ts Disabled remote store test pending ucd-store-v2 replacement
packages/fs-bridge/tsdown.config.ts Added bundling config for @luxass/msw-utils and exposed errors module
packages/fs-bridge/test/security/node/*.test.ts Enhanced security tests with better error assertions and recursive listdir coverage
packages/fs-bridge/test/security/http/*.test.ts Updated path format expectations and improved error message assertions
packages/fs-bridge/test/bridges/node/node.test.ts Added comprehensive shape consistency and error surface tests
packages/fs-bridge/test/bridges/http/http.test.ts Added Zod schema validation and fetch error handling tests
packages/fs-bridge/test/bridges/http/basepath.*.test.ts Updated mock responses to use correct path format (leading slashes)
packages/fs-bridge/test/bridge-methods.test.ts Removed redundant comments
packages/fs-bridge/src/utils.ts Integrated isMSWError utility, updated error handling flow, refactored error constructor calls
packages/fs-bridge/src/types.ts Extracted FileSystemBridgeArgs as reusable type
packages/fs-bridge/src/index.ts Added exports for isBuiltinHttpBridge and FileSystemBridgeArgs
packages/fs-bridge/src/guards.ts Added isBuiltinHttpBridge utility function
packages/fs-bridge/src/errors.ts Simplified BridgeGenericError constructor to use ErrorOptions
packages/fs-bridge/src/bridges/node.ts Added comprehensive documentation explaining parity differences with HTTP bridge
packages/fs-bridge/src/bridges/http.ts Replaced deprecated z.httpUrl with z.url config, added debug logging throughout, normalized listdir paths
packages/fs-bridge/playgrounds/node-playground.ts New playground for manual Node bridge testing
packages/fs-bridge/playgrounds/http-playground.ts New playground for manual HTTP bridge testing against real API
packages/fs-bridge/package.json Added playground scripts and errors export, included @luxass/msw-utils in devDependencies
packages/fs-bridge/eslint.config.js Added playgrounds directory to eslint ignore list
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Replaced instances of `BridgeGenericError` with `BridgeBaseError` in error handling logic to ensure consistent error classification across the file system bridge operations.
luxass added 2 commits January 7, 2026 16:05
- Introduced `kHttpBridgeSymbol` to uniquely identify the HTTP File System Bridge.
- Updated `defineFileSystemBridge` to accept an optional `symbol` property.
- Enhanced `isBuiltinHttpBridge` to check for the bridge type using the symbol.
@github-actions github-actions bot removed apps: api Changes related to the API. pkg: schemas Changes related to the FS Bridge package. labels Jan 7, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/fs-bridge/test/security/http/encoded-attacks.test.ts (1)

146-161: Use consistent version format matching other tests in the file.

The "excessive encoding" test (line 146-147) uses /api/v1/files/16.0.0 (without "v" prefix), but earlier tests in the same file use /api/v1/files/v16.0.0 (with "v" prefix) on lines 54-55 and 108-109. For consistency, change line 146-147 to use the "v" prefix:

Suggested change
-    describe("deep pathname (/api/v1/files/16.0.0)", () => {
-      const basePath = "/api/v1/files/16.0.0";
+    describe("deep pathname (/api/v1/files/v16.0.0)", () => {
+      const basePath = "/api/v1/files/v16.0.0";
🤖 Fix all issues with AI agents
In @packages/fs-bridge/test/security/node/excessive-encoding.test.ts:
- Around line 37-40: Tests use inconsistent error assertion styles: change the
second assertion that expects a thrown string "Failed to decode path" to assert
the specific error class FailedToDecodePathError instead. Update the expect call
around bridge.read(`${encodedTraversal}etc/passwd`) to use
.rejects.toThrow(FailedToDecodePathError) so both tests consistently assert the
same error type.

In @packages/fs-bridge/tsdown.config.ts:
- Around line 13-15: The current tsdown.config.ts forces bundling of
@luxass/msw-utils (listed in noExternal) which pulls test-only helpers like
isMSWError into production; remove @luxass/msw-utils from noExternal and either
(A) extract the isMSWError implementation into the @ucdjs-internal/shared
package and update src/utils.ts to import it from shared, or (B) change the
import in src/utils.ts to a conditional dynamic import (e.g., only load
@luxass/msw-utils when NODE_ENV !== 'production' or when running tests) and make
noExternal conditional on NODE_ENV so production builds do not bundle the
package; update all imports of isMSWError to the new location or to the guarded
dynamic import accordingly.
🧹 Nitpick comments (4)
packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts (1)

142-159: Consider adding assertions for path values.

The mock data was updated to include leading slashes in the path property ("/file1.txt", "/file2.txt"), but the test only asserts on the length of entries without validating the actual path values. Consider adding assertions to verify the path format matches the expected behavior:

💡 Suggested enhancement
 const entries = await bridge.listdir("");
 expect(entries).toHaveLength(2);
+expect(entries[0]?.path).toBe("/file1.txt");
+expect(entries[1]?.path).toBe("/file2.txt");
packages/fs-bridge/src/bridges/node.ts (1)

47-47: Refactor the duplicated path validation logic.

The TODO correctly identifies code duplication between read and write methods. Both validate trailing slashes identically (lines 48-53 vs 142-147). Consider extracting this validation into a reusable helper function.

♻️ Proposed refactor

Add a helper function at the module level:

+function validateFilePathFormat(path: string): void {
+  const trimmedPath = path.trim();
+  if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") {
+    throw new Error("Cannot access file: path ends with '/'");
+  }
+}

Then use it in both methods:

 async read(path) {
-  // TODO: duplicate code with write - refactor
-  // Reject file paths ending with / - files don't have trailing slashes
-  // Allow /, ./, and ../ as they are special directory references
-  const trimmedPath = path.trim();
-  if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") {
-    throw new Error("Cannot read file: path ends with '/'");
-  }
+  validateFilePathFormat(path);
   const resolvedPath = resolveSafePath(basePath, path);
   return fsp.readFile(resolvedPath, "utf-8");
 },

 async write(path, data, encoding = "utf-8") {
-  // Reject file paths ending with / - files don't have trailing slashes
-  // Allow /, ./, and ../ as they are special directory references
-  const trimmedPath = path.trim();
-  if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") {
-    throw new Error("Cannot write file: path ends with '/'");
-  }
+  validateFilePathFormat(path);
   const resolvedPath = resolveSafePath(basePath, path);
   // ... rest of write logic
packages/fs-bridge/playgrounds/node-playground.ts (1)

283-284: Exit handling is acceptable but could be more graceful.

Using process.exit(1) immediately terminates the process. While cleanup has already completed at this point, using process.exitCode = 1 would be more graceful and consistent with best practices for allowing any remaining async operations to complete naturally.

packages/fs-bridge/src/bridges/http.ts (1)

65-68: Simplify listdir path handling to match the pattern used in read method.

The listdir method explicitly prepends a / to the path (\/${path}`), while the readmethod and other methods use the path directly. SinceresolveSafePathinternally normalizes both cases to the same result, this redundant prefix adds unnecessary inconsistency. Alignlistdirwith the pattern used elsewhere by removing the explicit/` prefix.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c593695 and 6783289.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (26)
  • packages/fs-bridge/eslint.config.js
  • packages/fs-bridge/package.json
  • packages/fs-bridge/playgrounds/http-playground.ts
  • packages/fs-bridge/playgrounds/node-playground.ts
  • packages/fs-bridge/src/bridges/http.ts
  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/src/define.ts
  • packages/fs-bridge/src/errors.ts
  • packages/fs-bridge/src/guards.ts
  • packages/fs-bridge/src/index.ts
  • packages/fs-bridge/src/types.ts
  • packages/fs-bridge/src/utils.ts
  • packages/fs-bridge/test/bridge-methods.test.ts
  • packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts
  • packages/fs-bridge/test/bridges/http/basepath.http.relative.test.ts
  • packages/fs-bridge/test/bridges/http/http.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/test/security/http/encoded-attacks.test.ts
  • packages/fs-bridge/test/security/http/excessive-encoding.test.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/fs-bridge/test/security/node/encoded-attacks.test.ts
  • packages/fs-bridge/test/security/node/excessive-encoding.test.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
  • packages/fs-bridge/tsdown.config.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • pnpm-workspace.yaml
💤 Files with no reviewable changes (1)
  • packages/fs-bridge/test/bridge-methods.test.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{test,spec}.?(c|m)[jt]s?(x)

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.?(c|m)[jt]s?(x): Import test utilities from #test-utils/* path aliases instead of @ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies
Use testdir() from vitest-testdirs to create temporary test directories in filesystem tests
Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Files:

  • packages/fs-bridge/test/security/http/excessive-encoding.test.ts
  • packages/fs-bridge/test/security/node/excessive-encoding.test.ts
  • packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
  • packages/fs-bridge/test/bridges/http/basepath.http.relative.test.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/fs-bridge/test/bridges/http/http.test.ts
  • packages/fs-bridge/test/security/http/encoded-attacks.test.ts
  • packages/fs-bridge/test/security/node/encoded-attacks.test.ts
packages/*/package.json

📄 CodeRabbit inference engine (AGENTS.md)

Use workspace:* protocol for dependencies between workspace packages in package.json

Files:

  • packages/fs-bridge/package.json
🧠 Learnings (24)
📓 Common learnings
Learnt from: luxass
Repo: ucdjs/ucd PR: 6
File: packages/cli/src/cmd/codegen/fields.ts:68-82
Timestamp: 2025-05-04T11:52:22.858Z
Learning: User prefers to address the issue with Node.js API compatibility (`Dirent.parentPath` not being part of Node's API and the `recursive: true` option for `readdir` being only available in Node 21+) in a separate PR rather than the current one.
📚 Learning: 2025-07-29T06:02:32.422Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 175
File: packages/fs-bridge/test/bridges/node.test.ts:0-0
Timestamp: 2025-07-29T06:02:32.422Z
Learning: In the NodeFileSystemBridge security validation, path traversal detection occurs before critical system paths checks, which means absolute paths to critical system directories will always throw "Path traversal detected" rather than "Critical system path access denied", making it impossible to meaningfully test the critical system paths validation logic.

Applied to files:

  • packages/fs-bridge/test/security/http/excessive-encoding.test.ts
  • packages/fs-bridge/test/security/node/excessive-encoding.test.ts
  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/fs-bridge/test/bridges/http/http.test.ts
  • packages/fs-bridge/test/security/http/encoded-attacks.test.ts
  • packages/fs-bridge/test/security/node/encoded-attacks.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use File System Bridge Pattern (ucdjs/fs-bridge) abstraction for file system operations to support multiple backends (Node.js, HTTP, in-memory)

Applied to files:

  • packages/fs-bridge/src/guards.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/src/index.ts
  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/src/bridges/http.ts
  • packages/fs-bridge/playgrounds/node-playground.ts
  • packages/fs-bridge/playgrounds/http-playground.ts
  • packages/fs-bridge/src/utils.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/fs-bridge/src/define.ts
  • packages/fs-bridge/test/bridges/http/http.test.ts
  • packages/fs-bridge/src/types.ts
  • packages/fs-bridge/test/security/http/encoded-attacks.test.ts
📚 Learning: 2025-05-04T11:52:22.858Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 6
File: packages/cli/src/cmd/codegen/fields.ts:68-82
Timestamp: 2025-05-04T11:52:22.858Z
Learning: User prefers to address the issue with Node.js API compatibility (`Dirent.parentPath` not being part of Node's API and the `recursive: true` option for `readdir` being only available in Node 21+) in a separate PR rather than the current one.

Applied to files:

  • packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/tsdown.config.ts
  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/src/bridges/http.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
  • packages/fs-bridge/playgrounds/node-playground.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/fs-bridge/test/bridges/http/http.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Import test utilities from #test-utils/* path aliases instead of ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies

Applied to files:

  • packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/tsdown.config.ts
  • packages/fs-bridge/package.json
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
  • packages/fs-bridge/eslint.config.js
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to apps/api/test/**/*.{test,spec}.?(c|m)[jt]s?(x) : Place API app tests in apps/api/test/routes/** for endpoint tests and apps/api/test/unit/** for unit tests with mocks

Applied to files:

  • packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Applied to files:

  • packages/fs-bridge/test/bridges/http/basepath.http.absolute.test.ts
  • packages/fs-bridge/tsdown.config.ts
  • packages/fs-bridge/test/bridges/http/basepath.http.relative.test.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
📚 Learning: 2025-06-29T11:20:13.668Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 87
File: packages/worker-shared/tsconfig.build.json:1-4
Timestamp: 2025-06-29T11:20:13.668Z
Learning: In the ucdjs/ucd project, the packages use tsdown instead of tsc for building libraries. The tsconfig.build.json files are primarily for IDE experience and type checking, not for direct compilation, so including "test" directories in these configs doesn't affect build output.

Applied to files:

  • packages/fs-bridge/tsdown.config.ts
  • packages/fs-bridge/package.json
📚 Learning: 2025-07-20T05:37:40.565Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 131
File: tooling/eslint-plugin/package.json:0-0
Timestamp: 2025-07-20T05:37:40.565Z
Learning: In the ucdjs/ucd project, internal tooling packages (private packages in the tooling/ directory) export TypeScript files directly without requiring a build step, unlike published packages which use tsdown to build and export from ./dist/. Examples include ucdjs/tsdown-config and ucdjs/eslint-plugin.

Applied to files:

  • packages/fs-bridge/tsdown.config.ts
  • packages/fs-bridge/package.json
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use tsdown for building TypeScript packages with shared tooling configuration from ucdjs-tooling/tsdown-config

Applied to files:

  • packages/fs-bridge/tsdown.config.ts
  • packages/fs-bridge/package.json
📚 Learning: 2025-10-14T07:15:35.199Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 326
File: packages/shared/src/ucd-config.ts:34-58
Timestamp: 2025-10-14T07:15:35.199Z
Learning: In packages/shared/src/ucd-config.ts, the `getDefaultUCDEndpointConfig` function uses a build-time define `__UCD_ENDPOINT_DEFAULT_CONFIG__` that is replaced at build time by the bundler. The `??` operator is evaluated at build time, so the final code contains no runtime branching. Therefore, runtime unit tests for this function are not valuable—the build process itself handles the injection and fallback logic.

Applied to files:

  • packages/fs-bridge/tsdown.config.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to packages/**/.eslintrc.* : Use luxass/eslint-config for linting configuration in new packages

Applied to files:

  • packages/fs-bridge/package.json
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to packages/*/tsconfig.json : Use ucdjs-tooling/tsconfig for TypeScript configuration in new packages

Applied to files:

  • packages/fs-bridge/package.json
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use pnpm catalogs for centralized dependency version management organized by purpose (monorepo, testing, linting, prod, dev, workers, types, web, vscode, docs)

Applied to files:

  • packages/fs-bridge/package.json
  • pnpm-workspace.yaml
📚 Learning: 2025-06-14T05:20:20.149Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/validate.ts:115-130
Timestamp: 2025-06-14T05:20:20.149Z
Learning: Node.js 22 supports the `recursive` option in `fs.readdir()` (introduced in Node.js 18.17.0), which returns a flattened string array of all descendant files and directories when `recursive: true` is passed.

Applied to files:

  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/src/bridges/http.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/fs-bridge/test/bridges/http/http.test.ts
📚 Learning: 2025-06-14T05:20:24.527Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/fs-adapter.ts:47-51
Timestamp: 2025-06-14T05:20:24.527Z
Learning: The `recursive` option for `fs.readdir()` was introduced in Node.js v20.1.0 and is available in Node.js 22. When `recursive: true` is passed, it will recursively traverse directories and return all file paths as a flat string array.

Applied to files:

  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/src/bridges/http.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
📚 Learning: 2025-06-14T05:20:24.527Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/fs-adapter.ts:47-51
Timestamp: 2025-06-14T05:20:24.527Z
Learning: In Node.js 22, the `recursive` option for `fs.readdir()` is supported and will recursively find all files and return them in a string array when set to true.

Applied to files:

  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/src/bridges/http.ts
  • packages/fs-bridge/test/security/node/path-traversal.test.ts
📚 Learning: 2025-07-09T15:05:57.763Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 97
File: packages/utils/src/fs-bridge/node.ts:40-50
Timestamp: 2025-07-09T15:05:57.763Z
Learning: The `parentPath` property on `fs.Dirent` was added in Node.js v20.12, contrary to previous assumptions about it not being part of the Node.js API.

Applied to files:

  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-09-02T02:01:40.288Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 231
File: packages/fs-bridge/src/utils.ts:4-8
Timestamp: 2025-09-02T02:01:40.288Z
Learning: The ucdjs/ucd project uses ESLint for linting, not Biome. Don't suggest Biome-specific ignore comments for this codebase.

Applied to files:

  • packages/fs-bridge/eslint.config.js
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use pnpm workspaces with Turbo for build orchestration and Vitest for testing in this monorepo project

Applied to files:

  • packages/fs-bridge/eslint.config.js
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Require Node.js >= 22.18 and pnpm 10.26.1 for development in this project

Applied to files:

  • pnpm-workspace.yaml
📚 Learning: 2025-08-23T05:20:36.940Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:20:36.940Z
Learning: In the ucdjs/ucd codebase using modern Vitest, the assert export from "vitest" works as a callable function assert(condition, message) and provides TypeScript type narrowing, making it the preferred choice over expect() for runtime assertions that need compile-time type safety. The existing usage pattern assert(condition, message) throughout the test suite is working correctly.

Applied to files:

  • packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
  • packages/fs-bridge/test/security/http/encoded-attacks.test.ts
📚 Learning: 2025-08-17T10:10:19.096Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 206
File: packages/ucd-store/test/clean.test.ts:273-301
Timestamp: 2025-08-17T10:10:19.096Z
Learning: In UCD store clean tests, race conditions between analyze and delete phases are intentionally tested to verify robust handling of files that disappear during clean operations. The test pattern: start clean() → externally delete file during execution → verify file is marked as "skipped" rather than "failed".

Applied to files:

  • packages/ucd-store/test/maintenance/analyze.test.ts
📚 Learning: 2025-06-09T05:10:32.105Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 45
File: packages/ucd-store/src/download.ts:24-24
Timestamp: 2025-06-09T05:10:32.105Z
Learning: In the ucd-store package refactor, picomatch was moved from direct usage in download.ts to internal usage within the createPathFilter function in filter.ts. The pattern format is still picomatch-compatible, so JSDoc comments referencing picomatch pattern format remain correct.

Applied to files:

  • packages/ucd-store/test/maintenance/analyze.test.ts
🧬 Code graph analysis (8)
packages/fs-bridge/src/guards.ts (2)
packages/fs-bridge/src/types.ts (1)
  • FileSystemBridge (155-170)
packages/fs-bridge/src/bridges/http.ts (1)
  • kHttpBridgeSymbol (11-11)
packages/fs-bridge/test/bridges/node/node.test.ts (1)
tooling/moonbeam/src/esm-loader.mjs (1)
  • entries (44-44)
packages/fs-bridge/src/bridges/http.ts (1)
packages/path-utils/src/security.ts (1)
  • resolveSafePath (134-283)
packages/fs-bridge/src/utils.ts (3)
packages/fs-bridge/src/index.ts (3)
  • FileSystemBridgeOperations (20-20)
  • BridgeBaseError (4-4)
  • BridgeGenericError (7-7)
packages/path-utils/src/index.ts (1)
  • PathUtilsBaseError (6-6)
packages/fs-bridge/src/errors.ts (1)
  • BridgeGenericError (10-15)
packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts (1)
packages/test-utils/src/msw.ts (2)
  • mockFetch (16-19)
  • HttpResponse (11-11)
packages/fs-bridge/src/define.ts (1)
packages/fs-bridge/src/types.ts (2)
  • FileSystemBridgeObject (107-153)
  • FileSystemBridge (155-170)
packages/fs-bridge/src/types.ts (1)
packages/fs-bridge/src/index.ts (2)
  • FileSystemBridgeArgs (16-16)
  • FileSystemBridgeFactory (17-17)
packages/fs-bridge/test/security/http/encoded-attacks.test.ts (1)
packages/ucd-store-v2/src/core/context.ts (1)
  • basePath (78-80)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: typecheck
  • GitHub Check: lint
  • GitHub Check: test (ubuntu-latest)
  • GitHub Check: test (windows-latest)
🔇 Additional comments (38)
packages/fs-bridge/test/security/node/encoded-attacks.test.ts (1)

7-8: LGTM! Title casing corrected.

The title now correctly capitalizes "URL" as a proper noun, with appropriate ESLint suppression.

packages/fs-bridge/eslint.config.js (1)

8-12: LGTM! Playground scripts appropriately excluded from linting rules.

The addition of "playgrounds/**" to the ignore patterns aligns with the new playground validation scripts introduced in this PR and allows them to use Node.js built-ins without triggering the no-restricted-imports rule.

packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts (5)

1-2: LGTM! Type reference enables custom matcher support.

The reference directive provides type definitions for custom matchers like toMatchError used later in the test.


6-6: LGTM! Import aligns with updated error handling.

The BridgeGenericError import is required for the updated error expectation at line 69, where schema validation failures are now expected to throw this error type.


24-24: Path format updated to match HTTP bridge normalization.

The leading slash format aligns with the HTTP bridge's path schema, which expects directory paths to start with / and end with /.


42-71: LGTM! Defense-in-depth error handling implemented.

The test now validates that schema validation acts as the first line of defense, catching malformed paths before they reach traversal checks. The encoded path %2f%2e%2e%2f%2e%2e%2fetc%2f is rejected by the schema because it doesn't conform to the expected format (missing proper leading/trailing slashes), resulting in a BridgeGenericError with "Invalid response schema" message rather than a PathTraversalError.


84-104: Path assertions updated consistently.

Both the mock response and the assertion now use the normalized directory path format (/subdir/), maintaining consistency with the HTTP bridge's path schema.

packages/fs-bridge/test/security/http/encoded-attacks.test.ts (2)

8-9: LGTM! Title casing corrected.

Consistent with the Node test file, "URL" is now properly capitalized as a proper noun with appropriate ESLint suppression.


128-142: LGTM! Variable introduction improves test maintainability.

Extracting basePath as a variable and using it in both the URL construction and error message assertion reduces duplication and makes the test more maintainable. The dynamic reference in the error message (line 142) ensures the assertion remains accurate if the base path changes.

packages/fs-bridge/src/utils.ts (4)

14-14: LGTM! Import supports new MSW error handling.

The isMSWError utility is used at line 201 to detect and properly handle MSW-specific errors in tests.


184-198: LGTM! Error normalization uses native Error cause chain.

The refactor improves clarity by:

  1. Renaming to normalizedError (more descriptive than knownError)
  2. Using native ErrorOptions with { cause: err } for error chaining, aligning with the updated BridgeGenericError constructor signature

200-208: LGTM! MSW error handling improves test debugging.

Detecting and rethrowing MSW errors without wrapping ensures that mock-related failures in tests are surfaced with their original error messages, making test debugging significantly easier.


217-235: LGTM! Error handling correctly preserves Bridge error types.

The instanceof BridgeBaseError check at line 217 correctly detects all Bridge error subclasses (including BridgeGenericError, BridgeFileNotFound, etc.) and rethrows them without wrapping. Only truly unexpected errors are wrapped in BridgeGenericError at lines 232-235, with the original error preserved as the cause.

packages/fs-bridge/package.json (2)

29-29: LGTM! New errors export aligns with module structure.

The new ./errors export correctly maps to the built errors module and aligns with the new entry in tsdown.config.ts and the refactored errors.ts file.


47-48: LGTM! Playground scripts enable local testing.

The playground scripts provide a convenient way to test the Node and HTTP bridge implementations during development.

packages/fs-bridge/tsdown.config.ts (1)

8-9: LGTM! Errors module entry aligns with public export.

The new ./src/errors.ts entry correctly exposes the errors module, matching the public export in package.json.

packages/fs-bridge/src/types.ts (1)

172-183: LGTM! Type extraction improves reusability and clarity.

Extracting FileSystemBridgeArgs as a separate exported type alias improves:

  • Reusability: The type can now be imported and used by consumers
  • Clarity: Separates the argument-shaping logic from the factory signature
  • Maintainability: Single source of truth for argument type computation

The refactor preserves the existing conditional logic while making it more accessible.

packages/fs-bridge/src/errors.ts (1)

11-14: No breaking change - BridgeGenericError never exposed an originalError property.

The refactor to native ErrorOptions is correct and safe. BridgeGenericError was never designed to store the error in a custom property; it only passed the cause through options. All existing instantiations (lines 122, 194, 232 in utils.ts) already use the { cause: ... } pattern.

The inconsistency with BridgeSetupError is intentional: BridgeSetupError maintains the originalError property for backward compatibility while also using the standard cause field (see lines 18, 20, 25). Test utilities already handle both patterns (error-matchers.ts lines 82–83).

pnpm-workspace.yaml (1)

65-65: Verify compatibility with @luxass/[email protected].

The version bump should be backward compatible per semver, but publicly available release notes for this version are unavailable. Since this package is bundled in the fs-bridge production bundle via noExternal, confirm there are no breaking changes in the API exports used: createMockFetch and isMSWError/runtime-guards.

packages/fs-bridge/test/security/http/excessive-encoding.test.ts (1)

34-37: Verify error expectation consistency across test cases.

Similar to the node bridge tests, these tests expect the error message string "Failed to decode path" for traversal attempts (lines 36, 68), while other tests in the same file expect FailedToDecodePathError (lines 22, 54). This pattern is consistent with the node bridge tests, but should be verified to ensure it reflects the actual error handling behavior.

Also applies to: 66-69

packages/fs-bridge/src/guards.ts (1)

38-48: Excellent improvement to bridge identification.

The symbol-based detection approach effectively addresses the previous concern about fragile string matching. Using kHttpBridgeSymbol ensures the check is robust against name changes and cannot be easily spoofed by custom bridges. The defensive double-check pattern (in fs && === true) is sound.

packages/fs-bridge/test/bridges/node/node.test.ts (2)

425-535: LGTM! Comprehensive shape validation tests.

The listdir shape consistency tests thoroughly validate the output contract:

  • File entries have exactly the expected properties (type, name, path)
  • Directory entries consistently include a children array
  • Recursive mode properly populates nested structures
  • Shape consistency is maintained across multiple entries

The defensive checks using Object.keys() and type guards ensure the tests catch any deviations from the expected schema.


537-585: LGTM! Well-structured error handling tests.

The error surface tests consistently verify that:

  • Errors are properly wrapped in BridgeGenericError
  • Original Node.js error codes (ENOENT, ENOTDIR) are preserved in the cause property
  • The error wrapping pattern is uniform across different operations

The try-catch pattern with expect.fail() clearly documents the expected behavior and provides helpful failure messages.

packages/fs-bridge/src/define.ts (2)

2-2: LGTM! Symbol parameter enables runtime bridge identification.

The addition of the optional symbol property to the fsBridge parameter aligns with the new symbol-based bridge identification pattern introduced in this PR (e.g., kHttpBridgeSymbol and isBuiltinHttpBridge).

Also applies to: 23-23


63-63: Verify type safety of symbol attachment pattern.

The symbol attachment uses a double type assertion (bridge as unknown as Record<symbol, boolean>) to bypass TypeScript's type checking. While this enables the runtime feature, it creates a gap between the type system and runtime behavior:

  • The FileSystemBridge type doesn't declare symbol index signatures
  • Symbol properties won't be visible to TypeScript consumers
  • Type safety is lost for this feature

Consider whether this is the intended design or if an alternative approach would be more type-safe:

  1. Option 1 (Current): Accept runtime-only symbols for internal identification
  2. Option 2: Extend FileSystemBridge with an index signature: [key: symbol]: boolean | undefined
  3. Option 3: Use a WeakMap or separate registry for symbol-to-bridge mapping

Is the current runtime-only symbol pattern intentional, or should the FileSystemBridge type be extended to support symbol properties for better type safety?

Also applies to: 79-82

packages/fs-bridge/src/index.ts (1)

12-12: LGTM! Public API expansion is clear and consistent.

The new exports isBuiltinHttpBridge and FileSystemBridgeArgs enhance the public API:

  • isBuiltinHttpBridge enables consumers to detect built-in HTTP bridges
  • FileSystemBridgeArgs provides type-safe access to bridge factory parameters

Both additions follow existing naming conventions and integrate well with the PR's symbol-based identification pattern.

Also applies to: 16-16

packages/fs-bridge/test/bridges/http/http.test.ts (2)

135-135: LGTM! Consistent directory path convention.

The trailing slash convention for directory paths ("/subdir/" instead of "/subdir") standardizes the path representation across all fixtures. This change is applied consistently throughout the test expectations.

Also applies to: 168-168, 207-207, 269-269, 294-294


528-775: LGTM! Excellent test coverage for schema validation and error handling.

The new test suites add comprehensive coverage for critical scenarios:

  1. Schema validation (Zod): Tests enforce strict validation of listdir responses, catching missing/invalid fields early
  2. Fetch error handling: Covers network errors, server errors, and forbidden responses with appropriate assertions
  3. Content handling: Validates Content-Type agnosticism, edge cases (empty, large), and binary-like content

This significantly improves the robustness of the HTTP bridge implementation.

packages/fs-bridge/test/bridges/http/basepath.http.relative.test.ts (1)

177-178: LGTM! Fixture update aligns with path convention.

The mock data paths have been updated to use absolute paths with leading slashes ("/file1.txt" instead of "file1.txt"), consistent with the path format standardization across the HTTP bridge test suite.

packages/fs-bridge/test/security/node/path-traversal.test.ts (1)

112-178: LGTM! Comprehensive security coverage for recursive listdir.

The new "recursive listdir security" test suite adds critical security validation:

  1. Malicious directory names: Prevents traversal via "../" paths in listdir operations
  2. Encoded path components: Catches URL-encoded traversal attempts ("%2e%2e/") that might bypass naive checks
  3. Legitimate nested structures: Validates correct recursive behavior for safe paths

These tests complement the existing path-traversal prevention and strengthen the security posture of the Node bridge's listdir feature.

packages/fs-bridge/src/bridges/node.ts (2)

61-74: Excellent documentation of design decisions.

The docblock clearly explains why the Node bridge uses a different validation approach than the HTTP bridge, documents the FSEntry contract, and references verification tests. This is helpful context for maintainers.


107-139: Recursive directory listing implementation is sound.

The Map-based hierarchy building approach is efficient and correct. The use of entry.parentPath is appropriate given Node.js version requirements, and the path normalization handles cross-platform differences properly.

packages/fs-bridge/playgrounds/node-playground.ts (1)

46-255: Comprehensive test coverage for Node bridge operations.

The test suite covers all bridge methods with appropriate edge cases including path prefixes, trailing slashes, recursive options, and error scenarios. This provides good validation of the bridge implementation.

packages/fs-bridge/playgrounds/http-playground.ts (1)

31-236: Excellent HTTP bridge test coverage.

The test suite properly validates the read-only nature of the HTTP bridge, tests all supported operations, ensures mutating operations throw appropriately, and includes a realistic workflow test. The use of assertCapability is a good pattern for validating optional capabilities.

packages/fs-bridge/src/bridges/http.ts (4)

36-60: Debug logging enhancements improve observability.

The added debug logs at key points (read attempts, rejections, fetch operations, errors, and successes) will help troubleshoot issues and understand bridge behavior in production. The log messages include appropriate context.


63-158: Comprehensive debug logging for listdir operations.

The debug logs cover all major code paths including error conditions (404, 403, 500), schema validation failures, and recursive processing. This will significantly help with debugging and monitoring.


160-185: Exists method enhancements are well-implemented.

The debug logging and MSW error handling (for testing purposes) improve both observability and testability. Using HEAD requests for existence checks is the appropriate HTTP method.


13-20: [rewritten review comment]
[classification tag]

luxass added 2 commits January 7, 2026 18:00
… tests

This is fine for now, since ucd-store-v2 will replace it very soon
Updated the `createFSEntry` function to ensure all paths have a leading slash and directories have a trailing slash. This change improves path consistency across the file system bridge.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @packages/ucd-store/test/maintenance/mirror.test.ts:
- Line 12: Multiple tests are being disabled with describe.todo() across the
suite (including the instance in describe.todo("store mirror") and 20+
occurrences in other test files), so annotate each disabled describe.todo() with
an inline tracking comment referencing the migration (e.g., add "// TODO:
Re-enable after ucd-store-v2 migration") immediately above or on the same line
as the describe.todo() call to make scope and intent explicit; ensure you update
each describe.todo() occurrence (including nested ones in init.test,
errors.test, factory.test, and this mirror.test's describe.todo) rather than
only a few files, and leave existing correct uses of mockStoreApi() and testdir
unchanged.
🧹 Nitpick comments (1)
packages/fs-bridge/src/bridges/node.ts (1)

47-53: Consider extracting shared trailing slash validation.

The TODO is valid—the trailing slash validation logic (lines 48-53 and 153-158) is duplicated. A small helper like assertNotTrailingSlash(path) would reduce duplication and centralize the logic.

♻️ Optional: Extract shared validation
+function assertValidFilePath(path: string): void {
+  const trimmedPath = path.trim();
+  if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") {
+    throw new Error("Path ends with '/' - files don't have trailing slashes");
+  }
+}
+
 async read(path) {
-  // TODO: duplicate code with write - refactor
-  // Reject file paths ending with / - files don't have trailing slashes
-  // Allow /, ./, and ../ as they are special directory references
-  const trimmedPath = path.trim();
-  if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") {
-    throw new Error("Cannot read file: path ends with '/'");
-  }
+  assertValidFilePath(path);
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6783289 and df9b301.

📒 Files selected for processing (14)
  • packages/fs-bridge/src/bridges/node.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/ucd-store/test/core/errors.test.ts
  • packages/ucd-store/test/core/factory.test.ts
  • packages/ucd-store/test/core/init.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
  • packages/ucd-store/test/file-operations/file-tree.test.ts
  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/ucd-store/test/internal/files.test.ts
  • packages/ucd-store/test/maintenance/analyze.test.ts
  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/maintenance/mirror.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/ucd-store/test/internal/files.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ucd-store/test/maintenance/analyze.test.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.?(c|m)[jt]s?(x)

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.?(c|m)[jt]s?(x): Import test utilities from #test-utils/* path aliases instead of @ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies
Use testdir() from vitest-testdirs to create temporary test directories in filesystem tests
Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
  • packages/ucd-store/test/maintenance/mirror.test.ts
  • packages/ucd-store/test/file-operations/file-tree.test.ts
  • packages/ucd-store/test/core/init.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
  • packages/ucd-store/test/core/errors.test.ts
  • packages/ucd-store/test/core/factory.test.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: luxass
Repo: ucdjs/ucd PR: 6
File: packages/cli/src/cmd/codegen/fields.ts:68-82
Timestamp: 2025-05-04T11:52:22.858Z
Learning: User prefers to address the issue with Node.js API compatibility (`Dirent.parentPath` not being part of Node's API and the `recursive: true` option for `readdir` being only available in Node 21+) in a separate PR rather than the current one.
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use File System Bridge Pattern (ucdjs/fs-bridge) abstraction for file system operations to support multiple backends (Node.js, HTTP, in-memory)
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
  • packages/ucd-store/test/maintenance/mirror.test.ts
  • packages/ucd-store/test/file-operations/file-tree.test.ts
  • packages/ucd-store/test/core/init.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
  • packages/ucd-store/test/core/errors.test.ts
  • packages/ucd-store/test/core/factory.test.ts
📚 Learning: 2025-06-09T05:10:32.105Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 45
File: packages/ucd-store/src/download.ts:24-24
Timestamp: 2025-06-09T05:10:32.105Z
Learning: In the ucd-store package refactor, picomatch was moved from direct usage in download.ts to internal usage within the createPathFilter function in filter.ts. The pattern format is still picomatch-compatible, so JSDoc comments referencing picomatch pattern format remain correct.

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
  • packages/ucd-store/test/maintenance/mirror.test.ts
  • packages/ucd-store/test/file-operations/file-tree.test.ts
  • packages/ucd-store/test/core/init.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
  • packages/ucd-store/test/core/errors.test.ts
  • packages/ucd-store/test/core/factory.test.ts
📚 Learning: 2025-08-17T10:10:19.096Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 206
File: packages/ucd-store/test/clean.test.ts:273-301
Timestamp: 2025-08-17T10:10:19.096Z
Learning: In UCD store clean tests, race conditions between analyze and delete phases are intentionally tested to verify robust handling of files that disappear during clean operations. The test pattern: start clean() → externally delete file during execution → verify file is marked as "skipped" rather than "failed".

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Import test utilities from #test-utils/* path aliases instead of ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
  • packages/ucd-store/test/maintenance/mirror.test.ts
  • packages/ucd-store/test/file-operations/file-tree.test.ts
  • packages/ucd-store/test/core/init.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
  • packages/ucd-store/test/core/errors.test.ts
  • packages/ucd-store/test/core/factory.test.ts
📚 Learning: 2025-08-23T05:20:36.940Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:20:36.940Z
Learning: In the ucdjs/ucd codebase using modern Vitest, the assert export from "vitest" works as a callable function assert(condition, message) and provides TypeScript type narrowing, making it the preferred choice over expect() for runtime assertions that need compile-time type safety. The existing usage pattern assert(condition, message) throughout the test suite is working correctly.

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
  • packages/ucd-store/test/maintenance/mirror.test.ts
📚 Learning: 2025-08-23T05:20:36.940Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:20:36.940Z
Learning: In the ucdjs/ucd codebase, Vitest's assert import works as a callable function assert(condition, message) and provides TypeScript type narrowing, making it the preferred choice over expect() for runtime assertions that also need compile-time type safety.

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/maintenance/repair.test.ts
📚 Learning: 2025-08-23T05:16:26.866Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 209
File: packages/ucd-store/test/clean.test.ts:9-9
Timestamp: 2025-08-23T05:16:26.866Z
Learning: In the ucdjs/ucd codebase, the team prefers using `assert(condition, message)` over `expect(condition).toBeTruthy()` because assert provides TypeScript type narrowing while expect doesn't. This is important for maintaining type safety after runtime validation checks.

Applied to files:

  • packages/ucd-store/test/maintenance/clean.test.ts
  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
📚 Learning: 2025-10-14T07:15:35.199Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 326
File: packages/shared/src/ucd-config.ts:34-58
Timestamp: 2025-10-14T07:15:35.199Z
Learning: In packages/shared/src/ucd-config.ts, the `getDefaultUCDEndpointConfig` function uses a build-time define `__UCD_ENDPOINT_DEFAULT_CONFIG__` that is replaced at build time by the bundler. The `??` operator is evaluated at build time, so the final code contains no runtime branching. Therefore, runtime unit tests for this function are not valuable—the build process itself handles the injection and fallback logic.

Applied to files:

  • packages/ucd-store/test/file-operations/capability-requirements.test.ts
  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
  • packages/ucd-store/test/core/errors.test.ts
  • packages/ucd-store/test/core/factory.test.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Applies to **/*.{test,spec}.?(c|m)[jt]s?(x) : Use testdir() from vitest-testdirs to create temporary test directories in filesystem tests

Applied to files:

  • packages/ucd-store/test/file-operations/get-file.test.ts
  • packages/ucd-store/test/file-operations/file-tree.test.ts
  • packages/ucd-store/test/file-operations/file-paths.test.ts
📚 Learning: 2025-05-04T11:52:22.858Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 6
File: packages/cli/src/cmd/codegen/fields.ts:68-82
Timestamp: 2025-05-04T11:52:22.858Z
Learning: User prefers to address the issue with Node.js API compatibility (`Dirent.parentPath` not being part of Node's API and the `recursive: true` option for `readdir` being only available in Node 21+) in a separate PR rather than the current one.

Applied to files:

  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-12-27T11:08:54.630Z
Learnt from: CR
Repo: ucdjs/ucd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-27T11:08:54.630Z
Learning: Use File System Bridge Pattern (ucdjs/fs-bridge) abstraction for file system operations to support multiple backends (Node.js, HTTP, in-memory)

Applied to files:

  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/ucd-store/test/core/factory.test.ts
  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-07-09T15:05:57.763Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 97
File: packages/utils/src/fs-bridge/node.ts:40-50
Timestamp: 2025-07-09T15:05:57.763Z
Learning: The `parentPath` property on `fs.Dirent` was added in Node.js v20.12, contrary to previous assumptions about it not being part of the Node.js API.

Applied to files:

  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-07-29T06:02:32.422Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 175
File: packages/fs-bridge/test/bridges/node.test.ts:0-0
Timestamp: 2025-07-29T06:02:32.422Z
Learning: In the NodeFileSystemBridge security validation, path traversal detection occurs before critical system paths checks, which means absolute paths to critical system directories will always throw "Path traversal detected" rather than "Critical system path access denied", making it impossible to meaningfully test the critical system paths validation logic.

Applied to files:

  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-06-14T05:20:20.149Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/validate.ts:115-130
Timestamp: 2025-06-14T05:20:20.149Z
Learning: Node.js 22 supports the `recursive` option in `fs.readdir()` (introduced in Node.js 18.17.0), which returns a flattened string array of all descendant files and directories when `recursive: true` is passed.

Applied to files:

  • packages/fs-bridge/test/bridges/node/node.test.ts
  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-06-29T11:20:13.668Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 87
File: packages/worker-shared/tsconfig.build.json:1-4
Timestamp: 2025-06-29T11:20:13.668Z
Learning: In the ucdjs/ucd project, the packages use tsdown instead of tsc for building libraries. The tsconfig.build.json files are primarily for IDE experience and type checking, not for direct compilation, so including "test" directories in these configs doesn't affect build output.

Applied to files:

  • packages/ucd-store/test/file-operations/file-tree.test.ts
📚 Learning: 2025-06-14T05:20:24.527Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/fs-adapter.ts:47-51
Timestamp: 2025-06-14T05:20:24.527Z
Learning: The `recursive` option for `fs.readdir()` was introduced in Node.js v20.1.0 and is available in Node.js 22. When `recursive: true` is passed, it will recursively traverse directories and return all file paths as a flat string array.

Applied to files:

  • packages/fs-bridge/src/bridges/node.ts
📚 Learning: 2025-06-14T05:20:24.527Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 56
File: packages/utils/src/ucd-files/fs-adapter.ts:47-51
Timestamp: 2025-06-14T05:20:24.527Z
Learning: In Node.js 22, the `recursive` option for `fs.readdir()` is supported and will recursively find all files and return them in a string array when set to true.

Applied to files:

  • packages/fs-bridge/src/bridges/node.ts
🧬 Code graph analysis (1)
packages/fs-bridge/src/bridges/node.ts (2)
packages/path-utils/src/security.ts (1)
  • resolveSafePath (134-283)
packages/fs-bridge/src/types.ts (1)
  • FSEntry (16-25)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: lint
  • GitHub Check: typecheck
  • GitHub Check: test (macos-latest)
  • GitHub Check: test (windows-latest)
🔇 Additional comments (16)
packages/ucd-store/test/maintenance/clean.test.ts (1)

12-12: Test suite marked as pending for ucd-store-v2 migration.

The conversion to describe.todo intentionally defers execution of the clean operation tests while preserving their structure for future updates. This is consistent with the broader migration pattern across the ucd-store test suite.

packages/ucd-store/test/core/init.test.ts (1)

21-21: Initialization test suites marked as pending.

The conversion of these nested describe blocks to describe.todo defers the store initialization, loading, and version diff tests while preserving their definitions for the v2 migration.

Also applies to: 42-42, 156-156, 257-257

packages/ucd-store/test/file-operations/capability-requirements.test.ts (1)

8-8: Capability requirements tests marked as pending.

The test suite validating filesystem bridge capabilities is deferred during the migration. This preserves validation logic for re-enablement after ucd-store-v2 updates.

packages/ucd-store/test/core/factory.test.ts (1)

9-9: Factory function tests marked as pending.

The test suites for createUCDStore, createNodeUCDStore, and createHTTPUCDStore are deferred during the v2 migration, preserving validation of the public factory APIs for future re-enablement.

Also applies to: 15-15, 84-84, 154-154

packages/ucd-store/test/core/errors.test.ts (1)

13-14: Error class tests marked as pending.

The test suites validating all custom error classes (UCDStoreGenericError, UCDStoreFileNotFoundError, etc.) are deferred during the migration, preserving comprehensive error handling validation for future re-enablement.

Also applies to: 43-43, 71-71, 85-85, 147-147, 180-180

packages/fs-bridge/test/bridges/node/node.test.ts (6)

124-128: LGTM! Path format expectations align with new formatting conventions.

The updated expectations correctly reflect the new path formatting contract: files with leading slashes (/file1.txt), directories with leading and trailing slashes (/subdir/), and directories include an empty children array in non-recursive mode.


150-154: LGTM! Recursive listing expectations updated correctly.

The flattened path expectations now include leading slashes, consistent with the new path formatting contract.


425-535: Well-structured shape consistency tests.

These tests provide valuable coverage ensuring that FSEntry objects conform to the expected contract. The validation of property keys (lines 522-523, 528-529) is a good defensive measure against schema drift.


537-585: Good error surface coverage ensuring cause preservation.

These tests verify that BridgeGenericError properly wraps underlying Node.js errors while preserving the original error code in the cause property. This is valuable for consumers who need to handle specific error types.


608-613: LGTM! Complex workflow expectations updated correctly.

The project workspace test now expects paths with leading slashes and trailing slashes for directories, consistent with the updated FSEntry contract.


309-314: No changes needed: path format is correct for non-recursive listdir.

The expected path /nested.txt is the correct behavior. For non-recursive listdir operations, paths are returned as just the entry name with a leading slash (line 89 of the implementation uses entry.name as the path base). This differs intentionally from recursive mode, which returns full relative paths. The test is correctly aligned with the implementation.

packages/fs-bridge/src/bridges/node.ts (5)

61-74: Excellent documentation explaining the validation parity decision.

This JSDoc clearly explains why the Node bridge doesn't use Zod schema validation for listdir output (trusted local data vs. untrusted remote JSON), while documenting the shape contract that must be maintained. This addresses the concern from a previous review about bridge inconsistency.


78-86: Clean path formatting utility.

The formatEntryPath function centralizes the path formatting logic, ensuring consistent leading/trailing slash handling across all FSEntry objects. This is a good single-responsibility helper.


88-103: LGTM! Clear FSEntry construction with explicit path control.

The createFSEntry function properly handles both recursive (explicit relativePath) and non-recursive (fallback to entry.name) modes while ensuring consistent path formatting.


118-124: Good backward compatibility handling for entry.parentPath.

The fallback to entry.path ensures compatibility with Node.js versions before v20.12 where parentPath wasn't available. Based on learnings, parentPath was added in Node.js v20.12.


129-133: The map key consistency is correct. FSEntry entries are stored with normalizedPath as keys (e.g., "parent/child.txt"), and parent lookups use path.dirname(entryPath) which returns the matching format (e.g., "parent"). Root entries are properly skipped via the parentPath !== "." condition. No action needed.

@github-actions github-actions bot added the pkg: cli Changes related to the CLI package. label Jan 7, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @packages/cli/test/cmd/store/analyze.test.ts:
- Line 198: Add a short comment immediately above the it.todo("should show
complete status for store with all files", ...) test explaining why this test
was disabled and what must change to re-enable it (e.g., flaky behavior,
dependency missing, environment requirement, or a tracking issue ID like #1234);
include the expected conditions or a link to a ticket and an optional TODO with
an owner or ETA so future maintainers know when to restore the original it(...)
test.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between df9b301 and 5334e8c.

📒 Files selected for processing (1)
  • packages/cli/test/cmd/store/analyze.test.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.?(c|m)[jt]s?(x)

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.?(c|m)[jt]s?(x): Import test utilities from #test-utils/* path aliases instead of @ucdjs/test-utils in test files to avoid build step requirements and prevent cyclic dependencies
Use testdir() from vitest-testdirs to create temporary test directories in filesystem tests
Use mockStoreApi() utility from #test-utils/mock-store for MSW-based mocking of the UCD API in test files

Files:

  • packages/cli/test/cmd/store/analyze.test.ts
🧠 Learnings (1)
📚 Learning: 2025-06-09T05:10:32.105Z
Learnt from: luxass
Repo: ucdjs/ucd PR: 45
File: packages/ucd-store/src/download.ts:24-24
Timestamp: 2025-06-09T05:10:32.105Z
Learning: In the ucd-store package refactor, picomatch was moved from direct usage in download.ts to internal usage within the createPathFilter function in filter.ts. The pattern format is still picomatch-compatible, so JSDoc comments referencing picomatch pattern format remain correct.

Applied to files:

  • packages/cli/test/cmd/store/analyze.test.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: lint
  • GitHub Check: typecheck
  • GitHub Check: test (macos-latest)
  • GitHub Check: test (ubuntu-latest)
  • GitHub Check: test (windows-latest)

@luxass luxass merged commit 6b14f07 into main Jan 7, 2026
25 checks passed
@luxass luxass deleted the bridge-improvements branch January 7, 2026 17:31
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

38 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

const url = joinURL(
baseUrl.origin,
resolveSafePath(baseUrl.pathname, path),
resolveSafePath(baseUrl.pathname, `/${path}`),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prepending / to path may cause double slashes if path already starts with /

Suggested change
resolveSafePath(baseUrl.pathname, `/${path}`),
resolveSafePath(baseUrl.pathname, path),


return {
async read(path) {
// TODO: duplicate code with write - refactor
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate validation logic in read and write

Per TODO, refactor trailing slash validation into shared helper function

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. packages/fs-bridge/src/errors.ts, line 17-27 (link)

    style: Inconsistent error handling patterns - BridgeSetupError maintains both originalError property and cause, while BridgeGenericError only uses cause. Should all error classes use the same pattern for consistency?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

38 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

type: "directory",
name: "malicious",
path: "%2e%2e%2f%2e%2e%2fetc", // Encoded traversal
path: "%2f%2e%2e%2f%2e%2e%2fetc%2f", // Encoded traversal - rejected by schema
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: The encoded path starts and ends with %2f (/) which actually conforms to the schema - this may not trigger the expected schema validation error. Should this encoded path be designed to fail schema validation, or should it test traversal detection after decoding?

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/fs-bridge/test/security/http/recursive-listdir-security.test.ts
Line: 54:54

Comment:
**logic:** The encoded path starts and ends with %2f (/) which actually conforms to the schema - this may not trigger the expected schema validation error. Should this encoded path be designed to fail schema validation, or should it test traversal detection after decoding?

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: cli Changes related to the CLI package. pkg: fs-bridge Changes related to the FS Bridge package. pkg: ucd-store Changes related to the UCD Store package.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants