Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 5 additions & 5 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ If a user asks only **"what's next?"**, answer from repo docs instead of inventi

## High-level architecture

- `Wardoff` is a Windows-only Rust utility for preventing or aborting unwanted shutdown, reboot, sleep, hibernate, and related power transitions. The intended target is `x86_64-pc-windows-msvc`.
- `Wardoff` is a Windows-only Rust utility for protecting supported shutdown/reboot paths and preventing idle sleep and automatic display timeout. The intended target is `x86_64-pc-windows-msvc`.
- The product has two control surfaces that should stay aligned:
- a tray/background app with Block/Allow state and optional hidden mode
- a CLI exposing `--block`, `--allow`, `--status`, `--hide`, `--log`, `--tail`, `--autostart on|off`, and `--version`, with `--status` expected to produce JSON for scripting
Expand All @@ -66,7 +66,7 @@ If a user asks only **"what's next?"**, answer from repo docs instead of inventi
4. remote shutdown protection via repeated `AbortSystemShutdown(NULL)` polling
- Be explicit that Layer 3 can skip cleanly on editions such as LTSC where `\Microsoft\Windows\UpdateOrchestrator\Reboot` is absent; that is normal behavior, not a failure.
- For detailed layer-by-layer behavior and the cautious wording around ETW/local shutdown handling, read `docs/WINDOWS_SHUTDOWN_LAYERS.md`.
- Sleep/hibernate/display blocking is a separate toggle and is expected to use `SetThreadExecutionState(...)`.
- Idle-sleep/display-timeout prevention follows Block/Allow through process-owned Power Requests. Follow `docs/ARCHITECTURE.md` and `docs/MVP_VALIDATION_MATRIX.md` for lifecycle, resume behavior and Windows limits; do not promise an explicit Sleep/Hibernate veto.
- Autostart is handled via Task Scheduler rather than the `Run` registry key so elevated scenarios can be handled correctly.

## Implemented module structure
Expand All @@ -78,7 +78,7 @@ If a user asks only **"what's next?"**, answer from repo docs instead of inventi
- `src/blocker/local.rs`: current local shutdown worker implementation; keep its user-facing documentation conservative and aligned with MVP scope decisions
- `src/blocker/update.rs`: UpdateOrchestrator task monitoring and restore logic
- `src/blocker/remote.rs`: Layer 4 `AbortSystemShutdownW(None)` polling loop
- `src/blocker/sleep.rs`: `SetThreadExecutionState(...)` blocker
- `src/blocker/sleep.rs`: owned system/display Power Requests
- `src/blocker/abort.rs`: shared shutdown-abort privilege and result helpers
- `src/autostart.rs`: scheduled-task autostart management
- `src/instance.rs` and `src/ipc.rs`: single-instance ownership plus the named-pipe control and read-only status paths
Expand All @@ -91,7 +91,7 @@ If a user asks only **"what's next?"**, answer from repo docs instead of inventi

