Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
5ddcf08
fix(cli): strip Windows \\?\ verbatim prefix in uninstall path resolu…
githubrobbi Jun 30, 2026
7e9d50a
fix(cli): uninstall deep sweep decodes every search payload (was find…
githubrobbi Jun 30, 2026
84f5cab
fix(cli): uninstall drive-coverage prompt warns that indexing builds …
githubrobbi Jun 30, 2026
4373f6f
fix(cli): uninstall drive-coverage polls status_drives for readiness,…
githubrobbi Jun 30, 2026
81a1b90
feat(cli): stamp the git commit into `uffs --version` to verify the r…
githubrobbi Jun 30, 2026
e393be1
fix(cli): uninstall deep sweep keeps only real family files, not subs…
githubrobbi Jun 30, 2026
6d52931
fix(client): exe-resolution fallbacks carry .exe on Windows (no bare …
githubrobbi Jun 30, 2026
ed01d38
fix(cli): uninstall drops the legacy C++ uffs.exe GUI binary (PE subs…
githubrobbi Jun 30, 2026
5e6ac84
feat(cli): uninstall prints the running build's version + commit at t…
githubrobbi Jun 30, 2026
8f7a01c
fix(cli): uninstall drive-coverage waits long enough + shows index pr…
githubrobbi Jun 30, 2026
92ff706
fix(cli): uninstall indexes drives with live progress + clearer prompt
githubrobbi Jun 30, 2026
ea0e511
fix(cli): uninstall broker is optional when non-elevated + display po…
githubrobbi Jun 30, 2026
6481087
fix(cli): uninstall always indexes drives for the deep sweep (no prompt)
githubrobbi Jun 30, 2026
ad94b1d
feat(cli): uninstall removes the full workspace binary set, not just …
githubrobbi Jun 30, 2026
7d22fb0
fix(cli): uninstall gathers decisions up front, runs once, defers the…
githubrobbi Jun 30, 2026
1a4e666
fix(cli): uninstall does not taskkill the broker (it is a service; sc…
githubrobbi Jun 30, 2026
11b91a0
fix(cli): uninstall decides the broker/elevation up front, before the…
githubrobbi Jun 30, 2026
318b2cb
perf(uninstall): parallelize + timeout the deep-sweep version probes;…
githubrobbi Jun 30, 2026
76b1de8
feat(uninstall): redesign the discovered-binary table (one row/binary…
githubrobbi Jul 1, 2026
a735a06
fix(uninstall): make deep-sweep drive coverage robust (kill+start, no…
githubrobbi Jul 1, 2026
238adf9
fix(uninstall): never start the daemon in-process for coverage; degra…
githubrobbi Jul 1, 2026
889b0cd
fix(uninstall): reload daemon for coverage via the real CLI handlers …
githubrobbi Jul 1, 2026
a80496a
build(windows): embed icon + version-info + manifest into the 4 bare …
githubrobbi Jul 1, 2026
6276765
build(windows): embed UFFS icon + metadata into the 14 dev/CI binaries
githubrobbi Jul 1, 2026
f894430
fix(mft): bound the overlapped $UpCase/FRS read with a dedicated even…
githubrobbi Jul 1, 2026
4fc9a60
feat(uninstall): quieter UX — elevation asked first, one final summar…
githubrobbi Jul 1, 2026
9bd28a0
feat(uninstall): one-click elevate — 3-way gate + UAC helper at remov…
githubrobbi Jul 2, 2026
4c31b78
feat(uninstall): background gather + spinner, CORE/EXTRA tables, 3-wa…
githubrobbi Jul 2, 2026
b60fbc7
fix(uninstall): presentation order + EXTRA in the plan summary; quiet…
githubrobbi Jul 2, 2026
99d95af
style(uninstall): breathing room before the gate list and both Choice…
githubrobbi Jul 2, 2026
b6c17d0
fix(uninstall): teardown-last execution order + 5 live-run bugs from …
githubrobbi Jul 2, 2026
45532a6
feat(uninstall): sweep-elevation gate for the no-broker path + gracef…
githubrobbi Jul 2, 2026
cf7d1f9
fix(uninstall): tear down a sweep-started daemon (fixes uffsd.exe Acc…
githubrobbi Jul 2, 2026
9672a6e
fix(uninstall): silence the thin-client auto-start chatter during the…
githubrobbi Jul 2, 2026
f9da590
feat(uninstall): count binary sizes in the reclaim total (no more "~0…
githubrobbi Jul 2, 2026
05e718d
docs(ci): record why the rustdoc gate omits private_intra_doc_links
githubrobbi Jul 2, 2026
9249b98
fix(uninstall): flatten the removal plan + coherent decline wording
githubrobbi Jul 2, 2026
c509307
fix(uninstall): leave the broker cleanly when elevation is declined +…
githubrobbi Jul 2, 2026
45b3032
fix(uninstall): also leave the broker binary on the non-elevated "con…
githubrobbi Jul 2, 2026
aef2058
Merge branch 'main' into fix/uninstall-windows-followups
githubrobbi Jul 2, 2026
69232f1
chore(security): risk-accept the two quick-xml advisories (unreachabl…
githubrobbi Jul 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions assets/brand/app.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
SPDX-FileCopyrightText: 2025-2026 SKY, LLC.
SPDX-License-Identifier: MPL-2.0

Shared UFFS application manifest, embedded into the Windows binaries
(uffsd, uffs-broker, uffsmcp, uffs-mft) via winresource in each crate's
build.rs. The interactive CLI (uffs.exe) keeps its own crate-local manifest.

Declares:
- asInvoker: elevation is handled at runtime (the Access Broker service /
the daemon elevation policy), never at the manifest level.
- PerMonitorV2 DPI awareness.
- Long-path support (paths > 260 chars, which UFFS routinely handles).
- Windows 10 / 11 supported-OS id.
-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="UltraFastFileSearch" version="0.0.0.0"/>

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>

<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 (Windows 11 shares the same supportedOS GUID per MS docs). -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
</assembly>
5 changes: 5 additions & 0 deletions crates/uffs-bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,10 @@ tempfile.workspace = true
# ─────────────────────────────────────────────────────────────────────────────
# Lints (inherit from workspace)
# ─────────────────────────────────────────────────────────────────────────────
# Embeds the UFFS icon + version info + shared app.manifest into `uffs-bench.exe`
# (see build.rs) for branding consistency.
[build-dependencies]
winresource.workspace = true

[lints]
workspace = true
40 changes: 40 additions & 0 deletions crates/uffs-bench/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2025-2026 SKY, LLC.

// Build scripts run on the build host, not the shipping binary's target, so the
// workspace `deny(expect_used)` / `deny(unwrap_used)` runtime lints do not
// apply here; panicking on a build-host failure (missing icon / no resource
// compiler) is the idiomatic shape for a build script.
#![allow(
clippy::expect_used,
reason = "build scripts may panic on build-host failure; workspace deny-expect targets runtime code"
)]

//! Build script for `uffs-bench`.
//!
//! Embeds the UFFS icon + version info + shared `app.manifest` into
//! `uffs-bench.exe` via [`winresource`](https://crates.io/crates/winresource),
//! for branding consistency with the rest of the UFFS binary family.
//! MSVC-Windows only; a no-op on every other build target.

fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=../../assets/brand/icons/uffs.ico");
println!("cargo:rerun-if-changed=../../assets/brand/app.manifest");

let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
if target_os != "windows" || target_env != "msvc" {
return;
}

let mut res = winresource::WindowsResource::new();
res.set_icon("../../assets/brand/icons/uffs.ico")
.set("ProductName", "UltraFastFileSearch")
.set("FileDescription", "UFFS benchmark suite")
.set("CompanyName", "SKY, LLC.")
.set("LegalCopyright", "(c) 2025-2026 SKY, LLC. MPL-2.0.")
.set_manifest_file("../../assets/brand/app.manifest");
res.compile()
.expect("winresource: failed to embed uffs-bench resources");
}
6 changes: 6 additions & 0 deletions crates/uffs-broker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,11 @@ uffs-security.workspace = true
# `--stop` commands — the same locale-proof primitive the updater uses.
uffs-winsvc.workspace = true

# Embeds the UFFS icon + version info + shared app.manifest into
# `uffs-broker.exe` (see build.rs). A metadata-less binary is both unbranded
# and a mild antivirus false-positive signal.
[build-dependencies]
winresource.workspace = true

[lints]
workspace = true
46 changes: 46 additions & 0 deletions crates/uffs-broker/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2025-2026 SKY, LLC.

// Build scripts run on the build host, not the shipping binary's target, so the
// workspace `deny(expect_used)` / `deny(unwrap_used)` runtime lints do not
// apply here; panicking on a build-host failure (missing icon / no resource
// compiler) is the idiomatic shape for a build script.
#![allow(
clippy::expect_used,
reason = "build scripts may panic on build-host failure; workspace deny-expect targets runtime code"
)]

//! Build script for `uffs-broker`.
//!
//! Embeds Windows PE resources — the UFFS icon, version info (company, product,
//! description), and the shared `app.manifest` — into `uffs-broker.exe` via
//! [`winresource`](https://crates.io/crates/winresource), so the shipped binary
//! carries proper metadata instead of shipping bare. A bare binary is both
//! unbranded and a mild antivirus false-positive signal. MSVC-Windows only; a
//! no-op on every other build target.

fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=../../assets/brand/icons/uffs.ico");
println!("cargo:rerun-if-changed=../../assets/brand/app.manifest");

let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
if target_os != "windows" || target_env != "msvc" {
return;
}

let mut res = winresource::WindowsResource::new();
res.set_icon("../../assets/brand/icons/uffs.ico")
.set("ProductName", "UltraFastFileSearch")
.set(
"FileDescription",
"UFFS Access Broker (elevated MFT handle service)",
)
.set("CompanyName", "SKY, LLC.")
.set("LegalCopyright", "(c) 2025-2026 SKY, LLC. MPL-2.0.")
.set("OriginalFilename", "uffs-broker.exe")
.set_manifest_file("../../assets/brand/app.manifest");
res.compile()
.expect("winresource: failed to embed uffs-broker resources");
}
27 changes: 27 additions & 0 deletions crates/uffs-broker/src/broker/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,21 @@ fn sc_output(output: &std::process::Output) -> String {
.to_owned()
}

/// Print an in-progress step label without a trailing newline and flush, so
/// the operator sees what a slow step (e.g. the blocking `sc start`) is doing
/// before its "ok"/"failed" verdict lands on the same line.
#[cfg(windows)]
#[expect(
clippy::print_stdout,
reason = "CLI admin command — stdout is the user-visible result channel"
)]
fn print_step(label: &str) {
use std::io::Write as _;

print!("{label}");
let _flushed = std::io::stdout().flush();
}

/// Register the broker as an auto-start Windows Service and start it.
///
/// # Why the argv is split the way it is
Expand Down Expand Up @@ -79,7 +94,11 @@ pub(super) fn install_service() -> anyhow::Result<()> {
);
}

