76 Commits
Author SHA1 Message Date
nevaforget e513917eb8 Document the session discovery paths
Update PKGBUILD version / update-pkgver (push) Successful in 1s
v0.10.2
2026-08-07 15:55:32 +02:00
nevaforget 65a7a1ce99 Resolve helper programs and session dirs without FHS paths
systemctl was invoked as /usr/bin/systemctl, and session directories were
fixed to /usr/share. Both assume an FHS layout and fail on NixOS.

Programs now resolve via PATH; session directories walk XDG_DATA_DIRS with
/usr/share as fallback. Behaviour on Arch is unchanged.
2026-08-07 13:24:38 +02:00
nevaforget 7c9d5b182e Match nologin shells by file name, not full path
The nologin filter compared against fixed FHS paths, so accounts whose
shell lives elsewhere passed through. On NixOS the 32 nixbld build users
have UIDs in the 30001-30032 range and a shell at
/run/current-system/sw/bin/nologin, and were listed as login candidates.

Comparing the file name instead covers every distribution layout.
2026-08-07 13:03:41 +02:00
nevaforget 269caa49e2 docs: translate CLAUDE.md to English
Per the committed=English rule.
2026-06-16 10:46:13 +02:00
nevaforget 9b1b6d1231 ci: switch update-pkgver to tag-trigger (no-suffix pkgname) 2026-06-10 18:23:23 +02:00
nevaforget 2525496162 refactor: power-confirm via PowerAction table (v0.10.1)
Replace the two hand-wired reboot/shutdown handlers and the loose-param
show_power_confirm with a PowerAction table + create_power_button factory,
mirroring moonset's ActionDef pattern. Couples icon/prompt/error/action so
a mismatched prompt/action pair is unrepresentable.

Restore the in-flight re-trigger guard via power_box.set_sensitive(false)
(re-enabled on failure), superseding the v0.10.0 "no guard" tradeoff.
v0.10.1
2026-06-02 14:31:31 +02:00
nevaforget 3b7d917356 feat: confirm dialog before power actions (v0.10.0)
Reboot/shutdown buttons triggered immediately on click. Now show an
inline confirmation prompt, mirroring moonlock's show_power_confirm.

- i18n: reboot_confirm, shutdown_confirm, confirm_yes, confirm_no (DE/EN)
- greeter: confirm_area in login_box, handlers route through
  show_power_confirm/dismiss_power_confirm; execute_power_action drops
  the now-redundant button-disable guard
- style: .confirm-label/-yes/-no classes
v0.10.0
2026-06-02 13:53:28 +02:00
nevaforget 1c0f0f8f27 feat: apply cursor theme via GtkSettings (v0.9.0)
GTK4 under greetd does not honour XCURSOR_THEME reliably, so the greeter
showed the wrong cursor over GTK widgets on some machines. Set
gtk-cursor-theme-name / -size on GtkSettings from new [appearance] config
fields (cursor-theme, cursor-size), mirroring the gtk-theme handling and
reusing is_valid_gtk_theme validation.

Salvaged from commit 29ce185 — tagged v0.9.0 on 2026-04-24 but never
pushed. The orphan branch's keyboard refactor (v0.10.0) is discarded,
superseded by the v0.8.7 single-window fix.
v0.9.0
2026-06-02 12:58:59 +02:00
nevaforget b3fa3fea0c fix: power buttons via systemctl, single greeter window (v0.8.7)
Reboot/shutdown buttons always failed: power.rs called `loginctl
reboot|poweroff`, but loginctl has no such verbs (systemd 260) — those
belong to systemctl. moonlock/moonset already used systemctl; moongreet
was the outlier. Switch to `systemctl --no-ask-password reboot|poweroff`.

The multi-monitor greeter gave Exclusive keyboard only to the first
monitor's window, so a user focused on any other output could not type
the password. Drop the per-monitor loop + hotplug; create one window on
the focused output (no set_monitor) with Exclusive keyboard.

Polkit rule kept as a harmless safety net (it was never the blocker;
CanReboot returns yes). The missing journal errors were not a logging
bug — they were lost to a hard power-cut before journald synced.
v0.8.7
2026-06-02 12:46:13 +02:00
nevaforget 1167b8056a fix: audit LOW fixes — stdout null, utf-8 path, debug value, hidden sessions (v0.8.6)
- power::run_command: .stdout(Stdio::null()) — the pipe was never drained,
  structurally fragile even if no current caller hits it.
