Skip to content

[Social Work] - Deactivate Staff accounts after 60 days of inactivity - #1829

Open
landonshumway-ia wants to merge 21 commits into
csg-org:mainfrom
InspiringApps:feat/sw-staff-user-inactive-notifications
Open

[Social Work] - Deactivate Staff accounts after 60 days of inactivity#1829
landonshumway-ia wants to merge 21 commits into
csg-org:mainfrom
InspiringApps:feat/sw-staff-user-inactive-notifications

Conversation

@landonshumway-ia

@landonshumway-ia landonshumway-ia commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

The commission has requested that staff accounts automatically expire after they have not logged in after 60 days. Before reaching that point we will send out a notification 10 days prior, 3 days prior, and the last day before their account is deactivated. This adds a new CDK stack for a scheduled job that runs daily to list all of the staff users for the compact, checks the last time they logged in, and sends out notifications to users that match the specific period of inactivity notifying them that they need to log back in. The notifications are also sent to the associated state admins for the jurisdiction if the user only has permissions in a specific jurisdiction, or the compact admins if the user to be deactivated is the only state admin.

In order to support this, we needed to start tracking a 'lastLoginAt' timestamp field on the staff user DynamoDB record. This field is now updated in our token generation hook every time the user successfully logs in and generates an access token.

This also updates the re-invite user endpoint to re-enable the Cognito user so that an admin staff user can re-invite a user that has been deactivated.

The original implementation for staff user permission and attribute updates did not update the timestamp of the date. Although the UI does not rely on this change, it helps devops track when the latest changes have occurred on a record. This also updates the staff user related logic to update that field when changes are made.

Testing List

  • yarn test:unit:all should run without errors or warnings
  • yarn serve should run without errors or warnings
  • yarn build should run without errors or warnings
  • For API configuration changes: CDK tests added/updated in backend/compact-connect/tests/unit/test_api.py
  • For API endpoint changes: OpenAPI spec updated to show latest endpoint configuration run compact-connect/bin/download_oas30.py
  • Code review

Closes #1668

Summary by CodeRabbit

  • New Features

    • Added automated staff-user inactivity reminders at 10 days, 3 days, 1 day, and on the deactivation date.
    • Users are deactivated after 60 days of inactivity, with notifications sent to users and relevant administrators.
    • Added last-login tracking for accurate inactivity processing.
    • Reinvitation now re-enables accounts disabled for inactivity.
    • Added safeguards against duplicate notifications and deactivation attempts.
  • Bug Fixes

    • Improved handling of paginated staff-user records and users across multiple compacts.
    • Improved resilience when notification or deactivation operations fail.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 56b2eb53-920b-4243-a8fd-bac0c2dfc7d1

📥 Commits

Reviewing files that changed from the base of the PR and between 22f41d3 and 6723b87.

📒 Files selected for processing (1)
  • backend/social-work-app/lambdas/python/common/cc_common/data_model/user_client.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/social-work-app/lambdas/python/common/cc_common/data_model/user_client.py

📝 Walkthrough

Walkthrough

Adds staff-user inactivity tracking and lifecycle processing. The change records logins, identifies inactive users, sends reminder emails, deactivates users after the inactivity period, tracks workflow state, and provisions daily scheduled infrastructure.

Changes

Staff User Inactivity