// Step-by-step narration: `sc start` blocks until the service reports
// ready, which can take a minute — a silent wait reads as a hang.
let exe = std::env::current_exe()?;
println!("Installing the UFFS Access Broker service...");
print_step(" registering the service (sc create)... ");
let create = std::process::Command::new("sc.exe")
.args([
"create",
Expand All @@ -94,6 +113,7 @@ pub(super) fn install_service() -> anyhow::Result<()> {
.output()?;

if !create.status.success() {
println!("failed");
// AUDIT-OK(bytes): `sc` output surfaced verbatim to the operator —
// display only, no decision.
anyhow::bail!(
Expand All @@ -102,21 +122,28 @@ pub(super) fn install_service() -> anyhow::Result<()> {
sc_output(&create)
);
}
println!("ok");

// Start it now so the broker is usable immediately — the whole point
// is "no future UAC", which only holds once the service is running.
// `start= auto` also brings it back on every boot.
print_step(
" starting the service (Windows waits for it to report ready; \
this can take a minute)... ",
);
let start = std::process::Command::new("sc.exe")
.args(["start", SERVICE_NAME])
.output()?;

if start.status.success() {
println!("ok");
println!(
"UFFS Access Broker installed and started (auto-start on boot).\n\
Non-elevated `uffs` searches will now use the broker for volume \
access — no more UAC prompts."
);
} else {
println!("failed");
// AUDIT-OK(bytes): `sc` output surfaced verbatim to the operator.
println!(
"Service installed (auto-start on boot), but starting it failed: \
Expand Down
37 changes: 37 additions & 0 deletions crates/uffs-cli/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@ fn main() {
println!("cargo:rerun-if-changed=app.manifest");
println!("cargo:rerun-if-changed=../../assets/brand/icons/uffs.ico");

// Stamp the short git commit (+ `-dirty`) into `UFFS_GIT_SHA` so
// `uffs --version` can tie a running binary back to the exact build —
// closing the "ran a stale binary" trap. The daemon already does this in its
// startup log; the CLI surfaced no commit, so a rebuilt-but-not-deployed
// uffs.exe was indistinguishable from the old one.
emit_git_sha();

let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();

Expand Down Expand Up @@ -131,3 +138,33 @@ fn main() {
.expect("winresource: failed to embed icon + manifest");
}
}

/// Emit `UFFS_GIT_SHA` = the short `HEAD` commit, with a `-dirty` suffix when
/// the working tree has uncommitted changes (so a hand-tweaked local build is
/// never mistaken for the clean commit). Best-effort: `unknown` when git is
/// absent. Mirrors `uffs-daemon`'s build stamp; `../../.git/HEAD` is watched so
/// the stamp tracks the checked-out commit.
fn emit_git_sha() {
use std::process::Command;

let sha = Command::new("git")
.args(["rev-parse", "--short", "HEAD"])
.output()
.ok()
.filter(|out| out.status.success())
.and_then(|out| String::from_utf8(out.stdout).ok())
.map(|raw| raw.trim().to_owned())
.filter(|trimmed| !trimmed.is_empty())
.unwrap_or_else(|| "unknown".to_owned());

let dirty = Command::new("git")
.args(["status", "--porcelain"])
.output()
.ok()
.filter(|out| out.status.success())
.is_some_and(|out| !out.stdout.is_empty());

let stamp = if dirty { format!("{sha}-dirty") } else { sha };
println!("cargo:rustc-env=UFFS_GIT_SHA={stamp}");
println!("cargo:rerun-if-changed=../../.git/HEAD");
}
12 changes: 10 additions & 2 deletions crates/uffs-cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,18 @@ pub(crate) fn print_help() {
print!("{HELP}");
}

/// Print version and exit.
/// Print version and exit. Includes the build's short git commit (stamped by
/// `build.rs` into `UFFS_GIT_SHA`, with `-dirty` for an uncommitted tree) so a
/// running binary can be tied to the exact source it was built from — match it
/// against `git rev-parse --short HEAD` to confirm you are not on a stale
/// build.
#[expect(clippy::print_stdout, reason = "intentional version output")]
pub(crate) fn print_version() {
println!("uffs {}", env!("CARGO_PKG_VERSION"));
println!(
"uffs {} ({})",
env!("CARGO_PKG_VERSION"),
option_env!("UFFS_GIT_SHA").unwrap_or("unknown")
);
}

// ── Subcommand help texts ─────────────────────────────────────────────
Expand Down
1 change: 1 addition & 0 deletions crates/uffs-cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod aggregate;
pub(crate) mod daemon_load;
/// Daemon management subcommands.
pub(crate) mod daemon_mgmt;
pub(crate) mod daemon_status;
/// Memory-tiering operator commands (`hibernate` / `preload`).
///
/// Phase 8-B / 8-C — split off `daemon_mgmt` so each cluster stays
Expand Down
Loading
Loading