## Context

The user-profile spec requires authenticated users to view and update their profile (name, email, avatar). The User model already has `email`, `name`, and `avatar_url` fields. The auth system provides cookie-based JWT authentication. This change connects those pieces into a working profile management flow.

## Goals / Non-Goals

**Goals:**
- Provide `GET /users/me` to retrieve the current user's profile.
- Provide `PUT /users/me` to update name and email with validation.
- Provide `POST /users/me/avatar` to upload an avatar image (PNG/JPG, max 2MB).
- Store uploaded avatars locally under `apps/api/uploads/avatars/`.
- Add a frontend `/profile` page with edit form and avatar upload UI.
- Update the app shell to link to the profile page.

**Non-Goals:**
- Social features or public profile pages.
- External avatar providers (Gravatar, etc.).
- Image resizing or cropping.

## Decisions

1. **Add a dedicated `/users` router instead of extending `/auth/me`**
   - Rationale: cleaner separation of concerns; auth routes handle login/logout, user routes handle profile data.
   - Alternative: extend `/auth/me` to support PUT. Rejected to keep auth router focused.

2. **Use `UploadFile` from FastAPI for avatar uploads**
   - Rationale: standard FastAPI pattern, handles multipart parsing and streaming.
   - Alternative: raw bytes in JSON body. Rejected as it complicates client and server.

3. **Store avatars as files locally, not in the database**
   - Rationale: keeps the database lightweight; files are served statically.
   - Alternative: bytea/blob column. Rejected for performance and simplicity.

4. **Use a simple form-based profile page in the frontend**
   - Rationale: consistent with existing project pages and forms.
   - Alternative: modal or inline editing. Rejected to keep implementation straightforward.

## Risks / Trade-offs

- **[File storage path]** -> use an environment-configurable upload directory; default to `apps/api/uploads/avatars`.
- **[Filename collisions]** -> use UUID-based filenames to avoid collisions.
- **[Unauthorized access to avatars]** -> for now, serve via static mount; later can add auth if needed.
- **[Frontend state sync]** -> after profile update, refresh auth context so the app shell shows updated name.

## Migration Plan

1. Create backend users router with GET/PUT/avatar endpoints.
2. Register router in main.py.
3. Create frontend profile page, API methods, and routing.
4. Update app shell with profile link.
5. Run quality gates (pytest, mypy, ruff, typecheck, lint).

Rollback:
- Remove users router and frontend page; no database changes needed.

## Open Questions

- Should old avatars be deleted on new upload? (Yes, to avoid disk bloat.)