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 capturegetUserMedia (Chrome, Firefox, Safari)❌ (not needed)react-native-vision-cameraElectron BrowserWindow.webContents.session (webcam)✅ (fixed camera for doc scan)
Biometric authenticationWebAuthn / 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)
Geolocationnavigator.geolocationexpo-locationelectron-location
Local file system✅ File System Access API (Chrome) — picker onlyexpo-file-systemnode:fs in main; webContents.downloadURL in renderer✅ (limited)
Clipboardnavigator.clipboardexpo-clipboardelectron.clipboard
Deep links / universal links✅ (URL scheme, PWA manifest)expo-linkingelectron.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 APIexpo-background-fetch (limited on iOS)✅ Main process timer (Electron keeps process alive)
Screen wake locknavigator.wakeLock (kiosk-like use)expo-keep-awakeelectron-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