Overdue Notifications

Feature Development Plan

The core of this new feature is:If a user hasn't checked out by their expectedCheckOutTimestamp, the system should automatically send an SMS and an email to their selected emergency contact. These notifications should include details about the trip and any notes from the check-in.

This is a critical safety feature and will primarily involve backend logic. Here's how we can break down its development:

This plan outlines the steps to implement automated notifications to emergency contacts for overdue check-ins.


Phase 1: Backend Foundation - Data Model & Lambda Function Setup

This phase focuses on preparing your AWS Amplify backend.

  1. Update CheckInLog GraphQL Schema:
    • To prevent sending duplicate notifications for the same overdue event, we need to add a flag to the CheckInLog model.
    • After saving the schema file, run amplify codegen models in your terminal to update your local Dart model files in lib/models/.
  2. Create an AWS Lambda Function for Notifications:
    • This serverless function will contain the core logic to identify overdue check-ins and dispatch notifications.
    • Action: In your project root directory, run the command amplify add function.
      • Function type: Choose "Lambda function (serverless function)".
      • Name: Give it a descriptive name, for example, overdueCheckinNotifier.
      • Runtime: Select Node.js (as it has robust AWS SDK support and many examples are available) or Python if you prefer.
      • Template: You can start with a basic "Hello World" template and modify it.
      • Advanced settings / Resource access:
        • When prompted if you want to configure advanced settings, choose yes.
        • When asked if you want to access other Amplify resources, choose yes.
        • Select the API (GraphQL) category.
        • Choose your existing GraphQL API.
        • Grant permissions for the Lambda function to perform the following operations on these models:
          • CheckInLog: Query (to find overdue check-ins) and Update (to set the isOverdueNotified flag).
          • Trip: Query (to get trip details like name and destination).
          • EmergencyContact: Query (to get the contact's phone number and email).
          • Profile: Query (to get the name of the user who is on the trip).
      • You can skip Lambda layers for now unless you have specific shared code.
      • Environment variables can be configured later if needed (e.g., for a default sender email address for SES).
    • This setup will create a new directory structure for your Lambda function, typically under amplify/backend/function/overdueCheckinNotifier/.

Action: In your amplify/backend/api/<YOUR_API_NAME>/schema.graphql file, add a new field isOverdueNotified: Boolean to the CheckInLog type.GraphQL

type CheckInLog @model @auth(rules: [{ allow: owner }]) {
  # ... all your existing fields like id, tripID, expectedCheckOutTimestamp, notes, selectedEmergencyContactID ...
  isOverdueNotified: Boolean # New field to track if notification has been sent
  # ... createdAt, updatedAt ...
}

Phase 2: Lambda Function Logic - Identifying Overdue Check-ins & Fetching Necessary Data

This involves writing the code for the overdueCheckinNotifier Lambda function.

  • Location: The main code file will be something like amplify/backend/function/overdueCheckinNotifier/src/index.js (for Node.js) or app.py (for Python).
  • Core Logic:
    1. The Lambda function will be triggered periodically by a scheduler (detailed in Phase 4).
    2. Query for Overdue CheckInLogs:
      • The function will make a GraphQL query to your AppSync API.
      • It needs to find CheckInLog records that meet these criteria:
        • checkOutTimestamp is null (meaning the user hasn't checked out).
        • expectedCheckOutTimestamp is in the past (i.e., less than the current time).
        • isOverdueNotified is false or null (to ensure notifications are sent only once per overdue event).
    3. Iterate and Gather Details: For each overdue CheckInLog identified:
      • Use the tripID from the CheckInLog to query the Trip model and retrieve details like tripName and destination.
      • Use the selectedEmergencyContactID from the CheckInLog to query the EmergencyContact model for the contact's name, phone, and email.
      • Use the owner field (or a similar user identifier on the CheckInLog or Trip model, which usually corresponds to the user's Cognito sub) to query the Profile model and get the user's firstName and lastName.

Phase 3: Lambda Function Logic - Sending SMS & Email Notifications

This continues within the same Lambda function, processing each overdue check-in.

  • AWS SDK: You'll use the AWS SDK (for JavaScript or Python, depending on your Lambda runtime) to interact with SNS and SES.
  1. Send SMS via AWS SNS (Simple Notification Service):
    • Permissions: The Lambda function's IAM execution role needs permission to publish to SNS (e.g., sns:Publish). If Amplify didn't add this automatically when you granted API access, you'll need to add a custom policy to the Lambda's IAM role. This can often be done by modifying the function's CloudFormation template (e.g., overdueCheckinNotifier-cloudformation-template.json) or using a custom-policies.json file if supported by your Amplify CLI version.
    • Logic:
      • Check if the fetched emergency contact has a phone number.
      • Construct the SMS message. It should be concise and include key information: user's name, that they are overdue, trip name, expected checkout time, and any notes from the check-in.
      • Use the AWS SDK's SNS client to publish the SMS to the emergency contact's phone number. Ensure phone numbers are stored and used in the E.164 format (e.g., +12223334444).
  2. Send Email via AWS SES (Simple Email Service):
    • Permissions: The Lambda's IAM role needs permission to send emails via SES (e.g., ses:SendEmail or ses:SendRawEmail). Add this similarly to the SNS permission.
    • SES Setup (Important - Manual AWS Console Steps):
      • Verify Sender Identity: In the AWS SES console (for the AWS region you're using for SES), you must verify an email address (e.g., alerts@your-app-domain.com) or an entire domain. Emails can only originate from verified identities.
      • SES Sandbox: By default, SES accounts are in a "sandbox" environment, meaning you can only send emails to other email addresses that are also verified in your SES account. To send emails to any address (like your users' emergency contacts), you must request AWS to move your SES account out of the sandbox.
    • Logic:
      • Check if the fetched emergency contact has an email address.
      • Construct the email (subject and body). The body can be HTML or plain text and should include the user's name, trip name, destination, expected checkout time, check-in notes, and a clear message for the emergency contact.
      • Use the AWS SDK's SES client to send the email from your verified sender identity.
  3. Update CheckInLog Record:
    • After successfully attempting to send both SMS and email (or whichever is applicable based on available contact info):
    • The Lambda function must make a GraphQL mutation call back to your AppSync API to update the specific CheckInLog record.
    • Set the isOverdueNotified field to true. This is crucial to prevent sending repeated notifications for the same overdue check-in.

Example policy statement:JSON

{
  "Effect": "Allow",
  "Action": ["ses:SendEmail", "ses:SendRawEmail"],
  "Resource": "*" // Scope this to specific verified identities if possible
}

Example policy statement:JSON

{
  "Effect": "Allow",
  "Action": ["sns:Publish"],
  "Resource": "*" // It's better to scope this down if possible
}

Phase 4: Scheduling the Lambda Function

To automate the checking process, the Lambda function needs to be invoked periodically.

  • Method: The recommended way is to use Amazon EventBridge Scheduler.
  • Action:
    1. After you successfully deploy your Lambda function (via amplify push), log in to the AWS Management Console.
    2. Navigate to Amazon EventBridge.
    3. In the EventBridge console, go to Schedules.
    4. Create a new schedule:
      • Provide a Name (e.g., OverdueCheckinNotificationScheduler).
      • Define the Schedule pattern. You can use a rate-based expression (e.g., rate(10 minutes), rate(30 minutes)) or a cron expression for more specific timing. Consider the balance between responsiveness and cost/load.
      • For the Target, select "AWS Lambda".
      • Choose your overdueCheckinNotifier Lambda function from the list.
      • The Input to the Lambda can usually be left as default for this use case.
      • EventBridge will typically handle or guide you on setting up the necessary Permissions for it to invoke your Lambda function.

Phase 5: Implementation Details, Configuration & Deployment

This involves fleshing out the Lambda code, configuring services, and thorough testing.

  1. Lambda Code Implementation:
    • Write the actual Node.js or Python code for the overdueCheckinNotifier Lambda.
      • Properly set up the AWS SDK clients for AppSync (to make GraphQL calls), SNS, and SES.
      • Implement robust error handling and logging (e.g., console.log statements in Node.js will appear in Amazon CloudWatch Logs, which is essential for debugging).
      • Carefully construct your GraphQL queries and mutations. For querying AppSync from a Lambda with IAM auth (which Amplify typically sets up), you'll need to sign your HTTP requests to the GraphQL endpoint.
  2. Environment Variables for Lambda (Recommended):
    • Consider setting environment variables for your Lambda function for values like:
      • SES_SENDER_EMAIL: The verified email address you'll send notifications from.
      • SES_REGION: The AWS region where your SES identity is verified.
    • These can be configured in the Lambda's settings in the AWS console or by modifying its CloudFormation template provided by Amplify.
  3. Local Mocking & Testing (Limited):
    • While amplify mock function <functionName> can help with basic Lambda logic testing, fully testing SNS/SES integration and scheduled triggers usually requires deployment to a dev environment.
  4. Deploy Backend Changes:
    • Once the Lambda code is written and permissions are set up in the Amplify project, run amplify push. This will deploy the schema changes, the new Lambda function, its IAM role, and any related configurations.
  5. Post-Deployment Configuration & Rigorous Testing:
    • Double-check that the EventBridge Scheduler is enabled and configured correctly.
    • Monitor CloudWatch Logs for your overdueCheckinNotifier Lambda to see its execution logs, confirm it's being triggered, and debug any issues.
    • End-to-End Testing is Critical:
      • Create a new trip in the app.
      • Perform a check-in, setting an expectedCheckOutTimestamp that will occur soon (e.g., 15-20 minutes in the future). Select an emergency contact for which you can monitor SMS/email.
      • Do not check out of the trip.
      • Wait for the EventBridge schedule to trigger your Lambda function (past the expected checkout time).
      • Verify that the designated emergency contact receives both the SMS and email notifications.
      • Check the CheckInLog record in your database (e.g., via AppSync query or DynamoDB console) to ensure isOverdueNotified is set to true.
      • Confirm that on subsequent runs of the Lambda, notifications are not sent again for this same overdue event.

This is a fairly complex feature involving multiple interconnected services. Breaking it down into these phases should help manage the implementation. The Lambda function's code, particularly the interactions with AppSync, SNS, and SES, along with proper error handling and idempotency (ensuring isOverdueNotified is reliably set), will be the most detailed part.