EP-006: Housekeeping Management — Phase 1 Hardening
Phase 1 hardening sprint, 2026-04. All work committed to feature branches in
hmp-housekeeping-serviceandhmp-mobile-apps. Not yet pushed.
Three changes landed against the housekeeping epic in Phase 1: WebSocket gateway authentication (so real-time task updates can no longer be sniffed cross-tenant), the xPrisma → ServiceClient migration for room status updates (so the service stops crashing on the second housekeeping task per session), and the mobile app rebrand to KeyNova.
C1 — WebSocket Gateway JWT Authentication
Branch: feat/ws-jwt-auth (in hmp-housekeeping-service, hmp-mobile-apps)
What was fixed
HousekeepingGateway (/housekeeping namespace) now:
- Validates a JWT on
handleConnection, disconnecting unauthenticated clients. - Stores
client.data.userso subsequent message handlers can read tenant/property scope. - Verifies
joinPropertyandjoinFloorrequests against the JWT-claimed propertyId. - Emits task events to namespaced rooms (
property:<id>:floor:<n>) so cross-property leakage is structurally impossible.
Files touched
hmp-housekeeping-service/src/gateways/housekeeping.gateway.tshmp-housekeeping-service/src/gateways/housekeeping.gateway.spec.tshmp-mobile-apps/packages/shared-realtime/src/useRealtimeTasks.tshmp-mobile-apps/apps/housekeeping/src/screens/TaskListScreen.tsx
Tests
11 of the 22+ C1 tests live on the housekeeping gateway. All passing. See
architecture/websocket-gateway-auth.md
for the full pattern.
C4 — xPrisma → ServiceClient Migration (Room Status)
Branch: feat/xprisma-to-serviceclient (in hmp-housekeeping-service,
hmp-shared-packages)
What was fixed
tasks.service.ts updated room status by reaching directly into a room model that
doesn't exist in housekeeping-service's Prisma schema. The first call returned
undefined; subsequent calls crashed with Cannot read properties of undefined.
Migrated to PropertyServiceClient.updateRoomStatus({ propertyId, roomId, status }),
which calls property-service's HTTP API and is guarded by assertPropertyTenant() on the
receiver side.
Files touched
hmp-housekeeping-service/src/tasks/tasks.service.ts(2 sites)hmp-shared-packages/packages/service-clients/src/PropertyServiceClient.ts(updateRoomStatusmethod added)hmp-housekeeping-service/src/tasks/tasks.service.spec.ts(mock client)
Tests
72/72 housekeeping tests pass after migration. The 2 affected unit tests now mock
PropertyServiceClient.updateRoomStatus instead of xPrisma.room.update.
D5 — Mobile App KeyNova Branding (Housekeeping app)
Branch: feat/mobile-keynova-branding (in hmp-mobile-apps)
What was fixed
The HK mobile app got the full KeyNova branding pass:
app.jsonrenamed to "KeyNova Housekeeping". Bundle ID updated.- New
HeaderZoneandKeyNovaLogocomponents from@hmp/shared-ui/mobile, used on every screen header. - Theme tokens (Midnight Sovereign palette, Satoshi font sizing) imported from the shared package instead of hardcoded values.
- 0 instances of "HMP" text remaining in the HK app.
Files touched
hmp-mobile-apps/apps/housekeeping/app.jsonhmp-mobile-apps/apps/housekeeping/src/screens/*(4 screens)hmp-mobile-apps/packages/shared-ui/src/HeaderZone.tsx(new)hmp-mobile-apps/packages/shared-ui/src/KeyNovaLogo.tsx(new placeholder)hmp-mobile-apps/packages/shared-ui/src/theme.ts(new)
Open follow-ups
- KeyNovaLogo is a React-Native-rendered placeholder (View + Text composition). Real asset handoff from design team pending.
- Satoshi font falls back to system.
expo-fontintegration deferred to next mobile sprint.
Summary
| Story | Status before | Status after | Notes |
|---|---|---|---|
| US-006-001 (Task Assignment) | Built | Built | No functional change; safer over the wire |
| US-006-002 (Task Status Update) | Built | Built | C4: xPrisma → ServiceClient |
| US-006-003 (Real-time updates) | Partial | Built | C1 made the WebSocket flow secure enough for production |
| US-006-009 (Mobile HK app) | Partial | Partial | D5 brought UI to KeyNova brand; live API integration still pending |
Story-level status promotions: 1 (US-006-003 Partial → Built).