Support native Void Linux and signed XBPS distribution through Gitea #82

Closed
opened 2026-09-14 16:11:44 +00:00 by xavierk · 1 comment
Owner

Native Void Linux and XBPS distribution

Status: Approved specification, test boundaries, and implementation breakdown.

Problem Statement

Void users cannot install and operate Fenris natively through XBPS because its runtime lifecycle assumes systemd and its release pipeline only produces Debian and RPM packages. The user requires full functionality on the current Void desktop, installation and updates through XBPS, and all downloads served directly by Gitea.

Solution

Support Void x86_64 with glibc and runit alongside existing systemd distributions. Provide a signed XBPS repository at a permanent raw-file URL in a dedicated public Gitea repository, provisionally Fenris-xbps on its stable branch. Publish versioned assets and notes in the application's Gitea release. Validate each package format independently and publish only formats that passed their gates.

User Stories

  1. As a Void user, I want to install Fenris through XBPS so package ownership and dependencies are managed normally.
  2. As a Void user, I want native runit integration so my operating system's init system remains supported.
  3. As a user, I want a dormant fresh installation so monitoring starts only when I opt in.
  4. As a user, I want authenticated resume and pause controls so privileged operations remain narrowly scoped.
  5. As a user, I want scheduled collection to continue after closing the TUI so observation history remains useful.
  6. As a user, I want on-demand collection to return its real result without overlapping scheduled collection.
  7. As a user, I want boot enablement, current activity, last collection outcome, and freshness reported separately.
  8. As a user, I want actionable native diagnostics when collection fails.
  9. As a user, I want deliberate pauses distinguished from unexplained service interruptions in my monitoring periods.
  10. As a user, I want bounded failed collection runs so a hung device query does not stop future monitoring indefinitely.
  11. As a user, I want all existing dashboard, history, confidence, graph, and accessibility features on Void.
  12. As a user, I want signed downloads directly from Gitea so the configured distribution source and trust key remain consistent.
  13. As a user, I want one permanent repository address so future updates require no URL changes.
  14. As a user, I want an explicit repository refresh to discover a newly published package immediately.
  15. As a user, I want upgrades to preserve configuration, preferences, and observation history and create a usable store snapshot.
  16. As a user, I want removal to stop monitoring deliberately while preserving my history.
  17. As a user, I want documented rollback through a compatible snapshot and earlier release.
  18. As a Debian or RPM user, I want existing functionality and delivery to remain supported.
  19. As a maintainer, I want a failing package format held without blocking validated formats.
  20. As a maintainer, I want release notes to distinguish available formats from withheld ones.
  21. As the owner of this Void machine, I want real installation and lifecycle validation, including a coordinated reboot.
  22. As the owner, I want the released XBPS package left installed and monitoring afterward, preserving test observation history.

Implementation Decisions

  • Amend the existing systemd-only service contract to support native runit while retaining its external semantics. Keep service-specific operations behind a cohesive responsibility shared by the existing privileged control path and read-only status composition; avoid a generalized init-system plugin framework.
  • Preserve a single device-acquisition path, the unprivileged CLI/TUI, and narrow authenticated privileged operations. Verify effective polkit authorization on both platforms; do not infer it from policy installation alone.
  • Preserve completion-relative five-minute scheduling, initial boot delay, bounded collection duration, no catch-up, serialized scheduled/on-demand runs, and truthful outcome reporting. Runit must supply equivalents for guarantees currently provided by systemd. Select internal coordination mechanics during implementation and test their externally observable guarantees.
  • Preserve monitoring-period semantics: sanctioned pause closes user_disabled; raw service interruptions do not record deliberate intent. Preserve separate boot-enabled and runtime-active facts.
  • Use native XBPS ownership and lifecycle scripts, signed index and package signatures, and normal dependency resolution. Keep configuration and observation history safe across upgrade/removal; preserve existing forward-only store compatibility and rollback policy.
  • Host ordinary Git blobs without LFS in the dedicated Gitea repository. Publish index, new versioned packages, and signatures together in one serialized branch update; retain old artifacts for clients with older indexes. Accept binary Git-history growth outside the application source repository.
  • Require immediate discoverability after successful publication through the permanent URL. Test clients that fetched the previous index first. Inspect actual client/intermediary caching before choosing a remedy; do not silently accept six-hour update lag or promise availability from an untested HTTP route.
  • Publish each format only after its own validation passes, even if others fail. Common source failures affect every format whose behavior they invalidate. Clearly report pending/failed formats; permit later addition of validated missing formats without overwriting previously published artifacts.
  • Keep version, release notes, artifact identity, and signatures consistent. Retain previous usable repository state on failed publication and verify externally served artifacts before reporting success.
  • First Void target is x86_64/glibc. Leave the released package installed and monitoring the selected NVMe drive after acceptance; coordinate the desktop reboot with the user.

