J-05 — Arrive at Hotel & Check-In
One-liner: Guest arrives, ID is captured (OCR + HITL), lock credentials are issued (offline-cert online, mobile-key SMS path online), and the room is occupied — fully, partially, or fully offline.
1. Purpose
Guest arrives at the property; receptionist on the Electron desktop captures their ID (OCR + HITL), reconciles it with the reservation, issues lock credentials and (optionally) a mobile key, and marks the room Occupied. The journey must succeed in fully online, degraded online, and fully offline modes. Outcome: reservation status -> Checked-in; folio is open; lock is unlockable by issued credential; the guest leaves the desk with everything they need.
2. Persona Context
- Persona: Front desk receptionist (primary actor); guest (subject).
- Surface: Electron Desktop (
apps/desktop); auxiliary: Tenant Booking Mobile (mobile-key claim). - Primary BFF:
bff-backoffice-service-> domain services. Direct in offline mode through Electron's local SQLite + outbox. - Backing services:
front-desk-service,identity-verification-service(cloud OCR),audit-service,lock-and-key-service,notification-service. - Preconditions: Reservation exists in
Confirmedstate; tenant has lock vendor configured; receptionist signed in with active session and tenant scope. - Trigger: Receptionist clicks "Check-in" on a reservation row in the Front Desk screen, or scans a QR confirmation code.
3. Entry Points
| # | Entry | Notes |
|---|---|---|
| 1 | Click "Check-in" on reservation row | Default |
| 2 | Scan QR confirmation code (camera/barcode) | Auto-opens reservation |
| 3 | Online check-in pre-completed by guest -> Front-desk "Finalize" | See J-08 handoff |
4. Screen-by-Screen Flow
4.1 CheckInWizardStep1ReservationConfirmation
- Layout: Compact reservation summary card (guest name, room type, dates, balance), eligibility check (deposit on file, ID requirements per tenant policy), warnings if any.
- Components:
ReservationSummaryCard,EligibilityChecklist,Button("Continue"). - Offline: Reads from SQLite snapshot; warning banner "Working offline - changes will sync".
- AI: None.
- Errors: Reservation status invalid (e.g., already checked-in / cancelled) -> blocking modal with action.
- Loading: Skeleton if data still loading; usually instant from SQLite.
- A11y: Keyboard-completable; "Continue" enabled when checklist passes.
- RTL: Layout mirrors.
- Perf: Mount <= 200 ms (local cache).
- Telemetry:
frontend.checkin.wizard_started { reservationId }.
4.2 CheckInWizardStep2IdCapture
- Layout: Camera viewfinder with overlay for ID; capture/upload toggle; recently captured image preview; OCR result panel with HITL fields.
- Components:
IdCameraCapture,IdOcrPanel,BidiText(for Arabic-script names),Button("Confirm details"). - Offline: Edge ONNX OCR runs locally; lower confidence; result still editable; cloud reverification queued.
- AI: Cloud OCR (
identity-verification-service) when online; ONNX fallback edge model when offline. HITL canonical card. Provenance pill. - Errors: OCR low confidence -> all fields editable + warning banner; camera permission denied -> upload-image fallback.
- Loading: OCR streaming progress; capture takes <= 1 s, OCR <= 3 s p95 cloud, <= 1 s edge.
- A11y: Camera viewfinder has labelled live region announcing "ID detected" / "Hold steady"; OCR fields are labelled inputs with
aria-describedbyfor confidence. - RTL: Form mirrors; Arabic-script values bidi-safe.
- Perf: Edge OCR p95 <= 1 s; cloud OCR p95 <= 3 s.
- Telemetry:
frontend.checkin.id_captured { mode: edge|cloud };frontend.checkin.ocr_confidence { score }.
4.3 CheckInWizardStep3IdVerificationConfirm
- Layout: Side-by-side ID image and parsed fields; optional manual override; verification status pill (verified / queued for cloud reverification).
- Components:
IdSideBySideView,OverrideField,Button("Continue to room"). - Offline: Cloud reverification queued; status = "Queued"; downstream steps allowed.
- AI: Provenance carried forward; HITL applies for any overrides.
- Errors: Mismatch with reservation guest name -> banner "Names differ - confirm or cancel"; receptionist can override with reason (audit log entry).
- Loading: Verification spinner.
- A11y: Override field announces consequences via
aria-describedby. - RTL: Layout mirrors.
- Perf: Mount <= 200 ms.
- Telemetry:
frontend.checkin.id_verified { method: edge|cloud, overrides: [...] }.
4.4 CheckInWizardStep4RoomAssignment
- Layout: Suggested room (from policy + AI in P2) + alternatives; room status flags (Clean, Inspected); AI suggestion card with rationale.
- Components:
RoomAssignmentCard,AiSuggestionCard,RoomStatusBadge. - Offline: Reads from SQLite snapshot; AI suggestion fallback to deterministic rule.
- AI: Phase 2 —
ai-orchestrator-service /assignRoom; HITL with rationale. - Errors: No clean room of selected type -> manual override + housekeeping notification.
- Loading: Sub-200 ms.
- A11y: Room cards are tab stops; assignment confirmation announces room number.
- RTL: Mirror.
- Perf: <= 300 ms.
- Telemetry:
frontend.checkin.room_assigned { roomId, source: ai|manual }.
4.5 CheckInWizardStep5KeyIssuance
- Layout: Two columns: "Physical key" (lock vendor encoder workflow) and "Mobile key" (SMS link to guest's phone). Status pills per channel.
- Components:
LockEncoderPanel,MobileKeyInvitePanel,Button("Issue keys"). - Offline: Physical key:
offline-certissuance + queued event. Mobile key: SMS queued; visible status "Will send when online". - AI: None on issuance; potential P2 anomaly detection on lock issuance patterns.
- Errors: Vendor adapter timeout -> retry; lock encoder USB disconnect -> hardware error UX with reconnect prompt.
- Loading: Encoder progress shown via vendor SDK callback.
- A11y: Encoder progress announced; mobile-key invite copy spelled out for screen readers.
- RTL: Mirror.
- Perf: Encoder cycle p95 <= 8 s; mobile-key invite send <= 2 s p95.
- Telemetry:
frontend.checkin.key_issued { channel: physical|mobile, mode: online|offline_cert }.
4.6 CheckInWizardStep6FolioOpenAndComplete
- Layout: Folio summary, optional pre-charge of refundable deposit, "Done" CTA.
- Components:
FolioSummary,DepositForm,Button("Complete check-in"). - Offline: Folio created locally; deposit charge queued.
- AI: None.
- Errors: Deposit auth declined -> banner with retry / alternate method / skip-with-flag.
- Loading: Final spinner.
- A11y: "Done" announces "Check-in complete - guest checked in to room
". - RTL: Mirror.
- Perf: Total wizard p95 <= 90 s online (incl. encoder); offline <= 60 s (no cloud RTTs).
- Telemetry:
frontend.checkin.completed { reservationId, mode }.
5. State Machine
6. Data Requirements
6.1 Server state (online)
| Operation | Endpoint | Idempotency | Notes |
|---|---|---|---|
getReservation | GET /api/v1/reservations/:id | n/a | Cached in SQLite |
submitIdCapture | POST /api/v1/identity/verify | X-Idempotency-Key | Cloud OCR |
assignRoom | POST /api/v1/front-desk/checkin/:id/assign-room | X-Idempotency-Key | |
issueKey | POST /api/v1/lock/key/issue | X-Idempotency-Key | Returns vendor opaque payload |
openFolio | POST /api/v1/folio | X-Idempotency-Key | |
completeCheckin | POST /api/v1/front-desk/checkin/:id/complete | X-Idempotency-Key |
6.2 Local persistence
- SQLite tables:
reservations,rooms,folios,key_credentials_local,outbox. - Outbox entries with deterministic keys (per pending mutation).
- Offline-cert key payload signed by local cert valid for the day.
6.3 Idempotency
- Wizard generates one ULID per step's mutation; reused on retry.
7. AI Behavior
| Surface | Step | Purpose | Model | Edge / Cloud | HITL | Provenance | Fallback |
|---|---|---|---|---|---|---|---|
IdOcrPanel | Step 2 | OCR ID into structured fields | id-ocr-v1 | Cloud (online) / ONNX edge (offline) | Canonical card; receptionist confirms | Pill: model@version, prompt, trace, local=true if edge | Manual transcription |
RoomAssignmentCard (P2) | Step 4 | Suggest best-fit clean room | room-assign-v1 | Cloud | HITL | Pill | Deterministic rule (next clean room of type) |
8. Offline Behavior
- All steps available offline.
- ID OCR uses edge ONNX (lower accuracy; receptionist always confirms).
- Lock-key issuance uses
offline-cert(signed locally, valid for the day). - Mobile-key SMS invite queued; visible status "Will send when online".
- Folio created locally; deposit charges queued.
- Sync Center on Electron Home shows pending events count; on reconnect, outbox flushes.
9. Error States
| Error | Trigger | UX shown | Recovery | Telemetry |
|---|---|---|---|---|
MELMASTOON.IDENTITY.LOW_CONFIDENCE | OCR confidence < 0.7 | Banner: "Verify the details below"; all fields editable | Receptionist confirms / edits | frontend.checkin.ocr_low_confidence { score } |
CAMERA_PERMISSION_DENIED | OS denied | Upload-image fallback shown | Receptionist uploads image | frontend.checkin.camera_denied |
LOCK_ENCODER_USB_DISCONNECTED | USB unplug | Modal: "Reconnect encoder and retry" | Replug; auto-retry | frontend.checkin.encoder_disconnected |
LOCK_VENDOR_5XX | Vendor adapter timeout | Retry pill on key issuance step; offline-cert path offered | Retry or offline-cert | error.surfaced { code } |
MELMASTOON.NOTIFICATION.SMS_QUEUED | Offline mobile-key SMS | Status "Queued - will send on reconnect" | Auto-send on reconnect | frontend.checkin.mobile_key_queued |
RESERVATION_INVALID_STATE | Already checked-in / cancelled | Blocking modal with action options | Receptionist cancels wizard | frontend.checkin.invalid_reservation_state |
DEPOSIT_AUTH_DECLINED | Card auth declined | Inline error on deposit step; retry / alternate / skip-with-flag | Receptionist resolves | frontend.checkin.deposit_declined |
10. E2E Test Gates
- Composite gate
G-DESK-1: arrival -> ID capture -> verification -> room assignment -> physical key + mobile key -> folio -> done. Online + offline variants. - Lock encoder USB disconnect mid-cycle -> reconnect -> retry -> success.
- Mobile-key SMS offline -> reconnect -> SMS sent.
11. Performance Requirements
| Metric | Target |
|---|---|
| Wizard total (online) | <= 90 s p95 |
| Wizard total (offline) | <= 60 s p95 |
| Edge OCR | <= 1 s p95 |
| Cloud OCR | <= 3 s p95 |
| Encoder cycle | <= 8 s p95 |
| Mobile-key invite send | <= 2 s p95 |
| Step transitions | <= 200 ms |
12. Accessibility Requirements
- Wizard is keyboard-completable (all steps).
- Camera viewfinder has labelled live region.
- OCR fields announce confidence.
- Encoder progress announced.
- Mobile-key invite copy spelled out for screen readers.
- High-contrast mode honoured (front-desk often in well-lit lobby).
- Reduced-motion: wizard transitions collapse to opacity fades.
13. Telemetry
Frontend events
frontend.checkin.wizard_started { reservationId }frontend.checkin.id_captured { mode }frontend.checkin.ocr_confidence { score }frontend.checkin.id_verified { method, overrides }frontend.checkin.room_assigned { roomId, source }frontend.checkin.key_issued { channel, mode }frontend.checkin.completed { reservationId, mode }
Domain events emitted
melmastoon.front_desk.checkin.started.v1melmastoon.identity_verification.id.verified.v1melmastoon.front_desk.room.assigned.v1melmastoon.lock_and_key.credential.issued.v1melmastoon.folio.opened.v1melmastoon.front_desk.checkin.completed.v1melmastoon.audit.recorded.v1
14. Success Criteria
- Wizard completes <= 90 s p95 online and <= 60 s p95 offline.
- Zero "ghost rooms" in the property model after concurrent check-in attempts.
- Lock credential issuance verified end-to-end, including offline-cert path.
- Mobile-key SMS arrives <= 2 min online; queued correctly offline.
- Audit log holds an entry for each material step (ID verified, room assigned, key issued, folio opened, check-in completed).
- AI provenance recorded for every AI step (OCR mode visible).