Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

14 — QA Checklist (Biometric Module)

Module QA specific to framework + shared 00-shared/10. Every check derives from a specific backend behavior or blueprint rule so failure analysis is direct. The first block is testable today; the rest activates as planned endpoints land.


1. Functional — ingest pipeline (REAL today)

  • POST /api/v1/biometric/ingest with valid body → 201, returned doc has studentId/deviceId/timestamp/mode + tenantId from JWT (biometric.controller.ts:14-18, biometric.service.ts:14-16).
  • 400 on bad studentId (non-MongoId) / missing deviceId / non-ISO timestamp (create-biometric-log.dto.ts:4-20).
  • mode optional; omitted OK; extra body field rawData rejected silently or dropped — verify which (schema has it, DTO doesn't — OQ-2).
  • Duplicate ingest (same body twice) → two log rows (logs immutable; dedupe is derivation's job — confirm this is intended, OQ-6).
  • Tenant isolation: tenant A's log never visible via tenant B repo queries (BaseRepository scoping).
  • Unauthenticated request → 401 (global JwtAuthGuard, app.module.ts:130).
  • No permission check — any authenticated user can ingest (no @Permissions; confirm product intent, OQ-5).

2. Functional — device sync ((planned); queue stub today)

  • biometric-sync repeatable job registered */15 * * * * (scheduler.service.ts:70-76).
  • Known gap: no worker — jobs enqueue and stall. QA script: observe queue depth growth; expect 0 processed (OQ-4).
  • When worker lands: retries = 4, exponential 2000 ms (blueprint RETRIES.md:38); exhausted jobs reach DLQ (blueprint Biometric.md:58).
  • POST /biometric/devices/:id/sync triggers immediate run (planned).

3. Functional — device CRUD (planned)

  • Create: unique (tenantId, deviceId) enforced (biometric-device.schema.ts:36); duplicate → 409.
  • status restricted to active|inactive|offline (:7-11); default active (:24-25).
  • PATCH partial update; config object round-trips.

4. Functional — verify check-in (planned)

  • Punch timeline matches biometric_logs index order (tenantId, studentId, timestamp -1) (biometric-log.schema.ts:26).
  • AttendanceSource.BIOMETRIC rows render "source: biometric" (attendance.schema.ts:18).
  • Mismatch verdict appears when punch exists but no derived attendance (derivation gap — currently guaranteed, since derivation is (planned)).
  • No-punch day → clear evidence-absent state (never "absent" verdict without proof).

5. Template enrollment & storage (planned — OQ-3)

  • Storage format decision recorded (hash / encrypted blob / vendor raw) before UI build — nothing stored today; verify no template bytes in any response.
  • Template size bound defined (e.g., ≤ N KB per template) and enforced server-side.
  • "Maps to a verified student record" acceptance (ACCEPTANCE_CRITERIA.md:39).
  • Enrollment overwrite requires confirm; duplicate warning surfaced.
  • Privacy/security: templates never in logs, analytics, or screenshots; encrypted at rest; device config credentials live in integrations, encrypted (blueprint Biometric.md:59).

6. False-match / verification quality (planned)

  • Vendor SDK acceptance threshold documented; FAR/FRR targets defined before pilot.
  • Dry-hand / misread failure path reaches UI (capture-fail, retry) — no silent drop.
  • Mismatch between punch and attendance flagged, never auto-corrected.

7. Device sync failures & health

  • Offline device detection — nothing sets OFFLINE today (blueprint health-check Biometric.md:19 unbuilt): verify who flips status once implemented.
  • Sync failure banner copy matches retry policy (4× exp → DLQ).
  • Catch-up punches preserve original timestamp (blueprint COLLECTIONS.md:1883).
  • Retention: biometric_logs > 1 year TTL+archive (blueprint DATA_RETENTION.md:25); dispute UI explains vanished records.

8. Visual / layout

  • Hub reads at a glance (3-device summary ≤ 2 s); offline is banner-grade, not badge-grade.
  • Device/punch rows stable width (badge 72 dp fixed) — no jitter on refresh.
  • Dark-light parity on all state colors (11 §5).

9. Accessibility (00-shared/09)

  • TalkBack/VoiceOver: hub summary + sync results + verdicts announced (live regions).
  • Keyboard-only desktop: register form TAB order; menus operable.
  • Timeline nodes individually focusable; raw payload reader labeled read-only.
  • Contrast: state chips 3:1, body 4.5:1; reduced-motion → fades only.

10. Performance

  • Ingest p95 < 1 s (PRD PRODUCT_REQUIREMENTS_DOCUMENT.md:136).
  • Log list paginated (high-volume insert-only collection, blueprint INDEXING.md:68); no full-scan client fetches.
  • Memory stable over long log scrolling.

11. Offline & network (10 §2)

  • All writes blocked offline (banner + disabled CTA); reads cached last-good.
  • Verify verdicts never cached — offline = blocked, not stale.
  • Sync retry no-op if already running (single-flight).

12. Permissions & security

  • Route guards: Devices subtree needs biometric.device.manage; Logs subtree needs biometric.log.read (permissions.constants.ts:41-43).
  • biometric.sync permission missing from constants (blueprint Biometric.md:67) — decide name before sync UI ships.
  • Tokens never logged; ingest bodies never in analytics.
  • No template/biometric data on student-parent surfaces (privacy posture).
  • Machine ingest path uses dedicated token, not user rate tiers (OQ-5).

13. Localization

  • All strings i18n; status words (Active/Inactive/Offline) translatable, not hardcoded.
  • Timestamps locale-aware (relative + absolute).

QA scripts

  • Golden per component (light/dark × phone/tablet/desktop × key states).
  • E2E (when endpoints land): register device → sync → ingest → verify check-in → dispute → attendance hop.
  • Security smoke: cross-tenant ingest attempt (expected: tenant-scoped rejection); unauthenticated ingest (401); template response leak check.
  • Pipeline drill: kill device mid-sync → expect 4 retries → DLQ → replay.