# Settings Tab **Nav id**: `settings` **Icon**: ⚙ --- ## What it shows The client's security and encryption status — current encryption algorithm and KDF parameters, password change form, and a record count summary (messages, meetings, etc.). --- ## Data flow `getEncryptionSettings(token)` — `GET /vip/settings/encryption?token=` — returns `VipSettingsResponse`. --- ## Settings response object ```typescript interface VipSettingsResponse { encryption: VipEncryptionSettings | { enabled: false } records?: Record // e.g. { messages: 42, meetings: 3, gifts: 1 } } interface VipEncryptionSettings { enabled: true algorithm: string // e.g. "AES-256-GCM" kdf: string // e.g. "PBKDF2" kdfIterations: number keyCreatedAt: string | null loginBenchmarkMs: number | null } ``` --- ## Encryption section Displays status badge (Active / Not set up), algorithm, KDF + iteration count, key creation date, and last-login KDF benchmark in milliseconds (useful for performance tuning). The "Change password" / "Set up encryption" button toggles an inline form. On submit, `setupPassword(token, newPw)` re-derives and re-encrypts the content key server-side, returns a fresh `contentKey` which is written back to `sessionStorage`. This means the client does not get logged out when changing their password. After a successful change, "Password updated — content key re-encrypted." confirmation text appears. --- ## Add to another device (QR login) A "Show login QR code" button generates a QR code (rendered client-side via `qrcode` to a ``) encoding the full portal URL: `window.location.origin + '/' + token`. The client scans it with their phone's camera, which opens the portal URL directly — they then complete their normal password/WebAuthn auth on the new device. The QR uses the gold/cream palette (`#f0e6d3` dark dots on `#0d0d14` background) and is hidden by default, revealed on demand, with a Hide button to dismiss it. No server involvement — the QR is generated entirely in-browser from the token already in the component props. --- ## Records section If `settings.records` is present, renders a card listing each key/count pair. Keys are capitalized for display (`messages` → `Messages`). This gives the client a lightweight sense of how much data is in their account without exposing raw DB row counts. --- ## WebAuthn WebAuthn (Face ID / Touch ID) is registered during the first-visit `SetPasswordScreen` flow, not from the Settings tab. There is currently no UI in Settings to add or remove WebAuthn credentials after initial setup. If this is needed, it should be added here. --- ## Dev proxy In dev, `VITE_API_URL=''` makes all API calls relative. Vite proxies `/vip/*` to `localhost:3030` but the bypass function must list every API sub-path — otherwise Vite returns the SPA HTML instead. `/settings` must be in `apiPaths` in `vite.config.ts` or the tab shows "Could not load settings." ## Non-obvious details - `setupPassword` is reused for both initial setup (first visit) and password change (Settings tab). The API determines which path to take based on whether a key already exists for the token. - `loginBenchmarkMs` is written by the server after each successful password verification — it reflects how long PBKDF2/Argon2 derivation took on the server for that client's parameters. Useful for auditing that KDF cost is appropriate. - The `records` field is optional — the API may omit it if counting is expensive or not yet implemented for a given deployment.