Pro Profile and Branding Management
Summary
Authenticated pros can view and update their own profile. The GET endpoint returns a curated set of safe fields (password hash and other internals are never exposed). The PUT endpoint accepts a partial payload validated by proProfileUpdateSchema — schema-level additionalProperties: false prevents mass assignment of protected fields such as email, passwordHash, or isActive.
State Diagram
stateDiagram-v2 state "Pro authentifié" as Authenticated state "Profil consulté" as ProfileFetched state "Profil mis à jour" as ProfileUpdated [*] --> Authenticated Authenticated --> ProfileFetched: pro reads profile Authenticated --> ProfileUpdated: pro updates profile ProfileFetched --> [*] ProfileUpdated --> [*]
Steps
1. Read Profile (Actor: pro)
GET /pro/profile. Returns a fixed select of safe fields:
id, email, firstName, lastName, agencyName, jobTitle, phone, avatarUrl, logoUrl, siret, carteT, rcp, address, city, postalCode, latitude, longitude, isActive, createdAt, cniFilePath, cniVerifiedAt.
Never exposes passwordHash, deactivationReason, slackThreadTs, or raw token data.
Triggers: Pro loads their account page Outcome: Profile JSON returned
2. Update Profile (Actor: pro)
PUT /pro/profile with a partial body validated by proProfileUpdateSchema. Any subset of allowed fields can be sent — only those fields are updated (Prisma update with the validated body, which has additionalProperties: false).
Fields updatable by the pro include personal info (firstName, lastName, phone), agency details (agencyName, jobTitle), address (address, city, postalCode), geo coordinates (latitude, longitude), and branding URLs (avatarUrl, logoUrl).
Protected fields (email, passwordHash, isActive, siret, carteT, cniVerifiedAt, etc.) cannot be updated via this endpoint — the schema rejects them.
The response returns the same safe field set as GET (excluding branding fields that were not selected in the PUT response — see select in code).
Triggers: Pro edits their profile and saves Outcome: Updated Pro record returned
Error States
- Unauthenticated request → 401 (handled by
authenticateProhook) - CNI gate active (>72h, no CNI) → 403
CNI_REQUIRED(this route is NOT whitelisted) - Schema validation failure → 400 (Fastify JSON schema error)
Notes
avatarUrlandlogoUrlare plain string URLs — there is no upload endpoint for branding images through this route. Photo uploads for properties use a separate multipart route under/pro/properties/:id/photos.- The CNI upload endpoint lives at
/pro/profile/cni-uploadbut is documented separately in cni-upload-analysis because its security profile and flow differ significantly.
Related Processes
- cni-upload-analysis — CNI upload is a sub-route of profile but has its own process
- registration — initial profile data is collected at signup