Module 2: Card Dispenser, Personalization & Reader Subsystem
| Document ID | Revision | Date | Owner | Status |
|---|
| MR-ENG-M2-001 | A | 2026-09-13 | Hardware Engineering — Card Systems | Released for review |
2.1 Purpose and Scope
This document specifies the card issuance, personalization, and card reader subsystems for Money Roll. It covers the motorized card dispenser, card stock selection, on-device personalization data layout for the default Stellar-native card tier, the optional Lithic-issued Visa tier, the hybrid reader used for return customers, and PC/SC driver integration on the Debian 12 host. It interfaces with Module 5 (firmware/Stellar) for cryptographic operations and Horizon calls.
2.2 Card Issuance Module Selection
| Candidate | Hopper Capacity | Encoding | Printing | Interfaces | Power | Notes |
|---|
| Creator (Shenzhen Creator) CRT-591 | 200 cards, CR80 0.76 mm | IC (contact), RF (contactless), magnetic stripe | Optional integrated thermal printhead (300 dpi) | USB, RS-232 | 12 V DC, 3 A peak | Selected primary |
| Creator CRT-571 | 100 cards, CR80 0.76 mm | IC + RF | No integrated print (requires external printer module) | USB, RS-232 | 12 V DC, 2 A peak | Rejected: lower hopper capacity, no integrated print path |
| Evolis / Zebra OEM engine (e.g., Evolis Primacy 2 OEM) | 100-200 cards | IC + RF via add-on encoder module | Dye-sublimation, full-color | USB, Ethernet | 24 V DC, 5 A peak | Rejected for baseline: higher cost, higher power draw, overkill color printing not required |
2.2.1 Selection Rationale
The Creator CRT-591 is selected because it integrates card feed, contact IC encoding, contactless RF encoding, magnetic stripe encoding (retained for legacy compatibility though unused in the baseline data model), and monochrome thermal printing in a single compact module sized for the kiosk enclosure footprint (Module 3). The 200-card hopper supports approximately one week of median-volume operation between refills. The CRT-571 lacks integrated printing, which would require a second serial device and additional card-path length inside an already space-constrained enclosure. The Evolis/Zebra dye-sublimation OEM engines are reserved for a future full-color loyalty-card product tier; they are not justified for the plain QR/text card layout used here.
2.2.2 CRT-591 Reference Specifications
| Parameter | Value |
|---|
| Card size | CR80 (85.60 x 53.98 mm), 0.76 mm thickness |
| Hopper capacity | 200 cards |
| Host interface | USB 2.0 (primary), RS-232 (service/debug) |
| Power | 12 V DC, 3 A peak during motor/print cycle, 200 mA idle |
| IC interface | ISO 7816 contact station, class A/B/C auto-detect |
| RF interface | ISO 14443 A/B, 13.56 MHz antenna coil |
| Print | Thermal, 300 dpi, monochrome |
| Capture bin | Internal reject/capture bin, 50-card capacity |
| Error reporting | Status byte over RS-232/USB, per Section 2.5 |
2.3 Card Stock
| Tier | Card Stock | Chip | Use Case |
|---|
| Stellar-native (default) | CR80 PVC/PET-G composite, thermal-printable overlay | NXP JCOP4 J3R180 dual-interface Java Card (contact + ISO 14443-4 contactless) | Standard issuance, on-device key material, ECDSA challenge-response |
| NFC-only economy tier | CR80 PVC, thermal-printable overlay | MIFARE DESFire EV3 | Lower-cost issuance where contact IC and asymmetric crypto are not required (UID + symmetric AES authentication only) |
Both stocks use pre-printed graphic art (Money Roll branding, denomination-agnostic) with a reserved blank panel (30 mm x 40 mm) for the thermal printer to overlay the QR code, terminal ID, issue date, and balance line at personalization time.
2.4 Personalization Flow
At the point of dispensing, the terminal binds the physical card to the customer's active Stellar session address generated (or supplied) during the transaction.
2.4.1 Contact Chip Data Layout (JCOP4 Java Card Tier)
| Element | Value |
|---|
| Application AID | F0 4D 4F 4E 45 59 52 4F 4C 4C ("MONEYROLL") |
| EF.PUBKEY | 56-byte Stellar public key (G-address, StrKey-encoded, stored as raw 32-byte ed25519 key plus 24-byte padding/version metadata) |
| EF.META | Terminal ID (8 bytes), issued-at timestamp (8 bytes, Unix epoch), program ID (4 bytes, identifies Stellar-native vs. Lithic tier) |
| EF.TOKEN | 32-byte encrypted session token, AES-256-GCM, encrypted under the terminal fleet key with a per-card random salt (16 bytes) stored alongside the ciphertext |
The same application and file structure is mirrored over the ISO 14443-4 contactless interface so the reader in Section 2.6 can authenticate the card via either contact or contactless presentation.
2.4.2 NFC NDEF Mirror
| Element | Value |
|---|
| NDEF record type | URI record |
| URI payload | web+stellar:pay?destination=G... (customer's Stellar public key) |
| Purpose | Allows a standard consumer smartphone NFC tap to open a Stellar-compatible wallet app pre-filled with the destination address, independent of the terminal's own reader |
2.4.3 Thermal Print Layout
+--------------------------------------+
| MONEY ROLL |
| |
| [ QR CODE 22x22 mm, ECC-M ] |
| (encodes public key G-address) |
| |
| TERMINAL ID: MR-0000482 |
| ISSUED: 2026-09-13 |
| INITIAL BALANCE: 84.00 USDC |
| |
| ** NOT A BANK CARD ** |
+--------------------------------------+
The "NOT A BANK CARD" line is printed whenever the optional Lithic debit program is not enabled for the issuing terminal/tenant. When the Lithic program is enabled (Section 2.4.4) this disclosure line is omitted and replaced with card network branding supplied by Lithic's fulfillment partner.
2.4.4 Lithic Program Tier (Optional)
| Aspect | Stellar-Native Tier (default) | Lithic Tier (optional) |
|---|
| Card issuer of record | Money Roll operator (non-bank card) | Lithic, Inc., program-managed Visa |
| Provisioning call | N/A (local personalization only) | POST /v1/cards with type: PHYSICAL against Lithic API |
| Fulfillment | On-site CRT-591 dispense and print | Embossed/fulfilled by Lithic's fulfillment partner, or personalized on-site under a signed Lithic "custom personalization" agreement |
| Funding | Direct Stellar balance, no card network rails | Card balance funded from Stellar balance via operator-managed settlement, spendable on Visa network |
| Disclosure | "NOT A BANK CARD" printed | Standard Visa/Lithic program disclosures per Lithic cardholder agreement |
| Fallback | N/A | If Lithic API is unreachable or the tenant has not enabled the program, terminal automatically falls back to the Stellar-native tier for that transaction and logs the fallback event |
2.5 Dispenser Command Sequence
The CRT-591 uses a framed serial protocol: STX <command> <data> <BCC> ETX, where BCC is an XOR checksum over the command and data bytes.
| Command | Frame Purpose | Response |
|---|
| INIT | Reset dispenser, home card path | ACK / status byte |
| STATUS | Query hopper level, jam state, capture bin level | Status byte bitmap |
| MOVE_TO_ENCODE | Transport card from hopper to IC/RF encode station | ACK, position confirm |
| IC_POWER_ON / IC_POWER_OFF | Activate/deactivate contact station VCC | ACK |
| APDU_PASSTHROUGH | Forward ISO 7816 APDU to card, return response APDU | APDU response + SW1SW2 |
| RF_PASSTHROUGH | Forward ISO 14443-4 frame to card antenna, return response | RF response frame |
| PRINT | Send thermal print buffer, execute print pass | ACK, print-complete status |
| DISPENSE_TO_BEZEL | Transport personalized card to customer-facing bezel slot | ACK, card-present-at-bezel confirm |
| CAPTURE | Retract unclaimed or failed card into internal capture bin | ACK, capture-bin-count increment |
2.5.1 Error Handling
| Error Code | Meaning | Firmware Action |
|---|
| E01 | Hopper empty | Halt dispensing, alert service menu, allow deposit-only operation to continue |
| E02 | Card jam in transport path | Retry home cycle once, then CAPTURE and alert |
| E03 | IC encode failure (APDU error/timeout) | Retry personalization up to 2 times, then CAPTURE card and issue no-card receipt with QR fallback |
| E04 | RF encode failure | Same as E03 |
| E05 | Print head fault (thermal head over-temp or paper-equivalent ribbon fault) | Abort dispense, CAPTURE, alert service menu |
| E06 | Capture bin full | Disable dispensing (deposit-only mode continues), alert for service pickup |
| E07 | Card not taken from bezel within 30 s | Retract via CAPTURE, log unclaimed-card event |
2.6 Hybrid Card Reader (Return Customers)
| Candidate | Type | Interfaces | EMV Level | Contactless |
|---|
| Creator CRT-310 | Motorized dual-interface reader | USB, ISO 7816, ISO 14443 | EMV L1 certified | Integrated |
| Sankyo ICT3K5 | Motorized dual-interface reader | USB, ISO 7816, ISO 14443 | EMV L1 certified | Integrated |
| ID Tech Augusta (dip reader, PC/SC) | Insert/dip reader | USB (PC/SC/CCID) | EMV L1 certified | Not integrated (contact + stripe only) |
Selection: Creator CRT-310 motorized dual-interface reader as the primary hybrid reader, because it services both the Stellar-native contact chip and the ISO 14443-4 contactless mirror without a second peripheral. Where cost-reduced kiosk variants use the ID Tech Augusta dip reader (contact-only), a separate ACR1252U USB NFC reader is added to cover contactless presentation.
2.6.1 PC/SC Driver Stack (Debian 12)
apt-get install -y pcscd libccid pcsc-tools libpcsclite1
systemctl enable --now pcscd
# Verify reader enumeration
pcsc_scan
| Component | Role |
|---|
pcscd | PC/SC resource manager daemon |
libccid | USB CCID driver covering CRT-310, ID Tech Augusta, ACR1252U |
pcsc-tools | Diagnostic utilities (pcsc_scan) |
| Money Roll reader service | Systemd unit moneyroll-reader.service, links against libpcsclite, communicates with Module 5 firmware bridge over local Unix socket |
2.6.2 UID + Secure Token Authentication Flow
CARD READER/TERMINAL BACKEND (Horizon)
| | |
|<---- SELECT AID ---------- | |
|---- OK, AID selected ----->| |
|<---- READ EF.TOKEN ------- | |
|---- EF.TOKEN bytes ------->| |
| | decrypt EF.TOKEN with fleet key |
| | (AES-256-GCM, per-card salt) |
| | verify HMAC / session binding |
| |---- GET /accounts/{id} ---------->|
| |<---- balances, sequence ----------|
| | unlock deposit/transfer actions |
2.6.3 Anti-Cloning
| Tier | Mechanism | Assurance Level |
|---|
| JCOP4 Java Card (Stellar-native) | On-card ECDSA P-256 challenge-response applet: terminal sends random 32-byte challenge, card signs with private key never exported from the chip, terminal verifies against EF.PUBKEY-derived or separately provisioned P-256 public key | High assurance: deposit and transfer both permitted |
| MIFARE DESFire EV3 (UID-only / economy tier) | UID read plus static AES-128 authentication, no per-transaction asymmetric proof | Low assurance: deposit-only, transfer disabled |
2.6.4 Rate Limiting and Lockout
| Control | Value |
|---|
| Max failed authentication attempts | 5 per rolling 10-minute window |
| Lockout duration after max attempts | 30 minutes, card-specific (identified by EF.PUBKEY hash), enforced server-side |
| Max reader read attempts per physical presentation | 3 retries before "remove and re-present" prompt |
| Alerting | 3 consecutive lockouts on distinct cards within 1 hour at one terminal raises a fleet security alert |
2.7 Service Considerations
| Task | Interval | Procedure Summary |
|---|
| Hopper refill | As needed (approx. weekly at median volume) | Open front service panel, load up to 200 CR80 blanks oriented per hopper label, verify STATUS command reports correct count |
| Cleaning card pass | Monthly | Run manufacturer cleaning card (adhesive-roller type) through CRT-591 transport path per Creator maintenance guide |
| Firmware update | As released, via service USB or fleet OTA staging | Dispenser firmware image validated by checksum, applied via CRT-591 bootloader mode, verified with STATUS query post-flash |
| Capture bin handling | Emptied at each service visit or when E06 alert fires | Remove bin, log captured card count against dispense records for reconciliation, destroy captured cards per data-security procedure (shred, chip destruction) |