cargo-cooldown 0.3.0

Cargo wrapper that enforces a cooldown window for freshly published registry crates for improved supply chain security.
# Migration Guide

This guide covers the upgrade path from the 0.2.x configuration model to the
current registry-aware resolver.

## What changed

### Registry scoping is now opt-out

The resolver now applies cooldown to every Cargo registry that appears in the
resolved graph unless you explicitly skip it.

Previously, registry processing could be limited with `COOLDOWN_REGISTRY_INDEX`.
That variable no longer exists.

Use:

```toml
skip_registries = ["crates-io", "sparse+https://example.com/index/"]
```

or:

```bash
COOLDOWN_SKIP_REGISTRIES=crates-io,sparse+https://example.com/index/
```

### Lockfile baseline is now respected by default

By default, versions that were already present in the initial `Cargo.lock` are
not re-cooled.

If you want the previous "cool every eligible locked package" behavior, use:

```toml
lockfile_baseline = "ignore"
```

or:

```bash
COOLDOWN_LOCKFILE_BASELINE=ignore
```

### Allow rules are embedded in `cooldown.toml`

`cooldown-allowlist.toml`, `allowlist_path`, and `COOLDOWN_ALLOWLIST_PATH` no
longer exist.

Move allow rules into `cooldown.toml`:

```toml
[[allow.exact]]
crate = "serde"
version = "1.0.218"

[[allow.package]]
crate = "tokio"
minutes = 60

[allow.global]
minutes = 1440
```

If an existing rule uses `minimum_release_age`, rename that key to `minutes`.
Use lowercase TOML keys such as `cooldown_minutes`; environment variable names
are only accepted from the environment.

For workspaces, put shared rules in the workspace root file and use
member-local `cooldown.toml` overrides only for uniquely targeted member runs.

### Registry API routing is discovered automatically

The resolver reads the active registry configuration that Cargo is already using
and discovers the fallback HTTP API from that registry index.

`COOLDOWN_REGISTRY_API` no longer exists.

### `enforcement` replaces 0.2.x `mode`

`COOLDOWN_OFFLINE_OK` no longer exists.

0.2.x used:

- `mode = "strict"` / `COOLDOWN_MODE=strict`
- `mode = "best_effort"` / `COOLDOWN_MODE=best_effort`
- `mode = "off"` / `COOLDOWN_MODE=off`

This release uses:

- `enforcement = "strict"` / `COOLDOWN_ENFORCEMENT=strict`
- `enforcement = "cargo_compatible"` / `COOLDOWN_ENFORCEMENT=cargo_compatible`
- `enforcement = "off"` / `COOLDOWN_ENFORCEMENT=off`

If you previously used 0.2.x best-effort behavior and want to keep Cargo's best
valid lockfile while warning about fresh versions that Cargo still requires,
use:

```bash
COOLDOWN_ENFORCEMENT=cargo_compatible
```

This now prompts before accepting unresolved fresh versions. To keep the 0.2.x
non-interactive behavior, also set:

```bash
COOLDOWN_CARGO_COMPATIBLE_ACCEPT=auto
```

If you want a registry to be excluded from cooldown entirely, use
`skip_registries`.

## Required migration steps

1. Remove `COOLDOWN_REGISTRY_API` from your environment, shell wrappers, and CI
   helpers.
2. Remove `COOLDOWN_REGISTRY_INDEX` from your environment and `cooldown.toml`
   files.
3. Remove `COOLDOWN_OFFLINE_OK` from your environment and `cooldown.toml`
   files.
4. Remove `cooldown-allowlist.toml`, `allowlist_path`, and
   `COOLDOWN_ALLOWLIST_PATH`.
5. Move allow rules into `cooldown.toml`.
6. Add `skip_registries` or `COOLDOWN_SKIP_REGISTRIES` for any registry that
   should not participate in cooldown.
7. Replace `mode` with `enforcement` in `cooldown.toml`; rename the value
   `best_effort` to `cargo_compatible`.
8. Replace `COOLDOWN_MODE` with `COOLDOWN_ENFORCEMENT` in scripts and CI.
9. If you relied on 0.2.x best-effort behavior, switch to
   `COOLDOWN_ENFORCEMENT=cargo_compatible`.
10. If that flow must remain non-interactive, add
    `COOLDOWN_CARGO_COMPATIBLE_ACCEPT=auto`.

## Internal registries

Registries that participate in cooldown must expose enough release-time
metadata for the resolver to decide whether a locked version is fresh.

The resolver uses Cargo's local index `pubtime` first and falls back to
per-crate HTTP only when `pubtime` is missing.

If an internal registry still cannot provide timestamps:

- `strict` enforcement fails closed;
- `cargo_compatible` enforcement emits a warning and continues;
- `off` enforcement disables cooldown entirely.

For registries such as CodeArtifact, the practical migration path is usually:

1. keep crates.io under cooldown;
2. put the internal registry in `skip_registries` until it exposes compatible
   metadata.

See also:

- [Registries]registries.md
- [Troubleshooting]troubleshooting.md

## Behavior changes to expect

- package-scoped runs now cool only the selected workspace members and their
  dependency closure;
- unchanged lockfile entries are skipped by default unless
  `lockfile_baseline = "ignore"` is enabled;
- configuration discovery now starts from the effective Cargo root instead of
  implicitly following the current directory;
- allow rules now live inside `cooldown.toml`;
- `--manifest-path` is honored during cooldown inspection, batch validation,
  and the forwarded Cargo command;
- Cargo-style selectors such as `--manifest-path`, `--package`, `--workspace`,
  `--exclude`, and feature flags are accepted even when passed after the
  forwarded Cargo subcommand.

## Checklist

- no old `COOLDOWN_REGISTRY_*` variables remain in your environment;
- no `COOLDOWN_OFFLINE_OK` references remain in scripts or docs;
- no `cooldown-allowlist.toml`, `allowlist_path`, or
  `COOLDOWN_ALLOWLIST_PATH` references remain;
- registries that should be excluded are listed in `skip_registries`;
- 0.2.x `mode` keys were renamed to `enforcement`;
- 0.2.x `COOLDOWN_MODE` references were renamed to `COOLDOWN_ENFORCEMENT`;
- flows that expect 0.2.x best-effort behavior use
  `COOLDOWN_ENFORCEMENT=cargo_compatible`;
- non-interactive flows that expect 0.2.x best-effort behavior also use
  `COOLDOWN_CARGO_COMPATIBLE_ACCEPT=auto`.