Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
453f278
test: add e2e package install tests for .deb and .rpm
tyvsmith Apr 5, 2026
22269f7
test: add interactive shell recipes for e2e package containers
tyvsmith Apr 5, 2026
16de13c
fix: add SSL/CA deps to e2e containers for model downloads
tyvsmith Apr 5, 2026
dd6eb31
refactor: rename interactive shell recipes and mount host models
tyvsmith Apr 5, 2026
41f4a1b
fix: mount host ORT library into interactive shell containers
tyvsmith Apr 5, 2026
64f996e
fix: mount models read-write in interactive shell containers
tyvsmith Apr 5, 2026
7b14600
fix: mount model files individually to avoid rootless podman chmod issue
tyvsmith Apr 5, 2026
8de2df9
fix: resolve ORT symlink before mounting into containers
tyvsmith Apr 5, 2026
f0ed38d
fix: use portable CPU-only ORT for cross-distro shell containers
tyvsmith Apr 5, 2026
7d1e363
fix: copy test config into container instead of bind-mounting over it
tyvsmith Apr 6, 2026
4c21cc2
fix: copy host models into container instead of bind-mounting
tyvsmith Apr 6, 2026
389686a
feat: bundle ORT in e2e test packages to match real release packages
tyvsmith Apr 6, 2026
ac44202
fix: search lib64 bundled ORT path for Fedora/RHEL RPM packages
tyvsmith Apr 6, 2026
3d0caa5
style: apply cargo fmt to provider.rs
tyvsmith Apr 7, 2026
7567902
refactor: rename test recipes for consistency and add release shells
tyvsmith Apr 7, 2026
d82f3b3
refactor: rename Arch test recipes to test-arch-* for consistency
tyvsmith Apr 7, 2026
7228b3e
feat: add PAM, D-Bus, and package removal tests to e2e validation
tyvsmith Apr 7, 2026
34f8c56
fix: address PR review feedback on e2e container tests
tyvsmith Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/scripts/build-deb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ Description: ${DESCRIPTION}
${DESCRIPTION_LONG}
CTRL

# conffiles — preserve config on remove/upgrade
echo "/etc/facelock/config.toml" > "${PKG_DIR}/DEBIAN/conffiles"

# postinst and prerm scripts
cp dist/debian/postinst "${PKG_DIR}/DEBIAN/postinst"
chmod 755 "${PKG_DIR}/DEBIAN/postinst"
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ Supported providers: `cpu` (default), `cuda` (NVIDIA), `rocm` (AMD), `openvino`
|------|------|-----|
| 1 | Unit tests | `cargo test --workspace` |
| 2 | Hardware tests | `cargo test --workspace -- --ignored` |
| 3 | Container PAM smoke | `just test-pam` |
| 3b | Container E2E (daemon) | `just test-integration` |
| 3c | Container E2E (oneshot) | `just test-oneshot` |
| 3 | Arch container PAM smoke | `just test-arch-pam` |
| 3b | Arch container E2E (daemon) | `just test-arch-integration` |
| 3c | Arch container E2E (oneshot) | `just test-arch-oneshot` |
| 4 | VM testing | Disposable VM with snapshots |
| 5 | Host PAM | After tiers 3-4, with root shell backup |

Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ Requires a connected camera and downloaded models. These tests are marked `#[ign
### Tier 3: Container tests (requires podman)

```bash
just test-pam # PAM smoke tests (no camera)
just test-integration # end-to-end with camera (daemon mode)
just test-oneshot # end-to-end with camera (no daemon)
just test-shell # interactive container shell for debugging
just test-arch-pam # Arch PAM smoke tests (no camera)
just test-arch-integration # end-to-end with camera (daemon mode)
just test-arch-oneshot # end-to-end with camera (no daemon)
just test-arch-dev-shell # interactive container shell for debugging
```

Container tests validate PAM integration without risking host lockout.
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ This adds a face icon to the hyprlock password prompt and optionally sources a `

