Appearance
User Service API
Current Endpoints
GET /healthzGET /readyzGET /v1PUT /v1/users/{userId}/profile-snapshotGET /v1/users/{userId}/profilePATCH /v1/users/{userId}/profilePATCH /v1/users/{userId}/teacher-profilePATCH /v1/users/{userId}/student-profilePATCH /v1/users/{userId}/parent-profile
Native Profile Foundation
Phase 8 user-service starts with profile read/update ownership. This is an internal /v1 foundation, not a public /api/auth/me* cutover.
Legacy evidence:
apps/api/src/modules/auth/auth.controller.ts:189-245mapsGET /api/auth/me,PATCH /api/auth/me/profile, and password update.apps/api/src/modules/auth/auth.controller.ts:89-147maps role-specific teacher/student/parent profile update routes.apps/api/src/modules/auth/auth.service.ts:176-246delegates current-user profile hydration and profile updates to identity data APIs.apps/api/src/modules/app-data/app-data.identity-core.ts:209-258returns full user profile withteacherProfile,studentProfile,parentProfile, safeteacherKyc, and membership summaries.apps/api/src/modules/app-data/app-data.identity-core.ts:260-351upserts teacher, student, and parent profile rows and records audit logs.apps/api/src/modules/app-data/app-data.identity-core.ts:607-695validates and updates base profile fields, with email/phone conflict checks.packages/shared/src/index.ts:1027-1102definesprofileUpdateSchema,teacherProfileSchema,studentProfileSchema, andparentProfileSchema.apps/api/prisma/schema.prisma:247-325definesTeacherProfile,TeacherKyc,StudentProfile, andParentProfile.apps/web/components/account/profile-settings-client.tsx:255-556shows current frontend loading/auth/me, then PATCHing base and role-specific profile routes.
Native contract:
PUT /v1/users/{userId}/profile-snapshotupserts the user-service-owned public user row from auth-service/backfill data. It stores no password hash or refresh token.GET /v1/users/{userId}/profilereturns a full profile view with base user fields and nullableteacherProfile,studentProfile,parentProfile, andteacherKyc.PATCH /v1/users/{userId}/profileupdates base profile fields with legacy-compatible validation:fullNameis required, trimmed, length 2-120.emailis optional, lowercased, max 160, unique when present.- empty
phonebecomes null; non-emptyphonemax 32 and unique. - empty
avatarUrlbecomes null; non-empty URL must start withhttp://orhttps://.
PATCH /v1/users/{userId}/teacher-profileupserts teacher-specific profile fields.PATCH /v1/users/{userId}/student-profileupserts student-specific profile fields.PATCH /v1/users/{userId}/parent-profileupserts parent-specific profile fields.
Envelope:
json
{
"success": true,
"data": {
"id": "usr_123",
"accountCode": "HTA12345678",
"email": "teacher@example.com",
"fullName": "Teacher One",
"role": "TEACHER",
"status": "ACTIVE",
"teacherProfile": {
"schoolName": "THPT A",
"subjects": ["Toán"]
},
"studentProfile": null,
"parentProfile": null,
"teacherKyc": null,
"memberships": []
},
"message": "OK"
}Database:
services/user-service/migrations/000002_user_profiles.sqlcreatesusers,teacher_profiles,student_profiles,parent_profiles,teacher_kyc, andparent_students.users.legacy_idis nullable during native-only local creation and required for legacy backfill reports.users.password_hashis intentionally not present; credentials remain inauth-service.teacher_kyc.cccd_number_hashis present for migration/read redaction, but P8-002 does not implement submit/review APIs.
Validation queries:
sql
SELECT id, legacy_id, account_code, email, role, status
FROM users
ORDER BY created_at DESC
LIMIT 20;
SELECT user_id, school_name, subjects, updated_at
FROM teacher_profiles
ORDER BY updated_at DESC
LIMIT 20;
SELECT user_id, school_name, grade_level, updated_at
FROM student_profiles
ORDER BY updated_at DESC
LIMIT 20;
SELECT user_id, relation_to_student, updated_at
FROM parent_profiles
ORDER BY updated_at DESC
LIMIT 20;Rollback for this native slice:
- Keep
/api/auth/me*routed to legacy. - Disable gateway/auth-service callers for
/v1/users/*/profile*. - Drop user-service local profile tables with the migration down step if local test data must be reset.
Non-goals for P8-002:
- Password changes and refresh-token rotation.
- Teacher KYC submit/review.
- Email change/verification.
- Parent-student linking APIs.
- School-service membership validation and organization management.
- Public gateway adapter/cutover for
/api/auth/me*.