- Re-read `PLAN.md` before making major structural decisions. Use it as the roadmap and scope boundary document, while `README.md` stays the quickest current-state summary.
- Preserve the distinction between MVP and later phases:
- MVP is the safe, official-API release: standard shutdown blocking, UpdateOrchestrator handling, remote abort loop, tray basics, CLI basics, Task Scheduler autostart, sleep/hibernate/display blocking, and simple file logging
- MVP is the safe, official-API release: standard shutdown blocking, UpdateOrchestrator handling, remote abort loop, tray basics, CLI basics, Task Scheduler autostart, idle-sleep/display-timeout prevention, and simple file logging
- aggressive IFEO mode, Windows Event Log, profiles, timer, and toast notifications belong to later phases unless the plan is updated
- Be explicit about elevation boundaries. Update protection and aggressive `shutdown.exe` interception are planned as admin-only features; tray, UI, and CLI flows should surface that requirement clearly rather than failing silently.
- Prefer official Windows APIs first. Aggressive behavior is opt-in and should carry strong warnings because it may trigger EDR tooling.
Expand All @@ -113,7 +113,7 @@ Only these features belong in the current phase:
- Layer 1: ShutdownBlockReasonCreate + WM_QUERYENDSESSION + SetProcessShutdownParameters
- Layer 3: Task Scheduler UpdateOrchestrator\Reboot disable/re-check
- Layer 4: AbortSystemShutdown polling loop
- Sleep/hibernate/screensaver blocking via SetThreadExecutionState
- Idle-sleep/display-timeout prevention via Power Requests; no screensaver, lock or explicit Sleep/Hibernate veto
- Tray icon: Block/Allow toggle, right-click menu (Block, Allow, Shutdown, Reboot, Sleep, Hibernate, Quit)
- CLI: --block, --allow, --status (JSON output), --hide, --log, --tail, --autostart on|off, --version
- Auto-start via Task Scheduler
Expand Down
Binary file modified .gitignore
Binary file not shown.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
## [Unreleased]

### Changed
- Replaced the sleep layer's periodic `SetThreadExecutionState` worker with owned system/display Power Requests and an identifiable Wardoff reason. Activation failures now reach the coordinator synchronously, and Allow/exit release the request object.
- Kept the existing tray wake-restore flow and added only a request-pair renewal to the existing resume callback when the runtime remains in Block, based on the documented termination of requests at user-initiated sleep. No additional resume state machine, display notifications or polling was introduced.
- Corrected sleep claims throughout maintained docs, CLI help and runtime logs: protection concerns idle sleep and automatic display timeout, subject to Windows policy. Explicit Sleep/Hibernate are not vetoed; Modern Standby on battery has additional limits. The original v0.1.0 hibernation claim below was too broad.
- Hardened the session-scoped `WardoffControl` and `WardoffStatus` pipes against same-session squatting by claiming first pipe instances with bounded startup retries, failing closed until both IPC servers own their initial instances, and probing the singleton before `wardoff --status` opens IPC endpoints.
- Scoped the singleton mutex plus the `WardoffControl` and `WardoffStatus` named pipes to the current Windows session so cross-session mutex or pipe squatting no longer breaks Wardoff's single-instance model across all sessions.
- Hardened structured JSONL logging under `%LOCALAPPDATA%\Wardoff\logs` so Wardoff now creates its managed log directories one component at a time, refuses reparse points in the managed log tree and rotated files, and uses reparse-aware no-follow opens for active and read-only log file access.
Expand Down Expand Up @@ -34,7 +37,7 @@ All notable changes to this project will be documented in this file.
- Layer 1 interactive shutdown and sign-out blocking
- Layer 3 protection for `\Microsoft\Windows\UpdateOrchestrator\Reboot`
- Layer 4 best-effort remote shutdown abort polling
- Sleep, hibernate, and display-idle blocking via `SetThreadExecutionState(...)`
- Idle-sleep and display-timeout prevention via `SetThreadExecutionState(...)` (wording corrected: the original release description overstated hibernation protection)
- Tray UI with Block, Allow, Shutdown, Reboot, Sleep, Hibernate, and Quit actions
- CLI support for `--block`, `--allow`, `--hide`, `--status`, `--log`, `--tail`, and `--autostart`
- Structured rotating JSONL logging
Expand Down
42 changes: 42 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# --- CLAUDE.md pour Wardoff (racine du repo) ---

# Projet

Application Rust Windows : bloqueur de shutdown en 4 couches.
MVP tagué `v0.1.0-mvp`. Repo public, licence MIT.

# Build et vérification

```
cargo build --release
cargo test
cargo clippy -- -D warnings
```

Exécute les trois après chaque changement. Binary cible < 2MB, zéro runtime deps.

# Architecture

4 couches de blocage shutdown — consulter `src/` directement.
Architecture détaillée : @docs/ARCHITECTURE.md
Business model : @docs/BUSINESS_MODEL.md

