Skip to main content

C6 — Native API Capability Catalog

Scope: Per-surface availability matrix for every native API used by Ghasi Melmastoon. Covers camera, biometrics, push notifications, BLE, NFC, USB/serial, receipt printer, cash drawer, MRZ scanner, Apple/Google Wallet, and file system APIs.

How to use: Before implementing a feature that requires a native API, check the row for that API. If the capability is not available on the target surface, implement a graceful fallback (or skip the feature for that surface).


1. Capability matrix​

Capabilityconsumer-web (PWA)tenant-booking-webconsumer-mobile (RN)staff-mobile (RN)operator-desktop (Electron)kiosk (Electron)tablet-pos (RN/Electron)
Camera / photo capture✅ getUserMedia (Chrome, Firefox, Safari)❌ (not needed)✅ react-native-vision-camera✅✅ Electron BrowserWindow.webContents.session (webcam)✅ (fixed camera for doc scan)✅
Biometric authentication✅ WebAuthn / navigator.credentials (platform authenticator)❌✅ expo-local-authentication (TouchID, FaceID, fingerprint)✅✅ Windows Hello / macOS Touch ID via node-biometric❌✅
Push notifications (OS)✅ Web Push API (PushManager, serviceWorker.registration)❌✅ FCM + APNs via expo-notifications✅✅ Electron Notification API + FCM main process❌ (kiosk, no user context)✅
BLE (Bluetooth Low Energy)❌ (Web Bluetooth origin trial only; not production-ready)❌✅ react-native-ble-plx (R3, mobile key)✅ (R3)✅ noble / @abandonware/noble in Electron main✅✅
NFC❌ (partial: navigator.nfc on Android Chrome only)❌✅ iOS requires CoreNFC (reading only); Android react-native-nfc-manager (read/write)✅✅ via USB NFC reader + node-nfc driver✅ (RFID card tap for key issuance)✅
USB / serial (hardware)❌ (Web Serial API, Chrome-only, HTTPS required)❌❌❌✅ node-serialport in main process. Covers: card encoder, receipt printer, cash drawer, external keyboard wedge✅✅
Receipt printer (ESC/POS)❌❌❌❌✅ USB (serialport) + network (TCP socket). escpos npm package✅✅
Cash drawer❌❌❌❌✅ ESC/POS cash drawer kick via receipt printer serial interface❌✅ (POS)
MRZ scanner (passport reader)❌❌✅ Camera + ML Kit OCR (R2)❌✅ USB OCR reader via serialport OR camera + tesseract.js WASM✅ (fixed document scanner)✅
Apple Wallet / Passkit❌❌✅ iOS only, expo-passkit (R3)❌❌❌❌
Google Wallet❌❌✅ Android only, Google Pay Passes API (R3)❌❌❌❌
Geolocation✅ navigator.geolocation❌✅ expo-location✅✅ electron-location❌❌
Local file system✅ File System Access API (Chrome) — picker only❌✅ expo-file-system✅✅ node:fs in main; webContents.downloadURL in renderer✅ (limited)✅
Clipboard✅ navigator.clipboard✅✅ expo-clipboard✅✅ electron.clipboard❌✅
Deep links / universal links✅ (URL scheme, PWA manifest)✅✅ expo-linking✅✅ electron.app.setAsDefaultProtocolClient('melmastoon')❌✅
Offline storage (large)✅ IndexedDB (web) / OPFS (Origin Private File System)✅✅ MMKV (encrypted KV)✅ MMKV✅ SQLite (better-sqlite3)✅ SQLite✅
Background sync✅ Service Worker Background Sync API❌✅ expo-background-fetch (limited on iOS)✅✅ Main process timer (Electron keeps process alive)✅✅
Screen wake lock✅ navigator.wakeLock (kiosk-like use)❌✅ expo-keep-awake✅✅ electron-prevent-sleep✅ (always on)✅

Legend: ✅ Supported and implemented (or planned for specified release) · ❌ Not available or not applicable


2. Per-API implementation notes​

