Status Report Audiences
How program managers and project managers review status reports, the reminder flows, and the new caching + realtime invalidation pipeline.
Why Split the Audience?
- Program managers care about whether each project lead submitted their weekly update.
- Project managers need a focused list of teammates who still owe a report before they send the roll-up.
- Every report now carries a stored
audience(PROGRAM_MANAGERorPROJECT_MANAGER) so the API can hydrate the correct view without reclassifying on the fly.
Web Experience
- The workspace reports page now shows a Team Reviews tab for project managers that reuses
WorkplaceOwnerViewin team mode. - Managers can send member reminders directly from the pending list; reminders track per-recipient counts and last-sent timestamps.
- Owners and admins can request either audience through the TRPC router; the server authorises overrides only if the caller already has the matching role.
Mobile Experience
- The reports screen adds a My / Team toggle when the active workspace role is project manager.
GET /api/mobile/status-reports/teammirrors the server audience filters and surfaces pending members with reminder metadata.- Member reminders (
POST /api/mobile/status-reports/reminders/member) call the shared TRPC mutation so email content, logging, and cache busting stay consistent across platforms.
Caching and Realtime
- Workspace stats are cached per audience using the key pattern
workspace:{workspaceId}:stats:{weekStartDate}:{audience}. - The cache helper wraps Upstash Redis with stampede protection so concurrent viewers reuse the same computation.
- On submission the API broadcasts a payload containing
submissionAudience. The realtime worker deletes the matching cache key before fanning out events. - On manual reminders the API invalidates the
PROJECT_MANAGERcache immediately so pending counts and reminder badges refresh without waiting for the worker.
Operational Notes
- Manual reminders always create a
ReportReminderrow so repeat sends show accurate counts in both web and mobile UIs. - Cache invalidation falls back gracefully when Upstash is unavailable; the worker logs a warning and the next fetch recomputes stats.
- The Redis helpers run as no-ops when env variables are missing, keeping local development simple.
Last updated: 2025-11-11