```bash
just check # unit tests + clippy + fmt
just test-pam # container PAM smoke tests
just test-integration # end-to-end with camera (daemon mode)
just test-oneshot # end-to-end with camera (no daemon)
just test-shell # interactive container for manual testing
just test-arch-pam # Arch container PAM smoke tests
just test-arch-integration # end-to-end with camera (daemon mode)
just test-arch-oneshot # end-to-end with camera (no daemon)
just test-arch-dev-shell # interactive container for manual testing
```

See [docs/testing-safety.md](docs/testing-safety.md) before editing PAM config on your system.
Expand Down
8 changes: 4 additions & 4 deletions book/src/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ Requires a connected camera and downloaded models. These tests are marked `#[ign
### Tier 3: Container tests (requires podman)

```bash
just test-pam # PAM smoke tests (no camera)
just test-integration # end-to-end with camera (daemon mode)
just test-oneshot # end-to-end with camera (no daemon)
just test-shell # interactive container shell for debugging
just test-arch-pam # Arch PAM smoke tests (no camera)
just test-arch-integration # end-to-end with camera (daemon mode)
just test-arch-oneshot # end-to-end with camera (no daemon)
just test-arch-dev-shell # interactive container shell for debugging
```

Container tests validate PAM integration without risking host lockout.
Expand Down
8 changes: 4 additions & 4 deletions book/src/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ sudo facelock bench warm-auth # measure auth latency

```bash
just check # unit tests + clippy + fmt
just test-pam # container PAM smoke tests (no camera)
just test-integration # end-to-end with camera (daemon mode)
just test-oneshot # end-to-end with camera (no daemon)
just test-shell # interactive container shell
just test-arch-pam # Arch container PAM smoke tests (no camera)
just test-arch-integration # end-to-end with camera (daemon mode)
just test-arch-oneshot # end-to-end with camera (no daemon)
just test-arch-dev-shell # interactive container shell
```

## System Installation
Expand Down
16 changes: 8 additions & 8 deletions book/src/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ Requires camera and downloaded ONNX models. Tests capture, model loading, full p
### Tier 3: Container Tests (requires podman)

```bash
just test-pam # PAM smoke tests (no camera needed)
just test-integration # full E2E with camera (daemon mode)
just test-oneshot # full E2E with camera (no daemon)
just test-shell # interactive shell for manual testing
just test-arch-pam # Arch PAM smoke tests (no camera needed)
just test-arch-integration # full E2E with camera (daemon mode)
just test-arch-oneshot # full E2E with camera (no daemon)
just test-arch-dev-shell # interactive shell for manual testing
```

Container tests validate:
Expand Down Expand Up @@ -136,8 +136,8 @@ Local full CI: `bash test/run-tests.sh`
| `just test` | Unit tests |
| `just lint` | Clippy |
| `just check` | test + lint + fmt |
| `just test-pam` | Container PAM smoke |
| `just test-integration` | E2E daemon mode |
| `just test-oneshot` | E2E oneshot mode |
| `just test-shell` | Interactive container |
| `just test-arch-pam` | Arch container PAM smoke |
| `just test-arch-integration` | E2E daemon mode |
| `just test-arch-oneshot` | E2E oneshot mode |
| `just test-arch-dev-shell` | Interactive container |
| `just install` | System install (root) |
2 changes: 1 addition & 1 deletion book/src/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ cp /etc/pam.d/sudo.facelock-backup /etc/pam.d/sudo

### Prevention

- Always test in containers first (`just test-pam`).
- Always test in containers first (`just test-arch-pam`).
- Keep a root shell open during PAM testing.
- Start with `sudo` only -- do not add Facelock to `login` or `sddm` until `sudo` works reliably.
- Set `security.disabled = true` as an emergency kill switch (PAM returns IGNORE).
Expand Down
28 changes: 18 additions & 10 deletions crates/facelock-face/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ const SYSTEM_ORT_PATHS: &[&str] = &[
];

/// Bundled CPU-only ORT fallback, shipped with the facelock package.
const BUNDLED_ORT_PATH: &str = "/usr/lib/facelock/libonnxruntime.so";
/// Debian/Ubuntu use /usr/lib/, Fedora/RHEL use /usr/lib64/ on x86_64.
const BUNDLED_ORT_PATHS: &[&str] = &[
"/usr/lib/facelock/libonnxruntime.so",
"/usr/lib64/facelock/libonnxruntime.so",
];

/// Load the ONNX Runtime shared library.
///
Expand Down Expand Up @@ -55,15 +59,19 @@ fn load_ort() -> std::result::Result<(), String> {
}

// Fall back to bundled CPU-only ORT
let bundled = std::path::Path::new(BUNDLED_ORT_PATH);
if bundled.exists() {
match ort::init_from(bundled) {
Ok(_) => {
tracing::info!("Loaded bundled CPU ONNX Runtime from {BUNDLED_ORT_PATH}");
return;
}
Err(e) => {
tracing::warn!("Found bundled ORT but failed to load: {e}");
for bundled_path in BUNDLED_ORT_PATHS {
let bundled = std::path::Path::new(bundled_path);
if bundled.exists() {
match ort::init_from(bundled) {
Ok(_) => {
tracing::info!("Loaded bundled CPU ONNX Runtime from {bundled_path}");
return;
}
Err(e) => {
tracing::warn!(
"Found bundled ORT at {bundled_path} but failed to load: {e}"
);
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ sudo facelock bench warm-auth # measure auth latency

```bash
just check # unit tests + clippy + fmt
just test-pam # container PAM smoke tests (no camera)
just test-integration # end-to-end with camera (daemon mode)
just test-oneshot # end-to-end with camera (no daemon)
just test-shell # interactive container shell
just test-arch-pam # Arch container PAM smoke tests (no camera)
just test-arch-integration # end-to-end with camera (daemon mode)
just test-arch-oneshot # end-to-end with camera (no daemon)
just test-arch-dev-shell # interactive container shell
```

## System Installation
Expand Down
35 changes: 27 additions & 8 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,30 @@ Both `.deb` packages are uploaded to the GitHub Release for direct download. For
Before releasing, validate packages build and install correctly on each target:

```bash
just test-pam # Arch container PAM smoke tests (existing)
just test-rpm # Fedora container — build, install, validate file layout
just test-deb # Ubuntu container — build, install, validate file layout
# Automated (no camera needed)
just test-arch-pam # Arch container PAM smoke tests
just test-rpm # Fedora — validate file layout from manual install
just test-deb # Ubuntu — validate file layout from manual install
just test-deb-pkg # Ubuntu 24.04 — build real .deb, install via dpkg, validate
just test-deb-tpm-pkg # Debian trixie — build real TPM .deb, install via dpkg, validate
just test-rpm-pkg # Fedora — build real .rpm, install via dnf, validate