- config: replace to_string_lossy() on relative wallpaper paths with
  to_str() + log::warn, so non-UTF-8 paths are dropped cleanly instead
  of being mangled into unopenable U+FFFD strings.
- main: require MOONGREET_DEBUG=1 to raise verbosity. Mere presence of
  the var must not leak socket paths, usernames, and auth round counts
  into the journal.
- sessions: parse Hidden= and NoDisplay= keys, skip entries marked true.
  Keeps disabled or stub .desktop files out of the session dropdown.
v0.8.6
2026-04-24 14:08:35 +02:00
nevaforget c91923676e fix: audit MEDIUM fixes — FP race, async avatar, symlink, FD leak (v0.8.5)
- i18n test: assert four previously-missing string fields so future locales
  cannot ship empty strings unnoticed.
- greeter: atomic check-and-set fingerprint_probe_initializing to keep a
  fast user switch from spawning two parallel fprintd D-Bus inits.
- greeter: set_avatar_from_file decodes via gio::File::read_future +
  Pixbuf::from_stream_at_scale_future inside glib::spawn_future_local;
  shows default icon first, swaps on completion.
- greeter: cap MAX_WALLPAPER_FILE_SIZE at 10 MB and MAX_AVATAR_FILE_SIZE
  at 5 MB to bound worst-case decode latency.
- config: apply the same symlink-rejection check to the Moonarch
  wallpaper fallback that the user-configured path already uses.
- greeter: after login_worker returns, drop the cloned greetd socket
  held in shared state so repeated failed logins do not leak FDs.
v0.8.5
2026-04-24 13:26:52 +02:00
nevaforget 28966102ec fix: audit fix — reduce password copies in memory (v0.8.4)
- attempt_login takes Zeroizing<String> by value, eliminating the redundant
  Zeroizing::new(password.to_string()) that doubled the Rust-owned copy.
- Clear password_entry's internal buffer immediately after extracting the
  password, shortening the window during which the GTK GString persists in
  non-zeroizable libc memory.
v0.8.4
2026-04-24 12:52:59 +02:00
nevaforget 9915b182ca fix: ship polkit rule so greeter user can reboot/power off (v0.8.3)
The rule that grants the greeter user authorization for
org.freedesktop.login1.{reboot,power-off} lived only in the moonarch
repo and was never installed by any PKGBUILD. On a fresh install the
reboot/shutdown buttons silently failed because greetd's greeter
session is inactive in logind and polkit denies inactive sessions by
default.

Move the rule into the moongreet source tree where it belongs and
ship it via moongreet-git.
v0.8.3
2026-04-21 09:11:59 +02:00
nevaforget b9d3f65b0b docs: drop Selene persona, unify attribution on ClaudeCode
Remove the Selene persona block from CLAUDE.md and rewrite prior
DECISIONS entries from Selene to ClaudeCode for consistency with
the rest of the Moonarch ecosystem.
2026-04-21 09:03:21 +02:00
nevaforget beefdd02c5 fix: handle monitor hotplug for greeter windows (v0.8.2)
Greeter windows were only created at startup. Hotplugged monitors (e.g.
HDMI reconnect) would show no UI. Connect to the monitor ListModel's
items-changed signal to create greeter windows for newly added monitors.

