Cargo names a cdylib .dylib on macOS, so copying libahfail_pam.so out of
the target directory failed there, as the first real macOS build in the
Homebrew tap's Actions showed. The installed name stays .so.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
Homebrew could not clone the Gitea tap (git over HTTP is disabled), so
brew tap agw/ahfail never worked. The formula now lives in
asger-weirsoee/homebrew-tap, and releases update it with a deploy key.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
A second AUR package with the same release prebuilt. The workflow
builds the tag into a staged meson install tree (--prefix=/usr, no
update check), names the tarball after its sha256 so a published name
never changes bytes, uploads it to asger.weirsoe.dk/tarballz with a key
that may only write ahfail-* tarballs, checks that the public URL serves
the same bytes, and only then pushes ahfail-bin to the AUR. A manual run
can now publish source, bin or both.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
The Maintainer line uses the usual AUR form (asger at weircon dot dk)
instead of a raw address that spam crawlers harvest. The AUR workflow
can now also be started by hand with a version and pkgrel, so a fix to
the PKGBUILD alone can be published without a new upstream release.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
Gitea refuses secret names starting with GITEA_, so GITEA_TOKEN could
never be set and every release failed; it is RELEASE_TOKEN now. git over
HTTP is disabled on this Gitea, so the tap formula is updated through
the contents API instead of a clone and push.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
The PKGBUILD states what the package is: a real screen locker provided
as is, and parody media from Jurassic Park that the AGPL does not cover.
The ahfail command has only been tested on Linux, so macOS builds keep
the PAM hook and skip it; the README no longer promises it there.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
The runner rewrites Gitea URLs to SSH on port 2222, and without openssh
git falls back to the 'simple' SSH variant, which cannot set a port, so
checkout failed.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
The locker needs gtk-session-lock, which Ubuntu does not package, and
Arch is where the AUR package is built. The release tarball now carries
the ahfail binary and its PAM file as well.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
The README leads with ahfail, ahfail test and ahfail doctor, the
platform table, idle locking and what the lock does and does not
guarantee, including pam_faillock. The old gtklock module and PAM hook
move to a short legacy section. CLAUDE.md describes the five crates.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
Four cargo builds with four target directories compiled the GTK and
GStreamer bindings four times; one build with a shared target directory
takes a package build from about an hour to about seven minutes.
Adds the ahfail binary and /etc/pam.d/ahfail to the install, the
update_check option, an AUR PKGBUILD (offline build after cargo fetch
--locked) and a tag-triggered workflow that publishes it and mirrors the
PKGBUILD to the tarballz index.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
The Gitea update check is now the default feature update-check of
ahfail-ui; distro builds drop it, and the HTTP client with it.
ahfail-display refuses to run as root and keeps its lock file in
XDG_RUNTIME_DIR instead of a fixed name in the shared /tmp, and the PAM
module no longer spawns it from a root context such as a greeter.
Removes pam_tests.rs, which tested helpers dropped in v0.9.0 and has not
compiled since.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
ahfail locks the screen itself instead of hooking another locker: Wayland
through ext-session-lock-v1 (gtk-session-lock), X11 through an input grab.
It authenticates against its own PAM service, /etc/pam.d/ahfail, so a
package never has to edit another package's PAM file.
One command for every platform: ahfail (lock), ahfail test (the effect
without locking) and ahfail doctor (what is missing, with the fix).
Enter is handled directly and the entry uses no input method, since the
Wayland text-input IM swallowed Return. Sprites avoid the password box
in window coordinates, and placement gets 100 tries instead of 10.
Claude-Session: https://claude.ai/code/session_012LCTmU2ewo8tnM1dByYAoG
scripts/uninstall-linux-x11.sh — strips ahfail from common PAM service
files and removes binaries (via ninja uninstall or known paths).
scripts/uninstall-macos.sh — strips ahfail from screensaverui/screensaver
and removes /usr/local/lib/ahfail/.
README: add Uninstall section covering all four cases (X11, Wayland,
Homebrew macOS, manual macOS).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace bare config snippets with actual tee -a commands so there is no
way to mistake a file entry for a shell command to run directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without it meson defaults to /usr/local, so the installed paths don't
match the README and DEFAULT_PATH compiled into the PAM module is wrong.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Linux x86_64 binary install covers both Wayland and X11 from the same
tarball — clarified with a table showing which file is used by which.
macOS section now leads with Homebrew (brew tap + brew install) as the
recommended path, with script and manual install as fallbacks.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After uploading the release asset, the workflow now:
1. Computes the SHA256 of the source tarball from the Gitea archive endpoint
2. Clones homebrew-ahfail via token auth, patches url + sha256 in Formula/ahfail.rb
3. Commits and pushes — so `brew upgrade ahfail` works without any manual steps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Apple Silicon Homebrew uses /opt/homebrew as prefix, so hardcoding
/usr/local/lib/ahfail/ahfail-display as DEFAULT_PATH breaks there.
build.rs now falls back to /usr/local/lib on macOS and /usr/lib on Linux
when AHFAIL_LIBDIR is not set; macOS uses the same concat!(env!(...))
approach as Linux.
install-macos.sh passes -Dlibdir so the baked-in path matches INSTALL_DIR.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Clarify that the sprite is the author's face on Nedry's body
- Explicit Wayland (gtklock module) vs X11/macOS (PAM module) comparison table
with an explanation of how each integration works
- Accurate per-distro PAM paths (standard/Fedora multilib/Debian multiarch)
- scripts/install-macos.sh: one-shot installer for macOS — checks Homebrew,
installs brew deps, builds from source, copies binaries, and patches
/etc/pam.d/screensaverui (or screensaver) after the last auth line
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the manual curl-based release creation with the standard action,
consistent with other Gitea repos. Also bumps checkout to @v4.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dlopen with a bare filename searches LD_LIBRARY_PATH/ld.so cache, not the
build dir. Using the explicit absolute path avoids the lookup failure.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ahfail_tests.rs calls on_activation which initialises GTK — needs a virtual
display in CI just like the Meson test step.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ubuntu-latest now resolves to Ubuntu 24.04 which ships meson 1.3.2 (satisfies
>=1.3.0) and enforces PEP 668, blocking pip3 install without --break-system-packages.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Volume lock file now stores {pid}:{volume}:{muted} instead of "1":
- Allows recovery of saved volume state if the holder is SIGKILLed
- On stale lock detection (holder PID not alive), inherit saved volume state
and take ownership — prevents permanent volume loss and infinite lockout
PAM module DEFAULT_PATH now baked in at build time via AHFAIL_LIBDIR env var
passed by Meson, fixing the wrong path on multiarch Debian/Ubuntu where libdir
is /usr/lib/x86_64-linux-gnu rather than /usr/lib.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements a C-ABI PAM shared library that registers a pam_set_data
cleanup callback to detect auth failures and spawn/kill ahfail-display
via a double-fork, without ever touching credentials.
Implements the ahfail-display binary crate: GTK popup window that spawns
the Nedry sprite and plays the audio clip, with SIGTERM handling, 15-minute
failsafe, deadzone CLI parsing, volume save/restore, and update check.
Adds a build.rs that compiles GResources via glib-compile-resources so the
binary can be built with plain `cargo build` outside of Meson.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On the first failed unlock attempt, save the current system volume and
mute state then set volume to maximum unmuted; restore on g_module_unload.
A lock file under XDG_RUNTIME_DIR prevents double-acquisition when
multiple gtklock windows are active.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the single-crate Cargo.toml with a workspace containing
ahfail-gtklock (migrated from root src/) and three stub crates
(ahfail-ui, ahfail-pam, ahfail-display). Updates meson.build to
build with -p ahfail-gtklock.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>