Skip to content

fix(windows): normalize native host pipe identity#70

Open
ekroon wants to merge 1 commit intomainfrom
fix/windows-pipe-identity
Open

fix(windows): normalize native host pipe identity#70
ekroon wants to merge 1 commit intomainfrom
fix/windows-pipe-identity

Conversation

@ekroon
Copy link
Copy Markdown
Owner

@ekroon ekroon commented Mar 10, 2026

What

Fix native Windows host connectivity so mixed \\ and / path separators no longer cause the CLI and host runtime to derive different named-pipe endpoints.

This PR also improves the Windows error text for named-pipe connect failures so it reports the resolved profile, data dir, pipe path, OS error code, and a likely cause.

Why

A reported Windows PowerShell failure showed tabctl ping returning access denied (5) when the generated host wrapper was started manually. The investigation confirmed that native Windows ping uses the named-pipe transport, not TCP auth-token validation, and uncovered a real path-identity bug: semantically identical Windows paths could hash to different pipe names if one side used \\ and the other used /.

How

  • add shared Windows path normalization and pipe-derivation helpers in tabctl-shared
  • use the shared helpers from setup, CLI transport, and host runtime so pipe identity is stable
  • normalize persisted Windows host_path and data_dir values during setup
  • improve Windows named-pipe diagnostics and connectivity guidance
  • add regression tests for mixed-separator pipe resolution and diagnostic formatting

Testing

Validated locally on macOS:

  • cargo fmt --manifest-path rust/Cargo.toml --all
  • npm test
  • npm run test:integration

Windows local checkout test instructions

Please test from a native Windows PowerShell session using this branch from a local checkout, not a globally installed tabctl.

1. Checkout and build locally

From the repo root:

git checkout fix/windows-pipe-identity
npm install
npm run build

This builds the Rust workspace and produces the unpacked extension build in dist/extension.

2. Load the local extension build

Open edge://extensions or chrome://extensions, enable Developer mode, then Load unpacked and select:

<repo>\dist\extension

3. Run the local binary from the checkout

Use one of these options from the repo root so you are testing the branch build, not an already installed binary.

Option A: run via Cargo

cargo run --manifest-path rust/Cargo.toml -p tabctl -- setup --browser edge --extension-dir dist/extension
cargo run --manifest-path rust/Cargo.toml -p tabctl -- profile-show --json
cargo run --manifest-path rust/Cargo.toml -p tabctl -- ping

Option B: run the built debug binary directly after npm run build

.\rust\target\debug\tabctl.exe setup --browser edge --extension-dir dist/extension
.\rust\target\debug\tabctl.exe profile-show --json
.\rust\target\debug\tabctl.exe ping

If testing Chrome instead of Edge, replace --browser edge with --browser chrome.

4. Expected normal behavior

  • setup should write the native host manifest, wrapper script, and profile registration
  • the browser should launch the native host automatically when the extension connects
  • ping should succeed without needing to run the wrapper manually

5. If automatic startup still fails

Use the manual wrapper launch only as a diagnostic step:

  • run the generated tabctl-host.cmd wrapper manually from the same PowerShell/user context
  • in another PowerShell window for the same user, run the same local binary again:
cargo run --manifest-path rust/Cargo.toml -p tabctl -- ping

or

.\rust\target\debug\tabctl.exe ping

6. What to capture if it still fails

If ping fails, please capture the full new error text.

It should now include:

  • profile
  • data dir
  • the named-pipe path
  • the OS error code

Please also compare TABCTL_PROFILE, TABCTL_CONFIG_DIR, and TABCTL_DATA_DIR between the wrapper environment and the CLI shell.

If the failure is still a persistent os error 5 with matching profile/data-dir values, the next likely issue is named-pipe ACL/security behavior rather than auth-token handling.

Normalize Windows path strings before deriving host pipe names so the
CLI, setup flow, and host runtime resolve the same endpoint. Improve
named-pipe diagnostics and manual connectivity guidance to surface the
profile, data dir, pipe path, and likely cause when ping fails.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 10, 2026 11:54
Copy link
Copy Markdown

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

Fixes native Windows host connectivity by making named-pipe identity stable across mixed \ and / path separators, and improves named-pipe connection diagnostics to aid troubleshooting.

Changes:

  • Introduces shared Windows path normalization + named-pipe derivation helpers in tabctl_shared.
  • Updates CLI setup/transport and host runtime to use shared normalization and pipe derivation for consistent endpoints.
  • Improves Windows named-pipe connect error output and adds regression tests for mixed-separator behavior and diagnostics.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
rust/crates/tabctl/src/cli/transport.rs Uses shared pipe derivation; adds richer Windows pipe connect error formatting; normalizes resolved dirs.
rust/crates/tabctl/src/cli/setup.rs Persists host_path/data_dir using platform-normalized strings; normalizes Windows registry/manifest paths.
rust/crates/tabctl/src/cli/local.rs Adds connectivity troubleshooting guidance (including Windows-specific env var comparison).
rust/crates/tabctl/src/cli/impls.rs Imports shared helpers and adds regression tests for Windows pipe resolution and diagnostics.
rust/crates/shared/src/lib.rs Adds normalize_windows_path_string, path_to_platform_string, and windows_pipe_path helpers + tests.
rust/crates/shared/Cargo.toml Adds sha2 dependency to support shared pipe hashing.
rust/crates/host/src/host_impl/runtime.rs Normalizes env/registry-derived paths and uses shared pipe derivation for Windows.
rust/Cargo.lock Records dependency update for tabctl-shared (sha2).

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

Comment on lines +1036 to +1043
fn windows_pipe_connect_error_includes_profile_data_dir_and_hint() {
let err = std::io::Error::from_raw_os_error(5);
let rendered = format_windows_pipe_connect_error(
Some("edge"),
r"C:\Users\tester\AppData\Local\tabctl\profiles\edge",
r"\\.\pipe\tabctl-test",
&err,
);
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The test calls format_windows_pipe_connect_error, but that helper is defined as a private function inside the transport module, so it won’t be accessible from this tests module (a parent module can’t access private items of a child module, and use transport::* won’t glob-import non-public items). This will fail to compile on Windows. Make the helper pub(super)/pub(crate) (optionally gated behind #[cfg(any(windows, test))]), or move the test into cli/transport.rs where it has access.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants