feat: add scheduled refresh token and password reset cleanup job#114
feat: add scheduled refresh token and password reset cleanup job#114GitAddRemote wants to merge 11 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a scheduled cleanup job in the auth module to purge revoked/expired refresh tokens and used/expired password reset records, preventing unbounded table growth and reducing retention of sensitive token data (Issue #98).
Changes:
- Introduces
TokenCleanupServicewith a Nest@Cronjob to delete revoked/expired rows fromrefresh_tokensandpassword_resets. - Registers the cleanup service in
AuthModule. - Documents
REFRESH_TOKEN_CLEANUP_CRONinbackend/.env.example.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| backend/src/modules/auth/token-cleanup.service.ts | Adds the scheduled cleanup job implementation and logging. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService as an auth provider. |
| backend/.env.example | Documents the cron env var used to configure the schedule. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add TokenCleanupService to the auth module with a @Cron job that runs daily at 3am (configurable via REFRESH_TOKEN_CLEANUP_CRON) and deletes all refresh_tokens rows where revoked=true or expires_at < now, and all password_resets rows where used=true or expires_at < now. - Job skips early when NODE_ENV=test - Logs row count and duration on success, error stack on failure - Does not rethrow on failure so job errors cannot crash the process - ScheduleModule is already conditionally excluded in test env (AppModule) Closes #98
Co-authored-with: ISSUE-98
943ff4a to
0507031
Compare
…ice, add tests - Replace expires_at with "expiresAt" in both QueryBuilder WHERE clauses — TypeORM quotes identifiers so the DB column is case-sensitive "expiresAt", not expires_at, which would always error and silently skip cleanup - Remove ConfigService import and constructor injection — it was never used; @Cron() is evaluated at module-load time before DI so ConfigService cannot supply the cron expression regardless - Add TokenCleanupService unit tests covering early return in test env, correct WHERE clauses for both delete operations, and error handling
There was a problem hiding this comment.
Pull request overview
Adds a scheduled maintenance task in the backend auth module to periodically purge expired/revoked authentication artifacts from the database, addressing table growth and reducing retention of sensitive token records.
Changes:
- Introduces
TokenCleanupServicewith a configurable daily@Cronjob to delete revoked/expiredrefresh_tokensand used/expiredpassword_resets. - Wires the service into
AuthModuleproviders. - Adds unit tests for early-return behavior, delete query conditions, and non-throwing failure handling; documents the cron env var in
.env.example.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| backend/src/modules/auth/token-cleanup.service.ts | New cron-driven cleanup logic for refresh tokens and password reset tokens. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Unit tests covering skip behavior in tests, delete query clauses, and error handling. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService in the auth module providers. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON default cron expression. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…_WORKER_ID guard @Cron() expressions are evaluated at module-load time in Node.js CJS, before dotenv runs, so REFRESH_TOKEN_CLEANUP_CRON from .env was never read. Switching to OnApplicationBootstrap + SchedulerRegistry means the cron is registered after ConfigModule has fully loaded all env vars. - Remove @Cron() decorator; implement OnApplicationBootstrap - Register cron via SchedulerRegistry using ConfigService.get() so .env values are honoured; falls back to '0 3 * * *' if unset - Add JEST_WORKER_ID guard to onApplicationBootstrap() so cron is never registered in Jest worker processes even if NODE_ENV is not 'test' - Add cron as a direct dependency (was transitive via @nestjs/schedule) - Update spec: explicit NODE_ENV mock in cleanupExpiredTokens early-return test for determinism; add onApplicationBootstrap() coverage
There was a problem hiding this comment.
Pull request overview
Adds an auth-module scheduled cleanup job intended to periodically purge revoked/expired refresh tokens (and used/expired password resets) to prevent unbounded table growth and reduce retention of sensitive token records.
Changes:
- Introduces
TokenCleanupServicethat registers a cron job on bootstrap and executes DB DELETEs for expired/revoked tokens. - Adds unit tests for cron registration guards and deletion query construction/error handling.
- Adds
REFRESH_TOKEN_CLEANUP_CRONto.env.exampleand addscronas a direct dependency.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds cron dependency entry and updates lock metadata. |
| backend/package.json | Adds cron dependency for runtime CronJob usage. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON with default schedule. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService in Auth module providers. |
| backend/src/modules/auth/token-cleanup.service.ts | Implements bootstrap-time cron registration and cleanup queries + logging. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Adds unit coverage for bootstrap guards and cleanup behavior. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Add @optional() to SchedulerRegistry injection so service can be instantiated in test environments where ScheduleModule is excluded - Validate cron expression at runtime; fall back to '0 3 * * *' on invalid value - Treat blank/whitespace REFRESH_TOKEN_CLEANUP_CRON as unset (|| not ??) - Upgrade Dockerfile base image from node:14 to node:18-alpine - Add migration for token cleanup indexes (partial + range indexes on revoked, expiresAt for refresh_tokens and used, expiresAt for password_resets) - Expand spec: test @optional() path, invalid cron fallback, blank env var
There was a problem hiding this comment.
Pull request overview
Adds an Auth-module scheduled maintenance job to remove expired/revoked refresh tokens and used/expired password reset tokens, plus supporting DB indexes and runtime configuration.
Changes:
- Introduces
TokenCleanupServicethat registers a cron job at bootstrap usingSchedulerRegistryand a configurable cron expression. - Adds unit tests covering bootstrap registration and cleanup query behavior.
- Adds a migration creating indexes to support efficient cleanup deletes; updates Docker base image and dependency set (adds
cron).
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks cron dependency and updates lockfile metadata. |
| backend/src/modules/auth/token-cleanup.service.ts | Implements bootstrap-registered cron + cleanup DELETE queries and logging. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Adds unit coverage for cron registration paths and cleanup execution. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService provider in AuthModule. |
| backend/src/migrations/1765038000000-AddTokenCleanupIndexes.ts | Adds indexes (partial + expiresAt) to speed up cleanup deletes. |
| backend/package.json | Adds direct dependency on cron. |
| backend/Dockerfile | Upgrades base image to Node 18 Alpine. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON configuration. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Merge conflict resolutions: - .env.example: keep both REFRESH_TOKEN_CLEANUP_CRON and ALLOWED_ORIGIN - package.json: keep both cron and cookie-parser dependencies - auth.module.ts: keep TokenCleanupService, drop RefreshTokenStrategy (superseded by custom cookie-reading RefreshTokenAuthGuard on main) - pnpm-lock.yaml: regenerated with pnpm install Review item fixes: - Log correct (effective) expression after fallback, not the invalid one - Extend cleanupExpiredTokens() guard to also skip when JEST_WORKER_ID set - Switch Dockerfile from node:18-alpine to node:18-slim (musl/bcrypt compat) - Add spec case for JEST_WORKER_ID guard in cleanupExpiredTokens - Unset JEST_WORKER_ID in non-test-env describe block so DB tests can run
There was a problem hiding this comment.
Pull request overview
Adds an environment-configurable scheduled cleanup job to the backend auth module to purge expired/revoked refresh tokens and used/expired password reset tokens, along with supporting DB indexes and runtime/container updates.
Changes:
- Introduces
TokenCleanupServicethat registers a cron job at bootstrap viaSchedulerRegistry, with runtime-configurable expression and test-environment guards. - Adds unit tests covering cron registration behavior and cleanup delete queries.
- Adds a migration for cleanup-oriented indexes and updates backend runtime dependencies/container base image.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks the new cron dependency (and related lockfile metadata updates). |
| backend/src/modules/auth/token-cleanup.service.ts | Implements scheduled token cleanup via OnApplicationBootstrap + SchedulerRegistry with env-driven cron expression and safeguards. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Adds unit tests for cron registration and cleanup delete behavior/guards. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService as an auth module provider. |
| backend/src/migrations/1765038000000-AddTokenCleanupIndexes.ts | Adds indexes (partial boolean + expiresAt) to support cleanup DELETE performance. |
| backend/package.json | Adds direct cron dependency. |
| backend/Dockerfile | Updates base image to Node 18 (slim) for dependency compatibility. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON configuration. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The previous comments said the WHERE clause 'mirrors cleanup query', which implied full coverage of the OR condition. Each partial index only covers one predicate (revoked = true / used = true); the range index on expiresAt handles the other side. Updated comments to describe what each index actually covers.
There was a problem hiding this comment.
Pull request overview
Adds a scheduled maintenance job to the auth subsystem to periodically delete expired/revoked refresh tokens and used/expired password reset tokens, with runtime-configurable cron scheduling and supporting DB indexes.
Changes:
- Introduces
TokenCleanupServicethat registers aCronJobviaSchedulerRegistryon bootstrap (env-driven schedule, safe no-op in test/Jest environments). - Adds unit tests covering cron registration behavior and cleanup query execution/guards.
- Adds a migration creating indexes to support efficient cleanup deletes, plus wires the service into
AuthModuleand documents the env var in.env.example.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds the cron dependency to the lockfile (and related metadata updates). |
| backend/package.json | Adds cron as a direct backend dependency. |
| backend/src/modules/auth/token-cleanup.service.ts | Implements bootstrap-time cron registration and token cleanup delete logic. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Adds unit tests for cron registration guards/fallbacks and delete behavior. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService in the auth module providers. |
| backend/src/migrations/1765038000000-AddTokenCleanupIndexes.ts | Adds partial/range indexes to support cleanup queries efficiently. |
| backend/Dockerfile | Updates Node base image version for backend container builds. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON configuration. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Node 18 reached EOL; CI already runs on Node 20. Switching to node:20-slim (Debian/glibc) keeps the runtime in sync with CI and avoids the musl libc issues that alpine would introduce for bcrypt's native prebuilds.
There was a problem hiding this comment.
Pull request overview
Adds a scheduled maintenance job to the auth subsystem that periodically deletes expired/revoked refresh tokens and used/expired password reset tokens, with configurable cron timing and supporting DB indexes.
Changes:
- Introduces
TokenCleanupServicethat registers a runtime-configured cron job viaSchedulerRegistryand performs periodic cleanup DELETEs. - Adds unit tests for cron registration guards/fallback behavior and for the cleanup DELETE queries.
- Adds DB indexes (including partial indexes) to support efficient cleanup, plus wiring/env/docs and container/runtime dependency updates.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks new direct cron dependency and associated lockfile updates. |
| backend/src/modules/auth/token-cleanup.service.ts | Implements runtime cron registration + token/password reset cleanup logic. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Adds unit coverage for bootstrap guards, cron expression fallback, and DELETE query behavior. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService in the Auth module providers. |
| backend/src/migrations/1765038000000-AddTokenCleanupIndexes.ts | Adds indexes to support efficient cleanup DELETEs. |
| backend/package.json | Adds cron as a direct dependency. |
| backend/Dockerfile | Updates runtime base image to Node 20 slim. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON configuration. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Service: - Separate the schedulerRegistry guard from the test/JEST_WORKER_ID guard so a missing registry in a non-test environment emits a warn log rather than silently no-oping; production misconfiguration is now visible in logs - Split the single try/catch around both DELETE queries into two independent blocks so a failure in the refresh token cleanup does not prevent the password reset cleanup from running; each table logs its own error Spec: - Extract restoreWorker() helper that calls delete instead of assignment when the original JEST_WORKER_ID value was undefined; assigning undefined to process.env coerces it to the string 'undefined', which would leave the guard permanently set and contaminate later tests - Add test: 'should still clean up password resets when refresh token cleanup fails' to assert the new per-table resilience
Resolved conflict in backend/.env.example: kept main's sectioned format and FRONTEND_URL; added REFRESH_TOKEN_CLEANUP_CRON under a new 'Token Cleanup' section; dropped the duplicate Application block from HEAD.
There was a problem hiding this comment.
Pull request overview
Adds a scheduled maintenance job to the auth module that periodically deletes expired/revoked refresh tokens and used/expired password reset tokens, with supporting DB indexes and runtime-configurable scheduling.
Changes:
- Introduces
TokenCleanupServicethat registers aCronJobat bootstrap usingSchedulerRegistry, with env-driven cron expression and safe fallbacks/guards for test environments. - Adds unit tests covering cron registration paths and cleanup delete behavior, including error handling.
- Adds a migration to create indexes that support efficient cleanup deletes; updates Docker base image and env example; adds
crondependency.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks cron dependency version used by the backend. |
| backend/src/modules/auth/token-cleanup.service.ts | Implements bootstrap-time cron registration and DB cleanup deletes. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Unit tests for cron registration guards/fallbacks and cleanup query behavior. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService in the auth module providers. |
| backend/src/migrations/1765038000000-AddTokenCleanupIndexes.ts | Adds indexes for revoked/used and expiresAt to speed up cleanup deletes. |
| backend/package.json | Adds direct dependency on cron. |
| backend/Dockerfile | Updates backend container base image to Node 20 slim. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON configuration. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Replace the inaccurate comment ('evaluates before dotenv runs') with the
actual constraint: @Cron() decorator arguments are evaluated at class-
definition time before DI runs, so ConfigService cannot be used in them
- Define DEFAULT_CRON = '0 3 * * *' once and reference it throughout,
eliminating the duplicated string that could diverge on future edits
There was a problem hiding this comment.
Pull request overview
Adds an Auth-module-level scheduled cleanup job to periodically delete expired/revoked refresh tokens and used/expired password reset tokens, with supporting DB indexes and runtime-configurable cron scheduling.
Changes:
- Introduces
TokenCleanupServicethat registers aCronJobat bootstrap time viaSchedulerRegistry, with runtime cron expression fromREFRESH_TOKEN_CLEANUP_CRONand safe fallbacks/guards for test environments. - Adds unit tests covering cron registration behavior and the cleanup DELETE queries (including error isolation between the two tables).
- Adds a migration creating indexes to support the cleanup queries, and updates runtime/build config (cron dependency, Docker Node image,
.env.example).
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks the newly-added direct cron dependency. |
| backend/src/modules/auth/token-cleanup.service.ts | Implements bootstrap-time cron registration + cleanup DELETEs with test-env guards and fallback cron expression handling. |
| backend/src/modules/auth/token-cleanup.service.spec.ts | Adds unit test coverage for cron registration and cleanup behavior. |
| backend/src/modules/auth/auth.module.ts | Registers TokenCleanupService in the Auth module. |
| backend/src/migrations/1765038000000-AddTokenCleanupIndexes.ts | Adds indexes (including partial indexes) to support efficient cleanup deletes. |
| backend/package.json | Adds cron as a direct dependency. |
| backend/Dockerfile | Bumps base image to node:20-slim. |
| backend/.env.example | Documents REFRESH_TOKEN_CLEANUP_CRON configuration. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const DEFAULT_CRON = '0 3 * * *'; | ||
| const rawExpression = this.configService | ||
| .get<string>('REFRESH_TOKEN_CLEANUP_CRON') | ||
| ?.trim(); | ||
| const cronExpression = rawExpression || DEFAULT_CRON; |
Summary
Implements a scheduled token cleanup job that periodically purges expired and revoked refresh tokens and used/expired password reset tokens from the database.
Test plan