Guard Commands
Relevant source files
The following files were used as context for generating this wiki page:
Guard Commands are specialized cargo-cooldown subcommands that interpose a "cooling" pass on the dependency graph before executing standard Cargo operations. By validating and potentially rewriting the Cargo.lock file to avoid recently published crate versions, these commands ensure that the supply chain risk is mitigated before the compiler ever downloads or executes third-party code.
Within the cargo-cooldown ecosystem, these commands act as a protective layer. They use the current Cargo.lock as a baseline and, depending on configuration, either enforce strict version age requirements or provide warnings when "fresh" versions are unavoidable due to manifest constraints. Sources: README.md:16-24, src/main.rs:11-13
Architecture and Execution Flow
The execution of a Guard Command follows a specific lifecycle: argument normalization, isolated workspace preparation, lockfile cooling, and finally, forwarding to the original Cargo binary. Sources: src/main.rs:488-518
Lifecycle Stages
- Normalization: The wrapper parses CLI arguments to separate Cargo-specific selectors (like
--manifest-pathor--features) from the actual command to be guarded. Sources: src/main.rs:159-166 - Isolation: To prevent speculative resolution from polluting the user's workspace, the tool creates an
IsolatedWorkspace. Sources: src/main.rs:468-472 - The Cooling Loop: The
executormodule enters a loop that reads metadata, identifies fresh crates, and attempts to solve for older, compatible versions. Sources: src/executor.rs:88-110 - Forwarding: Once the lockfile is cooled and validated, the original command (e.g.,
cargo build) is executed with the modifiedCargo.lock. Sources: src/main.rs:517-518
The following diagram illustrates the high-level flow of a Guard Command:
The diagram shows how cargo-cooldown intercepts the request to manage the lockfile before Cargo takes over. Sources: src/main.rs:488-518, src/executor.rs:88-154
Core Guard Commands
The following table details the primary subcommands that function as guards:
| Command | Description | Timing Policy |
|---|---|---|
check | Cools the graph, then runs cargo check. | Pre-command pass. |
build | Cools the graph, then runs cargo build. | Pre-command pass. |
test | Cools the graph, then runs cargo test. | Pre-command pass. |
run | Cools the graph, then runs cargo run. | Pre-command pass. |
Sources: src/main.rs:69-95, README.md:21-25
Cooling Logic and Enforcement
The logic for guarding commands is primarily driven by the executor::run_pinning_flow_with_snapshot function. This function manages an iterative process where Cargo's resolved graph is repeatedly inspected and modified until a stable, "cool" state is reached or the process fails. Sources: src/executor.rs:88-112
Enforcement Modes
Guard commands behave differently based on the enforcement setting in cooldown.toml:
- Strict: If any crate remains within the cooldown window and cannot be downgraded to a compatible older version, the guard fails and restores the original lockfile. Sources: src/config.rs:24-27, src/executor.rs:194-205
- CargoCompatible: The guard attempts to cool the graph but permits "fresh" versions if Cargo requires them (e.g., due to semver constraints). It will prompt the user (unless
autois set) before continuing. Sources: src/config.rs:24-28, src/executor.rs:214-230 - Off: Cooldown checks are bypassed entirely. Sources: src/config.rs:24-29
Lockfile Baseline Behavior
The lockfile_baseline setting determines what the guard considers a "minimum" version:
- Floor: (Default) Treat versions already in the
Cargo.lockas the minimum floor. The guard will not downgrade below these versions unless explicitly instructed. Sources: src/config.rs:55-58, src/executor.rs:1134-1149 - Ignore: Allows the guard to downgrade even those versions already present in the initial lockfile if they are too fresh. Sources: src/config.rs:55-59, tests/integration.rs:63-70
Coordinated Bundle Solving
Sometimes crates are tied together by exact version requirements (e.g., =1.2.3). In these cases, Guard Commands utilize a coordinated solver that identifies these "bundles" and attempts to cool them as a single unit to maintain dependency coherence. Sources: src/executor.rs:1255-1275
The sequence diagram details the interaction between the executor and Cargo during the validation phase of a guard pass. Sources: src/executor.rs:600-640, src/executor.rs:684-700
Configuration Parameters
Guard Commands are influenced by several configuration options defined in src/config.rs:
| Key | Type | Default | Description |
|---|---|---|---|
cooldown_minutes | u64 | 0 | Age required for a crate version to be "cool". |
enforcement | Enum | Strict | Policy when fresh versions cannot be cooled. |
lockfile_baseline | Enum | Floor | Whether to treat initial lockfile as a floor. |
cargo_compatible_accept | Enum | Prompt | Interaction mode for unavoidable fresh versions. |
Sources: src/config.rs:72-84, src/init.rs:158-185
Summary
Guard Commands provide a proactive defense mechanism for Rust projects by intercepting standard development workflows. By ensuring the Cargo.lock is "cooled" before any download occurs, the tool protects against immediate exposure to recently published (and potentially compromised) packages. The system is designed to be transparent, forwarding the final command to Cargo only after all security constraints have been validated. Sources: README.md:144-149, src/main.rs:11-15