- users::User: drop the unused `uid` field and its getuid() assignment.
The compiler dead_code warning is gone, and the synthetic `u32::MAX`
sentinel in the panel fallback is obsolete too.
- panel: surface a log::warn! when dirs::home_dir() returns None instead
of silently falling back to an empty PathBuf that would make avatars
look for .face in the current working directory.
- Apply three clippy suggestions: two collapsible if-let + && chains in
users::get_avatar_path_with and config::resolve_background_path_with,
and a redundant closure in panel::execute_action's spawn_blocking.
- main: require MOONSET_DEBUG=1 to escalate log verbosity — mere
presence of the var must not dump path info into the journal.
- power: RAII DoneGuard sets done=true on every wait() exit path, so the
timeout thread no longer sleeps its full 30 s holding a spawn_blocking
slot when child.wait() errors. A separate timed_out AtomicBool marks
our own SIGKILL so we do not misclassify an external OOM-kill. Memory
ordering on the flags is now Release/Acquire.
- i18n: detect_locale now reads LC_ALL, LC_MESSAGES, LANG in POSIX
priority order before falling back to /etc/locale.conf, so systems
installed in English with LC_ALL=de_DE.UTF-8 pick up the correct UI.
- panel: execute_action desensitizes button_box on entry and re-enables
it on error paths, so double-click or keyboard repeat cannot fire the
same power action twice.
- config: accept_wallpaper helper applies an extension allowlist (jpg,
jpeg, png, webp) plus symlink rejection and a 10 MB size cap, applied
to both the user-configured path and the Moonarch ecosystem fallback.
Bounds worst-case decode latency and narrows the gdk-pixbuf parser
attack surface.
Piping stdout without draining while blocking in child.wait() risks deadlock
if a command writes more than one OS pipe buffer (~64 KB on Linux). Current
callers (systemctl, niri msg, loginctl) stay well under that, but the
structure was fragile. stdout is now discarded; stderr continues to be
captured for error reporting.
After cancelling a confirmation prompt, the focused widget was removed
from the tree without restoring focus to the action buttons. With
layer-shell exclusive keyboard mode, GTK does not recover focus
automatically — the UI became keyboard-unreachable.
- Replace canonicalize() with symlink_metadata + is_file + !is_symlink for avatar
lookup (prevents symlink traversal to arbitrary files)
- Fix blur padding offset from (0,0) to (-pad,-pad) to prevent edge darkening
- Add MAX_BLUR_DIMENSION (1920px) downscale before GPU blur
- Validate blur per config source (invalid user value preserves system default)
- Wallpaper: use symlink_metadata + is_file + !is_symlink in resolve_background_path
Colloid-Catppuccin theme loaded via ~/.config/gtk-4.0/gtk.css at
PRIORITY_USER (800) was overriding moonset's PRIORITY_APPLICATION (600),
causing action buttons to lose their circular border-radius.
- Use STYLE_PROVIDER_PRIORITY_USER for app CSS provider
- Replace border-radius: 50% with 9999px (GTK4 CSS percentage quirk)
GskBlurNode samples pixels outside texture bounds as transparent,
causing visible darkening at wallpaper edges. Fix renders the texture
with 3x-sigma padding before blur, then clips back to original size.
Three parallel audits (quality, performance, security) identified issues
across the codebase. This commit addresses all remaining findings:
- Replace busy-loop polling in run_command with child.wait() + timeout thread
- Canonicalize ~/.face and AccountsService avatar paths to prevent symlink abuse
- Add detect_locale_with() DI function for testable locale detection
- Move config I/O from activate() to main() to avoid blocking GTK main loop
- Validate background_blur range (0–200), reject invalid values with warning
- Remove embedded wallpaper from GResource — moonarch provides it via filesystem
(binary size ~3.2MB → ~1.3MB)
Replace env_logger with systemd-journal-logger for consistent logging
across moonset/moonlock/moongreet. Add MOONSET_DEBUG env var and debug
statements across all modules. Also includes shared blur cache for
multi-monitor and detached moonlock spawn for lock action.
Replace image crate + disk cache blur with GPU-side GskBlurNode,
symmetric with moonlock and moongreet. Removes ~15 transitive
dependencies and ~160 lines of caching code. Blur now happens once
on the GPU at widget realization — zero startup latency, no cache
management needed.
- Fix BGRA→RGBA channel swap in apply_blur so image::RgbaImage semantics
match the actual pixel data from GDK texture download
- Logout now calls app.quit() like lock does, via new quit_after field on
ActionDef (replaces fragile magic string comparison)
- Log TOML parse errors to stderr instead of silently ignoring
- Remove pointless zlib compression of JPEG wallpaper in GResource
- Add tests for quit_after behavior and config error handling
Add CHANGELOG documenting all changes since 0.1.0 and the initial
release. Add DECISIONS.md as an architectural decision log. Update
CLAUDE.md to reflect current architecture. Bump to 0.1.1 for the
security and correctness fixes in the previous commit.
Feature-parity with Python v0.2.0. Same CSS, same UI, same actions.
Single 3.1 MB binary with embedded resources (CSS, wallpaper, avatar).
Modules: power.rs, i18n.rs, config.rs, users.rs, panel.rs, main.rs
45 unit tests passing. Python sources retained as reference.