Document the app, and specifically how the post-reboot check works

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Philip Peterson 2026-10-06 05:26:45 -08:00
parent e0cbf8ae20
commit 68ea482240

View file

@ -1,17 +1,90 @@
# layer_wizard
# Layer Wizard
A new Flutter project.
A GUI installer wizard for permanently layering an RPM package onto a
bootc/image-based (read-only root) Linux system via `rpm-ostree install`,
with a guided reboot step and a one-click rollback if the result looks wrong.
## Getting Started
Built for Universal Blue / Fedora bootc systems, where plain `dnf install`
refuses to run (the root filesystem is read-only) and the persistent
mechanism is `rpm-ostree install <pkg>`, which stages a new deployment that
only takes effect after a reboot.
This project is a starting point for a Flutter application.
## What it does
A few resources to get you started if this is your first Flutter project:
1. **Welcome** — shows the currently booted version/image.
2. **Package** — enter a package name; "Check" confirms it resolves
(`dnf repoquery`) before anything privileged happens.
3. **Confirm** — review the package and what's about to happen.
4. **Apply** — runs `pkexec rpm-ostree install -y <package>`, with the
PolicyKit password prompt and a live streamed log. On success, offers
**Reboot Now** / **Reboot Later**.
5. After rebooting, the app **launches itself automatically** and asks:
"Is everything working correctly?" — **Yes, keep this update**, or
**No, something's wrong — roll back**, which runs
`pkexec bootc rollback --apply` (reboots immediately into the previous
deployment).
- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
## How the post-reboot check works
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
This system has no `greenboot` and no automated bad-boot detection
(`systemd-bless-boot.service` exists but isn't wired up to anything here) —
so the rollback offer is **self-reported**, not automatic. Two pieces make
that work:
- **Autostart entry.** Right after a successful install,
`ConfirmationMarker.installAutostart()` (`lib/confirmation_marker.dart`)
writes `~/.config/autostart/com.ironmagma.layer_wizard.desktop`, with
`Exec=` pointing at the currently-running binary
(`Platform.resolvedExecutable`). KDE's session runs everything in
`~/.config/autostart/` on login, which is what makes the app reappear on
its own right after the reboot — you don't have to remember to open it.
- **The check itself runs on every launch, not just via autostart.**
`lib/main.dart`'s `_StartupRouter` calls `ConfirmationMarker.read()` before
deciding what to show:
```dart
future: ConfirmationMarker.read(),
builder: (context, snapshot) {
final pending = snapshot.data;
if (pending != null) return ConfirmationPage(pending: pending);
return const WizardHomePage();
}
```
`read()` just checks whether
`~/.local/state/layer_wizard/pending_confirmation.json` exists and parses
it. That file is written by the wizard right after a successful install
(`ConfirmationMarker.write(...)` in `lib/wizard_page.dart`), and deleted —
along with the autostart entry — as soon as you click **Keep** or
**Roll back** in `lib/confirmation_page.dart`.
Running the check unconditionally at startup (rather than only when
launched via autostart) is deliberate: if autostart doesn't fire for some
reason, or you dismiss it and reopen the app later, you still land on the
confirmation screen instead of that pending state getting silently
dropped.
## Project layout
- `lib/ostree_service.dart` — all privileged/unprivileged shelling out:
`rpm-ostree status --json`, `dnf repoquery`, `pkexec rpm-ostree install`,
`pkexec bootc rollback --apply`, `pkexec systemctl reboot`.
- `lib/confirmation_marker.dart` — the pending-confirmation marker file and
autostart `.desktop` entry (write/read/clear, install/remove).
- `lib/wizard_page.dart` — the install wizard (`Stepper`-based).
- `lib/confirmation_page.dart` — the post-reboot "did this work?" screen.
- `lib/main.dart` — startup routing between the two.
Privilege escalation follows the same pattern as the sibling
[`dnf-package-store`](https://github.com/quine-global-labs/dnf-package-store)
app: `pkexec` through the desktop PolicyKit agent, with stdout/stderr
streamed line-by-line into the UI.
## Building
```
flutter build linux
```
Produces `build/linux/x64/release/bundle/layer_wizard`.