Aligned with moonlock's hotplug fix using the same pattern adapted for
gtk4-layer-shell (ListModel) instead of session-lock (connect_monitor).
v0.8.2
2026-04-09 15:06:29 +02:00
nevaforget 5a2c6b410c feat: show greeter UI on all monitors, not just one (v0.8.0)
Wayland surfaces belong to exactly one output — mirroring is not an option.
Create one full greeter window per monitor via set_monitor(), with only the
first receiving KeyboardMode::Exclusive. Removes the old wallpaper-only
secondary windows. Matches moonlock's per-monitor pattern.
v0.8.0
2026-04-08 08:48:04 +02:00
nevaforget ec34b6cae3 fix: grab keyboard focus on map instead of realize (v0.7.4)
Layer-shell keyboard grab is only confirmed by the compositor at map
time. The previous realize-time grab_focus() could fire before the
compositor assigned keyboard input, causing intermittent input loss.
v0.7.4
2026-04-06 22:29:37 +02:00
nevaforget 067f28518c fix: restore explicit gtk-theme in config for greetd session (v0.7.3)
GTK4 does not reliably read /etc/xdg/gtk-4.0/settings.ini under greetd
without a settings daemon, falling back to default blue accent instead
of Colloid-Grey-Dark-Catppuccin.
v0.7.3
2026-04-06 22:24:06 +02:00
nevaforget b5acec37be docs: rename Ragnar to ClaudeCode in DECISIONS.md 2026-04-02 10:13:34 +02:00
nevaforget c658e4edd8 fix: replace hardcoded CSS colors with GTK theme variables (v0.7.2)
Greeter used hardcoded colors (#1a1a2e, white, #ff6b6b) instead of
GTK theme variables, breaking theme consistency across the ecosystem.
Now uses @theme_bg_color, @theme_fg_color, @error_color etc. —
matching moonlock and moonset.
v0.7.2
2026-04-02 10:12:01 +02:00
nevaforget e94673d4c5 Remove unnecessary pacman git install from CI workflow
Git is already available in the runner image.
2026-04-02 08:28:06 +02:00
nevaforget 362081929a Remove gtk-theme from app config, use system-wide GTK settings instead
The GTK theme is now set globally via /etc/xdg/gtk-4.0/settings.ini
rather than per-application config.
2026-04-02 08:27:54 +02:00
nevaforget 1c5b762b5f Revert CI workaround: remove pacman install step
The act_runner now uses a custom Arch-based image with git
pre-installed, so per-workflow installs are no longer needed.
2026-04-01 16:17:47 +02:00
nevaforget 137e2106cc fix: audit fixes — power timeout, timing mitigation, release profile, GREETD_SOCK cache (v0.7.1)
- Add 30s timeout with SIGKILL to power actions (adapted from moonset)
- Add 500ms minimum login response time against timing enumeration
- Cache GREETD_SOCK in GreeterState at startup
- Add [profile.release] with LTO, codegen-units=1, strip
- Add compressed="true" to GResource CSS/SVG entries
- Add SYNC comments to duplicated blur/background functions
- Add nix dependency for signal handling in power timeout
v0.7.1 v0.8.1
2026-03-31 11:08:40 +02:00
nevaforget c6016581be docs: update README, fix build.rs comment, correct gtk-theme in config
README: replace LD_PRELOAD with MOONGREET_NO_LAYER_SHELL env var,
add missing features (GPU blur, journal logging, password wiping).
build.rs: remove wallpaper.jpg reference.
moongreet.toml: correct gtk-theme to Colloid-Grey-Dark-Catppuccin.
2026-03-31 09:36:19 +02:00
nevaforget 04b6802203 fix: audit fixes — password zeroize, blur downscale, symlink hardening, error filtering (v0.7.0)
- Add zeroize dependency, wrap password in Zeroizing<String> from entry extraction
  through to login_worker (prevents heap-resident plaintext)
- Add MAX_BLUR_DIMENSION (1920px) downscale before GPU blur to reduce 4K workload
- Wallpaper: use symlink_metadata + is_symlink rejection in greeter.rs and config.rs
- Avatar: add is_file() check, swap lookup order to ~/.face first (consistent with
  moonlock/moonset)
- greetd errors: show generic fallback in UI, log raw PAM details at debug level only
- fprintd: validate device path prefix before creating D-Bus proxy
- Locale: cache detected locale via OnceLock (avoid repeated env/file reads)
v0.7.0
2026-03-30 16:03:04 +02:00
nevaforget a60661c8c6 fix: security hardening, blur geometry, and performance audit fixes (v0.6.2)
Security: cache dirs now 0o700 via DirBuilder::mode(), blur config
validated (finite + clamp 0–200), TOCTOU socket pre-check removed.

Quality: GPU blur geometry fixed (texture shifted instead of stretched),
is_valid_username hardened, is_valid_gtk_theme extracted as testable fn,
save_last_session error handling consistent with save_last_user.

Performance: blurred texture cached across monitors (1x GPU renderpass
instead of N), FingerprintProbe device proxy cached in GreeterState with
generation counter to prevent race condition on fast user-switch.

Clippy: all 7 warnings resolved (collapsible if-let, redundant closure,
manual_range_contains, too_many_arguments suppressed for GTK widget fns).

Tests: 109 → 118 (GTK theme validation, Unicode usernames, cache dir
permissions, unwritable dir handling, blur config edge cases).
2026-03-30 14:31:28 +02:00
nevaforget b24db49131 ci: also update .SRCINFO in pkgver workflow
paru reads .SRCINFO (not PKGBUILD) for version comparison during
sysupgrade. Without updating .SRCINFO, paru never detects upgrades
for PKGBUILD repository packages.
2026-03-30 13:49:09 +02:00
nevaforget 488f6ba525 ci: add workflow to auto-update pkgver in moonarch-pkgbuilds 2026-03-29 23:05:16 +02:00
nevaforget c72685fa0d fix: elevate CSS priority to override GTK4 user theme (v0.6.1)
Colloid-Catppuccin theme loaded via ~/.config/gtk-4.0/gtk.css at
PRIORITY_USER (800) was overriding moongreet's PRIORITY_APPLICATION (600),
causing avatar to lose its circular border-radius.

- Use STYLE_PROVIDER_PRIORITY_USER for app CSS provider
- Replace border-radius: 50% with 9999px (GTK4 CSS percentage quirk)
- Include missed Cargo.lock and PKGBUILD updates from v0.6.0
v0.6.1
2026-03-29 14:26:19 +02:00
nevaforget ab422fa2b9 feat: add fprintd fingerprint authentication via greetd multi-stage PAM (v0.6.0)
Fingerprint auth was missing because moongreet rejected multi-stage
auth_message sequences from greetd. With pam_fprintd.so in the PAM
stack, greetd sends non-secret prompts for fingerprint and secret
prompts for password — moongreet now handles both in a loop.

- Replace single-pass auth with multi-stage auth_message loop
- fprintd D-Bus probe (gio::DBusProxy) for UI feedback only
- Fingerprint label shown when device available and fingers enrolled
- 60s socket timeout when fingerprint available (pam_fprintd scan time)
- Config option: [appearance] fingerprint-enabled (default: true)
- Fix: password entry focus loss after auth error (grab_focus while
  widget was insensitive — now re-enable before grab_focus)
v0.6.0
2026-03-29 13:47:57 +02:00
nevaforget 5b99d0b18b fix: prevent edge darkening on GPU-blurred wallpaper (v0.5.3)
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.
Symmetric fix with moonset v0.7.1.
2026-03-28 23:28:39 +01:00
nevaforget 2678ceb856 refactor: remove embedded wallpaper from binary (v0.5.2)
Wallpaper is installed by moonarch to /usr/share/moonarch/wallpaper.jpg.
Embedding a 374K JPEG in the binary was redundant. Without a wallpaper
file, GTK background color (Catppuccin Mocha base) shows through and
wallpaper-only windows on secondary monitors are skipped.
2026-03-28 23:26:33 +01:00
nevaforget 7213cba56d docs: update for wallpaper removal from binary
Sync documentation with greetd-moongreet wallpaper removal.
2026-03-28 23:23:10 +01:00
nevaforget e573e12d86 fix: make setup_logging() resilient to journal logger failure (v0.5.1)
Replace unwrap() calls with match-based error handling that falls back
to eprintln — prevents panic when running outside a systemd session.
Consistent with moonlock's logging init pattern.
v0.5.1
2026-03-28 22:56:39 +01:00
nevaforget 3c650de276 fix: re-audit findings — avatar path safety, persistence logging, tests
- Reject non-UTF-8 avatar paths early instead of passing empty string to GDK
- Log persistence write failures with warn! instead of silently discarding
- Reduce API surface: create_background_picture pub→fn
- Add boundary test for MAX_USERNAME_LENGTH and socket connect failure test
2026-03-28 22:47:21 +01:00
nevaforget c3ec958237 fix+perf: audit fixes and GPU blur migration (v0.5.0)
Address all findings from quality, performance, and security audits:
- Filter greetd error descriptions consistently (security)
- Re-enable power buttons after failed action (UX bug)
- Narrow TOCTOU window in avatar loading via symlink_metadata (security)
- Allow @ in usernames for LDAP compatibility
- Eliminate unnecessary Vec allocation in passwd parsing
- Remove dead i18n field, annotate retained-for-future struct fields
- Fix if/if→if/else and noisy test output in power.rs

Replace CPU blur (image crate + disk cache + async orchestration) with
GPU blur via GskBlurNode — symmetric with moonlock and moonset.
Removes ~15 transitive dependencies and ~200 lines of caching code.
2026-03-28 22:34:12 +01:00
nevaforget 814cd4fe80 perf: cache blurred wallpaper to disk to avoid re-blur on startup
First launch with blur blurs and saves to /var/cache/moongreet/.
Subsequent starts load the cached PNG directly. Cache invalidates
when wallpaper path, size, mtime, or sigma changes.
2026-03-28 21:23:36 +01:00
nevaforget 0e0eb1c8df chore: bump version to 0.4.0 v0.4.0 2026-03-28 14:55:18 +01:00
nevaforget a668df0aad feat: add optional background blur via image crate
Gaussian blur applied at texture load time when `background-blur` is
set in the [appearance] section of moongreet.toml. Blur runs once,
result is shared across monitors.
2026-03-28 14:53:16 +01:00
nevaforget be32095690 fix: audit findings — wallpaper safety, log filtering, error truncation (v0.4.1)
- Rework load_background_texture(): use resources_lookup_data()/from_bytes()
  for GResource path (no abort on missing resource), add 50 MB file size limit,
  handle non-UTF-8 paths gracefully
- Filter error details to debug level only — warn! logs without internal details
  to prevent system info leaking into journal
- Make debug logging opt-in via MOONGREET_DEBUG env var (default: Info)
- Truncate greetd error description in stale-session retry path using
  MAX_GREETD_ERROR_LENGTH (matching show_greetd_error())
- Add 3 unit tests for load_background_texture edge cases
2026-03-28 10:29:21 +01:00
nevaforget 3c233e5ffd fix: wallpaper windows on Layer::Bottom to prevent greeter occlusion
Wallpaper-only windows for secondary monitors were on Layer::Top — same
layer as the greeter window. Since they were created after the greeter,
they occluded the login UI, leaving only the wallpaper visible.
2026-03-28 01:30:22 +01:00
nevaforget 52b8b63c26 feat: switch to systemd-journal-logger, add debug logging (v0.4.0)
Replace env_logger file-based logging with systemd-journal-logger for
consistency with moonlock and native journalctl integration. Add debug-level
logging at all decision points: config loading, user/session detection,
avatar resolution, locale detection, IPC messages, login flow, and
persistence. No credentials are ever logged.
2026-03-28 01:23:18 +01:00
nevaforget 89d6c517d4 docs: update CLAUDE.md for v0.3.2 audit changes 2026-03-28 00:43:00 +01:00
nevaforget f8720e6a22 chore: bump version to 0.3.2 2026-03-28 00:37:51 +01:00
nevaforget b677b50d28 fix: audit findings — security, i18n, validation, dead code (v0.3.2)
Quality:
- Q-5: Allow relative session commands (e.g. niri-session), greetd resolves PATH
- Q-3: Socket read+write timeouts with proper error logging
- Q-2: Remove unused PowerError::Timeout variant
- Q-M1: i18n for all login_worker error messages (new: unexpected_greetd_response)
- Q-M2: Explicit INVALID_LIST_POSITION check in session dropdown
- Q-M4: Log SVG loader.close() errors instead of silencing
- Q-M6: Testable persistence functions with proper roundtrip tests

Security:
- S-2: Validate GTK theme name (alphanumeric, _, -, +, . only)
- S-3: Log file created with mode 0o640
- S-4: Cache files (last-user, last-session) created with mode 0o600

Performance:
- P-3: Single symlink_metadata() call instead of exists() + is_symlink()
- P-4: Avoid Vec allocation in IPC send_message (two write_all calls)

Config:
- Update example GTK theme to Colloid-Catppuccin
2026-03-28 00:37:35 +01:00
nevaforget fcb9b41689 fix: GECOS subfield trimming and trailing backslash handling (v0.3.1)
display_name() now returns only the first GECOS subfield (before comma)
instead of the full GECOS string with room numbers and phone extensions.

split_shell_words() returns None for trailing backslashes instead of
silently ignoring them.
v0.3.1
2026-03-28 00:07:29 +01:00
nevaforget 8597138cb1 feat: MOONGREET_NO_LAYER_SHELL env var for windowed development mode 2026-03-27 23:36:57 +01:00
nevaforget 557f57a15a Merge rust-rewrite: moongreet v0.3.0 Rust rewrite 2026-03-27 23:16:58 +01:00
nevaforget ae2a10475d Rewrite moongreet from Python to Rust (v0.3.0)
Complete rewrite of the greetd greeter from Python/PyGObject to Rust/gtk4-rs
for consistency with moonset, single binary without Python runtime, and
improved security through Rust memory safety.

Modules: main, greeter, ipc, config, i18n, users, sessions, power
86 unit tests covering all modules including login_worker IPC flow.
Security hardening: shell-word splitting for exec_cmd, absolute path
validation for session binaries, session-name sanitization, absolute
loginctl path, atomic IPC writes.
2026-03-27 22:08:33 +01:00