# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.8] - 2026-07-06

### Fixed
- **Config `fail_on` dead code**: `.dep-age.toml` `fail_on` field is now used as fallback when `--fail-on` is not passed on CLI
- **Config `ignore` list dropped**: `.dep-age.toml` `ignore` list is now merged with CLI `--ignore` and `.dep-age-ignore`
- **Composer `--no-dev` inverted**: `require-dev` packages are now correctly included when `--no-dev` is NOT passed (default)
- **Python environment markers**: `requests>=2.28; python_version>="3.6"` now correctly strips `;` and everything after
- **Library `eprintln!`**: Removed `eprintln!` from `RegistryCache::set()` — cache failures are non-fatal

### Added
- **Shared retry helper**: Extracted `fetch_with_retry<T,F>` generic function, reducing ~700 lines of duplicate retry logic to ~150
- **`#[must_use]`** on `DepResult`, `DepAgeSummary`, `CheckOptions`, `CacheStats`
- **`CacheStats` Serialize**: Now serializable for structured output
- **`parse_python_dep` public**: Made public directly (removed `#[doc(hidden)]` test wrapper)
- **`ConfigError::source()`**: Error chain now exposes inner error
- **`cargo audit` in CI**: Security vulnerability scanning on every push/PR
- **npm binary verification**: `install.js` verifies extracted binary exists
- **Edition 2024**: Upgraded from edition 2021
- **MSRV**: Added `rust-version = "1.85"` to Cargo.toml

### Changed
- Version bump to 0.1.8

## [0.1.7] - 2026-07-02

### Fixed
- **Ruby classify bug**: Unknown `published_at` now returns `Status::Error` instead of falsely classifying as `Fresh`
- **Composer classify bug**: Same fix — unknown publish time is an error, not fresh
- **HTML XSS**: Package names/versions are now escaped before insertion into HTML reports
- **detect_manifest double call**: Merged into single call to avoid redundant filesystem reads
- **README**: Updated `check_pypi_package` reference (now exists), version to 0.1.6, Registry doc to list all 7 types
- **Duplicate tests**: Removed duplicate Python extras tests from lib.rs (kept in python_tests.rs)

### Added
- **`check_pypi_package`**: Single-package convenience function for PyPI (matches `check_crate`/`check_npm_package` pattern)
- **`check_ruby_package`**: Single-package convenience function for RubyGems
- **`check_composer_package`**: Single-package convenience function for Packagist
- **`DepAgeSummary` Serialize/Deserialize**: Full summary is now serializable for library consumers
- **npm checksum verification**: `install.js` downloads `sha256sums.txt` and verifies SHA256 before extraction
- **npm version check in CI**: Release workflow verifies `npm/package.json` version matches tag
- **`--format` help text**: Now lists all 9 output formats

### Removed
- Dead `Theme` struct, `Theme::dark()`, `Theme::light()`, `Default for Theme` (was unused after `--theme` removal in v0.1.6)

### Changed
- Version bump to 0.1.7

## [0.1.6] - 2026-07-02

### Fixed
- **Go `.info` endpoint**: Fixed JSON deserialization (`resp.text()` → `resp.json()`) so Go module age is calculated correctly
- **Composer response**: Fixed `ComposerRepoResponse` struct to match actual Packagist API shape
- **`--fail-on any`**: Now includes `summary.errors` in the exit-code check
- **Config thresholds**: CLI `--fresh/--aging/--stale` now merge with config file values as fallback instead of overriding
- **`long_about`**: Updated to list all 8 manifest types (was missing Go, Docker, Ruby, Composer)
- **Python extras stripping**: `requests[security]>=2.28.0` now correctly extracts name=`requests`
- **Ruby gem flexible prefix**: Gems indented with tabs or >2 spaces now detected
- **`npm/run.js`**: Missing binary now exits with code 1 instead of silently succeeding
- **`npm/install.js`**: HTTP 4xx/5xx errors now rejected instead of silently written to disk
- **`npm/install.js`**: Redirects 307/308 now followed (was only 301/302)
- **`detect_manifest`**: Operator precedence clarified, dead `name != "lock"` check removed

### Added
- **Retry logic for Go proxy**: `fetch_go_module` now retries on 429/timeout (same pattern as crates.io)
- **Retry logic for Docker Hub**: `fetch_docker_image` now retries on 429/timeout
- **`npm/package.json` `files` field**: Whitelists only shipped files (`run.js`, `install.js`, `bin/`)
- **`npm/package.json` `engines.node`**: Bumped from >=14 to >=18
- **Tests**: Python extras stripping (3 tests), Ruby flexible indentation (2 tests), classify custom thresholds
- Removed dead code: `GoVersionInfo`, `GoModFile`, `GoModule`, `GoRequire`, `GoSumEntry`, `ComposerApiResponse`, `DockerHubTokenResponse`, `ThemeArg`, `get_theme`
- Removed vestigial `#[allow(dead_code)]` from `ComposerRepoResponse`

### Changed
- tokio features trimmed from `"full"` to `["rt-multi-thread", "macros", "time", "sync"]`
- Version bump to 0.1.6

## [0.1.5] - 2026-06-30

### Fixed
- Duplicate `starts_with('#')` check in `check_cargo_toml` (lib.rs)
- Unused `ProgressFn` type removed
- `expect()` calls in `check_crate`, `check_npm_package`, `check_docker_image`, `check_go_module` replaced with proper error handling
- Dead TUI code (`use_tui` variable) removed from main.rs

