Logs the full output of the 9-agent deep-dive run on 2026-05-05 to
docs/research/2026-05-05-agent-wave/. Pulls every actionable finding
into one indexed location so v0.5.32 planning has a paper trail.
Files:
docs/research/2026-05-05-agent-wave/README.md — index
docs/research/2026-05-05-agent-wave/01-...real-hardware.md — Plymouth + LUKS edge cases
docs/research/2026-05-05-agent-wave/02-...firstboot-ux.md — SDDM + first-boot UX
docs/research/2026-05-05-agent-wave/03-...spike-plan.md — bootc-image-builder 1-week spike
docs/research/2026-05-05-agent-wave/04-...tier-2.md — AppArmor + nftables + audit + homed
docs/research/2026-05-05-agent-wave/05-...launch.md — threat model + v0.7 launch checklist
docs/research/2026-05-05-agent-wave/06-...log-capture.md — virtio-9p host-share for anaconda logs
docs/research/2026-05-05-agent-wave/07-...skel-branding.md — /etc/skel gap audit
docs/research/2026-05-05-agent-wave/08-...ci-hardening.md — SHA-pin actions + SBOM + SLSA L3
docs/research/2026-05-05-agent-wave/09-...failure-modes.md — real-hardware pessimistic audit
Plus the prior linter-applied:
docs/ROADMAP.md — Lessons learned section, v0.5.32 active block,
v0.6 promotion of veilor-postinstall + veilor-doctor,
v0.7 bootc spike scheduled
docs/THREAT-MODEL.md — drafted by Agent 5; in/out scope, comparison
matrix, v0.7 launch checklist
Top blockers identified for v0.5.32 (cross-cited in README):
1. Suspend/resume wifi death (kernel.modules_disabled=1)
2. veilor-firstboot.service WantedBy=graphical.target
3. kernel-upgrade grub drift
4. USBGuard hash-rules problem (already learned on onyx)
5. firewalld blocks tailscale0
6. /etc/skel/ empty
7. virtio-9p log capture replaces broken virtio-serial path
Wave + verifier pattern (per ROADMAP lessons learned #4) validated:
9 parallel agents on distinct topics produced converging blocker
list. The same pattern landed v0.5.31 four-bug fix from the prior
4-agent verification wave on v0.5.30 outcome.
13 KiB
Roadmap
Versioned roadmap for veilor-os. Targets are intentionally short and testable. No fluff. Items in earlier versions are blockers for later ones unless explicitly noted.
For the historical record of what landed in each release, see
../CHANGELOG.md.
Lessons learned through v0.5.x install grind
Five things v0.5.27–31 changed about how we plan:
- Anaconda + RPM-6.0 +
--cmdlineis brittle — three install failures, kernel cmdline written to four places before one worked.--location=noneskipsCollectKernelArgumentsTask,kernel-installreads/etc/kernel/cmdlinenot/proc/cmdline, andtransaction_progress.pymasks real failures if patched too broadly. Justifies promoting the bootc-image-builder spike to v0.7. - Test procedure must gate every tag — v0.5.27 only surfaced four
bugs in one VM run because the run walked every step in order.
test/TESTING.mdandtest/test-runs/are now load-bearing. - Real hardware is not optional — VM catches install logic, not KMS / fbcon / firmware. Spare laptop + friend's laptop must run pre-tag, every time.
- Multi-agent debug waves work, but only with a verifier — the v0.5.31 four-bug fix came from a 4-agent verification wave on v0.5.30 outcome. Wave + verifier = signal; wave alone = noise.
- "We ask once, with sane defaults" is the distro UX — every
v0.5 install bug we shipped a workaround for (locale, hostname,
USBGuard policy, drivers) is something
veilor-postinstallcould ask the user about cleanly on first boot. That promotesveilor-postinstallfrom v0.6 background item to flagship.
v0.2 — green ISO + base hardening (DONE)
Reproducible CI build pipeline. UEFI+BIOS bootable live ISO from a single
kickstart. Single-prompt LUKS install. First-boot admin password flow.
Full overlay applied (sysctl, sshd, sudoers, tuned profiles, KDE black
theme, Fira Code, branded /etc/os-release). SELinux enforcing.
firewalld drop zone. fail2ban + auditd + USBGuard active. The build
chased five real bugs (DEST hardcoded, set -eu killing cp,
os-release symlink, missing admin user, LABEL= vs CDLABEL= in
livecd-tools) before greening.
Released v0.2.5 on 2026-05-01. CI on every push to main.
v0.5.27–v0.5.31 — install path stabilisation (DONE)
The bridge between v0.2 (greens at all) and v0.3 (looks polished). All
install-path bugs surfaced by the formal hybrid-VM test procedure
(test/TESTING.md). Five releases, ~hours of debug, three install
failures before greening.
- v0.5.27 (DONE) —
rd.luks.uuidviagrubby --update-kernel=ALL, GRUB rebrand,fbcon=nodefer, ASCII gum cursor. - v0.5.28 (DONE) — locale locked en_US.UTF-8, dropped updates repo,
patched anaconda
transaction_progress.pyto silenceConfiguring xxx.x86_64scroll, excluded man-db. - v0.5.29 (DONE) — narrowed anaconda patch (was masking real failures), LUKS UX, initramfs assertion. Five-fix bundle from 7-agent research wave.
- v0.5.30 (DONE) — broad error suppression, manual bootloader path, virtio log capture for post-mortem.
- v0.5.31 (DONE) —
--location=nonewas making anaconda skipCollectKernelArgumentsTask; kernel-install reads/etc/kernel/cmdlineas source of truth, veilor never wrote it, so BLS entries shipped with empty cmdline. Three-path write (/etc/kernel/cmdline+/etc/default/grub+ grubby) plus explicitkernel-install add.
v0.5.32 — next ship (active)
Outstanding from the grind, immediate priority for the next tag:
- End-to-end VM green run — v0.5.31 lands the kernel-cmdline fix
but no full hybrid-VM pass has signed it off. Run the procedure in
test/TESTING.mdto install + reboot + login, file the report intest/test-runs/, then tag. - Real-hardware run on the spare laptop — VM is necessary not sufficient. Friend's laptop is mate's-test, spare is ours. KMS, fbcon, USB controller, real-firmware Secure Boot only show up here.
- gum input render glitch — duplicate "Install", stray T in
password fields on linux fbcon. Replace
gum input --passwordwith bashread -srp; cosmetic only but visible on every install.
v0.3 — UX polish (in progress)
The visible polish layer that v0.2 deferred for build velocity.
- Plymouth black theme — boot splash matching the desktop. No Fedora
drum, no white flash.
assets/plymouth/veilor/. - SDDM theme — black login background, single-user prompt with
adminpre-filled, no userlist. - Konsole profile — black background, Fira Code, transparent panel off (no compositor cost on resume).
- Wallpaper SVG — flat black with subtle veilor wordmark, 1080p + 4K + ultrawide variants.
- Re-enable memory hygiene on installed system. v0.2.5 stripped
init_on_alloc=1 init_on_free=1from the live cmdline because they 5x'd KVM boot time. Re-add post-install viaveilor-firstbootso the installed system gets the protection without the ISO penalty. - USBGuard auto-snapshot on first boot. Currently the operator
runs
usbguard generate-policymanually. v0.3 wires this intoveilor-firstbootafter the password step (with a clear "plug in trusted devices first" prompt).
Target: this month. None of it is a kickstart change — pure overlay work.
v0.4 — distribution + signing
Get veilor-os to a state where the ISO is downloadable, verifiable, and trusted by Secure Boot without user shenanigans.
- GPG-signed releases. Tag → CI builds → CI signs ISO + sha256 with
veilor.org release key → GitHub Release artifact carries
.iso.asc. - Reproducible builds. Pin Fedora compose ID, lock package versions
via
dnf snapshotor equivalent, document how to verify two builds match. - Own MOK (Machine Owner Key) + sbsign for Secure Boot. Currently veilor-os relies on Fedora's signed shim chain. v0.4 ships our own MOK, signs the kernel + initramfs at build time, optionally enrols the MOK on first boot for users who want a cleaner trust path.
- ISO download mirror — static download page on veilor.org with current + previous release, sha256, gpg signature. Not an RPM mirror — veilor-os does not ship its own packages, only the spin configuration.
- Release process documented — tagging, CI, signing, mirror sync
in
docs/RELEASE.md.
v0.5 — hardening tier 2
Hardening that builds on v0.2's foundation. Each item is opt-in unless specified — defaults stay sane for a daily driver.
- AppArmor profiles in addition to SELinux. Stack-not-replace. Targeted at the browser, the mail client, and anything that touches attacker-controlled data. SELinux remains the primary MAC.
- systemd-homed — encrypted-per-user
~, suspend-aware, key unlocked at PAM login. Optional, opt-in via post-install helper. - nftables ruleset alongside firewalld defaults. Default firewalld policy stays drop; nftables provides advanced filtering for users who want it.
- Audit log shipping — opt-in
auditd-> remote syslog over TLS, for users running a central log aggregator. - Installer kickstart split — separate
veilor-os-install.ksfor installer ISO (real LUKS partitioning, not the live-rootfs simplification used in v0.2). Lets users install veilor-os as the primary OS without going through the live boot first. - Audit baseline — re-run the security audit (template in
security/audit-template.md) and target a lower risk score than v0.2.
v0.6 — ergonomics (PROMOTED — install grind proved we need this)
Smooth the operator experience so day-to-day work doesn't fight the
hardening. veilor-postinstall and veilor-doctor were v0.6 background
items — promoted to headline features after v0.5.27–31 made it
clear that "we ask once, with sane defaults" is what separates a
distro from a kickstart.
veilor-postinstall(PROMOTED — flagship of v0.6) — first-login welcome menu, EndeavourOS-style but cleaner. Single TUI screen: keyboard layout, locale (deferred from install per v0.5.28), hostname override, package presets (dev / media / homelab), drivers (NVIDIA / Intel / AMD), Bluetooth opt-in, USBGuard snapshot, audit baseline run,veilor-doctorfirst run. Each step skippable, runs once on first SDDM login, self-deletes the autostart after. This is the only UX feature that ships in v0.6 day one — everything else builds on it.veilor-doctor(PROMOTED — user-facing, not just dev tool) — the post-install audit. Walksgetenforce,mokutil --sb-state,firewall-cmd, fail2ban, USBGuard policy, sysctl drift, and reports drift from baseline. Runs fromveilor-postinstallon day one, then weekly viasystemd --usertimer. Plain-English output ("your firewall is OK", "USBGuard policy has 3 unknown devices"); not a JSON dump. Stretch: machine-readable mode forveilor-serverlater.veilor-update— wrapsdnf upgradeANDflatpak updatein one command. Perfeedback_system_update.md, partial-update is a recurring trap; veilor's update tool covers both by default. Adds pre-check (snapshot available?), auditd pause, post-update SELinux validation.- Opt-in installer ISO — flip from live-only to live + installer, user picks at boot menu. Installer uses the v0.5 kickstart with full LUKS + btrfs subvols + zram.
- First-boot UX — replace TTY password prompt with a small Plymouth-rendered dialog. Less raw.
- Bluetooth opt-in helper — single command to enable + bring up the daemon + add the user to the right group.
v0.7 — public flex + bootc spike
Take veilor-os out of "private repo, contained audience" mode. Order matters: people demand threat model FIRST when a security distro goes public, benchmarks come after.
- Threat model published (FIRST — gating item) — what veilor-os defends against, what it does not. Honest scope. No claim of anti-state-actor; concrete on lost-laptop, USB-attack, browser compromise, supply-chain. Reviewers will demand this before reading anything else.
- Public docs site — Hugo or mdBook on
veilor.org, generated fromdocs/. Single source of truth. - Repo public — flip GitHub visibility, announce.
- Comparison + benchmarks — published numbers vs stock Fedora KDE on cold boot, idle RAM, idle network egress, suspend/resume time. After threat model, not before.
- Press kit — wallpapers, logo, screenshots, feature one-liner.
bootc-image-builder spike (PROMOTED from v1.0+)
The v0.5.27–31 grind cost us hours on anaconda + RPM-6.0 +
--cmdline mode brittleness: three install failures, kernel-cmdline
written to four different places before one worked, transaction-progress
patches that masked real bugs. bootc-image-builder builds a
Containerfile once and gets a bootable image — no anaconda, no
kickstart, no %post --nochroot vs %post, no
CollectKernelArgumentsTask. A v0.7 spike (NOT v1.0) evaluates whether
the next major rev should rebase on it. Spike outcome determines
whether veilor-atomic (stretch goal) becomes the mainline.
v1.0 — production
The line where veilor-os is recommended for a non-author user as a daily driver.
- Multi-arch. x86_64 today; v1.0 ships aarch64 ISO too (laptops on ARM are real now). Build matrix in CI.
- LTS commitment — major versions tied to Fedora's release cadence, patch releases for security only, documented EOL per major.
- Recovery ISO — minimal rescue image with veilor tools (LUKS unlock, btrfs scrub, sysctl reset, fail2ban unban) for "I cannot log in to my system" days.
- TPM2 integration — sealed LUKS unlock against TPM2 PCRs (opt-in, default stays password). Ships as helper script, not silent default.
- Signed update channel — beyond GPG-signed ISOs, a signed metadata
repo so
veilor-doctorcan detect available updates without trusting Fedora's mirrorlists alone.
Stretch goals — not on the v0.x → v1.0 critical path
These are spin variants that share veilor-os DNA but need their own kickstart or build tool.
veilor-server— no KDE, no GUI, hardened headless Fedora for homelab / VPS (e.g. nullstone). Same overlay, different package set. Not blocked, but waits onveilor-doctormachine-readable mode (v0.6) so headless installs have a way to report drift without a TUI.veilor-kiosk— single-app Plasma session, locked-down user, read-only root. Not blocked.veilor-atomic— rpm-ostree / bootc-image-builder rebase. Status now depends on the v0.7 bootc spike: if the spike shows bootc fixes the anaconda-grind class of bugs,veilor-atomicbecomes the v1.0+ mainline rather than a stretch variant. If not, it stays a parallel track.