# Feature: Account Deletion Scheduler

## Overview

**Goal:** Implement a scheduler in the backend that will delete accounts that are marked for deletion after a period of time.

**User Story:**  
As an administrator, I want accounts that are marked for deletion to be deleted around X amount of hours after they were marked. I want the time to be adjustable.

---

## Configuration

### Environment Variables

- `ACCOUNT_DELETION_THRESHOLD_HOURS`: Hours to wait before deleting marked accounts (default: 720 hours / 30 days)
  - **Minimum:** 24 hours (enforced for safety)
  - **Maximum:** 720 hours (30 days)
  - Configurable via environment variable with validation on startup

### Scheduler Settings

- **Check Interval:** Every 1 hour
- **Implementation:** APScheduler (BackgroundScheduler)
- **Restart Handling:** On app restart, scheduler checks for users with `deletion_in_progress = True` and retries them
- **Retry Logic:** Maximum 3 attempts per user; tracked via `deletion_attempted_at` timestamp

---

## Data Model Changes

### User Model (`backend/models/user.py`)

Add two new fields to the `User` dataclass:

- `deletion_in_progress: bool` - Default `False`. Set to `True` when deletion is actively running
- `deletion_attempted_at: datetime | None` - Default `None`. Timestamp of last deletion attempt

**Serialization:**

- Both fields must be included in `to_dict()` and `from_dict()` methods

---

## Deletion Process & Order

When a user is due for deletion (current time >= `marked_for_deletion_at` + threshold), the scheduler performs deletion in this order:

1. **Set Flag:** `deletion_in_progress = True` (prevents concurrent deletion)
2. **Pending Rewards:** Remove all pending rewards for user's children
3. **Children:** Remove all children belonging to the user
4. **Tasks:** Remove all user-created tasks (where `user_id` matches)
5. **Rewards:** Remove all user-created rewards (where `user_id` matches)
6. **Images (Database):** Remove user's uploaded images from `image_db`
7. **Images (Filesystem):** Delete `data/images/[user_id]` directory and all contents
8. **User Record:** Remove the user from `users_db`
9. **Clear Flag:** `deletion_in_progress = False` (only if deletion failed; otherwise user is deleted)
10. **Update Timestamp:** Set `deletion_attempted_at` to current time (if deletion failed)

### Error Handling

- If any step fails, log the error and continue to next step
- If deletion fails completely, update `deletion_attempted_at` and set `deletion_in_progress = False`
- If a user has 3 failed attempts, log a critical error but continue processing other users
- Missing directories or empty tables are not considered errors

---

## Admin API Endpoints

### New Blueprint: `backend/api/admin_api.py`

All endpoints require JWT authentication and admin privileges.

**Note:** Endpoint paths below are as defined in Flask (without `/api` prefix). Frontend accesses them via nginx proxy at `/api/admin/*`.

#### `GET /admin/deletion-queue`

Returns list of users pending deletion.

**Response:** JSON with `count` and `users` array containing user objects with fields: `id`, `email`, `marked_for_deletion_at`, `deletion_due_at`, `deletion_in_progress`, `deletion_attempted_at`

#### `GET /admin/deletion-threshold`

Returns current deletion threshold configuration.

**Response:** JSON with `threshold_hours`, `threshold_min`, and `threshold_max` fields

#### `PUT /admin/deletion-threshold`

Updates deletion threshold (requires admin auth).

**Request:** JSON with `threshold_hours` field

**Response:** JSON with `message` and updated `threshold_hours`

**Validation:**

- Must be between 24 and 720 hours
- Returns 400 error if out of range

#### `POST /admin/deletion-queue/trigger`

Manually triggers the deletion scheduler (processes entire queue immediately).

**Response:** JSON with `message`, `processed`, `deleted`, and `failed` counts

---

## SSE Event

### New Event Type: `USER_DELETED`

**File:** `backend/events/types/user_deleted.py`

**Payload fields:**

- `user_id: str` - ID of deleted user
- `email: str` - Email of deleted user
- `deleted_at: str` - ISO format timestamp of deletion

**Broadcasting:**

- Event is sent only to **admin users** (not broadcast to all users)
- Triggered immediately after successful user deletion
- Frontend admin clients can listen to this event to update UI

---

## Implementation Details

### File Structure

- `backend/config/deletion_config.py` - Configuration with env variable
- `backend/utils/account_deletion_scheduler.py` - Scheduler logic
- `backend/api/admin_api.py` - New admin endpoints
- `backend/events/types/user_deleted.py` - New SSE event

### Scheduler Startup

In `backend/main.py`, import and call `start_deletion_scheduler()` after Flask app setup

### Logging Strategy

**Configuration:**

- Use dedicated logger: `account_deletion_scheduler`
- Log to both stdout (for Docker/dev) and rotating file (for persistence)
- File: `logs/account_deletion.log`
- Rotation: 10MB max file size, keep 5 backups
- Format: `%(asctime)s - %(name)s - %(levelname)s - %(message)s`

**Log Levels:**

- **INFO:** Each deletion step (e.g., "Deleted 5 children for user {user_id}")
- **INFO:** Summary after each run (e.g., "Deletion scheduler run: 3 users processed, 2 deleted, 1 failed")
- **ERROR:** Individual step failures (e.g., "Failed to delete images for user {user_id}: {error}")
- **CRITICAL:** User with 3+ failed attempts (e.g., "User {user_id} has failed deletion 3 times")
- **WARNING:** Threshold set below 168 hours (7 days)

---

## Acceptance Criteria (Definition of Done)

### Data Model

