3.4 KiB
3.4 KiB
Profile Protocol (Frontend <-> Backend)
This document defines the canonical backend contract for user profile read/write and avatar upload signing.
Protocol verification status:
- Backend model source:
backend/src/models/profile.py - Storage config source:
backend/src/core/config/settings.py - Current status: planned
Compatibility strategy
- Current strategy: breaking changes allowed during implementation phase (no production compatibility burden).
- Once production compatibility is required, switch to additive-only evolution.
Route overview
- Get profile:
GET /api/v1/users/me/profile - Update profile:
PATCH /api/v1/users/me/profile - Create avatar upload url:
POST /api/v1/users/me/avatar/upload-url - Upload avatar directly:
POST /api/v1/users/me/avatar(multipart)
Auth and trust boundary
- All routes require authenticated user context.
user_idis derived from verified JWTsub; never accepted from client payload.
Profile read contract
GET /api/v1/users/me/profile
Response:
{
"user_id": "uuid",
"display_name": "string",
"bio": "string|null",
"avatar_path": "avatars/{user_id}/{file}",
"avatar_url": "https://...signed-or-public...",
"settings": {
"version": 1,
"preferences": {
"interface_language": "zh-CN",
"ai_language": "zh-CN",
"timezone": "Asia/Shanghai",
"country": "CN"
},
"privacy": {},
"notification": {}
},
"updated_at": "2026-04-05T12:34:56+00:00"
}
Mapping note:
display_namemaps toprofiles.username.avatar_pathis stored in profile layer.avatar_urlis render-ready URL generated from storage strategy.
Profile update contract
PATCH /api/v1/users/me/profile
Request:
{
"display_name": "string(1..30)",
"bio": "string(0..200)",
"avatar_path": "avatars/{user_id}/{file}"
}
Rules:
- At least one field must be provided.
display_namemust be non-empty after trim.biocan be empty string and should be normalized tonullonly if agreed by API implementation.avatar_pathmust stay in current user prefix:avatars/{current_user.id}/.
Response:
- Returns the same shape as
GET /users/me/profile.
Avatar upload signing contract
POST /api/v1/users/me/avatar/upload-url
Request:
{
"mime_type": "image/png|image/jpeg|image/webp",
"file_size": 123456,
"ext": "png|jpg|jpeg|webp"
}
Response:
{
"bucket": "avatars",
"path": "avatars/{user_id}/{uuid}.png",
"upload_url": "https://...signed...",
"expires_in": 600
}
Validation rules:
bucketmust equalconfig.storage.avatar.bucket.file_sizemust be>0and<= config.storage.avatar.max_size_mb.- Only image mime types are allowed.
- Path must be server-generated and never trusted from client.
Direct avatar upload contract
POST /api/v1/users/me/avatar
Request:
multipart/form-data- field name:
file
Validation rules:
- extension must be one of
png|jpg|jpeg|webp - mime must map to image type (
image/png|image/jpeg|image/webp) - payload size must be
<= config.storage.avatar.max_size_mb
Behavior:
- backend writes avatar bytes to
bucket=config.storage.avatar.bucket - backend stores canonical path in profile
- response returns latest profile payload (
ProfileResponse)
Error contract linkage
- All errors must follow RFC7807
application/problem+json. codevalues must be registered indocs/protocols/common/http-error-codes.md.