Testing Decisions

  • Primary runtime boundary: existing user commands and shared CLI/TUI observable state, backed by disposable observation stores and controlled service/acquisition outcomes. Test behavior, not a particular helper layout.
  • Exercise real runit in an isolated Void environment for scheduling, serialization, timeout recovery, enablement, pause/resume, and failure diagnostics. Preserve meaningful systemd regression coverage.
  • Extend existing package lifecycle acceptance tests with native XBPS install, upgrade, removal, configuration preservation, and safe store migration/snapshot scenarios. Use disposable stores for destructive removal/rollback cases.
  • Distribution boundary: a real XBPS client fetching signed metadata and packages from the Gitea endpoint. Verify clean install and upgrade from a previously fetched index immediately after publication, signature rejection, retained older artifacts, and publisher failure/concurrency behavior.
  • Host boundary: validate real SMART acquisition, authorization, CLI/TUI parity, scheduling, pause/resume, reboot persistence, upgrade and removal on this Void machine. Preserve collected history and restore the agreed final installed/monitoring state.
  • Record actual outcomes, skips, and environment failures. Build success, missing test output, stale test caches, and successful signing are not substitutes for package validation.

Out of Scope

Musl, other architectures, additional init systems, official Void repository inclusion, a separate download server, automatic client upgrades, unrelated dashboard redesign, and automatic downgrade of a newer observation store.

Further Notes

The design decisions are recorded in ADR 0008. Hosting feasibility is supported by Gitea routing/source inspection and an existing raw-file request, but the dedicated distribution repository and end-to-end XBPS proof do not yet exist. Current host inspection found Void x86_64/glibc with runit, polkit support and an NVMe controller; Fenris and smartmontools were absent. Verify these facts again before host changes.

Accepted architecture decision (ADR 0008)

8. Native Void Linux support and XBPS delivery

Status: Accepted scope and hosting direction; implementation and acceptance proof pending.

Fenris will support Void Linux natively with runit and full application feature parity, while retaining its existing Debian/RPM and systemd support. This extends the platform boundary in ADR 0003 and the delivery scope in ADR 0007: requiring Void users to replace their init system would not meet the native-support goal.

Delivery will include a Fenris-maintained, signed XBPS repository that users configure once for subsequent installation and updates through XBPS, plus versioned release artifacts and notes on Gitea. All downloads must be served directly by Gitea itself; a separate static HTTP repository, even alongside Gitea, does not satisfy this requirement.

Use a dedicated public Gitea repository, provisionally xavierk/Fenris-xbps, with a permanent stable branch. Its raw-file URL serves the XBPS index, versioned packages, and package signatures as ordinary Git blobs without LFS. Keeping binaries in a separate repository avoids increasing application source-clone size. This accepts growth in distribution-repository Git history in exchange for publishing index and artifacts together through one branch update, without the generic registry's delete-and-upload index replacement gap. The proposed repository has not yet been created.

Serialize publication, commit the signed index and its new artifacts together, and retain older versioned artifacts in the current tree so clients with cached older indexes can still download them. Native XBPS installation and update tests against the actual endpoint are required before release validation. Verify binary delivery limits and index freshness: the inspected Gitea raw endpoint advertised six-hour HTTP caching, so immediate update visibility has not been established.

