The extra cropped-result panel duplicated what the crop pad already shows and the cleaned image supersedes it. Removes the panel, its state, the pointer- release refresh handlers and the app.js plumbing. The crop result is still uploaded (croppa stays the source when nothing is cleaned).
YOUreka Tools — Fingerprint Service
A small Express app that hosts the YOUreka tools landing page and the
Fingerprint Agent enrollment wizard. Fingerprint capture is performed by
the local fpagent binary (Socket.IO on
127.0.0.1:9000); this app provides the login (YOUreka Auth), the permitted
domain selection, and the a2loft integration that stores the enrolled
fingerprints.
Layout
tools/
├── server.js # Express app: routes, session middleware, proxies
├── yrka-auth.js # YOUreka Auth cookie session → PocketBase (authRefresh)
├── permit.js # OpenFGA domain permission checks + 5-minute cache
├── public/
│ ├── index.html # landing page (Image Cropper + Fingerprint Agent)
│ └── assets/
│ ├── style.css
│ └── fp/ # /fingerprint enrollment wizard (Vue 2 via CDN)
└── test/ # node --test suite (fake portal / PocketBase / a2loft)
Running
Prerequisites: Node.js 22+, fpagent installed and running on this laptop
(see the fingerprint-agent repository for installation), the U.are.U 4500
scanner attached.
cd tools
npm install
npm start # → http://localhost:4173
Open http://localhost:4173 and sign in with your YOUreka account.
fpagent must allow the tools origin. On a dev machine run it with:
fpagent -allowed-origins http://localhost:4173
How enrollment works
- Sign in — YOUreka Auth (portal web-auth redirect). The PocketBase session is kept in an httpOnly cookie and refreshed server-side.
- Pick a domain — the hardcoded catalog (UNICAL, Metropolitan Hotel, UCTH,
UNICAL Radio International, YOUreka) is filtered against the same portal
OpenFGA endpoint fpagent uses (
capture_biometricper domain). Results are cached for 5 minutes; the Refresh domains control unlocks once the cache expires. fpagent re-authorizes every capture regardless. - Locate the staff profile — reference + OTP, validated by
apis.a2loft.netthrough a same-origin proxy (the operator's phone comes from the session). - Capture — right thumb and right index finger, one capture at a time,
with per-scan progress and cancel; the PocketBase token, domain and
reference travel with every
fprint-enrollto fpagent. - Save — both templates are posted to a2loft (with a fresh OTP).
Configuration
Everything is hardcoded in tools/server.js by design — port 4173, portal
https://portal.yrka.app, PocketBase https://pb.itcass.net, a2loft
https://apis.a2loft.net, agent http://127.0.0.1:9000, and the domain
catalog. Change them there; there are no environment variables or config
files.
The Image Cropper
The /cropper page (Smart Photo Editor) lets operators review, crop and save
identity photos. It reuses the YOUreka session for identity, requires the
crop_image permission on domain:idid for every proxied action (verified
against the portal's OpenFGA endpoint — live on save, 5-minute cached on
reads), and keeps the a2loft OTP requirement only on the save step.
Its service credentials are the sole environment variables this app uses.
They live in dotenvx-encrypted files at the repository root — .env for
development, .env.production for deployment:
MINIO_ACCESS_KEY=… MINIO_SECRET_KEY=…
AZURE_STORAGE_CONNECTION_STRING=…
NODERED_HTTP_USERNAME=… NODERED_HTTP_PASSWORD=…
CARVEKIT_API_KEY=…
Without them the rest of the app works and /cropper routes answer 503.
The private decryption keys sit in .env.keys (gitignored, never commit it).
dotenvx run -f .env -- node tools/server.js # local, from the repo root
dotenvx set MINIO_SECRET_KEY "<value>" -f .env # add/rotate a value
The Docker image contains the encrypted .env.production and runs through
dotenvx; only the private key is supplied at runtime (never baked in):
docker build -t yreka-tools .
docker run -d -p 4173:4173 --name yreka-tools \
--env DOTENV_PRIVATE_KEY_PRODUCTION="$(grep -oP '^DOTENV_PRIVATE_KEY_PRODUCTION=\K.*' .env.keys)" \
yreka-tools
dotenvx run --strict makes the container exit rather than start with
undecryptable credentials. Note that --env values are visible to
docker inspect; on a shared host prefer an env file with restrictive
permissions (--env-file deploy.keys) or your platform's secret store.
Tests
cd tools
npm test # node --test — 35 tests, no network or hardware required
Docker
Docker
The app is stateless, so the container only serves the web front-end; fpagent
keeps running on the operator's laptop (the wizard connects to
http://127.0.0.1:9000 from the browser, wherever this container lives).
docker build -t yreka-tools .
docker run -d -p 4173:4173 --name yreka-tools yreka-tools
Behind a TLS-terminating proxy the app honours X-Forwarded-Proto
(trust proxy is enabled), so session cookies get the Secure flag
automatically.
Field walkthrough (real portal, PocketBase, a2loft, and U.are.U 4500): login → permitted-domain filtering → staff lookup → two scanner captures with cancel path → save → reset, all verified end to end via Playwright.