Skip to content

refactor(security): introduce PipeName newtype (Phase 4 sub-phase 5b.1)#256

Merged
githubrobbi merged 1 commit into
mainfrom
refactor/phase-4-5b1-pipe-name-newtype
May 15, 2026
Merged

refactor(security): introduce PipeName newtype (Phase 4 sub-phase 5b.1)#256
githubrobbi merged 1 commit into
mainfrom
refactor/phase-4-5b1-pipe-name-newtype

Conversation

@githubrobbi
Copy link
Copy Markdown
Collaborator

Summary

Sub-phase 5b.1 of the Phase 4 newtype migration: replace the free pipe_name_for_current_user() function and bare String pipe paths with a validated PipeName newtype in uffs-security::pipe, mirroring the DriveLetter precedent from sub-phase 5b.

Pipe paths now carry their Win32 invariants in the type system:

  • \\.\pipe\ prefix
  • non-empty name segment
  • ≤ 256 chars total (Win32 CreateNamedPipeW limit)

API surface

  • PipeName::for_current_user() -> io::Result<Self> — canonical deterministic per-user path (\\.\pipe\uffs-<fnv1a64-of-user-sid>).
  • PipeName::parse<Input: Into<String>>(input) -> Result<Self, PipeNameError> — validates owned-or-borrowed strings; returns a structured error enum (BadPrefix { raw } / Empty / TooLong { len }).
  • as_str(), Display, AsRef<str> for FFI + tracing call-sites.

Consumers migrated

  • uffs-client::daemon_ctl::pipe_name() now returns io::Result<PipeName>.
  • connect_platform.rs, connect_sync_platform.rs, the keep-alive nudge in daemon_ctl.rs, and the blackhole-pipe test in windows_deadline.rs all pass name.as_str() to Win32 .open().
  • uffs-daemon::ipc::create_pipe_server() takes &PipeName instead of &str, propagating the invariant to the FFI boundary.

Tests strengthened (no suppression hacks)

  • Pre-existing deterministic-per-user + canonical-shape tests now exercise the typed API.
  • 4 new parse-validation tests: accepts valid path, rejects missing prefix, rejects empty-after-prefix, rejects over-length input.
  • Round-trip test: for_current_user() output re-parses as a valid PipeName.
  • windows_deadline.rs test fixture builds its unique pipe path through PipeName::parse — doubles as a regression pin against invariant drift.

Lint posture

Full just lint-pre-push gate passes locally (fmt + clippy host + clippy Windows + lint-tests + rustdoc + doc-tests + tests + smoke + deny + manifest-audit). Zero #[allow] / #[expect] added; surgical fixes only.

Follow-ups (separate PRs)

  • Sub-phase 5c: Usn newtype
  • Sub-phase 5d: Frs newtype

Replace the free `pipe_name_for_current_user()` function and bare `String`
pipe paths with a validated `PipeName` newtype in `uffs-security::pipe`,
mirroring the `DriveLetter` precedent from sub-phase 5b.

Pipe paths now carry their Win32 invariants in the type system:
  * `\\.\pipe\` prefix
  * non-empty name segment
  * <= 256 chars total (Win32 `CreateNamedPipeW` limit)

API surface:
  * `PipeName::for_current_user() -> io::Result<Self>` — canonical
    deterministic per-user path (`\\.\pipe\uffs-<fnv1a64-of-user-sid>`).
  * `PipeName::parse<Input: Into<String>>(input) -> Result<Self, PipeNameError>`
    — validates an owned-or-borrowed string; returns a structured error
    enum (`BadPrefix { raw }` / `Empty` / `TooLong { len }`).
  * `as_str()`, `Display`, `AsRef<str>` for FFI / tracing call-sites.

Consumers migrated:
  * `uffs-client::daemon_ctl::pipe_name()` now returns `io::Result<PipeName>`.
  * `connect_platform.rs`, `connect_sync_platform.rs`, the keep-alive
    nudge in `daemon_ctl.rs`, and the blackhole-pipe test in
    `windows_deadline.rs` all pass `name.as_str()` to Win32 `.open()`.
  * `uffs-daemon::ipc::create_pipe_server()` takes `&PipeName` instead
    of `&str`, propagating the invariant to the FFI boundary.

Tests strengthened (no suppression hacks):
  * Pre-existing deterministic-per-user + canonical-shape tests now
    exercise the typed API.
  * Added 4 parse-validation tests: accepts valid path, rejects missing
    prefix, rejects empty-after-prefix, rejects over-length input.
  * Added round-trip test asserting `for_current_user()` output
    re-parses as a valid `PipeName`.
  * `windows_deadline.rs` test fixture builds its unique pipe path
    through `PipeName::parse`, doubling as a regression pin against
    invariant drift (prefix or length-cap changes).

Lint posture: full `just lint-pre-push` gate passes (fmt + clippy host
+ clippy Windows + lint-tests + rustdoc + doc-tests + tests + smoke +
deny + manifest-audit). No `#[allow]` / `#[expect]` added; surgical
fixes only.
@githubrobbi githubrobbi enabled auto-merge (squash) May 15, 2026 23:25
@githubrobbi githubrobbi merged commit d841543 into main May 15, 2026
20 checks passed
@githubrobbi githubrobbi deleted the refactor/phase-4-5b1-pipe-name-newtype branch May 15, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant