Every screen of the Biometric module, its intent, route, composition, states,
permissions, platform behavior and events. Authoritative components in 00-shared/03 ;
this file enumerates which ones each screen uses with module specifics. Screens marked
(planned) have no backend endpoint yet — inventory is design-forward.
States = idle / loading / success / empty / error(offline, sync, queue) / disabled / permission.
Analytics events follow {module}.{screen}.{action} (proposed; SDK open — 00-shared/10 §8 ).
Field Detail
Purpose Fleet health at a glance; the ops manager's landing (persona Riya)
Entry Settings → Biometric
Exit → device list, → logs, → verify check-in
Widgets status summary card (devices: active/offline counts), last-sync row, failed-sync banner, queue depth chip (Bull-Board link for Dev)
States loading skeleton; empty ("No devices — register one"); error (queue down); offline
Source planned: GET /biometric/devices + queue health; no real API today
Analytics biometric.hub.open, biometric.hub.sync_status (proposed)
Permission any biometric.* (hub visibility)
Field Detail
Purpose Manage all devices: register, open, disable
Entry hub → Devices
Exit → /biometric/devices/new; → /biometric/devices/:id
Source planned GET /biometric/devices; unique key (tenantId, deviceId) (biometric-device.schema.ts:36)
Row AppListTile: name, subtitle model · location, trailing status badge (DeviceStatus: active/inactive/offline, biometric-device.schema.ts:7-11)
Pull-to-refresh RefreshIndicator
Empty AppEmptyState "No devices registered"
CTA AppFAB "Register device"
Row menu AppMenu → Detail / Disable (confirm)
Permission biometric.device.manage (permissions.constants.ts:43)
Field Detail
Purpose Add a gate device to the tenant fleet
Form name*, deviceId*, model?, location?, config? (schema fields biometric-device.schema.ts:15-31)
Source planned POST /biometric/devices (blueprint Biometric.md:26)
Primary CTA "Register device"
States loading; 409 duplicate deviceId inline; success → detail
Permission biometric.device.manage
Field Detail
Purpose One device: config, status, sync, enrollment entry
Header name + status badge + model/location; config collapsible (raw, biometric-device.schema.ts:30-31)
Actions Sync now (POST /biometric/devices/:id/sync, blueprint Biometric.md:28), Enroll → /enroll, Disable (confirm), Edit (PATCH /biometric/devices/:id, blueprint :27)
Sync states idle → running (spinner) → success (punch count) / failed (retry; 4× exp backoff, blueprint RETRIES.md:38 → DLQ)
Punch preview last N logs for this device (biometric-log.schema.ts:26 index tenantId+deviceId+timestamp)
Permission biometric.device.manage; punch preview needs biometric.log.read
Field Detail
Purpose Capture a student's template on a device (clerk, persona Arjun)
Steps select student → device capture → confirm → success chip
Source blueprint: employeeCode mapping (COLLECTIONS.md:1878-1879); no endpoint/schema/template format today (OQ-3)
States per-step loading; capture-failed (re-try, dry-hands hint); duplicate-enrollment warning
Exit success → device detail ("Enrolled: {name}")
Permission biometric.device.manage
Blockers vendor SDK (FEATURE_ROADMAP.md:56); template storage decision; "maps to verified student record" (ACCEPTANCE_CRITERIA.md:39)
Field Detail
Purpose Evidence trail: search punches by student/device/date; dispute resolution (journey 4)
Source planned GET /biometric/logs (blueprint Biometric.md:30); log fields biometric-log.schema.ts:9-22
Filters student (deep-link ?student=:id), device, date range, mode
Row AppListTile: student name, deviceId · mode, timestamp
Empty AppEmptyState "No punches found"
Row tap → Log Detail sheet
Permission biometric.log.read (permissions.constants.ts:42)
Field Detail
Purpose Full immutable record incl. forensic payload
Content studentId, deviceId, timestamp, mode, rawData (raw JSON), createdAt; "immutable — never updated" note (blueprint COLLECTIONS.md:1866)
Action "Open attendance record" → student attendance list (GET /attendance/student/:studentId, attendance.controller.ts:37-43)
Permission biometric.log.read
Field Detail
Purpose Prove a student checked in (dispute) or preview today's biometric-fed marks
Input student search → date
Content punch timeline (logs) + derived attendance status per day; flags AttendanceSource.BIOMETRIC rows (attendance.schema.ts:18)
States no punches (evidence absent), matched (punch → attendance present), mismatched (punch without derived record — derivation gap)
Exit → attendance record edit (PATCH /attendance/:id)
Permission biometric.log.read (+ attendance.edit for the edit hop)
Phone-as-badge capture surface under the same hub; no server support; keep route dormant.
AppCard, AppListTile, AppButton, AppSnackbar, AppDialog, AppMenu, AppFAB,
AppSkeleton, AppEmptyState, AppOfflineBanner, AppBadge, AppChips, AppAvatar,
AppRefreshIndicator. Module-specific: DeviceStatusBadge, SyncStatusTile, PunchRow,
PunchTimeline, EnrollStepBar — defined in 07_Component_Library.md.
biometric.hub.{open,sync_status}, biometric.device.{list,register,open,sync,disable},
biometric.enroll.{start,capture_ok,capture_fail,complete},
biometric.log.{search,open}, biometric.verify.{matched,mismatch,no_punch}.
Forms (register/enroll): portrait-first, keyboard avoidance.
Devices/Logs: two-pane master-detail ≥ 840 px; desktop hover row highlight.
Sync Status: single column up to 600 dp; three-column tiles ≥ 1200 px.