fix: correct false breakage detection for flavored packages and config changes
Two bugs caused the UI to incorrectly warn about dependency breakages:
1. dryUpdate (version path): Flavored package versions (e.g. #knots:27.0.0:0)
failed exver.satisfies() against flavorless ranges (e.g. >=26.0.0) due to
flavor mismatch. Now checks the manifest's `satisfies` declarations,
matching the pattern already used in DepErrorService. Added `satisfies`
field to PackageVersionInfo so it's available from registry data.
2. checkConflicts (config path): fast-json-patch's compare() treated missing
keys as conflicts (add ops) and used positional array comparison, diverging
from the backend's conflicts() semantics. Replaced with a conflicts()
function that mirrors core/src/service/action.rs — missing keys are not
conflicts, and arrays use set-based comparison.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: unified restart notification with reason-specific messaging
Replace statusInfo.updated (bool) with serverInfo.restart (nullable enum)
to unify all restart-needed scenarios under a single PatchDB field.
Backend sets the restart reason in RPC handlers for hostname change (mdns),
language change, kiosk toggle, and OS update download. Init clears it on
boot. The update flow checks this field to prevent updates when a restart
is already pending.
Frontend shows a persistent action bar with reason-specific i18n messages
instead of per-feature restart dialogs. For .local hostname changes, the
existing "open new address" dialog is preserved — the restart toast
appears after the user logs in on the new address.
Also includes migration in v0_4_0_alpha_23 to remove statusInfo.updated
and initialize serverInfo.restart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix broken styling and improve settings layout
* refactor: move restart field from ServerInfo to ServerStatus
The restart reason belongs with other server state (shutting_down,
restarting, update_progress) rather than on the top-level ServerInfo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix PR comment
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Aiden McClelland <me@drbonez.dev>
Adds a VPS restart button to the settings page, above logout. Shows a
spinner while the RPC completes, then a dialog telling the user to wait
1-2 minutes and refresh.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- COW snapshot (cp --reflink=always) of package volumes before
install/update; restore on failure, remove on success
- Automatic ext4→btrfs conversion via btrfs-convert during disk attach
with e2fsck pre-check and post-conversion defrag
- Probe package-data filesystem during setup.disk.list (on both disk
and partition level) so the UI can warn about ext4 conversion
- Setup wizard preserve-overwrite dialog shows ext4 warning with
backup acknowledgment checkbox before allowing preserve
Adds stack overflow backtraces, debug info compilation, and SSH password
auth for development. Reduces shutdown timeouts from 60s to 100ms for
faster iteration. Fixes race condition in NetService cleanup.
Update version references from Angular 20 to Angular 21 and Taiga UI to
Taiga UI 5 across architecture docs. Update web/CLAUDE.md with improved
Taiga golden rules: prioritize MCP server for docs, remove hardcoded
component examples in favor of live doc lookups.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use generated TS types for tunnel API params and data models
- Simplify API service methods to use typed RPC calls
- Update port forward UI for optional labels
Generate DKMS MOK key pair during OS install, sign all unsigned kernel
modules, and enroll the MOK certificate using the user's master password.
On reboot, MokManager prompts the user to complete enrollment. Re-enrolls
on every boot if the key exists but isn't enrolled yet. Adds setup wizard
dialog to inform the user about the MokManager prompt.
When a restart is requested while the service is already restarting
(stopped but not yet started), set restart_again so the actor will
perform another stop→start cycle after the current one completes.