Proposed (batch stackra-50, STA-1097, STA-904). The vendor-SDK ADR that 0442 decision 4 and 0253
decision 3 ask for, for the
pax family. Certification pending: written from PAX’s public SDK
documents, not yet checked on a certified model.Amended by
0478
(2026-10-28): decision 2’s Kotlin moves out of the till app’s
src/native-sources/pax/ into the
printer, drawer and scanner module packages, split by capability, and the drivers move with it.
The rest of this page stands.Context
0442 (accepted by the owner on 2026-10-27, decision D4 of the Stackra finish plan; its page still waits to land here) gives the commerce till an Android target and asks for one ADR per vendor SDK before a family’s first build (0442 decision 4, 0253 decision 3). PAX’s terminals have a built-in printer, a drawer port and a built-in scanner that no Web API or LAN path reaches; only PAX’s SDK does (0339 open detail 2).Decision
- Driver name
pax.@stackra/peripheralsshipsPaxReceiptPrinterDriver,PaxCashDrawerDriverandPaxBarcodeScannerDriverin its./nativeentry, behind the unchangedReceiptPrinter,CashDrawerandBarcodeScannerports, selected byperipherals.printer,.drawerand.scannerset topax. - One Expo module,
StackraPax, a pass-through. The till app links an Expo module namedStackraPaxonly when its runway listsdevice:pax(0442 decision 3). It exposesprinterStatus(),printLines(lines),openDrawer()and anonScanevent carrying{ code }, each a direct call to PAX’s NeptuneLite API (IDAL): its printer (init, text printing,start,getStatus), its cash drawer on models with a drawer port, and its scanner with a result listener. The module maps nothing: it returns the SDK’s own status number and the decoded text. Its Kotlin lives in the till app’ssrc/native-sources/pax/(0345 decision 6). - Readiness in the driver.
IPrinter.getStatus()answers 0 when the printer is ready; every other value (busy, out of paper, overheated, voltage too low, a malfunction) refuses, with capabilityprint(ADR 0250 decision 3). The drawer is driven by the printer, so it checks the same status before each kick; the kick is one-way. - Text, not commands. Receipt lines go to the SDK as text with control characters removed; the SDK draws them. Arabic shaping is the SDK font’s and is a certification row. A raster or code-page path is not built.
- Absent means refused. In a build without
StackraPax(web, desktop, another family) the printer and drawer refuse withprintand the scanner withscanner; a subscription there does nothing. No call throws at the till. - The SDK stays the vendor’s. The SDK artefacts come from the PAX developer portal (PAXSTORE developer centre) under PAX’s terms and are linked by the till app’s build only; this repository holds no PAX binary or source.
Consequences
- The till drives a PAX terminal’s printer, drawer and scanner with the same ports and settings as the desktop till.
- The status table is one line of
POS_DEVICE_FAMILIES; the tests replay transcribed SDK answers until certified models are recorded (STA-739), and a wrong code shows there first. - The Kotlin module, the config plugin that removes it from other families’ builds, and the model list are the till template’s and Runway’s work (0442 decisions 3 and 5), not this package’s.
- Card payment, the label printer and the scale on these terminals are not covered; an acquirer SDK is its own ADR
(0442 decision 6). The second screen stays the
externalcustomer display (0430).
Enforcement
packages/experience/peripherals/src/native/**/__tests__/*.test.tsreplay thepaxfixture through a stand-inStackraPaxmodule.- planned — a certification run on each certified PAX model (STA-739) records the fixture again; Runway refuses an
Android till build listing
device:paxwithout this ADR (0442 enforcement).
Supersedes and sources
Supersedes: none. Sources: owner decision D4 of 2026-10-27 (notes/handover/batches/STACKRA-FINISH.md), the 0442
draft (notes/handover/app-shells/adr/0442-native-android-till-for-pos-terminals-from-the-commerce-till-template.mdx),
PAX’s public SDK documents, STA-904, STA-1097.