candle-annotator/openspec/changes/user-accounts/specs/user-settings/spec.md
Marko Djordjevic c36ab7c146 Implement task 6.1: Create PUT /api/auth/profile endpoint for updating user display name
- Create src/app/api/auth/profile/route.ts with PUT handler
- Validates user is authenticated (returns 401 if not)
- Validates request body has a non-empty name field
- Updates user's name in the database
- Returns 200 with updated user data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 10:20:20 +01:00

5.3 KiB

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