# Profile & Settings Flow

# Flow: Profile & Settings

**Document:** LLD-004
**Version:** 1.0
**Date:** 2026-02-21
**Author:** Frontend Architect (AI Agent)
**Status:** Draft
**Scope:** Profile page, personal information display, KYC status, settings management, GDPR data export, and account deletion flow

---

## 1. Overview

The profile section provides users with personal information display (sourced from BankID), KYC verification status, and configurable settings. It also handles GDPR compliance features including data export (right to portability) and account deletion (right to erasure) with mandatory AML data retention notices.

**Profile sub-pages (web):**
- `/profile` — Hub with user info and menu
- `/profile/personal` — BankID-verified personal details (read-only)
- `/profile/security` — Security settings and active devices
- `/profile/notifications` — Push and email notification toggles
- `/profile/language` — Language selection (nb, en, bs, sq)

---

## 2. Profile Load + Settings Update

### 2.1 Sequence Diagram

```mermaid
sequenceDiagram
    actor User
    participant App as Drop App<br/>(/profile)
    participant API as Drop API
    participant DB as Database

    User->>App: Navigate to /profile
    App->>App: useAuth() — verify authenticated
    App->>API: GET /api/auth/me
    API->>DB: SELECT user + bank_accounts
    API-->>App: { user: { id, firstName, lastName, email, kycStatus, ... } }
    App->>App: Render profile hub<br/>(avatar initials, name, email, menu items)

    User->>App: Tap "Personlig informasjon"
    App->>App: Navigate to /profile/personal
    App->>App: Display BankID-verified fields (read-only)

    User->>App: Tap "Varsler"
    App->>App: Navigate to /profile/notifications
    App->>API: GET /api/settings
    API->>DB: SELECT settings WHERE user_id = ?

    alt Settings exist
        API-->>App: { data: { currency, language, pushEnabled, emailEnabled } }
    else No settings
        API->>DB: INSERT default settings (NOK, nb, push=true, email=true)
        API-->>App: { data: { default settings } }
    end

    App->>App: Render notification toggles

    User->>App: Toggle push notifications OFF
    App->>App: Update local state immediately
    App->>API: PATCH /api/settings { pushEnabled: false }
    API->>DB: UPDATE settings SET push_enabled = 0
    API-->>App: 200 { updated settings }

    alt API failure
        App->>App: Revert toggle to previous state
    end

    User->>App: Tap "Sprak" (Language)
    App->>App: Navigate to /profile/language
    App->>API: GET /api/settings
    API-->>App: { language: "nb" }
    App->>App: Show language list with current selection

    User->>App: Select "English", tap "Lagre"
    App->>API: PATCH /api/settings { language: "en" }
    API-->>App: 200 { updated }
```

---

## 3. Account Deletion Flow

### 3.1 Sequence Diagram

```mermaid
sequenceDiagram
    actor User
    participant App as Drop App
    participant API as Drop API
    participant DB as Database

    User->>App: Navigate to /profile then "Slett konto"
    App->>App: Show deletion warning dialog<br/>"Er du sikker? Dette kan ikke angres."
    App->>App: Show AML retention notice<br/>"Data beholdes i 5 aar iht. hvitvaskingsloven"

    User->>App: Confirm "Ja, slett kontoen min"
    App->>API: DELETE /api/user/account

    API->>DB: BEGIN TRANSACTION
    API->>DB: UPDATE users SET deleted_at = datetime('now')
    API->>DB: UPDATE sessions SET revoked = 1 WHERE user_id = ?
    API->>DB: INSERT data_access_requests<br/>(type=erasure, status=completed)
    API->>DB: COMMIT

    API-->>App: 200 { message: "Account scheduled for deletion",<br/>retentionNote: "Data retained for 5 years per AML requirements" }

    App->>App: Clear auth cookie/token
    App->>App: Show confirmation screen
    App->>App: Navigate to /login after 5 seconds
```

### 3.2 Account Deletion Process Flow

