# Account, Profile, and Settings

The account domain is the customer-facing hub where a member manages **identity,
plan, preferences, privacy, consent, data rights, devices, notifications,
assistant memory, persona voice, Telegram linking, and safety settings**. It is
one calm surface composing controls whose enforcement lives in the substrates
documented elsewhere ([Iris](./iris-memory-identity.md) for memory,
[Lilith](./lilith-persona-policy.md) for crisis-aware safety,
[privacy/consent](./privacy-consent-portability.md) for data rights,
[support/billing](./support-billing.md) and
[crypto payments](./crypto-payments.md) for entitlements). This page is the
canonical feature reference for that hub; the per-route behavioral evidence
lives in the `WALKTHROUGH/customer/09-account/` walkthroughs, which deep-link
back here.

Like every V1 surface page, this one is candid about seams. The panel and its
BFF projections are real and authenticated. Where a section fronts a substrate
that is itself partially wired (for example live channel transports), the
substrate page linked from that section is the source of truth for what
enforcement actually runs.

## Where it lives

The hub is one shared panel composed across two entry routes, plus seven
specialization routes for the deeper journeys:

| Route                         | Source                                                  | What it is                                                  |
| ----------------------------- | ------------------------------------------------------- | ----------------------------------------------------------- |
| `/profile`                    | `apps/oshun/web/src/app/profile/page.tsx`               | The account hub — `ShellLayout` + `ProfileSettingsPanel`    |
| `/settings`                   | `apps/oshun/web/src/app/settings/page.tsx`              | Alias entry to the same panel (different breadcrumb)        |
| `/profile/memory`             | `apps/oshun/web/src/app/profile/memory/page.tsx`        | Assistant-memory controls — review, pause, export, delete   |
| `/profile/persona`            | `apps/oshun/web/src/app/profile/persona/page.tsx`       | Guide-voice selection with the consent gate readback        |
| `/profile/notifications`      | `apps/oshun/web/src/app/profile/notifications/page.tsx` | Notification preferences and channel bindings               |
| `/profile/safety`             | `apps/oshun/web/src/app/profile/safety/page.tsx`        | Crisis-aware safety settings journey                        |
| `/profile/telegram`           | `apps/oshun/web/src/app/profile/telegram/page.tsx`      | Telegram account linking and binding lifecycle              |
| `/profile/data`               | `apps/oshun/web/src/app/profile/data/page.tsx`          | Data portability — export and deletion requests             |
| `/billing`, `/billing/crypto` | `apps/oshun/web/src/app/billing/`                       | Billing index and the crypto entitlement-settlement surface |

`ProfileSettingsPanel`
(`apps/oshun/web/src/components/ProfileSettingsPanel.tsx`, ~1,820 lines) renders
the hub as a stack of collapsible sections under the masthead line _"Keep your
identity, privacy, and recovery in one calm place."_ The shipped section set, in
panel order: **Operator access** (governed Studio handoff), **Domain
statistics**, **Plans and billing**, **General preferences** (theme, language,
accessibility), **Personalization** (goals, domains, interests), **Onboarding
setup**, **Assistant and memory** (guide, disclosure, continuity),
**Notifications** (push, email, per-domain), **Privacy and access** (security,
consent, data controls), **Consent center** (memory, voice, avatar, data,
marketing), **Data requests** (export, deletion), **Connected services**,
**Connected domains**, **Legal & policies**, **Devices & sessions**,
**Notification channels**, and calendar sync.

## The BFF projection

Account data is served by `apps/oshun/bff/src/routes/profile.ts` (~790 lines),
authenticated (`createAuthPreHandler`) and abuse-protected on every route:

