MindFlow’s notification system runs entirely as a server-side background process. TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/J0S3-LEON/pf_pruebasAseguramientoCalid_SDD/llms.txt
Use this file to discover all available pages before exploring further.
NotificationService executes an hourly cron job that scans for upcoming task deadlines and dispatches reminders to eligible students. There is no public HTTP endpoint for notifications — the NotificationModule registers only a service provider, with no controller. Frontend dashboards learn about notification activity through the fatigueHistory and task fields already available on GET /api/v1/dashboard.
No public endpoint exists for notifications. The
NotificationModule contains only a NotificationService (cron job) and no controller. There is no GET /api/v1/notifications or any other HTTP route under /api/v1/notifications. Notification dispatch is triggered exclusively by the backend scheduler.How the cron job works
The@Cron(CronExpression.EVERY_HOUR) decorator on dispatchReminders() causes NestJS’s built-in scheduler (registered via ScheduleModule.forRoot() in AppModule) to invoke the method once per hour. Each run follows this flow:
- Find eligible tasks — queries all tasks where
isDeleted = false,deadlinefalls within the next 24 hours, and at least one micro-objective hasisCompleted = falseandisAuditOnly = false. - Per student–task pair — calls
processTaskNotification(studentId, taskId, now)for each eligible task. - Session suppression check — if the student has an active EMA session (
isActive = true), the notification is suppressed and aNotificationLogentry is persisted withstatus = 'suppressed'andattemptCount = 0. - Frequency cap check — counts
sentnotifications for the student within the last 24-hour rolling window. If the count is already 3 or more, the run is skipped without creating a new log entry. - Retry resolution — looks for an existing
NotificationLogentry for the same student–task pair withstatus IN ('pending', 'failed')andattemptCount < 3. If one exists, it is updated rather than a new entry being created. - Dispatch attempt — calls
deliver(studentId, taskId). On success the log entry is updated tostatus = 'sent'. On failure,attemptCountis incremented; onceattemptCountreaches 3 the entry is set tostatus = 'failed'and no further retries occur.
NotificationLog database record
Every notification event — whether sent, suppressed, pending, or failed — is persisted to thenotification_logs table via PrismaService. The schema for each record is:
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Primary key, server-generated. |
studentId | string (UUID) | The student this notification targets. |
taskId | string (UUID) | The task that triggered the reminder. |
status | string | One of pending, sent, failed, or suppressed. See the status reference below. |
attemptCount | integer | Number of dispatch attempts made. Range: 0 (suppressed) to 3 (max attempts exhausted). |
dispatchedAtUtc | DateTime | UTC timestamp of the most recent dispatch attempt or suppression event. |
updatedAt | DateTime | Auto-updated by Prisma on every write. |
Example NotificationLog record (internal)
Status values
| Status | Meaning |
|---|---|
pending | A dispatch was attempted but has not yet succeeded. The cron job will retry on its next run, provided attemptCount < 3. |
sent | The notification was delivered successfully. |
failed | All 3 consecutive delivery attempts failed. No further retries will be made for this log entry. |
suppressed | Dispatch was skipped because the student had an active EMA session at the time the cron ran. The attempt does not count toward the frequency cap. |
Dispatch rules reference
| Rule | Detail |
|---|---|
| Cron frequency | Every hour (CronExpression.EVERY_HOUR). |
| Deadline window | Tasks with deadline within the next 24 hours from the time of the cron run. |
| Eligibility filter | Task must have isDeleted = false and at least one micro-objective with isCompleted = false and isAuditOnly = false. |
| Session suppression | If the student has isActive = true on any session, the notification is suppressed and logged — no delivery is attempted. |
| Frequency cap | Maximum 3 sent notifications per student per 24-hour rolling window. Suppressed notifications do not count toward this cap. |
| Max retry attempts | 3 per student–task pair per frequency window. After 3 failed attempts the entry is permanently marked failed. |
| Persistence SLA | Every notification event is written to notification_logs in < 3 seconds. |
Extending the delivery mechanism
Thedeliver(studentId, taskId) private method is the integration point for adding real push, email, or WebSocket delivery. In the current implementation it logs the event and returns true. To add a real channel:
- Inject the external notification provider (e.g. a mailer or push service) into
NotificationService. - Replace the log-and-return-true body of
deliver()with a call to that provider. - Let exceptions propagate — the caller already catches failures and handles the
attemptCountincrement.
Example — adding an email channel