# Interactive (requires camera)
just test-deb-dev-shell # Ubuntu .deb with host models — fast iteration
just test-rpm-dev-shell # Fedora .rpm with host models — fast iteration
just test-deb-release-shell # Ubuntu .deb clean room — real user experience
just test-rpm-release-shell # Fedora .rpm clean room — real user experience
```

These containers don't need camera hardware. They validate that the package installs
all required files to the correct paths, PAM symbols are exported, D-Bus policy is
valid, and systemd units are present.
The `test-rpm` / `test-deb` recipes validate file layout from manually installed binaries.
The `*-pkg` recipes build real packages using the same scripts as CI, install them with
the actual package manager (`dnf` / `dpkg`), and validate the result — testing postinst
scripts, dependency resolution, ORT bundling, sysusers/tmpfiles triggers, and the full
install path.

The `*-dev-shell` recipes mount host models for fast interactive camera testing.
The `*-release-shell` recipes start from a clean package install with nothing from the
host — run `facelock setup` to download models, then enroll and test.

### Release preflight (recommended)

Expand All @@ -87,9 +103,12 @@ Run this before creating/pushing a release tag:
just release-preflight # stable release checks
just release-preflight v0.2.0-rc1 # prerelease checks (AUR/COPR secrets optional)
just check
just test-pam
just test-arch-pam
just test-rpm
just test-deb
just test-deb-pkg
just test-deb-tpm-pkg
just test-rpm-pkg
```

