Skip to main content
Proposed (batch stackra-50, STA-1097, STA-904). The vendor-SDK ADR that 0442 decision 4 and 0253 decision 3 ask for, for the imin family. Certification pending: written from iMin’s public SDK documents, not yet checked on a certified model.

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). iMin’s terminals have a built-in printer, a drawer port and a built-in scanner that no Web API or LAN path reaches; only iMin’s SDK does (0339 open detail 2).

Decision

  1. Driver name imin. @stackra/peripherals ships IminReceiptPrinterDriver, IminCashDrawerDriver and IminBarcodeScannerDriver in its ./native entry, behind the unchanged ReceiptPrinter, CashDrawer and BarcodeScanner ports, selected by peripherals.printer, .drawer and .scanner set to imin.
  2. One Expo module, StackraImin, a pass-through. The till app links an Expo module named StackraImin only when its runway lists device:imin (0442 decision 3). It exposes printerStatus(), printLines(lines), openDrawer() and an onScan event carrying { code }, each a direct call to iMin’s printer SDK: getPrinterStatus(), text printing with a line feed and the partial cut on models with a cutter, and the cash box call on models with a drawer port; the built-in scanner’s decoded-code broadcast documented in iMin’s scanner SDK. The module maps nothing: it returns the SDK’s own status number and the decoded text. Its Kotlin lives in the till app’s src/native-sources/imin/ (0345 decision 6).
  3. Readiness in the driver. getPrinterStatus() answers 0 when the printer is normal; every other value (not connected, head open, out of paper, overheated) refuses, with capability print (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.
  4. 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.
  5. Absent means refused. In a build without StackraImin (web, desktop, another family) the printer and drawer refuse with print and the scanner with scanner; a subscription there does nothing. No call throws at the till.
  6. The SDK stays the vendor’s. The SDK artefacts come from iMin’s developer documentation and its SDK downloads under iMin’s terms and are linked by the till app’s build only; this repository holds no iMin binary or source.

Consequences

  • The till drives a iMin 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 external customer display (0430).

Enforcement

  • packages/experience/peripherals/src/native/**/__tests__/*.test.ts replay the imin fixture through a stand-in StackraImin module.
  • planned — a certification run on each certified iMin model (STA-739) records the fixture again; Runway refuses an Android till build listing device:imin without 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), iMin’s public SDK documents, STA-904, STA-1097.