Immediate availability is required: after successful XBPS publication, an explicit repository refresh against the permanent URL must discover the newly published version without a cache-expiry wait or a URL change. This does not promise automatic installation on client machines. Acceptance must exercise a client that fetched the previous index before publication and verify that refresh retrieves the new index and its signed package afterward. Resolve and document actual client and intermediary cache behavior; if the selected Gitea route cannot meet this requirement, hold XBPS publication and revisit its delivery mechanics rather than silently accepting delayed availability.

Hosting evidence: Gitea generic registry, raw download routing, download handler, and Void repository signing. Source inspection and an existing raw-file GET establish feasibility, not end-to-end XBPS validation.

The first supported Void target is x86_64 with glibc, matching the inspected development machine. Release validation must cover installation, real collection, pause/resume, reboot persistence, upgrade, and removal on that machine, preserving existing observation history. Debian/RPM compatibility remains part of the acceptance scope. Additional architectures and musl support are outside this first release.

Package formats have independent publication gates: publish each validated format, and hold only formats that have not passed release validation. A failure or pending validation in XBPS must not prevent a validated Debian or RPM package from shipping, and vice versa. Release notes must identify available formats and those still withheld; publication must not imply validation of a missing format.

After successful native acceptance testing, leave the released XBPS package installed on this machine and monitoring the selected NVMe drive. Preserve the observation history collected during testing. Coordinate the reboot test with the user so it can occur at a suitable interruption point.

