feat: Implement distro-native version comparison for RPM, Debian, and Alpine packages

- Add RpmVersionComparer for RPM version comparison with epoch, version, and release handling.
- Introduce DebianVersion for parsing Debian EVR (Epoch:Version-Release) strings.
- Create ApkVersion for parsing Alpine APK version strings with suffix support.
- Define IVersionComparator interface for version comparison with proof-line generation.
- Implement VersionComparisonResult struct to encapsulate comparison results and proof lines.
- Add tests for Debian and RPM version comparers to ensure correct functionality and edge case handling.
- Create project files for the version comparison library and its tests.
This commit is contained in:
StellaOps Bot
2025-12-22 09:49:38 +02:00
parent aff0ceb2fe
commit 634233dfed
112 changed files with 31925 additions and 1813 deletions

View File

@@ -32,6 +32,35 @@
- **Cross-module edits:** none without sprint note; if needed, log in sprint Execution Log and Decisions & Risks.
- **CVSS v4.0 ingest:** when vendor advisories ship CVSS v4.0 vectors, parse without mutation, store provenance (source id + observation path), and emit vectors unchanged to Policy receipts. Do not derive fields; attach DSSE/observation refs for Policy reuse.
## Distro Backport Version Handling
> **Reference:** `docs/product-advisories/archived/22-Dec-2025 - Getting Distro Backport Logic Right.md`
When working with OS package advisories, follow these rules:
### Version Comparators
- **RPM (RHEL/CentOS/Fedora/openSUSE):** Use `NevraComparer` in `StellaOps.Concelier.Merge.Comparers`. Compares EVR (`epoch:version-release`) using `rpmvercmp` semantics. Tilde `~` sorts before anything.
- **Debian/Ubuntu:** Use `DebianEvrComparer`. Compares `epoch:upstream_version-debian_revision` using dpkg rules. Tilde `~` sorts lower than empty.
- **Alpine (APK):** Use `ApkVersionComparer` (via SPRINT_2000_0003_0001). Handles `-r<pkgrel>` and suffix ordering (`_alpha` < `_beta` < `_pre` < `_rc` < none < `_p`).
### Key Rules
1. **Never convert distro versions to SemVer.** Preserve native EVR/NEVRA/APK strings in `AffectedVersionRange`.
2. **Use `RangeKind` correctly:** `nevra` for RPM, `evr` for Debian/Ubuntu, `apk` for Alpine.
3. **Preserve release qualifiers:** `.el8_5`, `+deb12u2`, `-r0` encode backport information.
4. **Distro advisories take precedence:** When upstream says "fixed in 1.4.4" but distro claims "fixed in 1.4.3-5~deb12u2", prefer distro channel if source is trusted.
5. **Record evidence:** Store source (DSA/RHSA/USN), comparator used, installed version, fixed threshold, and result.
### Edge Cases to Handle
- Epoch jumps: `1:1.2-1` > `0:9.9-9`
- Tilde pre-releases: `2.0~rc1` < `2.0`
- Release qualifiers: `1.2-3.el9_2` < `1.2-3.el9_3`
- Rebuilds/backports: `1.2-3ubuntu0.1` vs `1.2-3`
### Test Corpus
Version comparators must be tested with 50+ cases per distro. See:
- `src/Concelier/__Tests/StellaOps.Concelier.Merge.Tests/Comparers/`
- SPRINT_2000_0003_0002 for comprehensive test requirements
## Coding & Observability Standards
- Target **.NET 10**; prefer latest C# preview features already enabled in repo.
- Npgsql driver for PostgreSQL; canonical JSON mapping in Storage.Postgres.