### Added
- `Serialize` derives on `Status`, `Registry`, `DepResult` for structured output
- `--output <file>` flag to write output to a file instead of stdout
- `render_html` and `render_step_summary` now return `String` instead of printing
- Proper Go.mod block `require ( ... )` parsing with state tracking
- Docker Compose YAML-first parsing with line-based fallback
- `serde_yaml` dependency for proper YAML parsing
- `DepAgeError::Yaml` error variant
- 13 new tests: output formatters (7), Go.mod parsing (3), Docker Compose (3)
- `# Errors` documentation on public check functions

### Changed
- `format_years` and `registry_url` helpers shared from `src/output/mod.rs`
- `quick-xml` bumped from 0.37 to 0.40
- 63 dependencies updated via `cargo update`
- `#[allow(clippy::items_after_test_module)]` removed
- Go.mod block require parsing uses proper state machine
- Docker Compose parsing filters out registry URLs with ports

## [0.1.4] - 2026-04-24

### Fixed
- **Custom file path support**: Now accepts any manifest file path (e.g., `my-app.toml`, `/path/to/Cargo.toml`)
- **Clippy fix**: Moved code after test module with allow attribute
- Content-based detection: parses file content to verify manifest type
- Suffix matching: accepts files ending with known manifest names

### Changed
- Updated version to 0.1.4

## [0.1.3] - 2026-04-24

### Added
- **Ruby Gem Support**:
  - Auto-detects `Gemfile`
  - Checks gem versions via RubyGems.org API
  - Library functions: `check_ruby_gemfile()`, `fetch_ruby()`
- **PHP Composer Support**:
  - Auto-detects `composer.json`
  - Checks package versions via Packagist.org API
  - Library functions: `check_composer_json()`, `fetch_composer()`
- **Go Modules Support**:
  - Auto-detects `go.mod` files
  - Checks package versions via Go proxy (proxy.golang.org)
- **Docker/OCI Image Support**:
  - Auto-detects `docker-compose.yml` and `docker-compose.yaml`
  - Checks image tags via Docker Hub API
- **Output Formats**:
  - `--format html` - HTML report with dark theme styling
  - `--format step-summary` - GitHub Actions markdown table
  - `--format ndjson` - Newline-delimited JSON for streaming
- **Theme Support**:
  - `--theme auto|dark|light` - Terminal output theming
- **Registry Enhancements**:
  - Timeout configurable in CheckOptions
  - Rate limit retry with exponential backoff

### Changed
- Updated description to include all supported manifest types
- Registry enum now supports: Crates, Npm, PyPI, Go, Docker, Ruby, Composer
- All output formats updated for new registries
- Improved error handling for network requests

## [0.1.2] - 2026-04-15

### Added
- **Output Formats**:
  - `--format github-checks` - GitHub Actions workflow annotations
  - `--format junit` - JUnit XML for CI systems (Jenkins, etc.)
  - `--format sarif` - SARIF for GitHub Advanced Security
- **Configuration File**:
  - `--config <path>` - Custom config file path
  - Auto-detects `.dep-age.toml` or `dep-age.toml`
  - Supports `[tool.dep-age]` section with thresholds, ignore lists, registry URLs
- **Check Mode**:
  - `--check` - Quiet mode, only exit code (no table output)
- **Diff/Trend Tracking**:
  - `--diff` - Show changes since last run
  - Auto-saves results to `.dep-age-history.json`
  - Shows newly stale, improved, and new packages

### Changed
- Improved error handling for network requests
- Added quick-xml dependency for XML generation

## [0.1.1] - 2026-04-13

### Added
- `--format csv` for CSV output (pipeable to spreadsheets)
- `--format json` as alternative to `--json`
- `--sort` flag to sort results by `age` (default), `name`, or `status`
- `--ignore <name>` flag to skip packages by name (repeatable)
- `.dep-age-ignore` file auto-loading — one package name per line, `#` comments supported
- Version gap column in output — shows `version` alongside `latest`
- PyPI support documented: `pyproject.toml` and `requirements.txt`
- `DepAgeSummary::is_all_fresh()` convenience method
- `CheckOptions.ignore_list` field for library consumers
- Homebrew tap: `brew tap Ayyankhan101/dep-age && brew install dep-age`
- CONTRIBUTING.md and SECURITY.md
- `--fail-on stale/aging/any/never` options for finer CI control

### Fixed
- crates.io publish skip check now sends `User-Agent` header (API requires it)
- `cargo publish --token` deprecation replaced with `cargo login`
- Hardcoded user-agent replaced with `env!("CARGO_PKG_VERSION")` constant
- README: PyPI support, `CheckOptions` table, `--cache`, `--fail-on` all documented

## [0.1.0] - 2026-04-12

### Added
- Check dependency age for both `Cargo.toml` (crates.io) and `package.json` (npm)
- Color-coded status output with icons (✓ fresh, ~ aging, ! stale, ✗ ancient)
- Custom thresholds via `--fresh`, `--aging`, `--stale` flags
- `--filter` to show only packages matching a status
- `--json` output for CI pipelines
- `--no-dev` to skip dev dependencies
- `--concurrency` to control parallel registry requests
- Exit code 1 when ancient packages are found (CI-friendly)
- Cargo workspace support
- Library API with `check_cargo_toml`, `check_package_json`, `check_crate`
- File-based registry cache with TTL
- Comprehensive test suite (unit, integration, mocked HTTP)
