bitspire/packages/hal
Padreug 76f3c2ff9d fix(hal): enable Apex escrow, use the real return bit, checksum the whole frame
Three protocol corrections from Pyramid's spec (RS_232 Rev G), all of which
this driver had guessed at because it was written clean-room without it.

**Escrow was never enabled.** BYTE 1 bit 4 is an enable, and the driver left
it clear on every poll. With it clear the acceptor does not stop at escrow,
so the host is never offered the stack-or-return decision and notes are
banked before anything has validated them. The entire FSM here is built
around that decision point, so this was not a missing nicety — the driver's
central flow could not have happened. It is now asserted on every poll.

**Return used the wrong mechanism.** The driver expressed "give the note
back" by zeroing the enable mask mid-escrow, under an in-code assumption
that "Apex has no distinct return opcode". It has one: BYTE 1 bit 6. The old
approach was flagged in a comment as needing hardware verification; the spec
settles it instead. Note the spec also distinguishes Returning (host refused
a valid note) from Rejected (acceptor judged it invalid), which is the
distinction this bit exists to express.

**The checksum range was hardcoded to the host frame.** computeChecksum
always XORed bytes 1..5, which is right for the 8-byte poll and wrong for
the 11-byte reply, where it should span 1..8. So every reply failed
validation. That was masked by the check being non-fatal "pending hardware
verification", which logged a warning and parsed anyway.

The range is now derived from the frame length, and verified against the two
reset frames the spec spells out literally with their checksums — the only
ground truth available without hardware. Those same frames are now a test.

With the range confirmed, a mismatch becomes a hard drop rather than a
warning. A corrupt frame carries a denomination field, and crediting a note
from a frame known to be damaged is the one outcome worth refusing. The raw
bytes are logged so a systematic framing error stays diagnosable.

Also records two operational facts from the spec that were not written down:
the interface is Mars/MEI GL5-compatible (hence the resemblance to the EBDS
driver), and polls must not fall more than 5s apart or the acceptor may dump
an escrowed note and stop accepting until the host resumes. Our 100ms cadence
is comfortably inside that.
2026-09-30 21:59:56 +02:00
..
src fix(hal): enable Apex escrow, use the real return bit, checksum the whole frame 2026-09-30 21:59:56 +02:00
build.rs feat(docker): add dev.sh with auto-funding and ATM app setup 2026-02-15 14:19:16 -05:00
Cargo.toml feat(docker): add dev.sh with auto-funding and ATM app setup 2026-02-15 14:19:16 -05:00
package.json refactor(rename): @lamassu/* → @bitSpire/* package scopes 2026-06-01 19:08:03 +02:00
tsconfig.json feat(docker): add dev.sh with auto-funding and ATM app setup 2026-02-15 14:19:16 -05:00