moonset/CLAUDE.md
nevaforget 5a6900e85a fix: address audit findings — polling, symlinks, validation, wallpaper removal (v0.7.0)
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)
2026-03-28 23:09:29 +01:00

2.5 KiB

Moonset

Name: Hekate (Göttin der Wegkreuzungen — passend zum Power-Menu, das den Weg der Session bestimmt)

Projekt

Moonset ist ein Wayland Session Power Menu, gebaut mit Rust + gtk4-rs + gtk4-layer-shell. Teil des Moonarch-Ökosystems. Per Keybind aufrufbares Overlay mit 5 Aktionen: Lock, Logout, Hibernate, Reboot, Shutdown.

Tech-Stack

  • Rust (Edition 2024), gtk4-rs 0.11, glib 0.22
  • gtk4-layer-shell 0.8 für Wayland Layer Shell (OVERLAY Layer)
  • cargo test für Unit-Tests

Projektstruktur

  • src/ — Rust-Quellcode (main.rs, power.rs, i18n.rs, config.rs, users.rs, panel.rs)
  • resources/ — GResource-Assets (style.css, default-avatar.svg)
  • config/ — Beispiel-Konfigurationsdateien

Kommandos

# Tests ausführen
cargo test

# Release-Build
cargo build --release

# Power-Menu starten (in Niri-Session)
LD_PRELOAD=/usr/lib/libgtk4-layer-shell.so ./target/release/moonset

Architektur

  • main.rs — Entry Point, GTK App, Layer Shell Setup, Multi-Monitor, systemd-Journal-Logging, Debug-Level per MOONSET_DEBUG Env-Var, zentrale GRESOURCE_PREFIX-Konstante
  • power.rs — 5 Power-Action-Wrapper mit absoluten Pfaden und 30s Timeout (lock, logout, hibernate, reboot, shutdown)
  • i18n.rs — Locale-Erkennung und String-Tabellen (DE/EN)
  • config.rs — TOML-Config + Wallpaper-Fallback
  • panel.rs — GTK4 UI (Action-Buttons, Inline-Confirmation, WallpaperWindow)
  • users.rs — User-Erkennung, Avatar-Loading (AccountsService, ~/.face, GResource-Fallback)
  • resources/style.css — GTK-Theme-Colors für Konsistenz mit dem aktiven Desktop-Theme

Design Decisions

Siehe DECISIONS.md für das vollständige Entscheidungsprotokoll.

Kurzfassung der wichtigsten Entscheidungen:

  • OVERLAY statt TOP Layer: Waybar liegt auf TOP, moonset muss darüber
  • Niri-spezifischer Logout (niri msg action quit): Moonarch setzt fest auf Niri
  • Einmal-Start per Keybind: Kein Daemon, GTK application_id verhindert Doppelstart
  • System-Icons: Adwaita/Catppuccin liefern alle benötigten symbolischen Icons
  • Lock ohne Confirmation: Lock ist sofort reversibel, braucht kein Confirm
  • Absolute Pfade für Binaries: /usr/bin/systemctl etc. statt relativer Pfade (Security)
  • GResource-Bundle: CSS und Default-Avatar sind in die Binary kompiliert (Wallpaper kommt vom Dateisystem)
  • Async Power Actions: glib::spawn_future_local + gio::spawn_blocking mit 30s Timeout
  • Journal-Logging: systemd-journal-logger statt File-Logging — journalctl -t moonset, Debug-Level per MOONSET_DEBUG Env-Var