Files
headquarter/openspec/changes/user-profile/design.md
T
Fusion 577b052c05 feat: implement user profile management and oauth/traefik integration
User Profile (US-004):
- Add authenticated profile endpoints (GET/PUT /users/me)
- Add avatar upload with file validation (PNG/JPEG, max 2MB)
- Create frontend profile page with edit form and avatar upload
- Update app shell to link to profile page

OAuth/Traefik Integration:
- Externalize all Authentik URLs to environment variables
- Add domain configuration (API_DOMAIN, WEB_DOMAIN, AUTHENTIK_DOMAIN)
- Create docker-compose.traefik.yml for reverse proxy deployment
- Update OAuth redirect/callback URLs to use configured domains
- Add VITE_APP_URL for frontend public URL configuration

Quality gates: pytest (50 passed), ruff, mypy, npm test (12 passed), typecheck, lint, build
2026-05-17 23:17:10 +02:00

2.7 KiB

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.)