Files
latchd/CHANGELOG.md

9.5 KiB

Changelog

Unreleased

  • Preview mode now loads $XDG_CONFIG_HOME/latchd/config.toml or ~/.config/latchd/config.toml when no --config path is set.

  • Added make install-user to create a user configuration without replacing an existing file.

  • Added Docker PTY screenshots and a short UI guide.

  • Fixed Wayland compositors launched through user services, including Niri, by providing the selected session type, desktop, seat, and VT to PAM before pam_open_session.

  • Session children now receive allowlisted runtime values produced by PAM, including the real logind session ID, runtime directory, and user D-Bus address. Latchd no longer fabricates XDG_SESSION_ID=latchd.

  • Extended the disposable PAM fixture to verify both sides of the handoff: selected session metadata entering PAM and PAM-generated values reaching the session child.

0.5.0 — PAM password policy flow

  • Added PAM password-change handling for accounts that return PAM_NEW_AUTHTOK_REQD or PAM_AUTHTOK_EXPIRED during login.
  • Added an explicit TUI new-password state. PAM still enforces password history, strength, and token policy; the login screen never implements its own password rules.
  • Added zeroizing old/new password buffers and conversation tests for the current-password/new-password prompt sequence.
  • Added redacted structured audit events for authentication, password changes, and session handoff. Raw PAM messages and password material are excluded.
  • Added TUI, core, and preference tests; the workspace now contains 37 Rust unit tests.
  • Added bounded, atomic last-session preferences per account with owner-only file permissions and a safe fallback when the state file is unavailable.
  • Added disposable PAM deny-policy fault-injection tests. Docker runs them as root; ordinary host runs skip them without touching the host PAM policy.

0.4.0 — Advanced login workflow

  • Added account policy inspection for locked passwords, password expiry, account expiry, inactivity, and missing shadow data without exposing hashes.
  • Added active UTMPX session discovery and systemd-logind capability detection with an explicit UTMPX fallback.
  • Improved faillock parsing for legacy, username-prefixed, and timestamped helper output. PAM remains authoritative for every login decision.
  • Added smart-case filtering for users and sessions, non-blocking Ctrl-R discovery refresh, contextual footer hints, high-contrast mode, and policy notices in the TUI.
  • Added bounded local authentication backoff after repeated failures and reset it when switching accounts.
  • Added CLI integration tests and host capability probes. Docker now runs the release binary through the safe CLI and capability suites.
  • Added documented strict VM validation for PAM policy, VT, X11, Wayland, and systemd-logind; missing capabilities are reported as skips in ordinary CI.
  • Bumped the workspace release version to 0.4.0.

0.3.0 — Rust workspace release preparation

  • Rust is the supported login manager; the Go/cgo prototype is quarantined at legacy/go/ and excluded from normal builds and release archives.
  • Added workspace crates for PAM authentication, session/config/account management, and the TUI, including account switching and advisory faillock.
  • Added optional terminal-cell wallpapers, cellular automata effects, and accessible motion/background controls.
  • Added GitLab CI verification, version-checked tag releases, optimized single-version Cargo builds, deterministic installation archives, SHA-256 checksums, and embedded build metadata.
  • Live VT, logind, PAM-policy, X11, and Wayland validation remains a deployment requirement on an isolated VM or target host.

Legacy Go history (not the Rust release)

0.1.0 — Unreleased

first public release

What's In

  • tui login screen with username/password fields, session switcher, and status messages
  • supports x11, wayland, and tty sessions
  • pam authentication via cgo (thread-locked for safety)
  • faillock integration — detects lockouts, shows remaining attempts, admin bypass via ctrl+u
  • conway's game of life background rendered at 30 fps with unicode half-block characters
  • spring animation on switcher transitions
  • shake animation on failed login
  • caps lock indicator via ioctl
  • configurable power controls (shutdown/reboot on f1/f2 by default)
  • toml configuration with $VARIABLE substitution
  • preview mode (--preview) to test the login screen without leaving your session
  • utmpx user accounting (glibc only)
  • x11 session setup — xauthority cookies, sigusr1 handshake, server timeout
  • privilege dropping for child processes
  • log piping with 64 mb cap

