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
| Capability | consumer-web (PWA) | tenant-booking-web | consumer-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
allowsInlineMediaPlaybackinWKWebViewConfigurationon iOS. - Mobile:
react-native-vision-camerawithuseCameraPermissionhook; prompt permission at first use of relevant flow, not on install. - Desktop / kiosk: Webcam frame via
getUserMediain renderer (Electron exposescontextBridge.exposeInMainWorld). MRZ/ID scanning uses WASM-based OCR (tesseract.jsin renderer worker).
2.2 Biometrics
- Mobile:
expo-local-authenticationis 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 viaLAContextbridged 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-plxrequires Bluetooth permission (iOSNSBluetoothAlwaysUsageDescription; AndroidBLUETOOTH_SCAN+BLUETOOTH_CONNECT). Request at key-issuance step. - Electron:
nobleruns in the main process (not renderer). IPC bridge exposesscanForKey,connectToLock,issueCredentialto 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).
| Peripheral | Baud rate | Protocol | Auto-detect |
|---|---|---|---|
| Receipt printer (Epson, Star) | 19200 / 9600 | ESC/POS | Yes (USB vendor ID) |
| Cash drawer | Triggered via printer | ESC/POS pulse | N/A |
| Card encoder (Mifare, RFID) | 9600 | Wiegand / proprietary | Yes (USB class) |
| MRZ reader (passport) | 9600 | MRZ OCR text stream | Yes (USB HID) |
| External keyboard wedge (barcode) | N/A | HID keyboard input | Yes |
2.5 Receipt printer
escposnpm 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 /printersin the Electron IPC.
2.6 Wallet (Apple / Google)
- Apple Wallet:
PKPassgenerated server-side bynotification-service→ signed with Apple certificate. The mobile app downloads and presents the pass viaexpo-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
- Request on demand, at the first moment the user takes an action that needs the permission. Not at install or app launch.
- Show a soft prompt explaining why the permission is needed before triggering the OS native prompt. Use the
<PermissionExplainer>component from@ghasi/ui-melmastoon. - Handle denial gracefully: show the feature as unavailable with an explanation and a path to re-enable in settings.
- 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
../desktop/21-desktop-app-specification.md../common/02-architecture-overview-frontend.mdC5-feature-flag-inventory.md(mobile-key-ble,mobile-key-wallet,kiosk-self-checkin)../../09-lock-and-key-integration.md