- [x] Add `deletion_in_progress` field to User model
- [x] Add `deletion_attempted_at` field to User model
- [x] Update `to_dict()` and `from_dict()` methods for serialization
- [x] Update TypeScript User interface in frontend

### Configuration

- [x] Create `backend/config/deletion_config.py` with `ACCOUNT_DELETION_THRESHOLD_HOURS`
- [x] Add environment variable support with default (720 hours)
- [x] Enforce minimum threshold of 24 hours
- [x] Enforce maximum threshold of 720 hours
- [x] Log warning if threshold is less than 168 hours

### Backend Implementation

- [x] Create `backend/utils/account_deletion_scheduler.py`
- [x] Implement APScheduler with 1-hour check interval
- [x] Implement deletion logic in correct order (pending_rewards → children → tasks → rewards → images → directory → user)
- [x] Add comprehensive error handling (log and continue)
- [x] Add restart handling (check `deletion_in_progress` flag on startup)
- [x] Add retry logic (max 3 attempts per user)
- [x] Integrate scheduler into `backend/main.py` startup

### Admin API

- [x] Create `backend/api/admin_api.py` blueprint
- [x] Implement `GET /admin/deletion-queue` endpoint
- [x] Implement `GET /admin/deletion-threshold` endpoint
- [x] Implement `PUT /admin/deletion-threshold` endpoint
- [x] Implement `POST /admin/deletion-queue/trigger` endpoint
- [x] Add JWT authentication checks for all admin endpoints
- [x] Add admin role validation

### SSE Event

- [x] Create `backend/events/types/user_deleted.py`
- [x] Add `USER_DELETED` to `event_types.py`
- [x] Implement admin-only event broadcasting
- [x] Trigger event after successful deletion

### Backend Unit Tests

#### Configuration Tests

- [x] Test default threshold value (720 hours)
- [x] Test environment variable override
- [x] Test minimum threshold enforcement (24 hours)
- [x] Test maximum threshold enforcement (720 hours)
- [x] Test invalid threshold values (negative, non-numeric)

#### Scheduler Tests

- [x] Test scheduler identifies users ready for deletion (past threshold)
- [x] Test scheduler ignores users not yet due for deletion
- [x] Test scheduler handles empty database
- [x] Test scheduler runs at correct interval (1 hour)
- [x] Test scheduler handles restart with `deletion_in_progress = True`
- [x] Test scheduler respects retry limit (max 3 attempts)

#### Deletion Process Tests

- [x] Test deletion removes pending_rewards for user's children
- [x] Test deletion removes children for user
- [x] Test deletion removes user's tasks (not system tasks)
- [x] Test deletion removes user's rewards (not system rewards)
- [x] Test deletion removes user's images from database
- [x] Test deletion removes user directory from filesystem
- [x] Test deletion removes user record from database
- [x] Test deletion handles missing directory gracefully
- [x] Test deletion order is correct (children before user, etc.)
- [x] Test `deletion_in_progress` flag is set during deletion
- [x] Test `deletion_attempted_at` is updated on failure

#### Edge Cases

- [x] Test deletion with user who has no children
- [x] Test deletion with user who has no custom tasks/rewards
- [x] Test deletion with user who has no uploaded images
- [x] Test partial deletion failure (continue with other users)
- [x] Test concurrent deletion attempts (flag prevents double-deletion)
- [x] Test user with exactly 3 failed attempts (logs critical, no retry)

#### Admin API Tests

- [x] Test `GET /admin/deletion-queue` returns correct users
- [x] Test `GET /admin/deletion-queue` requires authentication
- [x] Test `GET /admin/deletion-threshold` returns current threshold
- [x] Test `PUT /admin/deletion-threshold` updates threshold
- [x] Test `PUT /admin/deletion-threshold` validates min/max
- [x] Test `PUT /admin/deletion-threshold` requires admin role
- [x] Test `POST /admin/deletion-queue/trigger` triggers scheduler
- [x] Test `POST /admin/deletion-queue/trigger` returns summary

#### Integration Tests

- [x] Test full deletion flow from marking to deletion
- [x] Test multiple users deleted in same scheduler run
- [x] Test deletion with restart midway (recovery)

### Logging & Monitoring

- [x] Configure dedicated scheduler logger with rotating file handler
- [x] Create `logs/` directory for log files
- [x] Log each deletion step with INFO level
- [x] Log summary after each scheduler run (users processed, deleted, failed)
- [x] Log errors with user ID for debugging
- [x] Log critical error for users with 3+ failed attempts
- [x] Log warning if threshold is set below 168 hours

### Documentation

- [x] Create `README.md` at project root
- [x] Document scheduler feature and behavior
- [x] Document environment variable `ACCOUNT_DELETION_THRESHOLD_HOURS`
- [x] Document deletion process and order
- [x] Document admin API endpoints
- [x] Document restart/retry behavior

---

## Testing Strategy

All tests should use `DB_ENV=test` and operate on test databases in `backend/test_data/`.

### Unit Test Files

- `backend/tests/test_deletion_config.py` - Configuration validation
- `backend/tests/test_deletion_scheduler.py` - Scheduler logic
- `backend/tests/test_admin_api.py` - Admin endpoints

### Test Fixtures

- Create users with various `marked_for_deletion_at` timestamps
- Create users with children, tasks, rewards, images
- Create users with `deletion_in_progress = True` (for restart tests)

### Assertions

- Database records are removed in correct order
- Filesystem directories are deleted
- Flags and timestamps are updated correctly
- Error handling works (log and continue)
- Admin API responses match expected format

---

## Future Considerations

- Archive deleted accounts instead of hard deletion
- Email notification to admin when deletion completes
- Configurable retry count (currently hardcoded to 3)
- Soft delete with recovery option (within grace period)