# Tests

`cargo test` couvre les tests unitaires et tourne sans privilèges.
Les couches 3 (Update Orchestrator) et 4 (remote shutdown) ne s'arment qu'en session élevée — leur validation est manuelle.
Procédure complète et matrice : @docs/MVP_VALIDATION_MATRIX.md

# Git

- Branche principale : `main`
- Tags sémantiques : `v0.x.y`
- Commits atomiques
- Format Conventional Commits : `type: sujet` en minuscules. Types utilisés : `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `merge`. Sujet à l'impératif présent, sans point final.

# Ne PAS faire

- Pas de portabilité cross-platform — Windows only, c'est intentionnel
- Pas de telemetry, pas de paywall, pas de tracking
- Ne pas ajouter de dépendances sans demander
- Ne pas utiliser `unwrap()` en production
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Keep documentation and PR descriptions aligned with the current supported MVP su
- interactive shutdown/sign-out blocking is implemented
- Update Orchestrator reboot-task protection is implemented
- remote shutdown abort polling is implemented
- sleep/hibernate/display-idle blocking is implemented
- idle-sleep and automatic display-timeout prevention are implemented; explicit Sleep/Hibernate remain controlled by Windows
- tray, CLI, logging, IPC, autostart, and single-instance coordination are implemented

Do **not** claim the following as implemented unless your change really adds and validates them:
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ windows = { version = "0.62.2", features = [
"Win32_System_Diagnostics_Etw",
"Win32_System_Shutdown",
"Win32_System_Power",
"Win32_System_SystemServices",
"Win32_System_IO",
"Win32_System_Pipes",
"Win32_System_Time",
Expand Down
2 changes: 1 addition & 1 deletion PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The branch already contains a working runtime plus CLI centered on one main prom
- Layer 1 interactive shutdown and sign-out blocking
- Layer 3 protection for `\Microsoft\Windows\UpdateOrchestrator\Reboot` when that task exists on the machine
- Layer 4 best-effort remote shutdown abort polling
- sleep, hibernate, and display-idle blocking
- idle-sleep and automatic display-timeout prevention through Power Requests (no explicit Sleep/Hibernate veto)
- tray UI with Block/Allow state and power actions
- CLI control surface
- structured rotating JSONL logs
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
![Rust](https://img.shields.io/badge/language-Rust-orange)
![Windows](https://img.shields.io/badge/platform-Windows%2010%2B-blue)

*Open-source Windows shutdown/reboot/sleep blocker*
*Open-source Windows shutdown/reboot protection and idle-sleep prevention*

Wardoff is a Windows-native Rust utility for people who want a visible, scriptable way to keep a machine in a protected **Block** state during gaming sessions, overnight jobs, remote work, or maintenance windows. The project is intentionally honest about what the current MVP does today and what still belongs to later releases.

Expand All @@ -17,7 +17,7 @@ Wardoff currently ships a working tray/runtime app plus CLI with these MVP-level
- Layer 1 interactive shutdown and sign-out blocking through `WM_QUERYENDSESSION`, `ShutdownBlockReasonCreate()`, and `SetProcessShutdownParameters()`
- Layer 3 protection for the scheduled task `Microsoft\Windows\UpdateOrchestrator\Reboot` when that task exists
- Layer 4 best-effort remote shutdown abort polling with `AbortSystemShutdownW(None)`
- sleep, hibernate, and display-idle blocking via `SetThreadExecutionState(...)`
- idle-sleep and automatic display-timeout prevention through Windows Power Requests, subject to Windows power policy
- structured rotating JSONL logging under `%LOCALAPPDATA%\Wardoff\logs\`
- single-instance coordination so later CLI calls can control the primary runtime
- Task Scheduler autostart management
Expand Down Expand Up @@ -53,6 +53,9 @@ For why IFEO stays out of the current MVP, see [`docs/IFEO_WARNING.md`](docs/IFE

## Honest limits

- **Sleep protection means idle-sleep prevention.** Explicit Sleep or Hibernate, power-button actions and lid closure can still suspend the PC. Wardoff does not block the screen saver or promise to prevent session locking.
- Windows power policy and request overrides can ignore keep-awake requests. On Modern Standby running on battery, system-required requests expire five minutes after the system sleep timeout expires. See the [power behavior matrix and Microsoft sources](docs/MVP_VALIDATION_MATRIX.md#idle-power-behavior-and-windows-limits).
- `layers.sleep=true` means Wardoff acquired its system/display request pair; it is not a guarantee that Windows will refuse every power transition.
- **Wardoff does not promise to stop `shutdown /t 0 /f`.** A forced zero-second local shutdown is outside what a normal user-space app can reliably block.
- Windows Update reboot-task protection requires administrator rights.
- Remote shutdown abort logic only helps when Windows still exposes a timeout window and the process has the rights required for `AbortSystemShutdownW(None)`.
Expand Down
46 changes: 43 additions & 3 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Contains the layered protection logic.
- `local.rs` — local `shutdown.exe` ETW detection and best-effort abort attempts
- `update.rs` — Layer 3 Update Orchestrator reboot-task protection
- `remote.rs` — Layer 4 remote shutdown abort polling
- `sleep.rs` — sleep/hibernate/display-idle blocking
- `sleep.rs` — idle-sleep and automatic display-timeout prevention
- `abort.rs` — shared `AbortSystemShutdownW(None)` helpers used by local and remote shutdown code

### `src/tray/`
Expand Down Expand Up @@ -98,7 +98,7 @@ It holds:
- `LocalShutdownBlocker` for local `shutdown.exe` handling
- `UpdateRebootBlocker` for Update Orchestrator task protection
- `RemoteShutdownBlocker` for remote shutdown polling
- `SleepBlocker` for execution-state-based power-state blocking
- `SleepBlocker` for process-owned idle-power requests

It also owns the current `BlockerMode`:

Expand Down Expand Up @@ -142,6 +142,46 @@ When the runtime returns to Allow mode, it:

If a Block-mode transition fails partway through, `BlockerCoordinator` rolls back the already-started layers so the process does not remain half-armed.

## Idle-power request ownership (intentional architecture change)

The sleep layer uses one process-owned Power Request object with
`PowerRequestSystemRequired` and `PowerRequestDisplayRequired`, replacing the
thread-affine `SetThreadExecutionState` worker and its 30-second refresh.
The purpose is explicit ownership, synchronous activation errors, and a Wardoff
reason in `powercfg /requests`; this does not add a veto over explicit sleep or
hibernate. The existing `windows` dependency provides these APIs.

Block acquires both requests transactionally. Allow, rollback, normal exit and
forced-session cleanup release them and close the handle. The handle is private
to this process and is never duplicated or inherited. Windows closes process
handles on termination; forced termination must also be checked in the smoke
test. No power plan, registry, policy, button or lid setting is written.

The existing resume callback is sufficient. Microsoft's
[PowerSetRequest contract](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powersetrequest)
documents termination of requests at user-initiated sleep entry. When the
runtime remains in Block, that callback replaces the old owned request object
and reacquires the pair. It does not assume that the handle itself becomes
invalid. A tray power action already releases requests through Allow and
reacquires them through the existing restore-to-Block path. There is no new
resume state machine, display/presence subscription, timer, or battery-limit
bypass. Duplicate resume notifications must never accumulate request counts.
Physical S3/S4 and Modern Standby resume behavior remains a manual validation
requirement; API lifecycle tests are not evidence of an actual sleep transition.

`layers.sleep` retains its JSON name and means that Wardoff acquired the request
pair, not that Windows guarantees every power transition is prevented. System
policy can ignore requests. A failed initial acquisition uses the coordinator's
existing rollback; a failed resume acquisition reports an inactive sleep layer
and an error without disabling unrelated shutdown protections.

Away Mode is intentionally excluded: it substitutes apparent sleep on eligible
S3 systems, depends on the existing Allow Away Mode policy, and has no Modern
Standby coverage. Execution-required requests do not add the desired idle-sleep
guarantee. Neither the legacy API as a fallback nor obsolete suspend veto events
are combined with this backend. See the [validation matrix](MVP_VALIDATION_MATRIX.md)
for the power contract, source references, and hardware acceptance procedure.

## Process model and single-instance behavior

Wardoff is designed to have one primary runtime per Windows session boundary enforced by a named mutex.
Expand Down Expand Up @@ -376,7 +416,7 @@ For current documentation and review, treat these as supported, visible runtime
- Layer 1 interactive blocking
- Layer 3 update reboot-task protection
- Layer 4 remote abort polling
- sleep/hibernate/display-idle blocking
- idle-sleep and automatic display-timeout prevention
- tray UI
- CLI plus IPC control
- structured JSONL logging
Expand Down
6 changes: 3 additions & 3 deletions docs/COMPARISON.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

| Product | Source model | Current focus | What Wardoff can honestly claim today | Important gaps or planned items |
| --- | --- | --- | --- | --- |
| Wardoff | MIT, open source | Transparent shutdown and power-state control for modern Windows | Interactive shutdown/sign-out blocking, Update Orchestrator reboot-task protection, remote abort polling, sleep/hibernate/display-idle blocking, tray UI, CLI, JSONL logs, single-instance IPC, autostart | No IFEO mode, no Windows Event Log integration, and no promise to stop local `shutdown /t 0 /f` |
| Wardoff | MIT, open source | Transparent shutdown and power-state control for modern Windows | Interactive shutdown/sign-out blocking, Update Orchestrator reboot-task protection, remote abort polling, idle-sleep and automatic display-timeout prevention, tray UI, CLI, JSONL logs, single-instance IPC, autostart | No IFEO mode, no Windows Event Log integration, and no promise to stop local `shutdown /t 0 /f` |
| ShutdownBlocker | Closed freeware | Traditional shutdown blocking utility | Comparable motivation around shutdown prevention | Closed implementation, older maintenance history, and behavior cannot be audited here |
| ShutdownGuard | MIT, open source | Historical shutdown-blocking approach | Open-source reference point | Archived and unsupported |
| Don't Sleep | Closed freeware | Keep-awake / power-state prevention | Strong overlap on sleep-prevention use cases | Not positioned as a transparent layered shutdown-control tool |
Expand All @@ -21,7 +21,7 @@ Wardoff's current MVP is best described as a conservative, transparent Windows r
- Layer 1 interactive shutdown and sign-out blocking
- Layer 3 protection for `\Microsoft\Windows\UpdateOrchestrator\Reboot`
- Layer 4 best-effort remote shutdown abort polling
- sleep, hibernate, and display-idle blocking via `SetThreadExecutionState(...)`
- idle-sleep and automatic display-timeout prevention through Power Requests, subject to Windows power policy
- tray controls for Block, Allow, Shutdown, Reboot, Sleep, Hibernate, and Quit
- CLI control surface for `--block`, `--allow`, `--hide`, `--status`, `--log`, `--tail`, and `--autostart`
- structured rotating JSONL logs
Expand Down Expand Up @@ -115,7 +115,7 @@ Wardoff's current 0.1.0 positioning is:

- open and auditable
- conservative in what it claims
- useful today for interactive shutdown blocking, update-task protection, remote abort polling, and sleep prevention
- useful today for interactive shutdown blocking, update-task protection, remote abort polling, and idle-sleep prevention
- intentionally cautious about local `shutdown.exe`

That last point is the most important comparison decision:
Expand Down
Loading
Loading