Terminal Thin Client Blueprint

Android thin-client payment terminal — base UI + palm-vein capture with on-device 1:N match + card reader SPoC passthrough + PGW API client; no rail SDKs or EMV kernel on-device

   
Feature terminal-thin-client
Category Payment
Version 1.0.0
Tags terminal, thin-client, android, kotlin, palm, spoc, pgw-client
YAML Source View on GitHub
JSON API terminal-thin-client.json

Actors

ID Name Type Description
merchant Merchant / Cashier human  
customer Customer human  
palm_scanner Built-in Palm Scanner external  
card_reader Built-in SPoC card reader external  
pgw Payments Gateway external Central PGW that terminal calls via /v1/*

Fields

Name Type Required Label Description
device_id token Yes Attested device identifier  
merchant_id text Yes    
amount number Yes    
method select Yes    
palm_template_id token No Opaque palm template id (local; resolved via PGW)  

Rules

  • privacy: MUST: palm templates never leave the device (POPIA s.26), MUST: 1:N palm match runs on-device; only matched template_id crosses the network
  • security: MUST: terminal ↔ PGW connection is mTLS with device attestation on every call, MUST: card data never stored on device; SPoC-encrypted and forwarded immediately
  • offline: SHOULD: UI displays ‘cannot accept payments offline’ when PGW unreachable — no on-device decisioning

Outcomes

Pgw_unreachable (Priority: 10)

Given:

  • PGW request fails after retry

Then:

  • emit_event event: terminal.pgw_unreachable

Result: UI shows offline banner; no payment attempted

Palm_no_match (Priority: 20)

Given:

  • on-device 1:N match finds no template

Result: UI asks to rescan or use card

Palm_payment_initiated (Priority: 100)

Given:

  • merchant entered amount
  • customer chose palm method
  • on-device palm match returned template_id

Then:

  • call_service target: pgw.palm_sessions_resolve
  • call_service target: pgw.create_payment

Result: PGW returns settlement status; terminal shows receipt prompt

Card_payment_initiated (Priority: 110)

Given:

  • merchant entered amount
  • customer chose card method
  • SPoC reader returned encrypted card payload

Then:

  • call_service target: pgw.create_payment

Result: PGW runs EMV kernel and returns auth status

Events

Event Description Payload
terminal.payment_started    
terminal.pgw_unreachable    
Feature Relationship Reason
popia-compliance required Handles biometric templates and cardholder data
payments-gateway-api required Terminal is a thin client of the PGW
palm-vein required Palm-vein SDK for capture and on-device matching
device-attestation required TPM-backed attestation on every PGW call
biometric-auth required Shared enrolment + auth semantics