| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Attendances (hr_attendance)
• Discuss (mail) • Employees (hr) |
| Community Apps Dependencies | Show |
| Lines of code | 3119 |
| Technical Name |
eh_hr_face_kiosk |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Attendances (hr_attendance)
• Discuss (mail) • Employees (hr) |
| Community Apps Dependencies | Show |
| Lines of code | 3119 |
| Technical Name |
eh_hr_face_kiosk |
| License | LGPL-3 |
| Website | https://www.erpheritage.com.au/ |
Face Kiosk Attendance
Real biometric clock in for Odoo 19 Community. The browser captures a face, generates a 128 dimension numeric embedding, and sends only that to the server. The server runs a cosine match against active templates, posts to hr.attendance, and writes the audit trail. Raw images never leave the device.
Day in the life
A worker walks up, looks at the tablet, and the day starts.
The reception tablet sits at the front door open to /eh_hr/kiosk/<site code>. A worker walks up. The browser asks for camera permission once on first run. face-api.js detects a face, generates a 128 float embedding locally, and POSTs the embedding to the server with the kiosk token. The server cosine matches against active templates for the company; on a hit it creates an hr.attendance check in or closes the open one. The kiosk shows the worker's name, ticks, and resets to the welcome screen. Raw frames stay on the device.
Overview
What this module does, in one read.
eh_hr_face_kiosk turns any browser with a camera into a self hosted face attendance kiosk for Odoo 19 Community.
The browser does the embedding, the server does the match, and the suite base does the consent and audit. No third party cloud, no per employee subscription, no proprietary firmware. The kiosk runs out of your Odoo at /eh_hr/kiosk/<site code>; the site, device, and token live on the suite base.
Capabilities
Ten things this module gives you, with no padding.
In browser embedding
face-api.js loads once, captures a face from the device webcam, and generates a 128 float embedding locally. Only the embedding is sent to the server. Raw frames and intermediate images never leave the device.
Server side cosine match
The /eh_hr/kiosk/face/match controller normalises the incoming embedding and compares it against active templates for the device's company by cosine distance. The configurable match threshold defaults to 0.55; below threshold a low confidence exception is raised.
Multi sample enrolment
The HR enrolment wizard captures three to five samples and stores them as separate eh.hr.face.template rows. The match engine compares the incoming embedding against every active sample, so varied lighting, angle, and minor appearance changes still match.
Hard linked to consent
Every template is required to point at a granted face consent record for the same employee. A constraint refuses to reactivate a template whose consent is not granted. Privacy by design, enforced in code.
Optional per site geofence
Sites can opt into a centre point and radius. The match controller refuses to clock in a worker outside the radius and raises a geofence violation exception. Pass and fail outcomes both land in the audit trail.
Consent withdrawal cascade
Withdraw face consent on the employee record and the matching templates can no longer be reactivated. The match path filters for consent state granted at every search, so a withdrawn consent stops matching the moment it is written.
Auto toggling check in and check out
On a successful match the controller looks up the worker's open hr.attendance row. Open row found, it closes it. No open row, it creates a check in. The kiosk does not need a separate in or out button.
Authenticated kiosk endpoints
The match endpoint requires the X-EH-Kiosk-Token header issued by the suite base pairing flow. The token resolves to a device, which resolves to a site, which resolves to a company. Cross company match is impossible at this layer.
Every attempt audited
Each match request writes to eh.hr.kiosk.event: the attempt, the success or failure, and the resulting attendance check in or check out. Below threshold matches log the best distance for diagnostics.
Hardware agnostic
Any modern device with a camera and a Chromium, Firefox, or Safari based browser running on the local network. iPad, Android tablet, Windows PC, ChromeOS box, Linux thin client. No app install. No vendor firmware.
Compared
How this module stacks up.
Workflow
Install. Set up face-api.js. Enrol. Clock in.
Four steps, the same shape every other module in the suite uses.
Install
Pick eh_hr_face_kiosk in Apps. The suite base, hr_attendance, and the consent infrastructure come along automatically via the dependency chain.
Drop in face-api.js
The face-api.js model files are not bundled (about six megabytes; operators may want a specific release). Run the static/lib/face-api/README setup once and the kiosk picks it up.
Enrol
From the employee record, run the enrolment wizard. Capture three to five samples, acknowledge the consent text, save. The face consent is granted in the same transaction.
Clock in
Open /eh_hr/kiosk/<site code> on the reception tablet. Workers walk up, the browser handles the capture, the server handles the match.
Why Heritage
Where this module leads, where it matches, what we are honest about.
- Browser embeds, server matches; raw frames never network
- Templates hard linked to a granted consent
- Kiosk endpoint hardened by device token, scoped to a company
- Standard hr.attendance check in and check out
- Multi company isolation by record rule
- Suite namespaced privilege groups for ACL
- face-api.js model files are not bundled; one time setup required
- Comfort zone for the Python match loop is up to a couple of thousand templates per company; beyond that an index is the right answer
- Base face match alone does not stop a printed photo; pair with the liveness module for that
Engineering
Six engineering rules we hold ourselves to.
Browser does the embedding.Raw frames never reach the network. Only the 128 float embedding goes to the server.
Embedding validation at write time.Constraint checks JSON, list shape, dimension match, and numeric values. Bad embeddings are rejected on the model, not at the controller.
Consent before template.Templates require a granted face consent on the same employee. Reactivation refuses if the consent is no longer granted.
Token scoped to company.Device token resolves to a device, site, and company. Cross company match is impossible at the controller.
Every match writes audit rows.Attempts, successes, failures, geofence pass and fail, attendance in and out: each becomes an immutable kiosk event.
Capability focused descriptions.No competitor names in code or docs. Every claim describes what the module does, not what it replaces.
Frequently asked questions
Honest answers to the questions a buyer asks.
Does this run on Odoo 19 Community?
Yes. Standard hr.attendance and ORM, no Enterprise gates. The kiosk is a public route protected by the device token.
Do raw face images leave the device?
No. The browser runs face-api.js to produce a 128 float embedding locally and sends only that to the server. The server cannot reconstruct the original image from the embedding.
What hardware does it need?
Any modern device with a camera and a Chromium, Firefox, or Safari based browser on the local network: iPad, Android tablet, Windows PC, ChromeOS box, Linux thin client. No app install, no vendor firmware.
Why is face-api.js not bundled?
The model files are roughly six megabytes and many operators want to pin a specific release. The module ships a static/lib/face-api/README with the one off setup steps; once dropped in, the kiosk picks them up automatically.
How accurate is the match?
The default cosine distance threshold is 0.55, configurable per company. Below threshold a low confidence exception is raised and the kiosk asks the worker to retry. Multi sample enrolment keeps recall high under varied lighting and angles.
Does it scale?
The Python cosine match comfortably handles dozens to low hundreds of templates per company per kiosk hit. Past roughly two thousand templates per company an index becomes the right answer; that work is on the roadmap, not in the box today.
What stops a printed photo of someone's face?
Pure face match alone does not. Install eh_hr_face_liveness alongside this module for an active blink check before capture, which defeats low effort photo attacks. For higher security exposure, pair the kiosk with a paid passive liveness vendor.
Please log in to comment on this module