Install gate: move recency gate from flags to a config toggle#119
Merged
Conversation
A --force/--no-fail typed after the install verb is swept into clap's trailing-var-arg and forwarded to the package manager, so the gate never sees it and the block stands. Users (reasonably) read 'Pass --force' and retry with the flag in the same wrong slot. print_escape_hint now detects an accepted escape flag sitting in the forwarded args and prints a note naming the package manager that received it, plus the corrected invocation with the flag between manager and verb (corgea uv --force add requests). Covered by a pip integration test.
The recency block (a version published within --threshold blocks the
install) is gone, along with the -t/--threshold flag, the --no-fail
demotion flag, parse_threshold, and the RecencyOnly block reason. The
vuln-api verdict is now the gate's single block condition.
Every resolved package still shows its publish time for provenance
('published <age> ago at <UTC timestamp>') — now a neutral line on every
named target rather than a within-threshold warning. JSON drops
threshold_seconds and the per-result 'recent' status/count; verdict_mode
'recency-only' becomes 'none'.
Tests repurposed, not just deleted: fresh pins now assert they install;
the two npm gating tests assert the gate engaged via its Pre-checking
header / registry hit instead of a recency refusal. SKILL.md updated.
When pip backtracks a named target to a version the CLI never resolved, apply_verdicts adopts the installed version on the named row but its publish date / age belonged to the CLI-resolved version. Render then printed e.g. `flask@3.0.2 published … at <date-for-3.0.3>` — a wrong date presented as provenance, the one thing the recency-removal PR keeps. Make `TargetOutcome::Resolved.age` an `Option<Duration>`, set it to `None` in the backtrack collapse (rather than re-fetch on the gate's critical path), and have render omit the publish line (text) / null `published_at` + `age_seconds` (JSON) when it's absent. Tests assert the backtracked row carries no stale date and an exact match keeps its provenance. Also clean the stale "recency" wording the gate removal left behind: wrapper --help strings, SKILL.md, and the locked-install comments.
Bring back the recency block removed in dca9621, this time driven by ~/.corgea/config.toml instead of the -t/--threshold and --no-fail flags. Two new fields, both serde-defaulted so an upgraded config inherits the gate rather than silently disabling it: recency_gate = true (CORGEA_RECENCY_GATE) recency_threshold_days = 14 (CORGEA_RECENCY_THRESHOLD_DAYS) block_reason gains BlockReason::Recency as a softer second gate: a clean named target published within the window blocks only when no vulnerable/ unverifiable finding already did. Unknown publish dates (pip backtracking, age = None) never block, so the stale-provenance bug 1496887 fixed stays fixed. The refusal names each fresh package and points at the config toggle; --force still bypasses. JSON adds top-level recency_threshold_days (null when off) to pair with each result's age_seconds. Tests: a config unit test pins the opt-out default + back-compat; five e2e tests cover block-on, --force bypass, threshold-0 plumbing, old-pin allowed, and gate-off installs. The shared test harness pins the gate off so existing gate tests stay 'every block is the verdict's doing'. Docs: SKILL.md and README document the gate, window, and toggle.
Document the tag-driven release process: Cargo.toml as the version source of truth (PyPI via maturin dynamic; npm version from the v-tag), the three publish workflows and their order (PyPI wheels -> GitHub Release binaries -> npm), the manual changelog step, smoke tests, rollback, and known issues (the npm skip-guard checks the unscoped name; bin/corgea.js reinstall hint).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrate the install-gate recency check from CLI flags to a config toggle.
mainalready gates on recency via--threshold/--no-fail. This replacesthose flags with config in
~/.corgea/config.toml:recency_gate(bool, defaulttrue) — block installs of named targetspublished within the window; set
falseto disable.recency_threshold_days(u32, default14) — the window, in days.CORGEA_RECENCY_GATE,CORGEA_RECENCY_THRESHOLD_DAYS.Behavior: blocks named install targets published within the window; the vuln
verdict takes precedence over freshness; unknown publish dates (pip backtrack)
never block;
--forcebypasses for a single install.--jsonreportsrecency_threshold_days.Also in this PR:
--forcetyped after the verb).