Tenant UI — Devices (Full Spec)
Section

Devices — Tenant UI (Version 1.1)

Updated to tenant feedback • Version 1.1 • Author: Product / PO

1) Goal & Preconditions

Goal: Provide tenants with a lightweight, clear devices listing and device detail view so they can monitor device health (last reading) and raise Request Replacement or Report Issue for devices assigned to their facility.

Preconditions:

  • Facility and asset records exist and tenant user has explicit access to that facility (server-side access control).
  • Devices are synced into Climacert‑X via integration (Alef canonical). Devices in the UI are metadata-only; no lifecycle management in product.

2) Terminology — quick answers

RBAC: role-based permissions where roles grant capabilities (view devices, submit replacement request, etc.). Only users whose role allows access to a facility may view/act on devices for that facility.

SKU: device model/type identifier (e.g., IAQ-CO2-V1), optional vendor/model label for inventory matching.

3) High‑level user flow

Mermaid (placeholder)
flowchart TD
  A[Open Devices tab] --> B[List devices]
  B -->|Row click| C[Device drawer]
  C --> C1[Request Replacement]
  C --> C2[Report Issue]
  B -->|3-dots| C

4) Devices list (table) — required columns & behaviour

Note: No checkboxes / no bulk actions. Single-row interactions only.

Columns (minimum)

  • Device name (friendly)
  • Device ID (externalId)
  • Assigned asset (short breadcrumb)
  • Parameters (comma list, e.g., CO2, TEMP)
  • Last reading (value + timestamp)
  • Last seen (relative, e.g., "5m ago")
  • Status (online | offline | retired | pending_replacement)
  • Actions (3‑dots menu)

Behaviour

  • Rows are clickable to open a right-side detail drawer.
  • 3‑dots menu: View details, Request Replacement, Report Issue.
  • No multi-select, no bulk export in this view.

5) Device detail drawer (right‑side)

Displayed info (minimal)

  • Header: Device name + Device ID + status badge
  • Assigned asset breadcrumb (Facility > Location > Space)
  • Last reading (latest per primary parameter + timestamp)
  • Last seen (timestamp / relative)
  • Parameters list
  • No firmware/hardware/warranty/RSSI/SNR/installer/audit fields

Actions

  • Request Replacement (modal)
  • Report Issue (modal)

6) Actions & modals

Request Replacement

  • Fields: Reason (select preset), Comment (optional).
  • No image persistence; optional client-side attach for transmission only.
  • On submit: create request {requestId, deviceExternalId, facilityId, requesterId, reason, comment, createdAt}.

Report Issue

  • Fields: Issue Type (select), Description (required), optional client-side image preview (not persisted).
  • On submit: create issue ticket referenced to deviceExternalId and facility.

7) Permissions & rules (RBAC)

  • View devices: only users with explicit facility access (server must enforce on every GET).
  • Request replacement / Report issue: Tenant Admin or Tenant User with facility access.
  • Edit device metadata: Admins only; tenant users cannot edit device records.

8) Data model (minimal) — device object

{
  "externalId": "string",     // maps to Alef device id
  "name": "string",
  "assignedAssetId": "guid",
  "parameters": ["CO2","TEMP"],
  "lastReading": {"param":"CO2","value":412,"timestamp":"2025-08-22T10:00:00Z"},
  "lastSeen": "2025-08-22T10:00:05Z",
  "status": "online|offline|retired|pending_replacement"
}

Important: no audit fields on the device record in this model; admin-side updates logged separately if needed.

9) API stubs (minimal)

List devices
GET /v1/facilities/{facilityId}/devices
200 { items:[...], meta:{ total, page, limit } }

Device detail
GET /v1/devices/{externalId}
200 { device object }

Request replacement
POST /v1/devices/{externalId}/requests/replacement
Body: { reason: string, comment?: string }
200 { requestId, status: 'submitted' }

Report issue
POST /v1/devices/{externalId}/issues
Body: { type: string, description: string }
200 { issueId, status: 'submitted' }

10) Analytics events (minimal)

  • devices_tab_viewed { facilityId, userId, deviceCount }
  • device_opened { deviceExternalId, userId }
  • device_request_replacement_submitted { deviceExternalId, requesterId }
  • device_issue_reported { deviceExternalId, requesterId }

11) Edge cases & constraints

  • No image persistence in Climacert‑X for these actions.
  • No firmware/hardware metadata; device is treated as a lightweight sensor pointer.
  • No add-device UI; devices appear from integration by externalId.
  • Prevent duplicate replacement requests when a pending request exists for the same device.

12) Acceptance criteria (Given / When / Then)

  • Given user has facility access, When they open Devices tab, Then they see a list of devices with Last reading visible in each row.
  • Given a device row, When user clicks 3‑dots → Request Replacement and submits, Then a request is created and stored with device externalId and requester info.
  • Given a device with no recent readings, When opening drawer, Then lastReading shows null/No readings, lastSeen shows relative time.
  • Given a tenant without facility access, When fetching devices, Then server returns 403.

13) Questions / Gaps (for next iteration)

  • Expose short request lifecycle to tenant? (Submitted / Accepted / Scheduled / Completed)
  • Keep any request attachments server-side for ops? (Current spec: no image saving.)
  • Parameters column: show current values (e.g., CO2: 412) or types only? Current spec shows latest primary parameter in Last reading.