```mermaid
flowchart TD
    A[User requests account deletion] --> B{Confirmation dialog}
    B -->|Cancel| C[Return to profile]
    B -->|Confirm| D[Show AML retention notice]
    D --> E{User acknowledges retention}
    E -->|Cancel| C
    E -->|Proceed| F[DELETE /api/user/account]
    F --> G[Soft-delete user record<br/>deleted_at = now]
    G --> H[Revoke all active sessions]
    H --> I[Create erasure request record]
    I --> J[Clear auth cookie/token]
    J --> K[Show confirmation screen]
    K --> L[Redirect to /login]

    style D fill:#FEF3C7
    style G fill:#FEF2F2
```

---

## 4. Settings Matrix

### 4.1 User Settings

| Setting | API Field | Type | Options | Default | Persistence |
|---------|-----------|------|---------|---------|-------------|
| Display currency | `currency` | string | EUR, USD, GBP, BAM, CHF, PLN, NOK, RSD, TRY, PKR | NOK | `PATCH /api/settings` |
| Language | `language` | string | nb (Norsk Bokmal), en (English), bs (Bosanski), sq (Shqip) | nb | `PATCH /api/settings` |
| Push notifications | `pushEnabled` | boolean | true/false | true | `PATCH /api/settings` |
| Email notifications | `emailEnabled` | boolean | true/false | true | `PATCH /api/settings` |

### 4.2 Personal Information (Read-Only from BankID)

| Field | Source | Editable | Display Format |
|-------|--------|----------|----------------|
| First name | BankID ID token | No | Plain text |
| Last name | BankID ID token | No | Plain text |
| Email | User registration / BankID | No | Plain text |
| Phone | User registration | No | +47 XXX XX XXX |
| Date of birth | BankID pid (national ID) | No | DD. MMMM YYYY (e.g., "15. mars 1995") |
| KYC status | System (auto via BankID) | No | Badge: "Verifisert med BankID" (green) |

### 4.3 Security Settings (UI Display Only)

| Setting | Current Value | Status | Actionable |
|---------|--------------|--------|------------|
| Password | "Sist endret: Aldri" | Info display | Change button (planned) |
| BankID verification | Active | Green badge | N/A |
| Vipps verification | Not activated | Gray badge | Planned (Phase 2) |
| Active devices | iPhone 15 Pro (active), MacBook Pro (yesterday) | Live info | View/revoke (planned) |

---

## 5. GDPR Rights Mapping

| GDPR Right | Article | Implementation | API Endpoint | Status |
|------------|---------|---------------|--------------|--------|
| Right to access (innsyn) | Art. 15 | Full data export as JSON | `GET /api/user/data-export` | Implemented |
| Right to rectification (retting) | Art. 16 | BankID data is authoritative; address via support | N/A | Via support |
| Right to erasure (sletting) | Art. 17 | Soft-delete with 5-year AML retention | `DELETE /api/user/account` | Implemented |
| Right to data portability | Art. 20 | Same as data export (JSON format) | `GET /api/user/data-export` | Implemented |
| Right to withdraw consent | Art. 7 | Consent toggle + withdrawal tracking | `POST /api/consents { granted: false }` | Implemented |
| Right to lodge complaint | Art. 77 | Link to Datatilsynet on privacy page | N/A | Link provided |

### 5.1 Data Export Contents

`GET /api/user/data-export` returns:

| Section | Data |
|---------|------|
| `user` | id, email, first_name, last_name, phone, date_of_birth, kyc_status, role, created_at |
| `transactions` | All transaction records |
| `recipients` | All saved recipients |
| `bankAccounts` | Linked bank accounts (masked numbers) |
| `settings` | Currency, language, notification preferences |
| `consents` | All consent records with timestamps |

### 5.2 Data Retention After Deletion

| Data Category | Retention Period | Legal Basis |
|---------------|-----------------|-------------|
| Transaction records | 5 years | Hvitvaskingsloven (AML) |
| KYC/identity data | 5 years | Hvitvaskingsloven (AML) |
| AML alerts and STR reports | 5 years | Hvitvaskingsloven (AML) |
| Consent records | 5 years | GDPR proof of consent |
| User profile (soft-deleted) | 5 years | Legal obligation |
| Settings, preferences | Deleted immediately | No retention requirement |
| Notification history | Deleted immediately | No retention requirement |