2.1 Camera / photo capture​

  • Consumer web (PWA): Used for profile photo and ID document capture during guest self check-in (R2 Guest Portal). Requires HTTPS. Safari requires allowsInlineMediaPlayback in WKWebViewConfiguration on iOS.
  • Mobile: react-native-vision-camera with useCameraPermission hook; prompt permission at first use of relevant flow, not on install.
  • Desktop / kiosk: Webcam frame via getUserMedia in renderer (Electron exposes contextBridge.exposeInMainWorld). MRZ/ID scanning uses WASM-based OCR (tesseract.js in renderer worker).

2.2 Biometrics​

  • Mobile: expo-local-authentication is the abstraction. On iOS: Face ID / Touch ID. On Android: fingerprint, iris, face. Always surface a fallback PIN if biometrics not enrolled.
  • Desktop: Windows Hello via credentialManager.authenticate() (Windows 10 1903+). macOS Touch ID via LAContext bridged through a native Node addon. Linux: no biometric; fall back to PIN.
  • WebAuthn (web): Used for staff login on consumer web PWA in role-protected routes. Platform authenticator preferred; passkey cross-device as fallback.

2.3 BLE (mobile key, R3)​

  • Requirement: Tenant must have BLE-capable lock vendor (TTLock BLE, Dormakaba, Assa Abloy Aperio).
  • Permission flow: react-native-ble-plx requires Bluetooth permission (iOS NSBluetoothAlwaysUsageDescription; Android BLUETOOTH_SCAN + BLUETOOTH_CONNECT). Request at key-issuance step.
  • Electron: noble runs in the main process (not renderer). IPC bridge exposes scanForKey, connectToLock, issueCredential to renderer.

2.4 USB / serial (hardware peripherals)​

All hardware peripheral access on the desktop/kiosk uses node-serialport in the Electron main process. The renderer communicates via IPC (contextBridge).

PeripheralBaud rateProtocolAuto-detect
Receipt printer (Epson, Star)19200 / 9600ESC/POSYes (USB vendor ID)
Cash drawerTriggered via printerESC/POS pulseN/A
Card encoder (Mifare, RFID)9600Wiegand / proprietaryYes (USB class)
MRZ reader (passport)9600MRZ OCR text streamYes (USB HID)
External keyboard wedge (barcode)N/AHID keyboard inputYes

2.5 Receipt printer​

  • escpos npm package generates ESC/POS byte sequences.
  • Supported paper widths: 58mm, 80mm.
  • Character sets: CP437 (default), CP720 (Arabic), UTF-8 where hardware supports.
  • RTL languages (Pashto, Dari) are encoded using the Perso-Arabic character page and right-aligned manually in ESC/POS.
  • Printer health is checked at app start via GET /printers in the Electron IPC.

2.6 Wallet (Apple / Google)​

  • Apple Wallet: PKPass generated server-side by notification-service → signed with Apple certificate. The mobile app downloads and presents the pass via expo-passkit. Lock credentials are encoded as NFC payload in the pass.
  • Google Wallet: Google Pay Passes API (JWT-based). Similar flow via notification-service. Android only.
  • Fallback: If Wallet provisioning fails, the app falls back to displaying a QR code or PIN.

3. Permission request guidelines​

  1. Request on demand, at the first moment the user takes an action that needs the permission. Not at install or app launch.
  2. Show a soft prompt explaining why the permission is needed before triggering the OS native prompt. Use the <PermissionExplainer> component from @ghasi/ui-melmastoon.
  3. Handle denial gracefully: show the feature as unavailable with an explanation and a path to re-enable in settings.
  4. Never re-prompt immediately after denial: wait for next meaningful session.

4. Open Questions​

  • BLE mobile key: which lock vendors are confirmed for R3? TTLock BLE SDK requires a separate license agreement.
  • MRZ scanning: should we use ML Kit (online, Google Play Services required) or WASM Tesseract (offline-capable)? WASM is preferred for offline-first consistency but accuracy is lower.
  • Kiosk MRZ reader: USB HID or serial? Confirm with hardware vendor.
  • Cash drawer: can it be triggered independently (via a serial pulse) on properties where the receipt printer is networked, not USB?

References​