| Endpoint             | Method | Payload / behavior                                                                                                                                                                                                                                                                    |
| -------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/v1/profile`        | GET    | `ProfileRoutePayload` — `id`, `email`, `displayName`, `initials`, `plan: 'free' \| 'pro' \| 'premium'`, `verified`, `stats` (streakDays, savedItems, activeDomains), `domainConnections[]` (`connected \| limited \| disconnected`), `domainStats`, `connectedServices`, `avatarUrl?` |
| `/v1/profile`        | PATCH  | Updates `displayName` / `email` (schema-validated `UpdateProfileBody`)                                                                                                                                                                                                                |
| `/v1/profile/avatar` | POST   | Base64 upload, **1.5 MB binary limit**, with the route's own body-size ceiling raised because a 1.5 MB binary is ~2 MB base64-encoded — over Fastify's 1 MB default                                                                                                                   |
| `/v1/preferences`    | GET    | `PreferencesRoutePayload` — theme, language, notifications, accessibility, assistant, personalization                                                                                                                                                                                 |
| `/v1/preferences`    | PATCH  | Partial update over the same six preference groups                                                                                                                                                                                                                                    |

Both `GET` payloads carry `generatedAt` and a `revision` counter, so the panel
can detect concurrent edits and re-read rather than blind-overwrite.

## Assistant memory controls

The `/profile/memory` journey fronts the Iris adapter routes — the same
role-scoped registry documented in
[Iris Memory and Identity](./iris-memory-identity.md):
`/v1/iris/adapter/{review,pause,export,consents,continuity,profile,remember,search,plan-write,availability,capabilities}`
plus `DELETE /v1/iris/adapter/memory/:memoryId` (soft/hard delete). From the
account surface, a member can **review** stored facts, **pause** capture
(`?role=settings`), **export** a signed memory bundle, and **delete** individual
facts — each of which the Iris page documents at the retention/consent level.
The account panel is deliberately a _thin_ consent surface: scope semantics,
retention windows, and suppression live in the substrate, not in panel state.

## Safety, persona, channels, and data rights

- **Safety** (`/profile/safety`) runs the crisis-aware settings journey — the
  member-facing end of the [Lilith](./lilith-persona-policy.md) crisis catalog.
  Sensitive-intention handling and quiet-hour behavior are read from policy, not
  configured freehand.
- **Persona voice** (`/profile/persona`) reads eligible voices via
  `GET /v1/persona/voice` and switches via `POST /v1/personas/select`; a cloned
  or synthetic voice requires the consent grant (`POST /v1/consent/voice/grant`)
  whose artifact model is defined in
  [Persona, Avatar, and Voice Packs](./persona-avatar-voice-packs.md).
- **Notifications and channels** (`/profile/notifications`, plus the
  Notification-channels panel section) manage per-channel, per-category
  preferences and the email/SMS/Telegram/push binding lifecycle; delivery
  semantics and transport status per channel live in
  [Telegram Surfaces](./telegram-surfaces.md) and
  [Email, Push, SMS, Discord, Slack](./other-channels.md).
- **Data rights** (`/profile/data`, Data-requests section) submit export and
  deletion requests with the grace-period and DSAR semantics documented in
  [Privacy, Consent, and Data Portability](./privacy-consent-portability.md).
- **Billing** (`/billing`, `/billing/crypto`) surfaces plan state from the
  profile payload and hands off to the entitlement rails documented in
  [Support, Entitlements, and Billing](./support-billing.md) and
  [Crypto Payments](./crypto-payments.md).

## Honest status (V1)

- The hub panel, its section set, the `/v1/profile` and `/v1/preferences`
  projections, avatar upload, and the memory-controls journey are **real,
  authenticated, and walked**. The 09-account walkthroughs record live-BFF
  verification of the notification summary → delivery-editor handoff, the real
  push-preference flip through `/v1/preferences`, anonymous-redirect behavior,
  and service-worker offline shells.
- Sections that front partially-wired substrates inherit those substrates'
  status: e.g., a channel binding row is real panel state even where the
  channel's outbound transport is fail-closed (see
  [Channel Abstraction and Boundary](./channel-abstraction-and-boundary.md)).
- Cross-device session revocation and calendar-provider sync surface real panel
  affordances over integrations whose live end-to-end wiring is tracked in the
  backlog (`../TODOS.md`), not claimed here.

## Related

- [Product Surfaces](./product-surfaces.md) — where the account hub sits in the
  customer web/mobile shell.
- [Iris Memory and Identity](./iris-memory-identity.md) — the memory model the
  controls act on.
- [Privacy, Consent, and Data Portability](./privacy-consent-portability.md) —
  the rights machinery behind Data requests.
- [Support, Entitlements, Billing](./support-billing.md) ·
  [Crypto Payments](./crypto-payments.md) — the plan and settlement rails.
- Walkthrough evidence: `WALKTHROUGH/customer/09-account/`.