---

## 6. UI Components

### 6.1 Profile Hub (`/profile`)

| Element | Component | Source |
|---------|-----------|--------|
| Avatar | Green gradient circle with initials | Inline (gradient from #0B6E35 to #095a2b) |
| Edit button | Pen icon on avatar | Pen (lucide) |
| User info | Name (Fraunces font) + email | Text |
| Account section | Menu items with chevrons | ChevronRight (lucide) |
| Settings section | Menu items with chevrons | Bell, Shield, Globe (lucide) |
| Bottom navigation | 5-tab bar | BottomNav component |

### 6.2 Notification Settings (`/profile/notifications`)

| Element | Component | Behavior |
|---------|-----------|----------|
| Push toggle | Custom switch | Immediate PATCH, revert on failure |
| Email toggle | Custom switch | Immediate PATCH, revert on failure |

### 6.3 Language Settings (`/profile/language`)

| Element | Component | Behavior |
|---------|-----------|----------|
| Language list | Radio selection with green checkmark | Local state update |
| Save button | Green "Lagre" button | PATCH on click |

### 6.4 Figma Reference

Source of truth: `mockups/figma-make-export/src/app/screens/Profile.tsx`
- User avatar with initials and edit button
- Account section (Personlig informasjon, Bankkontoer)
- Settings section (Varsler, Sikkerhet, Sprak)

---

## 7. Platform Differences

| Feature | Web | Mobile |
|---------|-----|--------|
| Profile layout | Hub with 4 sub-pages | Single screen with inline settings |
| Personal info | Dedicated /profile/personal page | Inline section |
| Security settings | Dedicated /profile/security page | Not implemented |
| Notification settings | Dedicated /profile/notifications page | Inline in profile |
| Language | Dedicated /profile/language page | "Sprak" in settings menu |
| Recipients list | Not on profile (separate /recipients) | Inline "Mine mottakere" section |
| GDPR export | Via /profile or API | Not implemented |
| Account deletion | Via /profile | Not implemented |
| Logout | Confirmation dialog | Simple button with token clear |

---

## 8. Accessibility Considerations (WCAG 2.1 AA)

| Requirement | Implementation |
|-------------|---------------|
| Form labels | All settings have visible labels |
| Toggle state | Push/email toggles announce on/off state to screen readers |
| Read-only fields | Personal info fields use `disabled` attribute with visible label |
| KYC badge | Uses both color (green) and icon (ShieldCheck) for verification status |
| Navigation | Sub-page back buttons have aria-label "Tilbake" |
| Destructive action | Account deletion requires explicit confirmation dialog |
| Language names | Languages listed in their own script for recognition |
| Color contrast | Green badge (#0B6E35) on white meets 4.5:1 |

---

## 9. Cross-References

- **User data API:** `GET /api/auth/me` — See [API Reference](../../backend/API-REFERENCE.md)
- **Settings API:** `GET/PATCH /api/settings` — See [API Reference](../../backend/API-REFERENCE.md)
- **Data export API:** `GET /api/user/data-export` — See [API Reference](../../backend/API-REFERENCE.md)
- **Account deletion API:** `DELETE /api/user/account` — See [API Reference](../../backend/API-REFERENCE.md)
- **Consents API:** `GET/POST /api/consents` — See [API Reference](../../backend/API-REFERENCE.md)
- **Settings schema:** `settings` table — See [Database Schema](../../backend/DATABASE-SCHEMA.md)
- **Data access requests schema:** `data_access_requests` table — See [Database Schema](../../backend/DATABASE-SCHEMA.md)
- **Component overview:** See [component-overview.md](../hld/component-overview.md)
- **Figma profile screen:** `mockups/figma-make-export/src/app/screens/Profile.tsx`
- **Web profile pages:** `src/drop-app/src/app/profile/` — See [PAGES.md](../../frontend/PAGES.md)
- **Mobile profile screen:** `src/drop-mobile/app/(tabs)/profile.js` — See [MOBILE-APP.md](../../mobile/MOBILE-APP.md)
- **Authentication flow:** See [flow-login-authentication.md](flow-login-authentication.md)