Handling coach access and consent tickets
Coach access tickets are almost always about consent, and the answer is almost always that the member controls it. Never adjust a grant on a member's behalf.
## The one rule
**Being on a coach's roster grants nothing.** The roster is a referral list. Everything a coach can see is a separate, per-category permission the member turned on themselves, and permission is re-checked on every single read - so revoking closes the history too, not just what happens next.
## The ten categories
A member shares, one at a time: weight; activity; workouts; body measurements; progress photos; nutrition; fasting; cycle; supplements; streaks.
**Workouts, measurements and photos are three separate choices.** Sharing a training log does not share measurements, and neither shares photos. If a member says "my coach can see my photos and I never allowed that", check before believing it is a bug - but do check, because it would be serious:
SELECT field, granted_at, revoked_at FROM loopa_coach_share_grants WHERE user_id = ? AND coach_id = ?;
A row with revoked_at IS NULL is live. No row at all means denied - the
absence is the denial, and there is no default-allow anywhere in the path.
## "My coach says they cannot see my workouts"
Walk the same order the code does:
1. **Is the coach active?** A terminated coach fails before any per-field lookup.
1. **Is either party blocked?** Blocking severs access in both directions without
touching the grants, so the grants can look fine and the reads still fail.
1. **Is the roster link live?** loopa_coach_clients.ended_at must be NULL.
1. **Is there a live workouts grant?** This is the usual answer.
Send the member to **More, then Preferences, then Your coach**. They turn it on. You do not.
## "Can my coach schedule training for me?"
Only if the member has shared workouts. Assigning a program is a write and takes a stricter test than reading: a coach who can read a client's training is not thereby entitled to put a program on their calendar. Without the grant the coach gets a plain refusal saying the client has not shared workouts with them.
## "Can I see when my coach looked?"
Yes, and point them at it - a control the member can inspect is worth more than one they are told about. It is under **More, then Preferences, then Your Data**, and it distinguishes a coach glancing at their client list from a coach opening that member and reading.
That distinction is deliberate. Before it existed, a coach opening a list of forty names wrote the same record as a coach reading one person, and the member's screen overstated what had happened. A log that cries wolf gets ignored.
## "My coach messaged me / can I message my coach?"
There is **no coach-to-client messaging in Loopa**, and that is a design decision rather than a missing feature. Do not promise it is coming.
What exists is bounded and asymmetric:
* A coach can comment on a **completed session** the member has shared - at most ten per client per day. * The member can **reply on that thread**. They cannot start one. A member with no coach comment on a session has nothing to reply to, and the app says so. * Recommendations: three per client per day, one way, no reply path. * A plan offer, whose only member-to-coach text is a decline reason. * Two forum broadcasts a day into the coach's private forum.
A coach asking support to relay a longer message to a client should be told no. The bounds are the product.
## Reporting a coach comment
Members can report any comment on their own session. A reported comment keeps
reported_at and a reason; a moderated one is **hidden** and is never
served again - not grayed out with a "removed" placeholder, which would reproduce
the harm.
Coach suspension is loopa_coaches.status and only Patrick sets it. If a
report needs that, escalate; do not action it yourself.
## What to escalate immediately
A member reporting that a coach saw a category they never enabled, where the grant table shows no live row for it. That would be a boundary failure rather than a support question, and it goes straight to engineering with the user id, the coach id and the timestamp.