Layer / File(s) Summary
User activity lifecycle
backend/social-work-app/lambdas/python/common/cc_common/data_model/schema/user/*, backend/social-work-app/lambdas/python/common/cc_common/data_model/user_client.py, backend/social-work-app/lambdas/python/staff-user-pre-token/*, backend/social-work-app/lambdas/python/common/tests/*, backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_get_users.py
Adds StaffUserData, optional lastLoginAt fields, login recording, Cognito deactivation, paginated user iteration, and reinvitation re-enablement.
Inactivity notification delivery
backend/social-work-app/lambdas/nodejs/email-notification-service/*, backend/social-work-app/lambdas/python/common/cc_common/email_service_client.py, backend/social-work-app/lambdas/python/common/tests/unit/test_email_service_client.py
Adds the staffUserInactivityNotification template flow with specific recipients, formatted dates, account guidance, and validation.
Directory and event-state tracking
backend/social-work-app/lambdas/python/staff-users/staff_user_directory.py, backend/social-work-app/lambdas/python/staff-users/staff_user_inactivity_tracker.py, backend/social-work-app/lambdas/python/staff-users/tests/unit/*, backend/social-work-app/lambdas/python/staff-users/tests/function/test_staff_user_inactivity_tracker.py
Adds compact user classification, administrator indexes, inactivity filtering, and DynamoDB-backed tracking for notification and deactivation steps.
Inactivity processing workflow
backend/social-work-app/lambdas/python/staff-users/handlers/staff_user_inactivity.py, backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_staff_user_inactivity.py, backend/social-work-app/lambdas/python/staff-users/tests/unit/test_resolve_admin_recipients.py
Adds validation, reminder and day-of processing, administrator resolution, idempotent notifications, deactivation ordering, metrics, failure handling, replay support, and timeout handling.
Scheduled infrastructure and monitoring
backend/social-work-app/stacks/staff_user_inactivity_stack.py, backend/social-work-app/pipeline/backend_stage.py, backend/social-work-app/stacks/api_lambda_stack/staff_users.py, backend/social-work-app/stacks/persistent_stack/staff_users.py, backend/social-work-app/tests/app/*
Adds the inactivity Lambda, EventBridge schedules, IAM permissions, CloudWatch alarms and queries, pipeline integration, reinvitation permission assertions, and scope-customization error monitoring.

Estimated code review effort: 5 (Critical) | ~90 minutes

Mergeability Score: ⚪ Minimal · up to 6723b

This change adds automated staff-account inactivity notifications and deactivation behavior; no actionable merge-blocking risk remains based on the supplied evidence, so it is merge-ready after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant EventBridge
  participant StaffUserInactivityHandler
  participant CompactStaffUserDirectory
  participant StaffUserInactivityTracker
  participant EmailServiceClient
  participant UserClient
  EventBridge->>StaffUserInactivityHandler: Invoke scheduled inactivity event
  StaffUserInactivityHandler->>CompactStaffUserDirectory: Select inactive users and administrators
  StaffUserInactivityHandler->>StaffUserInactivityTracker: Check and record workflow steps
  StaffUserInactivityHandler->>EmailServiceClient: Send user and administrator emails
  StaffUserInactivityHandler->>UserClient: Deactivate user on day-of run
Loading

Possibly related PRs

  • csg-org/CompactConnect#1277: Adds a related inactivity notification workflow with idempotent tracking and email-service integration.
  • csg-org/CompactConnect#1548: Extends the email notification Lambda and shared email client with a template-specific notification method.

Suggested reviewers: jusdino, jlkravitz

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement the linked issue's staff-account expiration workflow, advance warnings, recipient notifications, and login-based activity tracking [#1668].
Out of Scope Changes check ✅ Passed The changes support the inactivity feature, including notifications, account lifecycle updates, scheduling, infrastructure, and related tests.
Title check ✅ Passed The title clearly summarizes the primary change: automatic deactivation of staff accounts after 60 days of inactivity.
Description check ✅ Passed The description explains the implementation, affected workflows, testing requirements, and linked issue, but omits the template's Requirements List heading.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
backend/social-work-app/lambdas/python/staff-users/staff_user_inactivity_tracker.py (1)

101-101: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the shared clock for the TTL.

The rest of this feature reads time from config.current_standard_datetime, and the function tests patch that property. This line reads time.time() directly, so the TTL is not controlled by the test clock. The TTL is not asserted today, so behavior is correct. Aligning the time source keeps one clock for the module.

♻️ Proposed change
-            'ttl': int(time.time()) + int(timedelta(days=self._TTL_DAYS).total_seconds()),
+            'ttl': int((config.current_standard_datetime + timedelta(days=self._TTL_DAYS)).timestamp()),

Remove the now-unused import time if no other reference remains.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/social-work-app/lambdas/python/staff-users/staff_user_inactivity_tracker.py`
at line 101, Update the TTL calculation in the inactivity-tracking flow to
derive the current timestamp from config.current_standard_datetime instead of
time.time(), preserving the existing _TTL_DAYS offset. Remove the time import if
it is no longer referenced elsewhere in the module.
backend/social-work-app/lambdas/nodejs/email-notification-service/lambda.ts (1)

352-358: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Tighten the validation of inactivityPeriodDays and deactivationDate.

Two points in this validation block:

  1. !event.templateVariables?.inactivityPeriodDays rejects the numeric value 0. Use an explicit undefined/null check for the number field.
  2. The block checks presence of deactivationDate but not its format. formatIsoDateAsSlashFormat in lib/email/email-notification-service.ts calls Number on each segment. A non-YYYY-MM-DD string renders NaN/NaN/undefined in the subject and body instead of failing.

The current Python producer always sends 60 and an ISO date, so neither case is reachable today. Both guards protect the email content against a future producer change.

♻️ Proposed validation
         case 'staffUserInactivityNotification':
             if (!event.templateVariables?.staffUserFirstName
                 || !event.templateVariables?.staffUserLastName
                 || !event.templateVariables?.staffUserEmail
                 || !event.templateVariables?.deactivationDate
-                || !event.templateVariables?.inactivityPeriodDays) {
+                || event.templateVariables?.inactivityPeriodDays === undefined
+                || event.templateVariables?.inactivityPeriodDays === null) {
                 throw new Error('Missing required template variables for staffUserInactivityNotification template.');
             }
+            if (!/^\d{4}-\d{2}-\d{2}$/.test(event.templateVariables.deactivationDate)) {
+                throw new Error('Invalid deactivationDate for staffUserInactivityNotification template. Expected YYYY-MM-DD.');
+            }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/social-work-app/lambdas/nodejs/email-notification-service/lambda.ts`
around lines 352 - 358, Update the validation block for the
staffUserInactivityNotification template to check inactivityPeriodDays
explicitly for null/undefined so numeric 0 is accepted, and validate
deactivationDate as a valid YYYY-MM-DD date before proceeding. Preserve the
existing required-field checks and throw the same missing-template-variables
error when either value is invalid.
backend/social-work-app/lambdas/nodejs/tests/email-notification-service.test.ts (1)

1187-1201: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the formatted date in the success test.

The test asserts the recipient only. The new formatIsoDateAsSlashFormat helper converts 2026-09-14 to 09/14/2026. Add an assertion on the rendered subject so a regression in the date format fails this test.

♻️ Proposed additional assertion
             expect(mockSESClient).toHaveReceivedCommandWith(SendEmailCommand, {
                 Destination: {
                     ToAddresses: ['jane@example.com']
-                }
+                },
+                Content: expect.objectContaining({
+                    Simple: expect.objectContaining({
+                        Subject: { Data: 'CompactConnect account for Jane Smith will be deactivated on 09/14/2026' }
+                    })
+                })
             });

Confirm the Content shape against the existing SES assertions in this file before applying.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/social-work-app/lambdas/nodejs/tests/email-notification-service.test.ts`
around lines 1187 - 1201, Update the successful staff inactivity notification
test to assert the SES SendEmailCommand subject includes the formatted date
“09/14/2026,” using the existing Content shape and SES assertion patterns in the
file. Keep the recipient assertion unchanged and target the rendered subject
produced by formatIsoDateAsSlashFormat.
backend/social-work-app/lambdas/python/staff-users/handlers/staff_user_inactivity.py (1)

250-252: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

already_done mixes email skips and deactivation skips.

Metrics.record_email_outcome increments already_done for a skipped email. This line increments the same counter for a skipped deactivation. A run that reports alreadyDone: 5 does not say which steps were skipped, which makes reconciliation of a partial run harder.

Add a separate counter for skipped deactivations.

♻️ Proposed change
 `@dataclass`
 class Metrics:
     ...
     deactivated: int = 0
     deactivations_failed: int = 0
+    deactivations_already_done: int = 0
     def as_dict(self) -> dict[str, int]:
         return {
             ...
             'deactivated': self.deactivated,
             'deactivationsFailed': self.deactivations_failed,
+            'deactivationsAlreadyDone': self.deactivations_already_done,
         }
     if tracker.was_already_done(InactivityStep.DEACTIVATION):
-        metrics.already_done += 1
+        metrics.deactivations_already_done += 1
         return

test_already_notified_users_are_not_emailed_twice asserts alreadyDone > 0 on a reminder run, so it stays valid.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/social-work-app/lambdas/python/staff-users/handlers/staff_user_inactivity.py`
around lines 250 - 252, Replace the deactivation skip increment in the handler’s
InactivityStep.DEACTIVATION branch with a dedicated skipped-deactivation metric,
leaving Metrics.record_email_outcome and its already_done behavior unchanged.
Define or reuse the corresponding Metrics field and ensure the reported metrics
expose this separate counter for reconciliation.
backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_staff_user_inactivity.py (1)

218-229: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for a partial email failure.

test_an_email_failure_is_counted_and_does_not_abort_the_run fails every send. The handler tracks USER_EMAIL and ADMIN_EMAIL as separate steps so that one failure retries only the failed half. No handler-level test proves that wiring.

Add a case where the admin send fails and the user send succeeds. Assert that a second run re-sends only to the admins.

💚 Proposed test
def test_a_failed_admin_send_is_retried_without_re_emailing_the_user(self):
    _, user_email = self._seed_user(days_since_login=51, jurisdictions={'oh': {WRITE}})
    _, admin_email = self._seed_user(days_since_login=1, jurisdictions={'oh': {ADMIN}})

    def fail_admin_only(**kwargs):
        if kwargs['recipient_emails'] == [admin_email]:
            raise RuntimeError('SES is down')

    with patch('cc_common.config._Config.email_service_client') as mock_email_client:
        mock_email_client.send_staff_user_inactivity_notification_email.side_effect = fail_admin_only
        self._run(days_before=10)

    with patch('cc_common.config._Config.email_service_client') as mock_email_client:
        result = self._run(days_before=10)

    self.assertEqual([[admin_email]], self._recipient_sets(mock_email_client))
    self.assertEqual(0, result['metrics']['userEmailsSent'])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_staff_user_inactivity.py`
around lines 218 - 229, Add a handler-level test alongside
test_an_email_failure_is_counted_and_does_not_abort_the_run that seeds a user
and admin, makes only the admin recipient send fail, then runs the handler again
with successful sending. Assert the second run invokes the email client only for
the admin recipient and reports zero user emails sent, proving USER_EMAIL
succeeds once while ADMIN_EMAIL is retried.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@backend/social-work-app/lambdas/python/common/cc_common/data_model/user_client.py`:
- Around line 168-176: Update the login-recording DynamoDB update in the
surrounding user-client method to conditionally succeed only while the user
record remains active and its lifecycle version is unchanged; prevent the stale
pre-token invocation from setting status back to StaffUserStatus.ACTIVE after
deactivate_user begins. Reuse the existing lifecycle/version field and handle
the conditional failure as a rejected login write, then add a concurrency test
covering login loading user_data before deactivation and attempting the update
afterward.

In `@backend/social-work-app/lambdas/python/staff-user-pre-token/main.py`:
- Around line 42-51: Make recording the login event mandatory in the pre-token
handler: update the flow around record_user_login so token issuance does not
continue when persistence fails. Remove the swallowed exception behavior and
propagate the failure, or otherwise ensure a durable retry/verification state
prevents inactivity deactivation until the login is recorded.

In
`@backend/social-work-app/lambdas/python/staff-users/handlers/staff_user_inactivity.py`:
- Around line 184-210: Update the comment above the user and admin sends to
describe only that they are separate sends with independent retry behavior;
remove the claim that one admin cannot see another admin’s address. Do not
change the existing recipient batching or tracking logic in the USER_EMAIL and
ADMIN_EMAIL flows.

In `@backend/social-work-app/lambdas/python/staff-users/staff_user_directory.py`:
- Around line 27-32: Update the administrator-bucket population in the
staff-user directory initialization to add users only when their status equals
StaffUserStatus.ACTIVE.value, covering both _compact_admins and
_jurisdiction_admins while preserving self._users for all users. Add regression
coverage for inactive compact and jurisdiction administrators to ensure
resolve_admin_recipients excludes them.

---

Nitpick comments:
In `@backend/social-work-app/lambdas/nodejs/email-notification-service/lambda.ts`:
- Around line 352-358: Update the validation block for the
staffUserInactivityNotification template to check inactivityPeriodDays
explicitly for null/undefined so numeric 0 is accepted, and validate
deactivationDate as a valid YYYY-MM-DD date before proceeding. Preserve the
existing required-field checks and throw the same missing-template-variables
error when either value is invalid.

In
`@backend/social-work-app/lambdas/nodejs/tests/email-notification-service.test.ts`:
- Around line 1187-1201: Update the successful staff inactivity notification
test to assert the SES SendEmailCommand subject includes the formatted date
“09/14/2026,” using the existing Content shape and SES assertion patterns in the
file. Keep the recipient assertion unchanged and target the rendered subject
produced by formatIsoDateAsSlashFormat.

In
`@backend/social-work-app/lambdas/python/staff-users/handlers/staff_user_inactivity.py`:
- Around line 250-252: Replace the deactivation skip increment in the handler’s
InactivityStep.DEACTIVATION branch with a dedicated skipped-deactivation metric,
leaving Metrics.record_email_outcome and its already_done behavior unchanged.
Define or reuse the corresponding Metrics field and ensure the reported metrics
expose this separate counter for reconciliation.

In
`@backend/social-work-app/lambdas/python/staff-users/staff_user_inactivity_tracker.py`:
- Line 101: Update the TTL calculation in the inactivity-tracking flow to derive
the current timestamp from config.current_standard_datetime instead of
time.time(), preserving the existing _TTL_DAYS offset. Remove the time import if
it is no longer referenced elsewhere in the module.

In
`@backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_staff_user_inactivity.py`:
- Around line 218-229: Add a handler-level test alongside
test_an_email_failure_is_counted_and_does_not_abort_the_run that seeds a user
and admin, makes only the admin recipient send fail, then runs the handler again
with successful sending. Assert the second run invokes the email client only for
the admin recipient and reports zero user emails sent, proving USER_EMAIL
succeeds once while ADMIN_EMAIL is retried.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 447b5744-7d34-41b7-af06-904a250da9de

📥 Commits

Reviewing files that changed from the base of the PR and between 5d7ca70 and e12f1ae.

📒 Files selected for processing (33)
  • backend/social-work-app/lambdas/nodejs/email-notification-service/lambda.ts
  • backend/social-work-app/lambdas/nodejs/lib/email/email-notification-service.ts
  • backend/social-work-app/lambdas/nodejs/tests/email-notification-service.test.ts
  • backend/social-work-app/lambdas/nodejs/tests/lib/email/email-notification-service.test.ts
  • backend/social-work-app/lambdas/python/common/cc_common/data_model/schema/user/__init__.py
  • backend/social-work-app/lambdas/python/common/cc_common/data_model/schema/user/api.py
  • backend/social-work-app/lambdas/python/common/cc_common/data_model/schema/user/record.py
  • backend/social-work-app/lambdas/python/common/cc_common/data_model/user_client.py
  • backend/social-work-app/lambdas/python/common/cc_common/email_service_client.py
  • backend/social-work-app/lambdas/python/common/common_test/test_constants.py
  • backend/social-work-app/lambdas/python/common/common_test/test_data_generator.py
  • backend/social-work-app/lambdas/python/common/tests/function/test_data_model/test_user_client.py
  • backend/social-work-app/lambdas/python/common/tests/unit/test_email_service_client.py
  • backend/social-work-app/lambdas/python/staff-user-pre-token/main.py
  • backend/social-work-app/lambdas/python/staff-user-pre-token/tests/test_main.py
  • backend/social-work-app/lambdas/python/staff-users/handlers/staff_user_inactivity.py
  • backend/social-work-app/lambdas/python/staff-users/staff_user_directory.py
  • backend/social-work-app/lambdas/python/staff-users/staff_user_inactivity_tracker.py
  • backend/social-work-app/lambdas/python/staff-users/tests/__init__.py
  • backend/social-work-app/lambdas/python/staff-users/tests/function/__init__.py
  • backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_get_users.py
  • backend/social-work-app/lambdas/python/staff-users/tests/function/test_handlers/test_staff_user_inactivity.py
  • backend/social-work-app/lambdas/python/staff-users/tests/function/test_staff_user_inactivity_tracker.py
  • backend/social-work-app/lambdas/python/staff-users/tests/unit/staff_user_test_data.py
  • backend/social-work-app/lambdas/python/staff-users/tests/unit/test_data_model/test_schema/test_user.py
  • backend/social-work-app/lambdas/python/staff-users/tests/unit/test_resolve_admin_recipients.py
  • backend/social-work-app/lambdas/python/staff-users/tests/unit/test_staff_user_directory.py
  • backend/social-work-app/pipeline/backend_stage.py
  • backend/social-work-app/stacks/api_lambda_stack/staff_users.py
  • backend/social-work-app/stacks/staff_user_inactivity_stack.py
  • backend/social-work-app/tests/app/base.py
  • backend/social-work-app/tests/app/test_api/test_staff_users_api.py
  • backend/social-work-app/tests/app/test_staff_user_inactivity_stack.py

Comment thread backend/social-work-app/lambdas/python/staff-user-pre-token/main.py
@landonshumway-ia
landonshumway-ia force-pushed the feat/sw-staff-user-inactive-notifications branch from fdcae0a to 46b7fe5 Compare August 14, 2026 18:25
@landonshumway-ia

Copy link
Copy Markdown
Collaborator Author

@jlkravitz This is now ready for your review. Thanks

@landonshumway-ia
landonshumway-ia force-pushed the feat/sw-staff-user-inactive-notifications branch from 96a07a0 to 4ab179d Compare August 18, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SW - Staff accounts auto expire after long period of inactivity

1 participant