Zoltan Kochan c4fce797b6 feat(config): POSIX root auto-detect for unsafePerm (#397 §14 follow-up) (#430)
* feat(config): POSIX root auto-detect for unsafePerm (#397 §14)

Completes the deferred half of #397 item 14. Adds `libc` to
workspace deps (Unix-only at the crate level via
`[target.'cfg(unix)'.dependencies]`) and implements
`default_unsafe_perm()` mirroring upstream's
[`extendBuildOptions.ts:83-86`](https://github.com/pnpm/pnpm/blob/94240bc046/building/after-install/src/extendBuildOptions.ts#L83-L86):

```ts
unsafePerm: process.platform === 'win32' ||
  process.platform === 'cygwin' ||
  !process.setgid ||
  process.getuid?.() !== 0
```

Pacquet equivalent:

- Windows → `true` (cfg!(windows) short-circuits; covers Cygwin
  too because Cygwin builds target windows-gnu, so the
  `'cygwin'` branch from upstream is implicitly handled).
- POSIX, running as root → `false` (drop privileges).
- POSIX, non-root → `true`.

The `!process.setgid` branch upstream is a Node-version
compatibility check for older Node where `setgid` doesn't exist;
it doesn't translate to Rust (libc's `setgid` is always available
on POSIX hosts where libc compiles).

`Config.unsafe_perm`'s default switches from a hard-coded `true`
to `default_unsafe_perm()`. Yaml override and the Windows
force-override in `WorkspaceSettings::apply_to` stay as they were.
`is_unsafe_perm_posix(uid)` is exposed for tests so the per-uid
logic can be exercised without root privileges.

Tests: new `is_unsafe_perm_posix_truth_table` (root vs non-root
uid table); `default_unsafe_perm_on_posix_matches_runtime_uid`
(POSIX-gated); `default_unsafe_perm_on_windows_is_always_true`
(Windows-gated). The existing `parses_unsafe_perm_from_yaml_and_applies`
drops the explicit "default is true" assertion since the default
now depends on the runtime uid — the test's purpose (yaml-`false`
wins on POSIX) is preserved.

* fix(config): address PR #430 review (Cygwin + non-POSIX + unsafe fn)

Four review-flagged issues from PR #430:

1. **Cygwin handling.** Rust's `x86_64-pc-cygwin` target emits
   `target_os = "cygwin"` with `cfg!(unix)` set and `cfg!(windows)`
   *unset*. The previous `cfg!(windows)` check fell through to the
   uid logic on Cygwin, which would flip to `false` when running
   as root — diverging from upstream's unconditional-true Cygwin
   branch. Added explicit `target_os = "cygwin"` matching alongside
   `windows`.

2. **Non-Unix, non-Windows targets.** The previous `posix_getuid`
   stub returned `0` on non-Unix targets, which made
   `default_unsafe_perm` return `false` (root-treating). Replaced
   with three cfg-gated `platform_unsafe_perm_default` overloads:
   Windows/Cygwin → `true`; POSIX-excluding-Cygwin → uid-based;
   anything else (`wasm32-*`, `redox`, etc.) → `true`.

3. **Over-marked `unsafe fn posix_getuid`.** Copilot was right
   that the safety comment described no per-call invariants, only
   the FFI boundary. Switched to a safe `fn` with the `unsafe`
   block contained inside, eliminating the unnecessary `unsafe`
   propagation to callers.

4. **Stale doc claim about Cygwin.** The doc said Cygwin builds
   target `windows-gnu` and that `cfg!(windows)` covers it.
   Neither is correct — `x86_64-pc-cygwin` is a distinct target.
   Updated the doc to describe the explicit `target_os = "cygwin"`
   branch with a link to rustc's platform-support page.

Cargo dep gate also narrowed: `[target.'cfg(all(unix, not(target_os
= "cygwin")))'.dependencies]` so libc isn't built on Cygwin (where
the POSIX branch isn't taken). The `default_unsafe_perm_on_posix_matches_runtime_uid`
test was correspondingly narrowed to the same cfg, and a new
`default_unsafe_perm_on_cygwin_is_always_true` test pins the
Cygwin short-circuit.
2026-05-13 01:49:32 +02:00
Description
No description provided
MIT 300 MiB
Languages
Rust 61.8%
TypeScript 37.7%
JavaScript 0.4%