Ordered by what blocks what, not by size.
The gaps documented in SECURITY_NOTES.md, in the order they should land. The first three are prepared and under review.
- Mask the pan in logs. First six and last four at most, everywhere the pan
is written. Stop logging the request body and the
curlcommand line. - Mask the pan on screen. The passenger needs to recognise the card, not read it back.
- Validate parsed fields. The pan is digits, the expiry is four digits. Reject anything else at the parser, before it reaches a buffer.
- Replace the shelled-out curl with libcurl. Removes the injection surface and the fragile status-code parsing in one change.
- Read configuration from
validator.env. Endpoint, paths and account stop being compiled-in constants. - Drop the sudo rule for a udev rule. Raw USB access by group membership instead of passwordless root.
- Mutual TLS to the backend. Per-unit client certificates, individually revocable.
The interface, the log messages and the code comments are in Azerbaijani and Turkish. Everything becomes English, in one pass so the codebase is never half converted:
- User-facing strings in
card_gui.py—Ödəmə Uğurludur,Ödəmə Uğursuzdur,Prosess Emal edilir, theYERI Validatorheader. - Console output in
card_gui.py— the startup control hints and the FIFO command traces. - Log messages in
parse_card_data.cpp— everylogInfo,logErrorandlogSuccessstring. - Console output in
run_ctls_read.expandstart_all.sh. - Code comments across all five source files.
The interface strings move into a lookup table in the same pass rather than being translated in place, so Azerbaijani returns as a selectable language instead of being lost. English becomes the default and the source of truth.
- Walk the TLV properly. Read the length byte instead of matching the
literal
5A08, so 13- and 19-digit pans parse. Strip theFnibble padding an odd-length pan. - Collapse the duplicated expiry reformat.
YYMMtoMM/YYhappens in both the C++ and the Python; it should happen once. - Reduce the doubled expiry field. The request sends
expiryDateandexpiry_datefor a backend contract that has since settled. - Retry with backoff. A single failed request is currently a decline. A transient 5xx or a dropped connection deserves a retry before the passenger is refused.
Built or in progress on the prototype, not yet in this repository:
- Offline store-and-forward queue and blacklist. Belongs inside
parse_card_data, in the same code path that would otherwise wait for the backend. - QR ticket validation. Camera capture and decode, for the printed receipt issued to passengers boarding without a card or phone.
- Passenger counting. Camera-based, with the IR ring for night operation.
- GPS telemetry and route analytics. Positioning is being built first in Robot-Tracker — same modem family, same coverage-gap problem — and folded back in.
- In-ride advertising on the display and speaker.
- Face-based payment. Research only. Gated on the regulatory position and on explicit passenger consent, neither of which is settled.
- Photographs of the prototype, assembly and field testing.
- The demonstration recordings consolidated and captioned.
- A social preview image so the repository presents properly when shared.