Skip to content

Releases: 0ctave/ward

Ward 0.5.0

Choose a tag to compare

@0ctave 0ctave released this 28 Oct 01:07

Launch readiness

  • The README now shows the face-free terminal demo (docs/demo.gif) as its hero.
  • Fixed the <you> placeholder in the package URLs (PKGBUILD, ward.spec, build-deb.sh) that
    would have shipped broken homepage links, and added packaging/README.md — a maintainer
    runbook for AUR / Fedora COPR / Ubuntu PPA / Flathub and the per-release checklist.

Docs: migrating from Howdy

  • New Migrating from Howdy guide and an honest Ward vs Howdy
    comparison table in the README (right camera, IR emitter, poses, measured threshold, liveness,
    fail-open, Wayland/greeter, zero-pip deps). GitHub Discussions is now the place for questions,
    ideas and "does it work on my laptop" reports (linked from the issue picker).

Polish

  • doctor and the app's health report now read the shadow-test latency cutoff from the engine's
    emitter.SHADOW_MAX_LATENCY_MS instead of a hardcoded 150, so the reported threshold can't drift
    from the one the engine actually gates on.
  • Fixed a latent cache leak: the shadow-test vote was cached on the Engine and reset only by
    authenticate(), so the lab (which reuses one Engine across samples) would have frozen the first
    shadow vote for the whole session once an emitter was wired in. The lab now resets it per sample.

Engine hardening & portability CI

  • The liveness accept/reject core is now a pure Engine._accept_votes(...) helper with its own
    unit-test case table (single PASS, strict-needs-a-strong-voter, any FAIL, all-abstain with/without
    require_liveness_when_available, n_pass ≥ required). It was previously inline in _decide with
    no direct test. Behaviour is unchanged — this is a refactor plus coverage of the security core.
  • Models.preload() now also builds the YuNet detector (a one-shot dummy detect, fail-soft), so
    the ~50–150 ms detector init overlaps the camera open instead of landing on the first frame on the
    cold path; the daemon's duplicate warm-up is removed.
  • New distros CI workflow (weekly + on-demand) runs the portability matrix — Debian 12,
    Ubuntu 22.04, Fedora, Arch, openSUSE Tumbleweed — via the existing container harness, so the
    version/distro fallbacks (3.10 TOML, 3.13 libcrypt, the YuNet graph split, dlib) are exercised.

Enrollment embeds the same frames auth does (accuracy)

  • Fixed a train/serve mismatch: unlock embedded a brightness-normalised crop while enrollment
    embedded the raw frame, so models captured in dim/bright/night light (the "change the light"
    and IR passes) could never be reproduced at unlock. Both paths now go through one shared
    brightness.embed_rgb helper — identical for in-range frames (well-lit enrolments unchanged),
    identically normalised for out-of-range ones. Re-enroll to rebuild the affected models.

Setup steers around the missing dlib embedder

  • On Debian/Ubuntu/Fedora python3-dlib isn't packaged and pip is not used, so the default
    recogniser=dlib had no embedder and failed at the first frame. ward setup now probes dlib and
    defaults to installing ArcFace when neither embedder is present, and doctor reports a missing
    dlib embedder as a real failure (with a fix) instead of a note.

PAM hardening

  • The keyring unseal (which materialises your cleartext login password for pam_gnome_keyring /
    pam_kwallet) now runs only for login/unlock services (gdm-password, sddm, lightdm,
    login, greetd, kde) — never for sudo/su/polkit, which don't unlock a keyring and so
    never need the password materialised.
  • ward pam enable now refuses to silently bypass a second factor: if a required/requisite 2FA
    module (pam_u2f, pam_google_authenticator, pam_yubico, …) sits after where the ward line
    goes, its success-jump would skip it, so enable stops with a clear message (use --force to
    override). (pam_faillock is not treated as a second factor — its authfail line only acts on
    failure, and it's in Fedora's default stack.)

Manager app: clearer setup, safer first run

  • The setup wizard's anti-spoof step now only appears when there's a colour camera (the CNN is
    colour-only and abstains on IR), and it reflects the current state — a satisfied "already on" step
    instead of an actionable "Turn on" when it's already enabled (the default). Matches the terminal
    ward setup.
  • Cancelling the admin password prompt during an in-app enroll/calibrate now shows a toast and
    reveals the console, instead of silently flipping back (it used to look like a dead button).
  • The Overview On switch can't enable face unlock with nobody enrolled: on first run it's
    disabled so "Start setup" is the single entry point, and toggling it on with no enrolled face
    routes through the wizard (which registers first) rather than wiring up a doomed face step.

Faster, less fussy enrollment hold

  • Each pose fills (and the "Hold still…" cue clears) sooner: the per-pose usable-sample target
    drops from 12 to 9 for the guided sweep and 8 for --style ring (the ring pools its
    honest held-out gate across 12 poses, so each one can hold fewer). Both still pool 24 held-out
    frames per spectrum and keep a 4-sample-per-pose model, so the measured gate is unchanged — the
    hold per pose is ~25 % shorter (guided) / ~33 % shorter (ring).
  • The pose arrival band widens 8° → 10°, so samples start banking while the head is still
    settling instead of only after a dead-stop; still well above the estimator's ±4° noise and below
    the 18° nearest inter-pose gap. The arrow's overshoot-reversal is now a fixed ~13.6° of overshoot
    (band-independent), so widening the band didn't push the reversal point out with it.

Ward v0.4.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 13:21