Recent Fixes

  • DesktopNames parsing — .desktop files now parse the DesktopNames field. the first semicolon-delimited entry becomes XDG_SESSION_DESKTOP, and the full list with : separators becomes XDG_CURRENT_DESKTOP. fixes GNOME/KDE sessions not getting proper environment variables

  • utmpx accounting wired — AddUtmpx and Close are now called from spawnSession so user logins appear in who/w/last

  • fixed hardcoded shell — Credentials.Shell now reads from /etc/passwd instead of always returning /bin/sh. removes duplicate userShell logic in exec.go

  • automata background wired — Automata.Frame() is now rendered in View() as the base layer with the login form card overlaid using ANSI cursor positioning. the form has a dark card background for readability

  • clock widget — added a datetime display (Mon Jan 02 15:04:05) to the top bar, updated every tick

  • session specifier label — the environment switcher now shows the session type (x11, wayland) above the session name, like ly's specifier

  • form card background — login content is rendered inside a padded card with a dark background so it reads cleanly over the animated automata

  • utmpx time field portability — replaced hardcoded C.__uint32_t / C.__int32_t casts with a C helper function (auth/utmpx_time.h) that lets the compiler handle type conversion. fixes build failure on systems where ut_tv uses struct timeval instead of the 32/64 compat struct

  • cgo pointer safety for pam — replaced unsafe.Pointer(&h) (Go stack pointer passed to C) with storeHandle/loadHandle helpers that keep the cgo.Handle in C-heap memory. fixes cgo argument has Go pointer to unpinned Go pointer panic on Go 1.22+

  • pam conversation callback — fixed unsafe.Slice using &r (pointer-to-pointer) as the backing array instead of r (the calloc'd response array), which wrote password bytes into random stack memory. also now only responds to PAM_PROMPT_ECHO_OFF/PAM_PROMPT_ECHO_ON messages — info and error messages get nil. fixes pam_unix: auth could not identify password

  • cgo handle lifecycle — moved cgo.Handle and its C-heap backing from Validate (where they were defer-freed on return) into the Credentials struct so they stay alive through OpenSession and until CloseSession. fixes misuse of an invalid Handle panic

  • session spawning — replaced the broken ForkExec (which relaunched the same binary with made-up flags) with a direct session.Spawn call that drops privileges and runs the desktop in-process. fixes flag provided but not defined: -user

  • renamed extra/ files — lemurs.pam → latchd.pam, lemurs.service → latchd.service

  • readme credits — added a credits section acknowledging lemurs for the extra/ directory structure and session scanning approach

  • makefile enable and update targets — make enable stops any running DM, disables the aliased display-manager, and enables latchd. make update runs uninstall → git pull → reinstall in one command

  • missing extra/ directory — added extra/config.toml, extra/xsetup.sh, extra/lemurs.pam, and extra/lemurs.service so make install can find them

  • makefile deps target — added make deps to automatically install libpam0g-dev and build-essential, and verify go is present

  • readme overhaul — rewrote for clarity: added "what problem does this solve", "how it works", known issues, simpler install instructions, and proper dependency listing

  • view cleanup — removed the non-functional automata background overlay from View() (the Frame() was never called, and the black-space placeholder caused EEEE garbage characters on some terminals). also removed a hardcoded 80-char width on the top bar so it adapts to the terminal

  • session environment setup — spawnSession now calls SetBasicVariables, SetDisplay, SetSessionParams, SetSeatVars, SetSessionVars, and SetXDGCommonPaths before spawning the desktop. fixes setupX failing immediately with missing DISPLAY/XDG_VTNR/HOME env vars because none were set

  • pam session error made non-fatal — pam_open_session failure (e.g. pam_systemd rejecting the DM process as session leader) is now logged as a warning instead of blocking the entire session spawn. also removed session include login from latchd.pam since the DM process can't register user sessions with systemd-logind

  • global session switching with , and . — sessions can now be switched from any mode (not just when the switcher is focused). arrows still work when switcher is focused

What's Missing

  • no tests
  • session leader is the latchd process, not the desktop — pam session tracking via systemd-logind may be imperfect
  • not all config options affect the rendering yet
  • occasional terminal state corruption on abrupt exit
  • automata background visible at screen edges; form card covers the center