perf: Verify managed tools at setup instead of every run (#14911)
### Description
`turbo exec` and `turbo setup` re-read every installed managed-tool file
on every run. In a repository with Go, Node, pnpm, Python, and uv
installed (615 MB, 19.5k files), `turbo exec -- node -v` took 17.7 s and
a no-op `turbo setup` took 30 s.
This PR moves byte verification to setup:
- `turbo run` and `turbo exec` use a new `Verification::Shallow` check.
It checks the manifest, the generation, the shims, the exported
executables, and the user-owned setup record that binds the manifest. It
never reads tool trees.
- `turbo setup --check` and setup's offline repeat re-hash every byte
(`Verification::Full`). `turbo setup --force` repairs from verified
artifacts. When setup publishes a new generation, it re-hashes each tool
it reuses and downloads a fresh copy if the bytes do not match.
- The stat-stamp cache (`stamps.json`, `Verification::Stamped`,
`windows_stat`) is deleted. A metadata-only change, such as an extended
attribute that bumps ctime, made a stamp stale forever, so every later
check re-hashed that tool.
- On Unix, setup makes every published tool file read-only before it
records the tree hash. Directories stay writable, so `rm -rf .turbo` and
`git clean -fdx` still work.
- `ManagedTools::inspect` no longer revalidates right after
`with_current` already did. Every consumer revalidates at its use
boundary.
- On aarch64 macOS, `sha2` uses the ARMv8 SHA instructions (`asm`
feature). Other targets are unchanged.
The trust model for `run` and `exec` now matches the shell hook. Bytes
are verified when setup installs them. A same-user process that edits an
installed file in place is not detected until `turbo setup --check`. The
same is true today for `node_modules/.bin` and for tools that version
managers install.
| Command (release build) | Before | After |
| --- | --- | --- |
| `turbo exec -- node -v` | 17.7 s | 23.5 ms (raw `node -v`: 11.8 ms) |
| `turbo setup`, nothing to do | 29.4 to 30.7 s | 1.13 s |
### Testing Instructions
- `cargo test -p turborepo-tool-install -p turborepo-setup`, `cargo test
-p turborepo-cli --lib`, and `cargo test -p turbo --test setup`.
- Manual smoke test in a repository with `futureFlags.experimentalSetup`
and Go, Node, pnpm, Python, and uv in `turbo.lock`:
1. `turbo --skip-infer setup --force`. All files under the new
generation's `tools/` are read-only and every directory is writable.
2. `turbo --skip-infer setup` twice. All tools report `reused`, and
`pnpm install`, `uv sync`, and `go mod download` succeed.
3. `turbo --skip-infer exec -- node -v`, `go version`, `uv run python -c
"print(1)"`, and `pnpm -v` succeed.
4. `turbo --skip-infer setup --check` succeeds.
5. Remove the `node` shim from the generation's `bin/`. `turbo exec --
node -v` fails with "managed tools are damaged or unsafe".