| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Attendances (hr_attendance)
• Discuss (mail) • Employees (hr) |
| Community Apps Dependencies | Show |
| Lines of code | 4541 |
| Technical Name |
eh_hr_face_liveness |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Versions | 16.0 17.0 18.0 19.0 |
Attended Face Capture
An attended-capture prompt in front of the face match that logs every check-in attempt for attendance audit.
Why this module
Attended Face Capture
Records what the kiosk reports, and says so
The outcome is computed in the browser and stored as client-asserted. Every record, the model help text, and the settings page state plainly that the server does not verify it. No inflated anti-spoofing claim to walk back later.
One write-once row per attempt
Each check-in attempt writes an attended-capture record with outcome, timestamp, device, site, duration, and prompt shown. Views are read-only, no group can edit, and only admins can delete. A matching kiosk event row is logged alongside, so the audit trail is consistent.
Per-company control and a self-cleaning log
Toggle the prompt, prompted blink count, timeout, and retention per company. A daily cron sweeps rows past the company horizon in capped batches, so the log stays queryable in Odoo instead of growing into a side spreadsheet.
Day in the life
Please blink slowly twice. A moment later, the day starts.
A worker steps up to the kiosk. The welcome screen hands off to an attended prompt that asks them to blink slowly. The browser runs face-api.js, counts blinks from the eye aspect ratio, and reports an outcome to the server, which records it as reported. On a reported pass the kiosk continues into face match; on a fail or timeout it shows a polite retry screen. Every attempt, pass, fail, or aborted, lands in the attended-capture log, so a fortnightly review can spot the depot with a spike of failed attempts. The server keeps an honest record of what the kiosk reported and never claims to have checked it.
Edge cases
The cases most modules quietly ignore.
In the shipped code today, each one a place where a cheaper module silently does the wrong thing.
The browser computes pass, fail, or aborted; the server stores it verbatim with client_asserted set to true and all fields read-only. Nothing in the server claims the result was verified, so a recorded pass is never presented as proof of a real person.
Both the config and log endpoints require a valid X-EH-Kiosk-Token tied to an active kiosk terminal. Unknown or missing tokens return 401, and company, site, and device are taken from the terminal record, not from the request body, so a caller cannot spoof which company a record lands in.
Config and log calls each pass through the shared rate limiter at 120 hits per scope, keyed by token or client IP, returning 429 when over budget. A noisy or looping kiosk cannot flood the audit log.
The log endpoint rejects any outcome outside passed, failed, or aborted with a 400, rejects malformed JSON bodies with a 400, and truncates prompt and fail-reason text to 255 characters before storing.
A global record rule restricts attended-capture records to the user's allowed companies, and each record carries a required company taken from the kiosk device. The retention cron loops company by company using each company's own horizon.
The daily retention sweep deletes in capped batches (default 2000 rows per run) and reports progress through the cron commit-progress hook, so it cannot starve other jobs or run unbounded on a large backlog.
Access rules grant read to managers and auditors and unlink only to admins; no role can write or create records through the UI. Records are created only by the kiosk endpoint, keeping the audit trail tamper-resistant.
What is inside
Built to do the job, end to end.
- Attended-capture record. The eh.hr.liveness.check model stores one read-only row per attempt: outcome, recorded-on timestamp, prompt shown, duration in ms, blinks reported, fail reason, kiosk device, site, optional employee, and company. A computed reference summarises outcome, employee, and time.
- Two kiosk endpoints. A config endpoint returns the per-company enabled flag, prompted blink count, and timeout for the calling device, and a log endpoint records the reported outcome. Both authenticate by kiosk device token and are rate limited.
- Browser blink prompt. A script injected into the kiosk shell adds a quick-check screen and a fail screen, runs blink detection from the face-api.js 68-point landmark model using eye aspect ratio, and posts the result. If the model is not loaded or the camera is denied, it reports a failed or aborted outcome rather than blocking the kiosk.
- Per-company settings. Settings on the company and the Attendance configuration page expose the attended-capture toggle, prompted blinks, capture prompt timeout in milliseconds, and retention days, defaulting to two blinks, an 8000 ms timeout, and a 180-day horizon.
- Retention cron and audit. A daily ir.cron runs the retention sweep per company in capped batches, and every logged attempt also writes a kiosk event (liveness pass or fail) referencing the capture record, with the client IP, for a consistent attendance audit trail.
Honest about the edges
What this does not do, so nothing surprises you.
- Not an anti-spoofing or server-verified liveness control. The outcome is computed entirely in the browser and recorded as reported. A printed photo or a screen held to the camera is not detected, and anyone who controls the kiosk device can report any outcome.
- Blink detection depends on the face-api.js library and its 68-landmark model being loaded by the kiosk; if the model is absent or the camera is denied, the attempt is recorded as failed or aborted and does not block check-in.
- The employee link on a record is optional and only set later by the kiosk after the subsequent face match identifies the worker; an attended-capture record on its own is not tied to a person.
- This module records and audits attempts; it does not perform the face match itself, which is handled by the face kiosk it depends on.
- Requires the ERP Heritage attendance base, face kiosk, and HR core modules; it extends the existing kiosk and is not a standalone attendance system.
- Targets Odoo 18 Community.
attended face capture, face kiosk check-in audit, kiosk attendance audit, hr attendance face capture, blink prompt kiosk, Odoo 18 face attendance, kiosk check-in log, attendance dispute resolution, client-asserted capture record, per-company attendance retention
Please log in to comment on this module