URD: Device
| Module | CORE-04 | Version | v0.3 |
|---|---|---|---|
| Status | In-progress | Date | 2026-06-15 |
Business documentation. This URD is Device's feature list - each feature below is one Functional Area (
<AREA>). The same<AREA>keys the feature's PRDs (PRD-<AREA>-NNN) and tests (TC-<AREA>-NNN), and each feature is listed in the Delivery feature catalog. See the Feature Spine convention.
1. Purpose
This document defines user-facing requirements for Device management and hardware integration. It covers how an organization registers, manages, and monitors physical devices (POS terminals, mobile apps, web clients), and how the platform integrates peripherals (printers, barcode scanners, SoundBox, SoftPOS/NFC, external displays).
2. Scope
| Included | Excluded |
|---|---|
| Device registration, lifecycle, search, soft-delete | VNPAY Terminal backend wiring (table exists, API not connected - QE finding) |
| Hardware / software / maintenance info | Label printer integration (Planned) |
Device identity (machine UID, x-device-info header) | Windows POS terminal (Planned) |
| Mobile, web, POS terminal apps + offline mode | Kitchen display, waiter, delivery apps (Planned) |
| Printer (USB/network, ESC/POS), scanner (HID/camera) | Cash drawer control (Planned) |
| SoundBox, SoftPOS/NFC, external display | Technical API specifications |
| Heartbeat / health monitoring, remote deactivation | Payment gateway internals (see Payment URD) |
| CSV import/export; role-based access | - |
3. Definitions
| Term | Definition |
|---|---|
| Device | A registered hardware unit (POS terminal, mobile device, workstation) that interacts with the platform |
| Device Identifier | System-generated unique string D_YYYYMMDD_<snowflakeId> assigned at registration |
| Device Code | Optional human-readable code, unique within the organization |
| Organization | Top-level owner of one or more merchants and devices |
| Merchant | A business unit within an organization; a device may be optionally assigned to one |
| Hardware Info | Manufacturer, model, serial number, IMEI, MAC, processor, RAM, storage, screen, battery |
| Software Info | OS, OS version, app version, firmware, last update, peripheral drivers |
| Device Status | Lifecycle state: NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED |
| Heartbeat | Periodic online ping (every 5 min); offline after 15 min of silence |
| Machine UID | Hardware-derived identifier sent in the x-device-info HTTP header |
| ESC/POS | Thermal-printer command language; Vietnamese support via code page 28 |
| HID Keyboard-Wedge | USB/Bluetooth scanner mode that emulates keyboard input |
| SoftPOS | NFC contactless card acceptance on an Android phone, activated via VNPAY KYC |
| SoundBox | VNPAY Bluetooth speaker announcing payment confirmations |
| POS Point | Logical sales station a device must be assigned to before processing sales |
4. Conceptual Model
Conceptual only - full schema lives in the Commerce domain model.
5. Feature Catalog
The feature list of this module. Each row is one feature (a Functional Area). Detail in §6. Mirrored in the Delivery feature catalog.
| Feature ID | Feature | Phase | Status | Priority |
|---|---|---|---|---|
DEV | Device Registration & Management | P2 | In-progress | High |
MOB | Mobile App | P1 | Built | High |
WEB | Web Application | P1 | Built | High |
POS | POS Terminal | P2 | In-progress | High |
PRN | Printer | P2 | In-progress | High |
SCN | Barcode Scanner | P2 | In-progress | High |
SBX | SoundBox | P1 | Built | High |
NFC | SoftPOS / NFC | P3 | Planned | High |
DSX | Device Shift & Printer Binding | P2 | Built | High |
MON | Device Identity & Health Monitoring | P2 | In-progress | High |
Status: live from Plane where mapped, otherwise registry-declared. Vocabulary mirrors Plane (state-group / phase).
6. Features
One sub-section per feature, in catalog order. Each feature keeps its description, requirements, and acceptance together. Priority = MoSCoW (Must / Should / Could / Won't).
DEV - Device Registration & Management In-progress
Feature ID: device/DEV · Phase: P2 · PRDs: - · Dev: @nx/commerce
What it does for users: owners register each piece of hardware with an i18n name, type, and organization; move it through a status lifecycle; record hardware, software, and maintenance details; and search, import, and export their device fleet.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-DEV-001 | M | Owner can register a device with a name, type, and organization assignment |
| URD-DEV-002 | M | System auto-generates a unique Device Identifier D_YYYYMMDD_<snowflakeId> at registration |
| URD-DEV-003 | M | Device name supports i18n (English + Vietnamese) |
| URD-DEV-004 | M | Device status follows the lifecycle NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED; only valid transitions are permitted |
| URD-DEV-005 | M | Owner can activate a registered device (NEW → ACTIVATED) |
| URD-DEV-006 | M | Owner can deactivate (ACTIVATED → DEACTIVATED) and reactivate (DEACTIVATED → ACTIVATED) a device |
| URD-DEV-007 | M | Owner can suspend a device (ACTIVATED → SUSPENDED) for a security concern |
| URD-DEV-008 | M | Owner can archive a device (permanently read-only, hidden from POS) |
| URD-DEV-009 | M | All device records use soft-delete; records are never physically removed |
| URD-DEV-010 | M | Device API access requires authentication (JWT or Basic Auth) |
| URD-DEV-011 | M | Device code, when provided, must be unique within the organization |
| URD-DEV-012 | S | Owner can record maintenance info (purchase date, warranty expiry, maintenance dates, notes) |
| URD-DEV-013 | M | A device is auto-registered and activated on first app login; existing devices are reused |
| URD-DEV-014 | M | Owner can search devices by name, identifier, code, status, and type |
| URD-DEV-015 | S | Owner can import and export device records via CSV |
| URD-DEV-016 | M | Owner can assign / unassign a device to a merchant; assignment is optional |
| URD-DEV-017 | S | Owner can record hardware information for a device |
| URD-DEV-018 | S | Owner can record software information for a device |
| URD-DEV-019 | S | Owner can set a PIN on a device for local authentication |
Device Statuses
| Status | Meaning |
|---|---|
| NEW | Registered, not yet activated (default) |
| ACTIVATED | Active and authorized to process transactions |
| DEACTIVATED | Temporarily disabled; reactivatable |
| SUSPENDED | Suspended pending investigation; cannot transact |
| ARCHIVED | Permanently retired; read-only |
Device Types
| Type Code | Label |
|---|---|
| 100_POS_TERMINAL | POS Terminal |
| 101_POS_WORKSTATION | POS Workstation |
| 200_MOBILE_POS | Mobile POS |
| 400_TABLET | Tablet |
| 401_BARCODE_SCANNER | Barcode Scanner Device |
| 999_OTHER | Other |
Acceptance
AC-DEV-01: Registration
| Given | When | Then |
|---|---|---|
| Owner | Registers a device with name + type + organization | Device created with status NEW; unique identifier auto-generated |
| Code provided | Code is unique within the organization |
MOB - Mobile App Built
Feature ID: device/MOB · Phase: P1 · PRDs: - · Dev: sale-renderer
What it does for users: owners and cashiers run the POS, orders, payments, invoicing, and reporting on an iOS/Android app built with Tauri, with Bluetooth peripherals and offline capture that syncs on reconnect.
iOS/Android app built with Tauri; primary app for owners and cashiers.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-MOB-001 | M | App is available on iOS 14+ and Android 8+ |
| URD-MOB-002 | M | Owner can sign in and access POS, orders, payments, invoicing, and reporting |
| URD-MOB-003 | M | Cashier can sign in and access the POS screen (owner-only screens restricted) |
| URD-MOB-004 | S | App supports Bluetooth peripheral connectivity (scanner, printer, SoundBox) |
| URD-MOB-005 | S | App supports offline mode: transactions captured locally and synced on reconnect |
| URD-MOB-006 | M | Login creates a device session linked to the device record (auto-register if new) |
Acceptance
AC-MOB-01: Mobile sign-in & session
| Given | When | Then |
|---|---|---|
| Owner or cashier on iOS 14+ / Android 8+ | Signs in to the app | A device session is created and linked to the device record (auto-registered if new) |
WEB - Web Application Built
Feature ID: device/WEB · Phase: P1 · PRDs: - · Dev: client
What it does for users: owners run full back-office management - devices, products, orders, reports, settings - and a basic Web POS in modern browsers, over HTTPS with session expiry.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-WEB-001 | M | Web app runs on modern browsers (Chrome, Edge, Firefox, Safari) |
| URD-WEB-002 | M | Web app provides full back-office management (devices, products, orders, reports, settings) |
| URD-WEB-003 | S | Web app supports a basic Web POS mode |
| URD-WEB-004 | M | Web app enforces HTTPS and session expiry/logout |
| URD-WEB-005 | S | Web app is usable at 1024px+ width; warns below the minimum |
Acceptance
AC-WEB-01: Back-office access
| Given | When | Then |
|---|---|---|
| Owner on a modern browser | Signs in over HTTPS | Full back-office management is available; session expires/logs out per policy |
POS - POS Terminal In-progress
Feature ID: device/POS · Phase: P2 · PRDs: - · Dev: sale-renderer
What it does for users: dedicated Android hardware runs the POS app full-screen with integrated peripherals; a device must be assigned to a POS Point and holds one active session before it can process sales.
Dedicated Android hardware running the POS app full-screen with integrated peripherals.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-POS-001 | M | POS app runs on Android 8+ with ≥2 GB RAM and ≥16 GB storage |
| URD-POS-002 | M | A device must be assigned to a POS Point before it can process sales; one active session per device |
| URD-POS-003 | M | POS app supports built-in peripherals (card reader, printer, scanner, cash drawer) where present |
| URD-POS-004 | S | POS app runs on certified hardware (VNPAY V-POS, Sunmi T2) |
| URD-POS-005 | M | POS app supports peripheral setup via Settings > Devices |
Acceptance
AC-POS-01: POS Point assignment
| Given | When | Then |
|---|---|---|
| Activated device on Android 8+ | Assigned to a POS Point | Device can process sales with one active session at a time |
PRN - Printer In-progress
Feature ID: device/PRN · Phase: P2 · PRDs: - · Dev: sale-main
What it does for users: the system prints ESC/POS receipts over USB and network thermal printers - text, images, QR, and barcodes - with Vietnamese code page 28, 58/80mm paper, auto-cut, and cash-drawer trigger.
USB (Tauri/WebUSB) and network (WebSocket) thermal printers; ESC/POS with Vietnamese code page 28.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-PRN-001 | M | System connects to printers over Bluetooth, USB, and network |
| URD-PRN-002 | M | System detects USB printers by USB class code 0x07 |
| URD-PRN-003 | M | ESC/POS engine prints text, embedded image, QR code, and barcode |
| URD-PRN-004 | M | ESC/POS markup supports alignment, bold, underline, font size, barcode, QR, image |
| URD-PRN-005 | M | System rasterizes PDF content with Floyd-Steinberg dithering for thermal output |
| URD-PRN-006 | M | Vietnamese characters print correctly via code page 28 |
| URD-PRN-007 | M | System supports 58mm and 80mm paper widths, configurable per printer |
| URD-PRN-008 | S | System supports auto-cut and a cash drawer triggered on print |
| URD-PRN-009 | S | Cash drawer trigger command is sent via the printer on cash payment |
| URD-PRN-010 | M | Print lifecycle (connect, disconnect, send job) surfaces a clear error on failure; no silent drop |
| URD-PRN-011 | S | System connects to network printers via WebSocket and handles disconnection gracefully |
| URD-PRN-012 | M | System falls back to WebUSB when the Tauri USB plugin is unavailable |
Acceptance
AC-PRN-01: Receipt Printing
| Given | When | Then |
|---|---|---|
| Paired printer | Transaction completed | Receipt printed (auto or manual) |
| Print fails | Error shown with retry option | |
| Vietnamese content | Code page 28 set automatically |
SCN - Barcode Scanner In-progress
Feature ID: device/SCN · Phase: P2 · PRDs: - · Dev: sale-main
What it does for users: HID keyboard-wedge and mobile camera/QR scanning resolve against Product Identifiers - a successful scan on the POS screen adds the matched product to the cart.
HID keyboard-wedge (USB/Bluetooth) and mobile camera/QR scanning resolved against Product Identifiers.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-SCN-001 | M | System captures HID keyboard-wedge scanner input automatically (no pairing UI) |
| URD-SCN-002 | M | Scanner input must be 10-20 characters, completed within a 100ms keystroke timeout |
| URD-SCN-003 | M | Enter key (or 100ms pause) triggers the scan and lookup |
| URD-SCN-004 | M | Camera QR scanner is available on mobile via the Tauri barcode plugin |
| URD-SCN-005 | M | On a successful scan in the POS screen, the matched product is added to the cart |
| URD-SCN-006 | S | System supports 1D (EAN-13/8, UPC-A/E, Code 128/39) and 2D (QR, Data Matrix) formats |
| URD-SCN-007 | S | Scanning works across multiple contexts (product search, invoice lookup) |
Acceptance
AC-SCN-01: Barcode Scanning
| Given | When | Then |
|---|---|---|
| HID scanner | Scan a barcode | Product looked up and added to cart |
| Camera scanner (mobile) | Scan a QR | Product/invoice looked up |
| Unknown barcode | Scan | Clear error message shown |
SBX - SoundBox Built
Feature ID: device/SBX · Phase: P1 · PRDs: - · Dev: sale-renderer
What it does for users: a VNPAY Bluetooth speaker announces payment confirmations in Vietnamese/English - amount and method - per device, with configurable volume, LED status, and graceful disconnection.
VNPAY Bluetooth speaker announcing payment confirmations in Vietnamese/English, paired per device.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-SBX-001 | M | System pairs a VNPAY SoundBox (V1/V2) to a device via Bluetooth |
| URD-SBX-002 | M | On payment confirmation, system triggers a voice announcement; if disconnected, payment still succeeds (no blocking error) |
| URD-SBX-003 | M | Announcement language follows configuration (Vietnamese / English), including amount and method |
| URD-SBX-004 | S | SoundBox LED states reflect status: blue blinking (pairing), blue solid (connected), green (success), red (error/low battery) |
| URD-SBX-005 | S | User can configure volume (1-10) and toggle whether amount / method are announced |
| URD-SBX-006 | S | SoundBox operates within its rated Bluetooth range (~10 m); beyond range, disconnection is handled gracefully |
Acceptance
AC-SBX-01: SoundBox Confirmation
| Given | When | Then |
|---|---|---|
| Paired SoundBox | Payment confirmed | Amount + method announced in configured language |
| SoundBox disconnected | Payment confirmed | Payment still succeeds; announcement silently skipped |
NFC - SoftPOS / NFC Planned
Feature ID: device/NFC · Phase: P3 · PRDs: - · Dev: sale-main
What it does for users: Android phones accept contactless card payments over NFC via VNPAY after KYC activation; the option is hidden on iOS and blocked when NFC is unavailable.
NFC contactless acceptance on Android via VNPAY; requires KYC.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-NFC-001 | M | System checks NFC hardware availability before enabling SoftPOS |
| URD-NFC-002 | M | SoftPOS requires VNPAY KYC activation before first use |
| URD-NFC-003 | M | SoftPOS activation is blocked when NFC is unavailable or disabled, with a clear message |
| URD-NFC-004 | S | SoftPOS is Android-only; the option is hidden on iOS |
Acceptance
AC-NFC-01: SoftPOS activation
| Given | When | Then |
|---|---|---|
| Android device with NFC available, KYC completed | SoftPOS is activated | Contactless card acceptance is enabled |
| NFC unavailable or disabled | Activation attempted | Activation is blocked with a clear message |
MON - Device Identity & Health Monitoring In-progress
Feature ID: device/MON · Phase: P2 · PRDs: - · Dev: @nx/commerce · @nx/signal
What it does for users: administrators see each device's online/offline status, last-seen time, and app version via a 5-minute heartbeat, and can remotely deactivate or wipe a compromised device.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-MON-001 | M | Active device sends a heartbeat every 5 minutes; platform records last activity |
| URD-MON-002 | M | Platform marks a device offline after 15 minutes without a heartbeat; back online on next ping |
| URD-MON-003 | M | Administrators can view device health (online/offline, last seen, app version) and filter by status |
| URD-MON-004 | M | System can remotely deactivate a device and revoke its active session |
| URD-MON-005 | S | System supports remote data wipe for a compromised device (queued if offline) |
Acceptance
AC-MON-01: Health Monitoring
| Given | When | Then |
|---|---|---|
| Active device | Sends a heartbeat | Last-activity timestamp updated |
| No heartbeat for 15 min | Device marked offline | |
| Admin views device list | Online/offline status visible |
DSX - Device Shift & Printer Binding Built
Feature ID: device/DSX · Phase: P2 · PRDs: PRD-DSX-001 · Dev: @nx/sale · @nx/commerce
What it does for users: the registered device becomes the runtime anchor of a sales station - the x-device-info header resolves every shift action to a device and derives its merchant, a single shift is opened or joined per sale channel, cash-drawer-enabled devices get a per-device drawer, the current context reports device participation, X/Z reports key on the device, and each station binds to its own printer.
Requirements
| ID | P | Requirement |
|---|---|---|
| URD-DSX-001 | M | Every device-scoped shift action resolves its device from the x-device-info header; the merchant is derived from that device record, never supplied by the client |
| URD-DSX-002 | M | A missing x-device-info header on a device-scoped action is rejected with a clear error; back-office reads (e.g. shift list) may run without a device using the active-merchant scope |
| URD-DSX-003 | M | The device must exist, be assigned to a merchant, and (when a merchant is also supplied) match it; otherwise the action is rejected |
| URD-DSX-004 | M | Tenant access is enforced on the resolved merchant for every shift action |
| URD-DSX-005 | M | Opening a shift opens or joins the single open shift for the device's sale channel; a concurrent open by another device joins the same shift rather than creating a duplicate |
| URD-DSX-006 | M | A sale channel supplied on open must belong to the resolved merchant |
| URD-DSX-007 | M | The opening/joining device is enrolled in the shift, and the opening employee is checked in alongside it |
| URD-DSX-008 | S | A per-device cash drawer is created on open only for cash-drawer-enabled devices; other devices join without a drawer |
| URD-DSX-009 | M | The current-context endpoint returns the device's shift, its enrollment, optional drawer, expected cash, and device participation (active count, joined count, pending devices) |
| URD-DSX-010 | M | Expected cash is omitted from the context when the merchant's blind-count policy is enabled or there is no drawer |
| URD-DSX-011 | M | X (mid-shift) and Z (end-of-shift) reports can be generated per device and per shift, keyed on the resolved device |
| URD-DSX-012 | M | A device is registered against a merchant; the device record is the merchant-scoped anchor every shift, drawer, and report binds to |
| URD-DSX-013 | M | Device API access is merchant-scoped and authenticated (JWT or Basic Auth); device search is limited to the merchants the signed-in user has joined |
| URD-DSX-014 | M | A device declares whether it drives a cash drawer; the flag governs drawer creation at shift open |
| URD-DSX-015 | S | A print destination is bound per kitchen station (printer, copy count, auto-print); print jobs route to the bound printer |
Acceptance
AC-DSX-01: Device-scoped shift resolution
| Given | When | Then |
|---|---|---|
Registered device, x-device-info header present | A shift action is called | The device is resolved, the merchant is derived from it, and tenant access is enforced |
| Header missing on a device-scoped action | The action is called | Rejected with a clear error |
| Device assigned to another merchant | The action is called | Rejected - merchant mismatch / forbidden |
AC-DSX-02: Open or join one shift per channel
| Given | When | Then |
|---|---|---|
| No open shift for the channel | A device opens a shift | A new open shift is created and the device is enrolled |
| An open shift exists for the channel | Another device opens | It joins the same shift; no duplicate is created |
| Two devices open the same channel concurrently | Both open | They converge on one shift |
AC-DSX-03: Drawer & participation
| Given | When | Then |
|---|---|---|
| Cash-drawer-enabled device | Opens a shift | A per-device drawer is created with the opening float |
| Drawer-less device | Opens / joins a shift | It joins without a drawer |
| Merchant blind-count enabled | Current context is read | Expected cash is omitted; participation still returned |
AC-DSX-04: Printer binding
| Given | When | Then |
|---|---|---|
| A kitchen station bound to a printer (printer, copies, auto-print) | A print job is produced for that station | The job routes to the bound printer with the configured copies |
7. Constraints & Non-Goals
Constraints
| ID | Constraint |
|---|---|
| C-01 | All devices must be registered before they can operate |
| C-02 | A device must be assigned to a POS Point before processing sales |
| C-03 | Only one active session is permitted per device at a time |
| C-04 | Device Identifiers are auto-generated and immutable |
| C-05 | Device codes must be unique within the organization |
| C-06 | All device records use soft-delete |
| C-07 | Status transitions follow the defined lifecycle; invalid transitions are rejected |
| C-08 | SoftPOS is Android-only and requires VNPAY KYC |
| C-09 | Each POS should have exactly one default printer |
| C-10 | Maximum devices per organization is configurable by the operator |
| C-11 | Heartbeat is every 5 min; offline threshold is 15 min |
| C-12 | HID scanner input must be 10-20 chars within a 100ms timeout |
| C-13 | USB printer code page 28 (Vietnamese) is set automatically on connection |
Non-Goals
- VNPAY Terminal backend API wiring (table exists, no backend connected - QE finding)
- Label printer integration; Windows POS terminal support
- Kitchen display, waiter/service, delivery, and inventory specialized apps
- Cash drawer control; advanced peripheral driver management UI
- Technical API specifications and payment-gateway integration details
8. Version History
| Date | Author | Description | Ver |
|---|---|---|---|
| 2026-02-28 | Q. Do - QE | Initial URD from code-level and documentation analysis | v0.1 |
| 2026-06-04 | Claude (AI pair) | Reorganize by feature (Feature Spine) | v0.2 |
| 2026-06-15 | Sale squad | Add DSX - Device Shift & Printer Binding (Built) | v0.3 |