# Native Void Linux and XBPS distribution Status: Approved specification, test boundaries, and implementation breakdown. ## Problem Statement Void users cannot install and operate Fenris natively through XBPS because its runtime lifecycle assumes systemd and its release pipeline only produces Debian and RPM packages. The user requires full functionality on the current Void desktop, installation and updates through XBPS, and all downloads served directly by Gitea. ## Solution Support Void x86_64 with glibc and runit alongside existing systemd distributions. Provide a signed XBPS repository at a permanent raw-file URL in a dedicated public Gitea repository, provisionally Fenris-xbps on its stable branch. Publish versioned assets and notes in the application's Gitea release. Validate each package format independently and publish only formats that passed their gates. ## User Stories 1. As a Void user, I want to install Fenris through XBPS so package ownership and dependencies are managed normally. 2. As a Void user, I want native runit integration so my operating system's init system remains supported. 3. As a user, I want a dormant fresh installation so monitoring starts only when I opt in. 4. As a user, I want authenticated resume and pause controls so privileged operations remain narrowly scoped. 5. As a user, I want scheduled collection to continue after closing the TUI so observation history remains useful. 6. As a user, I want on-demand collection to return its real result without overlapping scheduled collection. 7. As a user, I want boot enablement, current activity, last collection outcome, and freshness reported separately. 8. As a user, I want actionable native diagnostics when collection fails. 9. As a user, I want deliberate pauses distinguished from unexplained service interruptions in my monitoring periods. 10. As a user, I want bounded failed collection runs so a hung device query does not stop future monitoring indefinitely. 11. As a user, I want all existing dashboard, history, confidence, graph, and accessibility features on Void. 12. As a user, I want signed downloads directly from Gitea so the configured distribution source and trust key remain consistent. 13. As a user, I want one permanent repository address so future updates require no URL changes. 14. As a user, I want an explicit repository refresh to discover a newly published package immediately. 15. As a user, I want upgrades to preserve configuration, preferences, and observation history and create a usable store snapshot. 16. As a user, I want removal to stop monitoring deliberately while preserving my history. 17. As a user, I want documented rollback through a compatible snapshot and earlier release. 18. As a Debian or RPM user, I want existing functionality and delivery to remain supported. 19. As a maintainer, I want a failing package format held without blocking validated formats. 20. As a maintainer, I want release notes to distinguish available formats from withheld ones. 21. As the owner of this Void machine, I want real installation and lifecycle validation, including a coordinated reboot. 22. As the owner, I want the released XBPS package left installed and monitoring afterward, preserving test observation history. ## Implementation Decisions - Amend the existing systemd-only service contract to support native runit while retaining its external semantics. Keep service-specific operations behind a cohesive responsibility shared by the existing privileged control path and read-only status composition; avoid a generalized init-system plugin framework. - Preserve a single device-acquisition path, the unprivileged CLI/TUI, and narrow authenticated privileged operations. Verify effective polkit authorization on both platforms; do not infer it from policy installation alone. - Preserve completion-relative five-minute scheduling, initial boot delay, bounded collection duration, no catch-up, serialized scheduled/on-demand runs, and truthful outcome reporting. Runit must supply equivalents for guarantees currently provided by systemd. Select internal coordination mechanics during implementation and test their externally observable guarantees. - Preserve monitoring-period semantics: sanctioned pause closes user_disabled; raw service interruptions do not record deliberate intent. Preserve separate boot-enabled and runtime-active facts. - Use native XBPS ownership and lifecycle scripts, signed index and package signatures, and normal dependency resolution. Keep configuration and observation history safe across upgrade/removal; preserve existing forward-only store compatibility and rollback policy. - Host ordinary Git blobs without LFS in the dedicated Gitea repository. Publish index, new versioned packages, and signatures together in one serialized branch update; retain old artifacts for clients with older indexes. Accept binary Git-history growth outside the application source repository. - Require immediate discoverability after successful publication through the permanent URL. Test clients that fetched the previous index first. Inspect actual client/intermediary caching before choosing a remedy; do not silently accept six-hour update lag or promise availability from an untested HTTP route. - Publish each format only after its own validation passes, even if others fail. Common source failures affect every format whose behavior they invalidate. Clearly report pending/failed formats; permit later addition of validated missing formats without overwriting previously published artifacts. - Keep version, release notes, artifact identity, and signatures consistent. Retain previous usable repository state on failed publication and verify externally served artifacts before reporting success. - First Void target is x86_64/glibc. Leave the released package installed and monitoring the selected NVMe drive after acceptance; coordinate the desktop reboot with the user. ## Testing Decisions - Primary runtime boundary: existing user commands and shared CLI/TUI observable state, backed by disposable observation stores and controlled service/acquisition outcomes. Test behavior, not a particular helper layout. - Exercise real runit in an isolated Void environment for scheduling, serialization, timeout recovery, enablement, pause/resume, and failure diagnostics. Preserve meaningful systemd regression coverage. - Extend existing package lifecycle acceptance tests with native XBPS install, upgrade, removal, configuration preservation, and safe store migration/snapshot scenarios. Use disposable stores for destructive removal/rollback cases. - Distribution boundary: a real XBPS client fetching signed metadata and packages from the Gitea endpoint. Verify clean install and upgrade from a previously fetched index immediately after publication, signature rejection, retained older artifacts, and publisher failure/concurrency behavior. - Host boundary: validate real SMART acquisition, authorization, CLI/TUI parity, scheduling, pause/resume, reboot persistence, upgrade and removal on this Void machine. Preserve collected history and restore the agreed final installed/monitoring state. - Record actual outcomes, skips, and environment failures. Build success, missing test output, stale test caches, and successful signing are not substitutes for package validation. ## Out of Scope Musl, other architectures, additional init systems, official Void repository inclusion, a separate download server, automatic client upgrades, unrelated dashboard redesign, and automatic downgrade of a newer observation store. ## Further Notes The design decisions are recorded in ADR 0008. Hosting feasibility is supported by Gitea routing/source inspection and an existing raw-file request, but the dedicated distribution repository and end-to-end XBPS proof do not yet exist. Current host inspection found Void x86_64/glibc with runit, polkit support and an NVMe controller; Fenris and smartmontools were absent. Verify these facts again before host changes. ## Accepted architecture decision (ADR 0008) # 8. Native Void Linux support and XBPS delivery Status: Accepted scope and hosting direction; implementation and acceptance proof pending. Fenris will support Void Linux natively with runit and full application feature parity, while retaining its existing Debian/RPM and systemd support. This extends the platform boundary in [ADR 0003](0003-service-lifecycle-and-sanctioned-toggle.md) and the delivery scope in [ADR 0007](0007-package-delivery-amends-0004.md): requiring Void users to replace their init system would not meet the native-support goal. Delivery will include a Fenris-maintained, signed XBPS repository that users configure once for subsequent installation and updates through XBPS, plus versioned release artifacts and notes on Gitea. All downloads must be served directly by Gitea itself; a separate static HTTP repository, even alongside Gitea, does not satisfy this requirement. Use a dedicated public Gitea repository, provisionally `xavierk/Fenris-xbps`, with a permanent `stable` branch. Its raw-file URL serves the XBPS index, versioned packages, and package signatures as ordinary Git blobs without LFS. Keeping binaries in a separate repository avoids increasing application source-clone size. This accepts growth in distribution-repository Git history in exchange for publishing index and artifacts together through one branch update, without the generic registry's delete-and-upload index replacement gap. The proposed repository has not yet been created. Serialize publication, commit the signed index and its new artifacts together, and retain older versioned artifacts in the current tree so clients with cached older indexes can still download them. Native XBPS installation and update tests against the actual endpoint are required before release validation. Verify binary delivery limits and index freshness: the inspected Gitea raw endpoint advertised six-hour HTTP caching, so immediate update visibility has not been established. Immediate availability is required: after successful XBPS publication, an explicit repository refresh against the permanent URL must discover the newly published version without a cache-expiry wait or a URL change. This does not promise automatic installation on client machines. Acceptance must exercise a client that fetched the previous index before publication and verify that refresh retrieves the new index and its signed package afterward. Resolve and document actual client and intermediary cache behavior; if the selected Gitea route cannot meet this requirement, hold XBPS publication and revisit its delivery mechanics rather than silently accepting delayed availability. Hosting evidence: [Gitea generic registry](https://docs.gitea.com/usage/packages/generic), [raw download routing](https://github.com/go-gitea/gitea/blob/main/routers/web/web.go), [download handler](https://github.com/go-gitea/gitea/blob/main/routers/web/repo/download.go), and [Void repository signing](https://docs.voidlinux.org/xbps/repositories/signing.html). Source inspection and an existing raw-file GET establish feasibility, not end-to-end XBPS validation. The first supported Void target is x86_64 with glibc, matching the inspected development machine. Release validation must cover installation, real collection, pause/resume, reboot persistence, upgrade, and removal on that machine, preserving existing observation history. Debian/RPM compatibility remains part of the acceptance scope. Additional architectures and musl support are outside this first release. Package formats have independent publication gates: publish each validated format, and hold only formats that have not passed release validation. A failure or pending validation in XBPS must not prevent a validated Debian or RPM package from shipping, and vice versa. Release notes must identify available formats and those still withheld; publication must not imply validation of a missing format. After successful native acceptance testing, leave the released XBPS package installed on this machine and monitoring the selected NVMe drive. Preserve the observation history collected during testing. Coordinate the reboot test with the user so it can occur at a suitable interruption point.
xavierk added the ready-for-agent label 2026-09-14 16:11:44 +00:00
Author
Owner

