Context
0253 made@stackra/peripherals Web-API first with device
presets and allowed a native module only on evidence and with its own ADR. The retail edition’s requirement, confirmed
by the owner on 2026-10-24, is the full kit on day one: a receipt printer that prints Arabic, label printers, a cash
drawer, a scanner, a customer-facing display, on a browser till, an Electron desktop till and a handheld native staff
app that also checks out. Handheld checkout prints to a Bluetooth printer, which no Web API reaches from a native app,
so that is the evidence 0253 decision 3 asked for.
Decision
-
The ports.
@stackra/peripheralsexposes one port per peripheral:ReceiptPrinter(ESC/POS),LabelPrinter(ZPL),CashDrawer,Scanner,CustomerDisplayandCardTerminal(the terminal’s own protocol stays in the payments driver; the port only pairs and reports). Each port is a class, and a client takes it by type. - Arabic prints as raster. The ESC/POS driver renders a receipt to an image and prints it as raster, so Arabic shaping and bidirectional text are the renderer’s job, not the printer’s. Text mode is a fallback for Latin-only receipts on printers that cannot take raster.
-
The drawer kicks through the printer.
CashDraweropens the drawer through the receipt printer’s kick pulse by default; a drawer on its own interface is a driver. -
The scanner is a keyboard wedge first.
Scannerreads HID keyboard-wedge input with a prefix and suffix from the preset, and takes camera scanning as a second driver. Serial and Bluetooth scanners are drivers added on evidence, under decision 3 of 0253. - Drivers per target. Web: WebUSB, WebSerial and network (a browser has no raw TCP, so the web reaches a LAN printer only through the printer’s HTTP or WebSocket interface where it has one; raw TCP printing is a desktop and native driver). Electron: serial and USB through the main process, exposed to the renderer by the desktop bridge. Native: Bluetooth printers, as decision 6. A port’s driver is chosen by target at build time, as 0250 does for capabilities.
-
The native Bluetooth printer driver is approved. It is the first native module of
0253 decision 3, for the
ReceiptPrinterandLabelPrinterports on the native target only, through an Expo module. Its evidence is handheld checkout. Any other native peripheral module needs its own ADR, as before. - Presets name the kit. The POS preset of 0253 decision 4 lists its devices by vendor and model with their prefixes, page widths, code pages and kick pulse. A till picks a preset; a new device is a preset entry, not code.
Consequences
- A browser till prints Arabic receipts correctly on any ESC/POS printer that takes raster, and a handheld prints to a Bluetooth printer with the same port.
- Electron is needed only where the browser cannot reach the hardware; the port is the same on both.
- One native module exists, with a stated reason, and the bar for the next one is unchanged.
Enforcement
- planned — each driver has a test against a recorded device fixture (0253’s rule), including an Arabic raster receipt compared to a golden image.
- planned — the validator rejects a native module in
@stackra/peripheralsother than the Bluetooth printer module unless an ADR reference names it.
Open questions
-
Integrated card terminals. The retail edition needs integrated terminals from day one, with the provider chosen per
country (an owner item).
CardTerminalpairs and reports; the terminal’s own SDK on the native staff app and the Electron till is a native module, and under 0253 decision 3 each provider’s SDK needs its evidence and its own ADR. The evidence is stated here; the per-provider ADRs follow the owner’s provider choice. An integrated card payment never completes offline. - Android POS terminals (Sunmi, PAX, iMin). The retail pilot runs on every till kind, and these terminals’ built-in printer and scanner have no Web API and no LAN path: each vendor’s SDK is a native module, so under 0253 decision 3 each vendor gets its own ADR, with that evidence. The ports of decision 1 are unchanged; only the drivers are added.
-
Customer display on every till kind.
CustomerDisplayof decision 1 needs a driver per till: a second Electron window, the Android Presentation API, and an external-display scene on the iPad (which needs multi-scene support in the Expo app). The platform-targets ADR records where each lives. - Wallet passes. Loyalty cards and receipts as Apple Wallet and Google Wallet passes are an integration surface, not a peripheral: a separate ADR, with the pass-signing certificate names in Infisical and no value in git.