Table of Contents
- 1) Goal & Preconditions
- 2) Terminology — quick answers
- 3) High‑level user flow
- 4) Devices list (table)
- 5) Device detail drawer
- 6) Actions & modals
- 7) Permissions & rules
- 8) Data model — device object
- 9) API stubs
- 10) Analytics events
- 11) Edge cases & constraints
- 12) Acceptance criteria
- 13) Questions / Gaps
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.