Skip to content

Make Debian eligible: a version floor of 12, and a reason in is_supported where there is none #238

Description

@vladimirrott

docs/distro-support.md:120 already promises this (this issue said line 91 when it was filed; the row has been at 120 the whole time):

| Debian stable/testing | Planned after Ubuntu hardening |

Ubuntu hardening is where it was meant to be: three LTS releases validated at 79/79 on live VMs with committed replay twins. This issue is the follow-through.

What already exists

Debian is not an unrecognised distro. It is a parsed, first-class variant that is deliberately refused:

  • DistroId::Debian { version: Option<u32> } (crates/sysknife-core/src/distro.rs:142)
  • detect_debian parses VERSION_ID into that field (distro.rs:453)
  • family() already returns DistroFamily::Debian for it (distro.rs:205)
  • a Debian 12 bookworm fixture and its parse and detect tests exist (distro.rs:643, :764, :958)
  • Linux Mint and Pop!_OS already fall back to the Debian family via ID_LIKE

The single line that refuses it (distro.rs:252):

Self::UbuntuCore { .. } | Self::Debian { .. } | Self::Other { .. } => false,

Note what the doc comment above it justifies and what it does not. Pre-20.04 Ubuntu is excluded because it stops receiving security updates. UbuntuCore is excluded structurally, having no apt and a read-only root. Plain Fedora stays detectable so the planner can explain the gap. Debian is given no reason at all. It sits in that arm because nothing has needed it to be elsewhere.

Why it is cheap

Of the 67 Debian-family actions, 57 run on Debian unchanged, and all 97 All
actions already do. That is 154 of 189, ≈ 81.5 %, with no new action code. #237
did the inventory and the list surgery, and it merged as #384 today, so nothing
blocks this now.

Recounted 2026-09-09 at 5673d20. This paragraph said 43 actions and 140
of 189 when it was filed. #237 split the fences, so the 57 now falls out of
the constants directly: DEBIAN_ONLY_ACTIONS (19) plus
NON_CANONICAL_ON_FEDORA (38), leaving behind the 10 in
UBUNTU_ONLY_ACTIONS. The three sets are disjoint and their union is exactly
the 67.

$ python3 - <<'PY'
import re, pathlib, collections
rows=[l for l in pathlib.Path("docs/action-reference.md").read_text().splitlines()
      if re.match(r'^\|\s*`[A-Za-z0-9_]+`\s*\|', l)]
tally=collections.Counter(); noclass=[]
for l in rows:
    fields=[f.strip() for f in l.split('|')]
    hits=[f for f in fields if f in ("All","Ubuntu","Fedora")]
    if len(hits)==1: tally[hits[0]]+=1
    else: noclass.append((fields[1], hits))
print("action rows:", len(rows))
print(dict(tally), "sum:", sum(tally.values()))
print("unclassified:", len(noclass))
PY
action rows: 189
{'Fedora': 25, 'All': 97, 'Ubuntu': 67} sum: 189
unclassified: 0
$ python3 - <<'PY'
import re,pathlib
src=pathlib.Path("crates/sysknife-core/src/action_family.rs").read_text()
def const(name):
    m=re.search(r'pub const '+name+r': &\[&str\] = &\[(.*?)\];', src, re.S)
    return set(re.findall(r'"([A-Za-z0-9_]+)"', m.group(1)))
d,u,n,f=const("DEBIAN_ONLY_ACTIONS"),const("UBUNTU_ONLY_ACTIONS"),const("NON_CANONICAL_ON_FEDORA"),const("FEDORA_ONLY_ACTIONS")
print("sizes", len(d),len(u),len(n),len(f))
print("pairwise overlaps", len(d&u), len(d&n), len(u&n))
print("union of the three", len(d|u|n))
print("runs on Debian unchanged (debian_only + non_canonical)", len(d|n))
PY
sizes 19 10 38 25
pairwise overlaps 0 0 0
union of the three 67
runs on Debian unchanged (debian_only + non_canonical) 57

Recount against the constants rather than trusting either figure, and say in
the PR which number you got. Whether all 57 belong in a Debian support claim
is a judgement about apt behaviour on bookworm, not arithmetic.

The version floor, and the decision it needs

Ubuntu's floor is major >= 20 (the constant at distro.rs:36, the comparison at distro.rs:251) on the stated rationale that older releases stop receiving security updates. Applying the same rule to Debian, with dates from Debian's own release pages:

release full support ended LTS ends eligible under the Ubuntu rule?
11 bullseye 2024-08-14 2026-08-31 no, LTS ended on 2026-08-31
12 bookworm 2026-07-11 2028-06-30 yes, in LTS
13 trixie 2028-08-09 2030-06-30 yes, current stable

So the floor is 12, and OLDEST_SUPPORTED_DEBIAN alongside its Ubuntu sibling is the natural shape.

The part that needs your call: version is Option<u32> because Debian testing and sid publish no VERSION_ID at all, so both parse to None. Debian's security team does not support sid. Refusing None is consistent with the security-updates rationale and is what I would do, but it means Debian stable/testing in the support matrix becomes stable-only, and that row should then be reworded.

Scope

  • Add OLDEST_SUPPORTED_DEBIAN: u32 = 12 and give Debian { version } its own arm comparing against it, which also closes a standing gap: the parsed version is currently never compared by any gate, so Debian 11, 12 and 13 are indistinguishable to the whole tree.
  • Decide and encode the None case.
  • Extend the doc comment on is_supported to state Debian's reason, the way it does for the other three.
  • Invert unsupported_debian (distro.rs:1094), which asserts Debian { version: Some(12) } is unsupported. It is a real test, not a vacuous one, so it will fail and should.
  • Add os-release fixtures for trixie and for a no-VERSION_ID testing image, following the bookworm fixture at :643.
  • Update docs/distro-support.md: the eligibility prose, the tier row, and the wording of the Debian stable/testing line.

Validation before claiming support

Eligibility is not validation, and this repo keeps those apart deliberately. A Debian row should not read Validated until the story suite has run on it, which means ubuntu-vm.sh needs a Debian target or a sibling script. Expect real failures on the first run rather than a clean pass: NetplanGetConfig and GetAuthorizedKeys already fail on stock Ubuntu 24.04 for permission reasons, and Debian's firewall default is nftables rather than ufw (#239).

Recording a live run needs provider credentials, so comment here before starting that part.

Difficulty

medium. The code change is small and the judgement calls plus the validation run are the work.

Getting started

CONTRIBUTING.md has the build and test commands, and docs/distro-support.md explains the eligibility-versus-validation split. No CLA and no copyright waiver. The project is MIT.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is neededmediumDifficulty: needs familiarity with one subsystemtwir-listedListed in a This Week in Rust CfP. Do not offer to anyone until that issue publishes.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions