Add freshness threshold to security gate#149
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b2e350fbc2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| age_hours = (now.astimezone(timezone.utc) - parsed.astimezone(timezone.utc)).total_seconds() | ||
| return round(age_hours / 3600, 3), None |
There was a problem hiding this comment.
Reject future-dated truth snapshots
When --max-age-hours is used and generated_at is later than now (for example because the truth file was produced with a bad clock or corrupted timestamp), this returns a negative source_age_hours with no freshness_error. Since SecurityGateReport.is_stale only checks source_age_hours > max_age_hours, the gate can report a clear scanned snapshot as fresh until wall time catches up, even though the repo's own seam-linter treats future generated_at values as a freshness violation. Please fail freshness validation for future timestamps as well.
Useful? React with 👍 / 👎.
What
Adds optional freshness enforcement to
audit security-gatevia--max-age-hours.Why
The portfolio security gate should distinguish
clear and currentfromclear but stale. Without an age threshold, a clean old snapshot could suppress a security follow-up decision.Review Of What Was Built
stalegate status whenportfolio-truth-latest.jsonis older than the configured threshold or has an invalidgenerated_at.max_age_hours,source_age_hours, andfreshness_errorto the JSON output.audit security-gate --max-age-hours Ninto the CLI.Cleanup Review
Kept freshness inside the existing security gate instead of adding another command, report, or dashboard.
Verification Summary
python3.13 -m ruff check src/portfolio_security_gate.py tests/test_portfolio_security_gate.py src/cli.pypassed.python3.13 -m pytest -q tests/test_portfolio_security_gate.py tests/test_portfolio_decision_queue.py tests/test_security_burndown.py tests/test_cli_subcommands.py tests/test_cli_hardening.pypassed: 145 tests.python3.13 -m src.cli security-gate --output-dir output --max-age-hours 168 --jsonpassed against the live snapshot: 135 scanned, 0 critical, 0 high, fresh within threshold.Shipped Summary
The branch makes the security gate suitable for recurring review use: high/critical drift, missing overlay, and stale truth now all produce nonzero outcomes.
Next Phase
Keep the weekly portfolio-review automation pointed at
--max-age-hours 168so stale truth becomes a concrete decision instead of quiet noise.Remaining Roadmap