## ADDED Requirements ### Requirement: Settings page at /app/settings The system SHALL serve a settings page at `/app/settings` (route `src/app/app/settings/page.tsx`). The page SHALL be accessible only to authenticated users. #### Scenario: Settings page renders - **WHEN** an authenticated user navigates to `/app/settings` - **THEN** the settings page renders with Profile, Security, and Danger Zone sections #### Scenario: Unauthenticated access - **WHEN** an unauthenticated user navigates to `/app/settings` - **THEN** they are redirected to `/login` ### Requirement: Profile section The Profile section SHALL display the user's name and email. The user SHALL be able to edit their display name via an input field and "Save" button. The email field SHALL be read-only. #### Scenario: View profile - **WHEN** the settings page loads - **THEN** the user's current name and email are displayed #### Scenario: Update display name - **WHEN** a user changes their name and clicks "Save" - **THEN** a PUT request is sent to `/api/auth/profile` with `{ name }` - **AND** on success, a toast confirms "Profile updated" #### Scenario: Empty name rejected - **WHEN** a user clears the name field and clicks "Save" - **THEN** validation prevents submission with an error message ### Requirement: Security section (credentials users) The Security section SHALL display a "Change Password" form with current password, new password, and confirm password fields. This section SHALL only be visible to users with `provider: 'credentials'`. #### Scenario: Change password successfully - **WHEN** a credentials user enters correct current password, new password (8+ chars), and matching confirmation - **THEN** a PUT request is sent to `/api/auth/password` with `{ currentPassword, newPassword }` - **AND** on success, a toast confirms "Password changed" #### Scenario: Wrong current password - **WHEN** a user enters incorrect current password - **THEN** the API returns HTTP 403 and an error message is displayed: "Current password is incorrect" #### Scenario: New password too short - **WHEN** a user enters a new password shorter than 8 characters - **THEN** validation prevents submission with an error message #### Scenario: Passwords don't match - **WHEN** the new password and confirmation don't match - **THEN** client-side validation shows "Passwords do not match" #### Scenario: OAuth user sees provider info - **WHEN** an OAuth user views the Security section - **THEN** instead of the password form, they see "Signed in via Google" with the Google icon ### Requirement: Profile update API endpoint The system SHALL provide a `PUT /api/auth/profile` endpoint that updates the authenticated user's display name. #### Scenario: Update name - **WHEN** PUT /api/auth/profile is called with `{ name: "New Name" }` by an authenticated user - **THEN** the user's name is updated in the database and HTTP 200 is returned #### Scenario: Unauthenticated - **WHEN** PUT /api/auth/profile is called without authentication - **THEN** HTTP 401 is returned ### Requirement: Password change API endpoint The system SHALL provide a `PUT /api/auth/password` endpoint that changes the authenticated user's password. The endpoint SHALL verify the current password before updating. #### Scenario: Successful password change - **WHEN** PUT /api/auth/password is called with correct `currentPassword` and valid `newPassword` - **THEN** the password_hash is updated with bcryptjs and HTTP 200 is returned #### Scenario: Wrong current password - **WHEN** PUT /api/auth/password is called with incorrect `currentPassword` - **THEN** HTTP 403 is returned with `{ error: "Current password is incorrect" }` #### Scenario: OAuth user attempts password change - **WHEN** an OAuth user calls PUT /api/auth/password - **THEN** HTTP 400 is returned with `{ error: "Password change not available for OAuth accounts" }` ### Requirement: Danger zone - delete account The Danger Zone section SHALL display a "Delete Account" button styled in red/destructive. Clicking it SHALL open a confirmation dialog requiring the user to type "DELETE" to confirm. #### Scenario: Delete account flow - **WHEN** a user clicks "Delete Account" and types "DELETE" in the confirmation dialog and confirms - **THEN** a DELETE request is sent to `/api/auth/account` - **AND** on success, the user is signed out and redirected to `/` #### Scenario: Cancel deletion - **WHEN** a user clicks "Delete Account" but dismisses the confirmation dialog - **THEN** no deletion occurs ### Requirement: Account deletion API endpoint The system SHALL provide a `DELETE /api/auth/account` endpoint that deletes the authenticated user and all their associated data (charts, annotations, annotation_types, span_annotations, span_label_types). #### Scenario: Successful deletion - **WHEN** DELETE /api/auth/account is called by an authenticated user - **THEN** all user data is deleted (cascade), the user record is deleted, and HTTP 200 is returned #### Scenario: Unauthenticated - **WHEN** DELETE /api/auth/account is called without authentication - **THEN** HTTP 401 is returned ### Requirement: Back to app navigation The settings page SHALL include a back link/button to return to `/app`. #### Scenario: Navigate back - **WHEN** a user clicks the back button on the settings page - **THEN** they are navigated to `/app`