`just release-preflight` checks local tools, required packaging files, and whether
Expand Down Expand Up @@ -249,7 +268,7 @@ The bundled ORT version is pinned in `.github/workflows/release.yml` as `ORT_VER
Since facelock is a PAM module, broken releases can lock users out. Every release must:

1. Pass `just check` (tests + clippy + fmt)
2. Pass `just test-pam` (container PAM smoke tests)
2. Pass `just test-arch-pam` (Arch container PAM smoke tests)
3. Pass `just test-rpm` and `just test-deb` (multi-distro package validation)
4. Not change PAM auth semantics without explicit changelog entry
5. Preserve `/etc/pam.d/sudo` backup on install (`sudo.facelock-backup`)
Expand Down
6 changes: 3 additions & 3 deletions docs/testing-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ locally before merging camera-related changes.

### Tier 3a: Container PAM Smoke Tests

**How:** `just test-pam` (podman, Arch Linux container)
**How:** `just test-arch-pam` (podman, Arch Linux container)
**Status:** Active, runs in CI (`container-pam-test` job). 13 tests.

Validates the PAM module in an isolated container without a camera:
Expand All @@ -47,7 +47,7 @@ Validates the PAM module in an isolated container without a camera:

### Tier 3b: Container E2E (Daemon Mode)

**How:** `just test-integration` (podman, passes `/dev/video*` devices)
**How:** `just test-arch-integration` (podman, passes `/dev/video*` devices)
**Status:** Active locally. Cannot run in CI (needs camera). 7 tests.

Full daemon-mode flow inside a container with a real camera:
Expand All @@ -61,7 +61,7 @@ Full daemon-mode flow inside a container with a real camera:

### Tier 3c: Container E2E (Oneshot Mode)

**How:** `just test-oneshot` (podman, passes `/dev/video*` devices)
**How:** `just test-arch-oneshot` (podman, passes `/dev/video*` devices)
**Status:** Active locally. Cannot run in CI (needs camera). 10 tests.

Same as 3b but fully daemonless: verifies no socket exists, enrollment,
Expand Down
16 changes: 8 additions & 8 deletions docs/testing-safety.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ Requires camera and downloaded ONNX models. Tests capture, model loading, full p
### Tier 3: Container Tests (requires podman)

```bash
just test-pam # PAM smoke tests (no camera needed)
just test-integration # full E2E with camera (daemon mode)
just test-oneshot # full E2E with camera (no daemon)
just test-shell # interactive shell for manual testing
just test-arch-pam # Arch PAM smoke tests (no camera needed)
just test-arch-integration # full E2E with camera (daemon mode)
just test-arch-oneshot # full E2E with camera (no daemon)
just test-arch-dev-shell # interactive shell for manual testing
```

Container tests validate:
Expand Down Expand Up @@ -136,8 +136,8 @@ Local full CI: `bash test/run-tests.sh`
| `just test` | Unit tests |
| `just lint` | Clippy |
| `just check` | test + lint + fmt |
| `just test-pam` | Container PAM smoke |
| `just test-integration` | E2E daemon mode |
| `just test-oneshot` | E2E oneshot mode |
| `just test-shell` | Interactive container |
| `just test-arch-pam` | Arch container PAM smoke |
| `just test-arch-integration` | E2E daemon mode |
| `just test-arch-oneshot` | E2E oneshot mode |
| `just test-arch-dev-shell` | Interactive container |
| `just install` | System install (root) |
2 changes: 1 addition & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ cp /etc/pam.d/sudo.facelock-backup /etc/pam.d/sudo

### Prevention

- Always test in containers first (`just test-pam`).
- Always test in containers first (`just test-arch-pam`).
- Keep a root shell open during PAM testing.
- Start with `sudo` only -- do not add Facelock to `login` or `sddm` until `sudo` works reliably.
- Set `security.disabled = true` as an emergency kill switch (PAM returns IGNORE).
Expand Down
Loading
Loading