Table of Contents
16 — Family caseload and support lifecycle
Technical reference. For task-based help, see the corresponding user guide.
Documentation status: complete for the current implementation
Reviewed: 2026-07-21
Primary users: subscribed coaches
Surfaces: coach admin portal, mobile coach workspace and platform API
Purpose
The family caseload is the coach's operational source of truth for current client relationships. It combines accepted assignments, pending invitations, support dates/status, team labels, recent and unseen activity, baby context and gated entry points such as session prep, family view-as and chat.
The lifecycle intentionally distinguishes expired support from revoked assignment. Expired support can be extended while the assignment remains current. Revocation permanently ends that assignment and requires a new invitation and family acceptance to work together again.
User outcomes
| User need | Outcome |
|---|---|
| Find a family | Search family/email/baby/team-label data, filter status or team label, and sort/paginate the list. |
| Review workload | Compare active, paused, needs-attention, recent and expired counts. |
| Manage support | Set start/end dates, pause, resume or extend an eligible assignment. |
| End the relationship | Revoke with explicit confirmation and remove record access. |
| Organize the practice | Assign one saved team/case-owner label to a current family. |
| Begin work | Open view-as, session prep, activity review or chat when each capability is eligible. |
Entry points
| Surface | Route/area | Function |
|---|---|---|
| Mobile | /coach | Current family cards, search/filter/sort, support actions and expired-family workflow. |
| Mobile | /coach/families | Full family picker, invitations, summary and family actions. |
| Coach portal | Families | Paginated current roster, status/team filters, invitations and support management. |
| Platform | GET /coach/families | Return canonical visible assignment per family plus pending invitations. |
| Platform | GET /coach/families/:familyId | Resolve full family detail and trusted subject permissions. |
Roster data and controls
Each family item can contain name/email/profile/timezone, baby count/names, team label, assignment and redemption dates, support dates/status, premium state, edit/date permissions, last/recent activity, unseen summaries and a lightweight sleep summary.
The coach portal pages 10 families at a time. Search covers family name, email, family identifier, baby names and team label. Filters include Active, Paused, Not started and Ended compatibility states; Expired has its own action modal. Quick summary filters also identify:
- Review: no last activity, or paused/expired/not-started/ended state;
- Recent: last activity within the previous seven days; and
- Expired: active assignments whose support entitlement no longer permits record access.
Mobile adds name/status/start/end/baby sorting, period summary, recent activity presentation, today's sleep, running sleep timer and notification mute controls.
Canonical assignment selection
- The platform returns at most one canonical assignment for a family to this coach.
- A current active assignment with usable support ranks ahead of an expired active assignment, which ranks ahead of a revoked historical assignment.
- The coach must still be an active organization member and the organization/billing context must allow coach access.
- Pending, unexpired invitations are returned separately from accepted families.
- The route accepts
scope=current|past|all(and a legacyincludePast) for compatibility. The current implementation deliberately returns the visible current/expired active roster;pastreturns no families andalldoes not restore revoked records.
“Families worked with all time” is an anonymized analytics count, not a past-family directory. Former names and records cannot be recovered by changing the roster query scope.
Support states
| Display state | Meaning | Record access | Normal next action |
|---|---|---|---|
| Active support | Active assignment and support entitlement currently permits records. | According to assignment read/edit permissions. | Work normally, change dates or pause. |
| Paused | Support entitlement is paused. | Still allowed; paused families remain current. | Resume or adjust dates. |
| Not started | Current entitlement/roster has not established a normal support start. | Uses the permissions returned by the platform. | Set/review dates. |
| Expired | Assignment is still active but entitlement is expired, terminal or past its end. | Denied; activity/sleep summaries are redacted to empty values. | Extend to a future end or revoke. |
| Revoked / ended | Assignment status is no longer active. | Denied. | Send a new invitation if work should resume. |
Premium family access and coach record access are related but not identical. The roster presents both support status and the resolved premium disabled reason so the coach can distinguish expiry, billing and assignment problems.
Functional flow
1. Change support dates
- The coach can set or clear
startsAtandendsAtwherecanManageSupportDatesis true. - If both exist, the end cannot precede the start.
- An already expired entitlement can be reactivated only by supplying an end date later than now.
- Portal date inputs send the start at
00:00:00.000Zand end at23:59:59.000Zfor the selected UTC calendar day. - Changes are audited and chat/access capability is reconciled after a support-boundary change.
2. Pause and resume
- Pausing requires an end date and is rejected for already expired support.
- Paused support remains visible and continues to allow authorized coach record access.
- Resuming a pause extends the existing end by the elapsed paused duration, preserving the intended amount of active support time.
- An expired paused/active record must first be extended with a future end date.
3. Handle expiry
- Expired families are removed from the ordinary current cards and shown in a dedicated modal/control.
- The coach chooses a future end date to extend support, or confirms revocation.
- Until extension succeeds, protected record fields, session prep, private notes, notifications and messaging are unavailable through backend authorization.
4. Revoke the assignment
- The UI explains that removal is not a reversible pause and asks for confirmation.
- Revocation changes the assignment to
revoked, expires related coach-invite entitlements, updates organization capacity and writes audit events. - Chat relationship reconciliation runs so the conversation enters its former lifecycle.
- The family disappears from the coach's current workspace.
- The family can also revoke its own active coach assignment from its access controls.
5. Restore compatibility behavior
Some client types and portal UI still contain a Restore coach access action for an ended row. The platform route PATCH /coach/families/:familyId/restore is intentionally retained only as a compatibility endpoint and always returns 403 with guidance to send a new invite.
Do not build a recovery workflow around the restore response type. A revoked assignment must not be mutated back to active; the family must knowingly accept a new invitation.
6. Team/case-owner labels
- A current family can be assigned one label from the organization's saved label list or cleared to Unassigned.
- Labels are normalized for whitespace and case-insensitive uniqueness.
- A label is limited to 40 characters; an organization can save up to 25.
- Organization-level rename operations can update affected family selections. Label-list management belongs to Feature 23.
7. Review and mark general activity seen
- Roster unseen counts use an assignment
lastActivitySeenAtcursor, falling back to redemption/assignment time. - Opening a family view-as can call
PATCH /coach/families/:familyId/activity-seenand clear the general roster unseen summary. - This cursor is separate from the per-family notification-feed watermark in Feature 22. Clearing one must not be assumed to clear the other.
Platform API contract
| Method and path | Role |
|---|---|
GET /coach/families?scope=current | Current/expired canonical roster and pending invitations. |
GET /coach/families/:familyId | Family detail with resolved subject access. |
PATCH /coach/families/:familyId/access-period | Set at least one support boundary. |
PATCH /coach/families/:familyId/support-status | Set active or paused. |
PATCH /coach/families/:familyId/revoke | Permanently revoke the current assignment. |
PATCH /coach/families/:familyId/restore | Compatibility route; always denied. |
PATCH /coach/families/:familyId/case-owner-label | Set one saved label or null. |
PATCH /coach/families/:familyId/activity-seen | Advance the general roster review cursor. |
GET/PUT /coach/organization/case-owner-labels | Read/update the saved label vocabulary. |
POST /coach/family-invitations | Begin a new family relationship. |
Authorization and privacy rules
- Every operation requires a coach role, matching assignment ownership, active organization membership and an eligible organization/subscription.
- Record reads also require
canViewLogsand a support entitlement that allows record access; writes require the corresponding trusted permission. - Paused support remains record-accessible by design. Expired, revoked, canceled and inactive-billing support does not.
- Expired families may remain minimally visible so the coach can extend or revoke them, but activity, sleep and unseen detail is withheld.
- Revoked assignments do not appear through past/all roster scopes. Historical counts remain aggregate-only.
- Team labels are organization-scoped operational metadata, not a global cross-tenant directory.
- Client status filters and disabled buttons are presentation only; backend checks run on every mutation.
Loading, empty and failure states
| State | Expected behavior |
|---|---|
| No accepted families | Explain that accepted assignments appear after invite redemption and offer Invite. |
| No search/filter match | Keep filters visible and show a no-matching-clients message. |
| Expired family | Present Extend or Revoke without exposing protected records. |
| Support mutation timeout/error | Keep the prior server-backed family state and offer retry. |
| Revocation error | Keep the confirmation/error visible; do not remove the card optimistically as final. |
| Restore attempted | Display the server denial and new-invite guidance. |
| Refresh with existing rows | Preserve the authorized list while identifying the refresh failure. |
Acceptance checklist
- Search, status/team filters, sorting and portal pagination operate on the authorized current list.
- Active, paused, not-started, expired and revoked meanings are not conflated.
- Pause requires a valid end date; resume extends the end by elapsed pause time.
- Expired support can be extended only with a future end and exposes no protected record detail before success.
- Revocation removes current access and cannot be reversed through the restore compatibility route.
- Team labels must come from the saved organization list and respect count/length limits.
- General activity-seen and activity-notification-seen remain separate cursors.
scope=pastandscope=allcannot enumerate former families.
Source evidence
Coach portal
admin-web/src/routes/FamiliesPanel.tsxadmin-web/src/routes/FamilyInvitationsPanel.tsx
Mobile web
mobile-web/src/routes/CoachDashboard.tsxmobile-web/src/components/CoachFamilyPicker.tsxmobile-web/src/components/CoachExpiredFamiliesModal.tsx
Platform and contracts
platform/apps/api/src/routes/coach-routes.tsplatform/apps/api/src/services/prisma-invite-flow-service.tsplatform/apps/api/src/services/coach-support-window-service.tsplatform/apps/api/src/services/authorization-service.tsplatform/packages/shared/src/coach.tsplatform/packages/shared/src/family.ts
