09 - User Behaviour (Houses Module)
- 1. Behaviours observed (from source + domain)
- 2. Trust & estimation behaviour
- 3. Error-handling behaviour
- G. Gaps the behaviour exposes (flagged
(planned)unless noted)
Observed/derived user behaviour patterns and the design decisions they force. Behavioural baselines (offline, motion, a11y) live in 00-shared/08-10; this file records houses-specific behaviours and the gaps they expose.
1. Behaviours observed (from source + domain)
| # | Behaviour | Evidence / rationale | Design consequence |
|---|---|---|---|
| B1 | Admins create houses in a single batch at year start | Houses are few (typically 4-8); list is never huge | Grid of cards, no heavy pagination UI; pagination still wired (houses.service.ts:25-34) |
| B2 | Code is the identity key, name is the label | Unique index on code only (house.schema.ts:23); service 409 on code (houses.service.ts:19-21) | Code shown as chip; duplicates of name allowed (no block, 08 §3) |
| B3 | Colour is the fast-recognition channel | color is a free string (house.schema.ts:15-16) | Tokenized swatches (11 §3); never color-only semantics |
| B4 | Assignment happens at admission, not at the house | houseId lives on the student (student.schema.ts:41-42), set via student DTOs (create-student.dto.ts:39-42) | Houses module must not fake a "manage members" write surface; deep-link to student edit instead |
| B5 | Reassignment = PATCH student, keeps history silently | update $sets houseId (student.service.ts:142-155); transfer keeps house (:185-192) | No history UI (no server audit field); accept and document |
| B6 | Users expect member counts on a house | Core detail-screen ask | Client-join today + HouseCountBadge verified/unverified duality (07 §5) |
| B7 | Deletion is rare and consequential | Soft delete only (houses.service.ts:51-54) | Confirm dialog with consequence copy (07 §7) |
2. Trust & estimation behaviour
- Never present estimated data as authoritative: member count from the client
join is a filtered snapshot, not a server truth →
~prefix (07 §5). - Never claim protection the backend lacks: no delete guard exists, so the dialog says "members keep their house reference" instead of promising a cascade.
3. Error-handling behaviour
| Situation | User expectation | Implementation |
|---|---|---|
| Duplicate code | "That code is taken" | 409 verbatim inline (houses.service.ts:19-21, 07 §6) |
| House deleted mid-edit | "It's gone" | 404 → snackbar + pop (08 §5) |
| Offline | Still see houses | cached list + offline banner, mutations blocked (00-shared/10 §2, 13 §6) |
| Update race (duplicate code via index) | clear message | error map → conflict copy (08 §3, 14 §2.5) |
G. Gaps the behaviour exposes (flagged (planned) unless noted)
- G1 Member list/filter: no
houseIdfilter onGET /students(student.service.ts:106filters{};PaginationQueryDtohas only page/limit/sort/q) and noGET /houses/:id/members. Client joins full student list - unacceptable past a few hundred students.(planned)GET /students?houseId=or members endpoint. - G2 Delete cascade: deleting a house leaves dangling
student.houseId(student.schema.ts:41-42); no 409, no unset.(planned)guard or cascade event. - G3 Identity fields: mascot, house master, points absent from
house.schema.ts:9-19- the domain asks for them (B6/B7).(planned). - G4 Events: no
HouseCreated/Updated/DeletedorStudentHouseAssignedevents (students module emitsStudentCreated/Updatedbut nothing house-specific,student.service.ts:79-91, 146-155).(planned)if other modules react. - G5 List sorting/search:
sort/qparams exist (pagination-query.dto.ts:21-29) but houses list ignores them (houses.service.ts:30).(planned).