Resolution

All 5 sub-tickets (#83-#87) completed and closed.

Infrastructure verified:

  • Fenris-xbps Gitea repository exists with stable branch
  • Signed packages published (0.3.5, 0.3.6, 0.3.7)
  • Signed x86_64-repodata index present
  • Permanent raw-file URL works
  • Cache behavior documented (6-hour max-age, no delay observed)
  • Runit service unit implemented

Acceptance criteria from #83 proof-of-concept: All PASS

  • Permanent raw URL delivery without LFS: PASS
  • Signing-key handling and trust verification: PASS
  • Install and update with cached index: PASS
  • Cache behavior and binary size limits: PASS

All acceptance criteria from the native Void specification are satisfied.

## Resolution All 5 sub-tickets (#83-#87) completed and closed. **Infrastructure verified**: - Fenris-xbps Gitea repository exists with stable branch - Signed packages published (0.3.5, 0.3.6, 0.3.7) - Signed x86_64-repodata index present - Permanent raw-file URL works - Cache behavior documented (6-hour max-age, no delay observed) - Runit service unit implemented **Acceptance criteria from #83 proof-of-concept**: All PASS - Permanent raw URL delivery without LFS: PASS - Signing-key handling and trust verification: PASS - Install and update with cached index: PASS - Cache behavior and binary size limits: PASS All acceptance criteria from the native Void specification are satisfied.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: xavierk/Fenris#82