PRD: Device registration, management & peripherals
| Module | Device (CORE-04) | PRD ID | PRD-DEV-001 |
| Status | In-progress | Owner | Device squad |
| Date | 2026-05-19 | Version | v0.1 |
| Packages | @nx/commerce · @nx/signal · apps/client · sale-renderer · sale-main | URD | DEV · MON · PRN · SCN · SBX · NFC |
TL;DR
Gives an organization a single place to register, manage, and monitor the hardware that runs KICKO - POS terminals, mobile and web apps, and their peripherals. Every device gets a stable identity (
x-device-infoheader, auto-registered on first login), an optional merchant assignment, a controlled status lifecycle, and a searchable back-office fleet view; printers, scanners, SoundBox, SoftPOS, and a 5-minute heartbeat hang off that record. The result: owners can see and control their whole fleet, and the runtime always knows which device a session belongs to.
1. Context & Problem
Merchants run KICKO on a mix of POS terminals, mobile apps, and web clients, each with attached peripherals (printers, scanners, SoundBox). A Device entity and its D_YYYYMMDD_<snowflakeId> identifier exist in the commerce model, but owners have no back-office surface to manage their fleet, and the runtime does not consistently produce or reference a device record. Without this, an owner cannot list or audit their hardware, a session cannot be reliably tied to a physical device, and there is no controlled lifecycle between "registered" and "retired".
This increment closes the gap on two fronts: a full back-office device page for managing the fleet, and runtime device identity (the x-device-info header plus auto-registration on login) so every session resolves to a device record. The peripheral and health concerns build on this device record rather than standing alone.
2. Goals & Non-Goals
Goals
- A back-office device page (list, create, edit) with a sectioned form: general information, hardware config, software config, and other settings.
- Runtime device identity via the
x-device-infoheader; a device record is auto-registered and activated on first app login, and reused for existing devices. - Optional merchant assignment on a device - a device hangs off the organization with an optional assignment to one merchant.
- Device discoverability through the search stack (Typesense device collection with description-field search).
- A controlled status lifecycle (
NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED) with soft-delete and per-organization code uniqueness. - The peripheral & health stack built on the device record: printer (ESC/POS), barcode scanner, SoundBox, and a heartbeat-driven health view with remote deactivation.
Non-Goals
- VNPAY Terminal backend API wiring (table exists; backend not connected - QE finding).
- Label printer integration and Windows POS terminal support.
- SoftPOS / NFC contactless acceptance - Planned (P3).
- Cash drawer control and an advanced peripheral driver-management UI.
- Kitchen display, waiter/service, and delivery apps.
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Identity coverage | 100% of app sessions resolve to a device record via x-device-info (no orphan sessions) |
| Auto-registration | First login on a new device creates exactly one device record; subsequent logins reuse it |
| Fleet visibility | Owners can list, search, and edit every registered device from the back office |
| Health accuracy | Online/offline status matches the 5-min heartbeat / 15-min offline threshold |
| Peripheral reliability | Print/scan/SoundBox failures surface a clear error; payment never blocked by a disconnected SoundBox |
4. Personas & Use Cases
| Persona | Goal |
|---|---|
| Owner | Register, manage, and monitor the device fleet; assign devices to merchants; remotely deactivate a compromised device |
| Manager | View devices and health, configure peripherals within scope |
| Cashier | Operate the POS on an activated device; pair and use printer / scanner / SoundBox |
Core scenarios: an owner registers a device (or it auto-registers on first login) → assigns it to a merchant and activates it → the runtime carries device identity in x-device-info → peripherals pair to the device → the owner monitors health via heartbeat and can remotely deactivate.
5. User Stories
- As an owner, I want a back-office page to list, create, and edit my devices, so that I can manage my whole fleet in one place.
- As an owner, I want a device to auto-register and activate on first app login, so that staff don't have to register hardware manually.
- As an owner, I want to assign a device to a merchant (optionally), so that I can scope a device to a business unit.
- As an owner, I want to search devices by name, identifier, code, status, and type, so that I can find a specific unit quickly.
- As an owner, I want each device to carry a stable identity in the
x-device-infoheader, so that every session is tied to a known device. - As a cashier, I want printer, scanner, and SoundBox to pair to my device, so that I can print receipts, scan products, and hear payment confirmations.
- As an administrator, I want to see device health and remotely deactivate a compromised device, so that I can protect the fleet.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Register a device with i18n name, type, and organization; auto-generate the D_YYYYMMDD_<snowflakeId> identifier | URD-DEV-001..003 |
| FR-2 | Status lifecycle NEW → ACTIVATED → DEACTIVATED → SUSPENDED → ARCHIVED; only valid transitions; soft-delete | URD-DEV-004..009 |
| FR-3 | Device code, when provided, is unique within the organization | URD-DEV-011 |
| FR-4 | A device is auto-registered and activated on first app login; existing devices are reused | URD-DEV-013 |
| FR-5 | Search devices by name, identifier, code, status, and type (Typesense collection) | URD-DEV-014 |
| FR-6 | Assign / unassign a device to a merchant; assignment is optional | URD-DEV-016 |
| FR-7 | Record hardware and software information per device | URD-DEV-017..018 |
| FR-8 | Device identity carried in the x-device-info header on API calls | URD-MON-001 |
| FR-9 | Heartbeat every 5 min; offline after 15 min; health view (online/offline, last seen, app version); remote deactivation | URD-MON-001..005 |
| FR-10 | Printer (ESC/POS), barcode scanner, and SoundBox pair to a device and surface clear errors on failure | URD-PRN · URD-SCN · URD-SBX |
| FR-11 | SoftPOS / NFC contactless acceptance on Android via VNPAY KYC (Planned) | URD-NFC-001..004 |
Full requirement text and acceptance criteria live in the Device URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Data integrity | A device hangs off the organization with an optional merchant assignment; identifiers are immutable; records use soft-delete |
| Identity | Every API call carries device identity in x-device-info; one active session per device |
| Tenancy & authz | Operations scoped per organization (and merchant where assigned); API access requires authentication (JWT or Basic Auth) |
| Performance / scale | Device search is index-backed (Typesense); heartbeat cadence (5 min) bounds write load |
| Resilience | A disconnected SoundBox never blocks payment; print/scan failures surface, never silently drop |
| i18n | Device name and user-facing labels are bilingual ({ en, vi }); ESC/POS prints Vietnamese via code page 28 |
8. UX & Flows
Key screens: the back-office device page in apps/client - list/table, create, edit, and a sectioned form (general, hardware config, software config, other settings), under the authenticated root navigation. POS peripheral flows (scanning, printing, SoundBox, SoftPOS) live in sale-renderer with the Tauri native layer in sale-main.
9. Data & Domain
| Entity | Role |
|---|---|
Device | The device record - i18n name, type, status, identifier, organization, optional merchant relation, hardware/software info |
| Hardware info | Manufacturer, model, serial, IMEI, MAC, processor, RAM, storage, screen, battery |
| Software info | OS, OS version, app version, firmware, last update, peripheral drivers |
| Device session | An active session linked to a device, opened on login |
| Device search collection | Typesense collection indexing devices (incl. description fields) |
Conceptual only - full schema and invariants in the commerce domain model.
10. Dependencies & Assumptions
Depends on
- Commerce (
@nx/commerce) - owns theDeviceentity, organization ownership, optional merchant assignment, hardware/software info, and the status lifecycle. - Signal (
@nx/signal) - real-time edge for device/payment events and the device search collection. - Client apps -
apps/client(back-office management),sale-renderer(POS UI),sale-main(Tauri native USB/NFC/printer/scanner plugins).
Assumptions
- The organization exists; a merchant exists when assignment is used.
- The app sends a stable machine UID in the
x-device-infoheader. - Certified hardware (VNPAY V-POS, Sunmi T2) is available for POS-terminal scenarios.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
Duplicate device records if x-device-info is unstable across logins | Auto-register reuses an existing record by machine UID; identifier is immutable |
| VNPAY Terminal backend not wired (table exists) | Out of scope - flagged QE finding; tracked for a later increment |
| SoftPOS / NFC depends on VNPAY KYC and Android hardware | Planned (P3); option hidden on iOS, blocked when NFC unavailable |
| Heartbeat write load at fleet scale | Bounded by 5-min cadence; revisit cadence if load grows |
| Remote wipe when a device is offline | Queued and applied on next reconnect |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | DEV / POS / PRN / SCN / MON = P2 (In-progress); MOB / WEB / SBX = P1 (Built); NFC = P3 (Planned) - see URD feature catalog |
| Rollout | All organizations; no feature flag |
| Migration | Model cleanup - organizerId removed, merchant relation added, unique index corrected; no data backfill required |
| Launch criteria | Back-office list/create/edit verified; first-login auto-registration verified; x-device-info identity resolves on every session; device search returns expected results |
| Monitoring | Auto-registration rate, orphan-session count, heartbeat online/offline accuracy, peripheral error rate |
13. FAQ
Do I have to register every device manually? No - a device auto-registers and activates on first app login, and existing devices are reused. The back-office page is for managing and editing the fleet.
Does a device belong to a merchant or an organization? It belongs to the organization, with an optional assignment to one merchant. There is no organizerId column on the model.
What identifies a device at runtime? The x-device-info header (a machine UID), which replaced the old deviceId field.
Will a disconnected SoundBox block a payment? No - if the SoundBox is disconnected, the payment still succeeds; the announcement is silently skipped.
Is SoftPOS available now? No - SoftPOS / NFC is Planned (P3), Android-only, and requires VNPAY KYC.
References
- URD: Device - DEV · MON · PRN · SCN · SBX · NFC · MOB · WEB · POS
- Module: Device - overview + traceability
- Developer: @nx/commerce · @nx/signal · domain model
- Apps: sale-renderer · sale-main · client