From 12588cf78d57a08cd842944208e5ba4b5bb42dcb Mon Sep 17 00:00:00 2001 From: hushen <190065939+918154429@users.noreply.github.com> Date: Thu, 10 Sep 2026 13:09:05 +0800 Subject: [PATCH] fix(core): enable supported Debian stable releases Signed-off-by: hushen <190065939+918154429@users.noreply.github.com> --- CHANGELOG.md | 3 ++ apps/sysknife-cli/src/distro_routing.rs | 7 ++- crates/sysknife-core/src/action_family.rs | 4 +- crates/sysknife-core/src/distro.rs | 54 ++++++++++++++++++++--- crates/sysknife-daemon/src/dispatcher.rs | 10 ++++- docs/distro-support.md | 13 +++++- 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d8d55fb..4e1b3ae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ Releases before `0.2.5` predate the public launch; their notes live in the ### Changed +- Make Debian stable releases 12 and later eligible, while refusing an unknown + version and releases below the security-support floor. Debian eligibility is + separate from live-VM validation; Ubuntu-only actions remain excluded (#238). - Separate Ubuntu identity requirements from Debian-family mechanisms and planner defaults. Canonical services, PPAs and the reboot sentinel require Ubuntu itself; portable tools are no longer refused merely for being another diff --git a/apps/sysknife-cli/src/distro_routing.rs b/apps/sysknife-cli/src/distro_routing.rs index f6aca051..0bd7f90b 100644 --- a/apps/sysknife-cli/src/distro_routing.rs +++ b/apps/sysknife-cli/src/distro_routing.rs @@ -211,7 +211,8 @@ mod tests { "AptUpdate", ] { for distro in [ - DistroId::Debian { version: Some(13) }, + DistroId::Debian { version: Some(11) }, + DistroId::Debian { version: None }, DistroId::Ubuntu { major: 18, minor: 4, @@ -229,13 +230,15 @@ mod tests { ); } for distro in [ + DistroId::Debian { version: Some(12) }, + DistroId::Debian { version: Some(13) }, DistroId::Ubuntu { major: 24, minor: 4, }, DistroId::FedoraSilverblue { version: 41 }, ] { - if action != "AptUpdate" { + if action != "AptUpdate" || matches!(distro, DistroId::Debian { .. }) { assert!( check_action_distro(action, Some(&distro)).is_ok(), "portable {action} must remain usable on {distro}" diff --git a/crates/sysknife-core/src/action_family.rs b/crates/sysknife-core/src/action_family.rs index 88ded1b6..707dae13 100644 --- a/crates/sysknife-core/src/action_family.rs +++ b/crates/sysknife-core/src/action_family.rs @@ -358,8 +358,8 @@ mod tests { assert!(action_matches_distro(action, &debian), "{action}"); } assert!( - !debian.is_supported(), - "classification must not enable Debian" + !derivative.is_supported(), + "Debian-family membership must not enable an unrecognised derivative" ); } } diff --git a/crates/sysknife-core/src/distro.rs b/crates/sysknife-core/src/distro.rs index a106ec1b..43edf34e 100644 --- a/crates/sysknife-core/src/distro.rs +++ b/crates/sysknife-core/src/distro.rs @@ -35,6 +35,10 @@ pub const OLDEST_ELIGIBLE_FEDORA_ATOMIC: u32 = 41; /// every release in a year, interim ones included. pub const OLDEST_SUPPORTED_UBUNTU_MAJOR: u32 = 20; +/// Oldest eligible Debian stable release. Debian 11 LTS ended in August 2026; +/// Debian 12 remains in LTS through June 2028. +pub const OLDEST_SUPPORTED_DEBIAN: u32 = 12; + // --------------------------------------------------------------------------- // Error types // --------------------------------------------------------------------------- @@ -231,6 +235,10 @@ impl DistroId { /// Ubuntu is validation effort, not support, because Ubuntu has far more /// users. See `docs/distro-support.md`. /// + /// - Debian stable releases 12 and later are eligible. An absent version + /// (including testing/sid) is refused: security support cannot be inferred + /// from Debian identity alone. + /// /// # Eligibility is not validation coverage /// /// This predicate answers "may SysKnife act on this host at all" — the @@ -249,7 +257,8 @@ impl DistroId { Self::Fedora { .. } => false, Self::FedoraSilverblue { version } => *version >= OLDEST_ELIGIBLE_FEDORA_ATOMIC, Self::Ubuntu { major, .. } => *major >= OLDEST_SUPPORTED_UBUNTU_MAJOR, - Self::UbuntuCore { .. } | Self::Debian { .. } | Self::Other { .. } => false, + Self::Debian { version } => version.is_some_and(|v| v >= OLDEST_SUPPORTED_DEBIAN), + Self::UbuntuCore { .. } | Self::Other { .. } => false, } } } @@ -649,6 +658,20 @@ ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/" +"#; + + const DEBIAN_13: &str = r#"PRETTY_NAME="Debian GNU/Linux 13 (trixie)" +NAME="Debian GNU/Linux" +VERSION_ID="13" +VERSION="13 (trixie)" +VERSION_CODENAME=trixie +ID=debian +"#; + + const DEBIAN_TESTING: &str = r#"PRETTY_NAME="Debian GNU/Linux forky/sid" +NAME="Debian GNU/Linux" +VERSION_CODENAME=forky +ID=debian "#; /// Linux Mint 22 (ID=linuxmint, ID_LIKE="ubuntu debian"). @@ -955,9 +978,17 @@ SUPPORT_END="2028-03-15" } #[test] - fn detect_debian_12() { - let r = parse_os_release(DEBIAN_12).unwrap(); - assert_eq!(detect_distro(&r), DistroId::Debian { version: Some(12) }); + fn detect_debian_stable_and_testing() { + for (fixture, version, eligible) in [ + (DEBIAN_12, Some(12), true), + (DEBIAN_13, Some(13), true), + (DEBIAN_TESTING, None, false), + ] { + let r = parse_os_release(fixture).unwrap(); + let distro = detect_distro(&r); + assert_eq!(distro, DistroId::Debian { version }); + assert_eq!(distro.is_supported(), eligible); + } } #[test] @@ -1091,8 +1122,19 @@ SUPPORT_END="2028-03-15" } #[test] - fn unsupported_debian() { - assert!(!DistroId::Debian { version: Some(12) }.is_supported()); + fn debian_eligibility_requires_a_supported_known_version() { + for (version, expected) in [ + (Some(11), false), + (Some(12), true), + (Some(13), true), + (None, false), + ] { + assert_eq!( + DistroId::Debian { version }.is_supported(), + expected, + "{version:?}" + ); + } } #[test] diff --git a/crates/sysknife-daemon/src/dispatcher.rs b/crates/sysknife-daemon/src/dispatcher.rs index b8f13221..14a4ea06 100644 --- a/crates/sysknife-daemon/src/dispatcher.rs +++ b/crates/sysknife-daemon/src/dispatcher.rs @@ -5082,7 +5082,7 @@ mod tests { // why the platform gate does not exempt reads at all. let dir = tempdir().unwrap(); let mut state = test_state(&dir); - state.host_distro = Some(sysknife_core::distro::DistroId::Debian { version: Some(12) }); + state.host_distro = Some(sysknife_core::distro::DistroId::Debian { version: Some(11) }); assert!( !state.host_distro.as_ref().unwrap().is_supported(), "this test needs an ineligible host" @@ -5096,6 +5096,14 @@ mod tests { validate_action_platform(&state, "AptUpdate").is_err(), "a privileged mutation must stay refused on an ineligible host" ); + for version in [None, Some(11), Some(12), Some(13)] { + state.host_distro = Some(sysknife_core::distro::DistroId::Debian { version }); + assert_eq!( + validate_action_platform(&state, "AptUpdate").is_ok(), + matches!(version, Some(12 | 13)) + ); + assert!(validate_action_platform(&state, "AddPpa").is_err()); + } } #[test] fn raising_a_read_only_action_via_risk_overrides_does_not_arm_the_platform_fence() { diff --git a/docs/distro-support.md b/docs/distro-support.md index a1d0eea6..1a64174e 100644 --- a/docs/distro-support.md +++ b/docs/distro-support.md @@ -20,7 +20,8 @@ the bug this section now documents: - **Eligibility** — will the daemon act on this host at all? That is `DistroId::is_supported()` in `crates/sysknife-core/src/distro.rs`, and the daemon refuses every *mutating* action when it is false. It is true for all - Ubuntu releases from 20.04 up, and for Fedora Atomic 41 and later. + Ubuntu releases from 20.04 up, Fedora Atomic 41 and later, and Debian stable + releases with a known version of 12 or later. - **Validation tier** — has the full story suite been run on that release? That is the table below, and it will always be narrower than eligibility. @@ -31,6 +32,13 @@ ineligible because they no longer receive Ubuntu security updates, and Ubuntu Core stays ineligible for a structural reason rather than an age one — it has no apt and a read-only root, so the Debian-family action set cannot apply. +Debian 11 is below the floor because its LTS ended on 2026-08-31. Debian 12 +remains eligible during LTS; Debian 13 is eligible as well. Testing/sid images +without `VERSION_ID` remain ineligible: Debian identity alone does not establish +security support. This enables the existing Debian mechanisms, not Ubuntu-only +services, PPAs or reboot-sentinel assumptions. Firewall backend coverage remains +tracked separately in [#239](https://github.com/lacs-project/sysknife/issues/239). + ## Status definitions | Tier | Meaning | @@ -52,6 +60,7 @@ apt and a read-only root, so the Debian-family action set cannot apply. | **Fedora Silverblue 44** | rpm-ostree, Flatpak, toolbox, firewalld, systemd, containers | Harness and fixture coverage; no live-VM run on this release | **Blocked** (`make install` does not complete on rpm-ostree, [#301](https://github.com/lacs-project/sysknife/issues/301)) | | **Other Fedora Atomic 41+ variants** | rpm-ostree family | Detection and shared action tests, plus a live VM run on Fedora 43 Silverblue (2026-08-24) that provisioned and then stopped at `make install` | **Blocked** (`make install` does not complete on rpm-ostree, [#301](https://github.com/lacs-project/sysknife/issues/301)) | | **Fedora Workstation / Server** | `dnf` family incomplete | Detection tests only | **Experimental** | +| **Debian stable 12+** | Existing apt/dpkg and portable actions; Ubuntu-only actions excluded | Version and routing fixtures; no live Debian story-suite run | **Current validation required** | ## Fedora Atomic cannot be installed yet @@ -117,7 +126,7 @@ Fedora-family systems receive a warning rather than a false support claim. | Distro | State | |---|---| -| Debian stable/testing | Planned after Ubuntu hardening | +| Debian testing / sid without `VERSION_ID` | Ineligible; no known supported stable version | | Arch / EndeavourOS | Planned; requires a `pacman` action family | | openSUSE Leap / Tumbleweed | Planned; requires `zypper` and transactional-update design | | NixOS | Out of scope; configuration evaluation does not fit per-action mutation |