Profile and settings
Bối cảnh
Trên Shukah, app thay đổi hồ sơ và công tắc push-notification bằng một lời gọi,
PUT /maeda/client/{client_id}, và báo cho Shukah về phone bằng
POST /maeda/client/add-device-id. Auth service có ba route cho việc này: một cho hồ sơ,
một cho công tắc push, và một route device-id. Có ba điều cần chú ý: công tắc push cần một lời gọi riêng
vì route hồ sơ bỏ qua push_enabled, route hồ sơ từ chối phone bị đổi, và
route device-id là stub không lưu gì cả.
Tính năng
Cả ba lời gọi đều là một phần của các màn hình tài khoản của client đã đăng nhập. Trong snapshot app ngày 2026-02-26 chúng xảy ra ở đây:
| Lời gọi | Ở đâu trong app |
|---|---|
| Update profile | Trên màn hình Personal info, khi client bấm lưu. Một lời gọi mang client_id, contact_phone, first_name, last_name, email_address, sex, receive_offers và birth_date (dạng YYYY-MM-DD). Field phone được hiển thị nhưng bị vô hiệu hóa, và giá trị của nó là phone mà app đã tải cùng hồ sơ, nên app gửi lại đúng phone nó đã nhận. |
| Update setting | Trên màn hình Settings, khi client bật/tắt công tắc push-notification. App gửi client_id và push_enabled (0 hoặc 1). Trên Shukah việc này đi qua cùng route với hồ sơ. |
| Add device id | Khi app khởi động, ngay sau bước kiểm tra hồ sơ (verify-token), khi client đã đăng nhập và lời gọi chưa được thực hiện trên bản cài này. Nó gửi id duy nhất của thiết bị một lần. Sau câu trả lời 200 app ghi lại rằng đã gửi và không bao giờ gửi lại. |
Hai lời gọi đầu cần JWT Locate (xem "Lấy test token" ở trang tổng quan module) và trả về hồ sơ của client, cùng 13 field như Verify token, sau thay đổi. Lời gọi device-id không cần token.
PUT /api/v1/clients/:client_id
PUT /maeda/client/:client_id✅ Đã thay thế- 🔴 Token Shukah nhận 401 "Unauthorization"; hãy gửi JWT của Locate (lấy từ exchange-token; giữ lại token Shukah).
- 🟡 push_enabled bị bỏ qua trên route này (app vẫn gửi ở đây: user.dto.ts:100-101); xem update-setting.
- 🟡 contact_phone phải bằng số điện thoại đã lưu, kèm "+", nếu không trả 400; quy tắc đổi số của Shukah chưa được kiểm tra.
- 🟡 Dữ liệu sai trả 400 {status,message,stack} trên Locate, 422 [{field,message}] trên Shukah; app mất field.
- 🟡 Chỉnh sửa chỉ nằm ở Locate và không được đẩy sang Shukah (update-profile/index.js không có bước push).
Request
Cập nhật một phần: chỉ các key có trong body mới thay đổi. Service trả về vấn đề đầu tiên nó
tìm thấy và kiểm tra theo thứ tự: client_id, contact_phone, first_name, last_name,
email_address, birth_date.
| Field | Vị trí | Kiểu | Bắt buộc | Ràng buộc | Mô tả |
|---|---|---|---|---|---|
Authorization | header | string | có | Bearer <locate-jwt>. Token Shukah nhận 401. | JWT của Locate. |
client_id | path | integer | có | Phải bằng client id trong token, nếu không 400 client_id does not match the authenticated client. | Id của chính người gọi. |
client_id | body | integer hoặc numeric string | không | Nếu gửi, nó cũng phải bằng client id của token, với cùng 400. null thì lỗi. | Lại là id của chính người gọi, như app gửi. |
contact_phone | body | string | không | Không thể đổi. Nếu gửi, giá trị đã bỏ khoảng trắng phải bằng đúng phone đã lưu, kể cả dấu + ở đầu (966500000000 không khớp +966500000000), nếu không 400 contact_phone cannot be changed. Nó không bao giờ được ghi. | Phone của client. |
first_name, last_name | body | string hoặc null | không | null hoặc một chuỗi tối đa 100 ký tự sau khi trim, nếu không 400 first_name is invalid hoặc last_name is invalid. Lưu đã trim. null xóa nó, và "" được lưu là "". | Tên. |
email_address | body | string hoặc null | không | Mọi chuỗi hoặc null: không kiểm tra định dạng và không giới hạn độ dài, nếu không 400 email_address is invalid. Lưu đã trim. | Email. |
birth_date | body | string hoặc null | không | Một giá trị mà new Date() của JavaScript đọc được, lưu dưới dạng ngày UTC YYYY-MM-DD. null xóa nó. Giá trị không đọc được, kể cả "", cho 400 birth_date is invalid. | Ngày sinh. App gửi YYYY-MM-DD. |
sex | body | integer | không | Không validate. 1 là nam và 2 là nữ. Mọi giá trị khác, kể cả 0, 9 và null, được lưu là không rõ và đọc lại là 0. | Giới tính. |
receive_offers | body | 0, 1 hoặc boolean | không | Không validate. Chỉ 1, "1" và true nghĩa là bật. Mọi giá trị khác nghĩa là tắt. | Client có nhận ưu đãi hay không. |
push_enabled và mọi key khác | body | — | không | Bị bỏ qua. Công tắc push có route riêng. | — |
Một request dùng cho capture bên dưới, ghi lại đúng giá trị hiện tại của client:
{
"client_id": 356259,
"receive_offers": 0
}
Response
200 kèm hồ sơ 13 field sau khi cập nhật, không có wrapper. Các field và quy tắc của chúng là
bảng ở Verify token.
{
"client_id": 356259,
"odoo_id": "1342170",
"contact_phone": "+966500000000",
"status": "active",
"email_address": "user@example.com",
"first_name": "Test",
"last_name": "User",
"sex": 1,
"birth_date": "1990-01-01",
"receive_offers": 0,
"push_enabled": 0,
"is_food_truck_user": 1,
"is_cod_disabled": 0
}
Capture trên dev, 2026-10-01 (client 356259, Task 9 live write, giá trị hiện tại được ghi lại); các field cá nhân đã được thay thế.
Lỗi
| HTTP | Body | Khi nào |
|---|---|---|
400 | {"status":400,"message":"birth_date is invalid"} | birth_date không đọc được thành ngày. Các message của các field khác có cùng shape: client_id does not match the authenticated client, contact_phone cannot be changed, first_name is invalid, last_name is invalid, email_address is invalid. Chỉ message lỗi đầu tiên được trả về. Trên dev body cũng có field stack (xem bên dưới). |
401 | {"status":401,"message":"Unauthorization"} | Không có token, token không phải JWT Locate, hoặc client không active. Điều này xảy ra trước mọi kiểm tra body. |
500 | Trên dev: {"status":500,"message":"<raw error text>","stack":"<stack trace>"}. Trên production: {"status":500,"message":"Internal server error"}. | Lỗi không mong đợi. Chưa capture. Trên dev message là text lỗi gốc và có thêm field stack; Internal server error chỉ xuất hiện trên production (UAT và production: Chưa được tài liệu hóa). |
400 của birth_date được capture trên dev vào 2026-10-01, và lại vào 2026-10-02 với
"birth_date":"not-a-date". Các message 400 khác lấy từ code và tài liệu service, và chưa được
capture. Body 401 được capture trên dev vào 2026-10-01 khi không có token. Trên dev mọi body 400
cũng mang field stack với một stack trace của server dạng text, ví dụ
{"status":400,"message":"birth_date is invalid","stack":"<stack trace>"} (capture 2026-10-02). Các
sample trong bảng bỏ nó đi.
Thử ngay
Lời gọi đầu ghi vào dev, nên hãy gửi giá trị hiện tại của client, như capture đã làm. Lời gọi thứ hai bị từ chối và không ghi gì.
export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
export CLIENT_ID='<client-id-in-the-token>'
curl -s -X PUT "$AUTH_BASE_URL/api/v1/clients/$CLIENT_ID" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "{\"client_id\":$CLIENT_ID,\"receive_offers\":0}"
curl -s -X PUT "$AUTH_BASE_URL/api/v1/clients/$CLIENT_ID" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"birth_date":"not-a-date"}'
Kỳ vọng: lời gọi đầu cho 200 và hồ sơ như ở mục Response. Lời gọi thứ hai cho 400 với
birth_date is invalid.
Khác biệt so với Shukah
| Khía cạnh | Shukah | Locate | Tác động lên app |
|---|---|---|---|
| URL | PUT $SHUKAH_BASE_URL/maeda/client/{client_id} | PUT $AUTH_BASE_URL/api/v1/clients/{client_id} | Đổi base URL và path. |
| Token | Token opaque của Shukah. | Chỉ JWT của Locate. | Lấy JWT bằng exchange-token trước, và giữ token Shukah cho order-v2. Chưa chuyển đăng nhập sang Locate. |
push_enabled | Cùng route này cũng nhận push_enabled, và app gửi nó ở đây cho công tắc push. | Bị bỏ qua. Lời gọi vẫn trả 200 với hồ sơ không đổi. | Chuyển công tắc push sang lời gọi setting bên dưới, nếu không nó lặng lẽ không làm gì (đọc code, chưa capture). |
contact_phone | Shukah có chấp nhận phone bị đổi hay không: Chưa được tài liệu hóa. | Phải bằng đúng phone đã lưu, nếu không 400. | Không có, miễn là app gửi lại đúng phone đã tải từ Locate. Đừng định dạng lại nó. |
| Validation và lỗi | 422 với một mảng lỗi theo field: [{"field":"birth_date","message":"The birth date field must match the format Y-m-d."}] cho "birth_date":"not-a-date" (capture trên dev, 2026-10-02). Các quy tắc khác của Shukah: Chưa được tài liệu hóa. | 400 với {"status":400,"message":"..."} (cộng stack trên dev), các quy tắc trong bảng Request. | Status đổi từ 422 sang 400, và tên field không còn. App hiển thị message. Hãy kiểm tra cách diễn đạt trên màn hình Personal info. |
| Body thành công | Hồ sơ 13 field (capture trên dev, 2026-10-02, với request ở trên). | Hồ sơ 13 field (capture trên dev, 2026-10-01 và 2026-10-02). | Không có: cùng 13 key, type và giá trị cho client 356259 vào 2026-10-02. |
sex | Type của app cho phép 9 là "not applicable". | 9 được lưu là không rõ và đọc lại là 0. | Client có hồ sơ Shukah mang 9 sẽ đọc là không rõ sau khi chuyển. Form Personal info chỉ có nam và nữ. |
| Copy sang Shukah | Không áp dụng. | Chỉnh sửa ở lại Locate và không được copy sang Shukah. | Mọi thứ vẫn đọc hồ sơ từ Shukah sẽ giữ giá trị cũ. |
PUT /api/v1/clients/setting
PUT /maeda/client/:client_id✅ Đã thay thế- 🔴 Token Shukah nhận 401 "Unauthorization"; hãy gửi JWT của Locate (lấy từ exchange-token; giữ lại token Shukah).
- 🔴 App bật/tắt push qua PUT client/:id; Locate bỏ qua push_enabled ở đó, nên hãy gọi PUT /clients/setting.
- 🟡 client_id bắt buộc trong body và phải bằng client_id của token; thiếu push_enabled trả 400.
- 🟡 Thay đổi chỉ nằm ở Locate và không được đẩy sang Shukah.
- 🟡 Cặp lệnh gọi ghi đúng giá trị hiện tại (push_enabled 0), nên chưa chứng minh được Shukah áp dụng push_enabled ở route này.
Request
| Field | Vị trí | Kiểu | Bắt buộc | Ràng buộc | Mô tả |
|---|---|---|---|---|---|
Authorization | header | string | có | Bearer <locate-jwt>. Token Shukah nhận 401. | JWT của Locate. |
client_id | body | integer hoặc numeric string | có | Phải bằng client id trong token. Thiếu hoặc khác cho 400 client_id does not match the authenticated client. | Id của chính người gọi. Không có id trong path. |
push_enabled | body | 0, 1 hoặc boolean | có | Key phải có mặt, nếu không 400 push_enabled is required. Chỉ 1, "1" và true bật nó. Mọi thứ khác tắt nó, kể cả null, "true" và 2. | Bật hoặc tắt push notification. |
client_id được kiểm tra trước. Hiện nay route này chỉ hỗ trợ push_enabled.
Một request dùng cho capture bên dưới, ghi lại giá trị hiện tại:
{
"client_id": 356259,
"push_enabled": 0
}
Response
200 kèm hồ sơ 13 field sau khi cập nhật, không có wrapper, giống như ở
Verify token. push_enabled hiển thị giá trị mới.
{
"client_id": 356259,
"odoo_id": "1342170",
"contact_phone": "+966500000000",
"status": "active",
"email_address": "user@example.com",
"first_name": "Test",
"last_name": "User",
"sex": 1,
"birth_date": "1990-01-01",
"receive_offers": 0,
"push_enabled": 0,
"is_food_truck_user": 1,
"is_cod_disabled": 0
}
Capture trên dev, 2026-10-01 (client 356259, Task 9 live write, giá trị hiện tại được ghi lại); các field cá nhân đã được thay thế.
Lỗi
| HTTP | Body | Khi nào |
|---|---|---|
400 | {"status":400,"message":"client_id does not match the authenticated client"} | client_id thiếu hoặc không phải client của token. Điều này bao gồm một request không có JSON body, mà service đọc là {}. Đã capture với client_id đặt là 1. |
400 | {"status":400,"message":"push_enabled is required"} | Key push_enabled vắng mặt và client_id đúng. Chưa capture. |
401 | {"status":401,"message":"Unauthorization"} | Không có token, token không phải JWT Locate, hoặc client không active. |
500 | Trên dev: {"status":500,"message":"<raw error text>","stack":"<stack trace>"}. Trên production: {"status":500,"message":"Internal server error"}. | Lỗi không mong đợi. Chưa capture. Trên dev message là text lỗi gốc và có thêm field stack; Internal server error chỉ xuất hiện trên production (UAT và production: Chưa được tài liệu hóa). |
400 của client_id và 401 được capture trên dev vào 2026-10-01 (401 khi không có token).
400 của push_enabled lấy từ code và tài liệu service. Trên dev body 400 cũng mang field
stack, mà trang này bỏ đi.
Thử ngay
Lời gọi đầu ghi vào dev, nên hãy gửi giá trị hiện tại của client. Lời gọi thứ hai bị từ chối và không ghi gì.
export AUTH_BASE_URL=https://dev.authentication.locate.sa
export TOKEN='<locate-jwt>' # see "Getting a test token" on the module overview
export CLIENT_ID='<client-id-in-the-token>'
curl -s -X PUT "$AUTH_BASE_URL/api/v1/clients/setting" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "{\"client_id\":$CLIENT_ID,\"push_enabled\":0}"
curl -s -X PUT "$AUTH_BASE_URL/api/v1/clients/setting" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"client_id":1,"push_enabled":0}'
Kỳ vọng: lời gọi đầu cho 200 và hồ sơ. Lời gọi thứ hai cho 400 với
client_id does not match the authenticated client.
Khác biệt so với Shukah
| Khía cạnh | Shukah | Locate | Tác động lên app |
|---|---|---|---|
| URL | PUT $SHUKAH_BASE_URL/maeda/client/{client_id}, cùng route với cập nhật hồ sơ. Body là {client_id, push_enabled}. | PUT $AUTH_BASE_URL/api/v1/clients/setting, không có id trong path. | Công tắc push của app hiện gọi cập nhật hồ sơ. Hãy trỏ nó sang route này, nếu không Locate bỏ qua thay đổi. |
| Token | Token opaque của Shukah. | Chỉ JWT của Locate. | Lấy JWT bằng exchange-token trước, và giữ token Shukah cho order-v2. Chưa chuyển đăng nhập sang Locate. |
client_id | Gửi trong path và body. Shukah có kiểm tra nó với token hay không: Chưa được tài liệu hóa. | Phải có trong body và phải bằng client của token. | Không có: app đã gửi client_id trong body. |
| Validation và lỗi | Chưa được tài liệu hóa. | 400 với {"status":400,"message":"..."} cho client_id sai hoặc thiếu push_enabled. | App đã gửi cả hai key, nên các lỗi này không nên xảy ra. |
| Body thành công | Hồ sơ 13 field với push_enabled là 0 (capture trên dev, 2026-10-02, body {"client_id":356259,"push_enabled":0}, giá trị hiện tại được ghi lại). | Cùng hồ sơ 13 field đó (capture trên dev, 2026-10-02). | App đọc push_enabled từ câu trả lời để đặt công tắc. Capture ghi giá trị hiện tại, nên nó không chứng minh rằng Shukah áp dụng thay đổi trên route này. |
| Copy sang Shukah | Không áp dụng. | Thay đổi ở lại Locate và không được copy sang Shukah. | Shukah giữ giá trị cũ. |
POST /api/v1/clients/add-device-id
POST /maeda/client/add-device-id✅ Đã thay thế- 🟡 Locate không lưu gì; Shukah lưu một dòng thiết bị (id 1074); app vẫn đánh dấu id là đã gửi.
- 🟡 Locate trả lại id cố định 920 và client_id 356315 cho mọi người; Shukah trả client_id của người gọi.
- 🟡 Locate không cần token (không có guard, routes/client.js:23); app có thể tiếp tục gửi token.
Request
Không cần token: token hay bất kỳ header nào khác đều bị bỏ qua.
| Field | Vị trí | Kiểu | Bắt buộc | Ràng buộc | Mô tả |
|---|---|---|---|---|---|
device_id | body | string | không | Không validate. Nó được echo lại khi có. | Id duy nhất của thiết bị. |
| Bất kỳ body key, query key hoặc header nào khác | body, query, header | — | không | Bị bỏ qua, ví dụ language. | — |
{
"device_id": "00000000-0000-4000-8000-000000000000"
}
Response
200 kèm một bản ghi thiết bị. Nó là stub, nên hai trong ba giá trị là cố định:
| Field | Kiểu | Nullable | Định dạng / ràng buộc | Mô tả |
|---|---|---|---|---|
id | integer | không | Luôn là 920, cho mọi caller. | Một id bản ghi thiết bị giả. |
client_id | integer | không | Luôn là 356315, cho mọi caller. Nó không phải id của người gọi. | Một client id giả. |
device_id | string | không | device_id từ request. Khi request không có, là một id mẫu cố định 46AE56EF-29BA-40AE-B436-AF22B119FE1E. | Device id, được echo lại. |
{
"id": 920,
"client_id": 356315,
"device_id": "00000000-0000-4000-8000-000000000000"
}
Capture trên dev, 2026-10-01 (lời gọi live của Task 9, không token; request là cái ở trên). Lời gọi này không lưu gì.
Lỗi
Không có lỗi nào được định nghĩa. Không có 401, vì route không kiểm tra token. Một request không có
JSON body được đọc là body rỗng và vẫn trả 200 (lời gọi body rỗng được capture vào
2026-10-01).
Thử ngay
export AUTH_BASE_URL=https://dev.authentication.locate.sa
curl -s -X POST "$AUTH_BASE_URL/api/v1/clients/add-device-id" -H "Content-Type: application/json" -d '{"device_id":"00000000-0000-4000-8000-000000000000"}'
Kỳ vọng: 200 và bản ghi như ở mục Response. Gọi an toàn: nó không ghi gì.
Khác biệt so với Shukah
| Khía cạnh | Shukah | Locate | Tác động lên app |
|---|---|---|---|
| URL | POST $SHUKAH_BASE_URL/maeda/client/add-device-id | POST $AUTH_BASE_URL/api/v1/clients/add-device-id | Đổi base URL và path. |
| Nó làm gì | Lưu một dòng thiết bị mới cho người gọi ở mỗi lời gọi (capture trên dev, 2026-10-02: dòng 1074). Không có API nào xóa nó. | Không gì cả: không lưu, không liên kết với client, không kiểm tra token. | Sau khi chuyển, không thiết bị nào được đăng ký bởi lời gọi này. Nếu có thứ gì trên Shukah phụ thuộc vào bản ghi thiết bị, nó sẽ ngừng: Chưa được tài liệu hóa. |
| Câu trả lời | {"id":1074,"client_id":356259,"device_id":"<the id sent>"}: id của dòng mới và id của người gọi (capture trên dev, 2026-10-02). App bỏ qua câu trả lời. | {id: 920, client_id: 356315, device_id} cho mọi người. | Không có tác động với app. |
| Token | App gửi token Shukah của nó. Shukah có yêu cầu nó hay không: Chưa được tài liệu hóa. | Không cần, không kiểm tra. | Không có. |
| Thử lại | App ghi lại rằng đã gửi id sau câu trả lời 200. | Stub luôn trả 200. | App sẽ đánh dấu thiết bị là đã gửi và không bao giờ thử lại, dù không có gì được lưu. |
Lưu ý
- Route hồ sơ bỏ qua
push_enabledvà vẫn trả200với giá trị cũ, nên công tắc push phải gọiPUT /api/v1/clients/settingthay vào đó. contact_phonephải bằng đúng phone đã lưu, kể cả dấu+ở đầu, nếu không lời gọi lỗi với400.add-device-idluôn trả200và không lưu gì, nên app đánh dấu thiết bị là đã gửi dù không có thiết bị nào được đăng ký.
Chi tiết (cho backend)
Chỉ kiểm tra dev: host https://dev.authentication.locate.sa, prefix /api/v1. Host và prefix của UAT
và production: Chưa được tài liệu hóa. Body lỗi trên dev mang field stack (capture
2026-10-01 trên các 400 của profile và setting), nên dev không chạy với NODE_ENV=production;
handler chỉ thêm stack ngoài production (src/middlewares/error-handler.js:12-35). Cùng handler đó làm cho một 500 không mong đợi mang text lỗi gốc và một stack trên dev, và Internal server error chỉ trên production (src/middlewares/error-handler.js:28-33).
Thứ tự route và guard
PUT /clients/setting được đăng ký trước PUT /clients/:client_id, nên setting không bao giờ bị đọc
như một client id. Cả hai chạy guard client, nên các quy tắc token là của
Verify token. Route device-id chỉ có async wrapper và không có
guard (src/routes/client.js:23-26).
Cập nhật hồ sơ
- Các kiểm tra là các chuỗi express-validator chạy sau guard. Handler throw message đầu tiên,
nên chỉ một message
400được trả về (src/controllers/client/update-profile/validate.js:12-31,src/controllers/client/update-profile/index.js:12-15). check('client_id')nhìn vào body, cookie, header, params và query, nên mộtclient_idkhông khớp trong query string hay một header cũng lỗi với cùng message (kiểm tra offline, 2026-10-01: các chuỗi validator thật được chạy với khoảng 20 request tự tạo).contact_phoneđược so sánh saunormalizePhone, chỉ bỏ khoảng trắng. Giá trịnulllỗi, và giá trị không bao giờ được ghi (src/controllers/client/update-profile/validate.js:20-23,src/controllers/client/update-profile/parse-payload.js:8-9,src/sync/lib/casts.js:40-41).- Tên và email được lưu đã trim.
nullđược lưu lànullvà""là""(src/controllers/client/update-profile/parse-payload.js:5,11-13). birth_datequa được khi nó lànullhoặctoBirthDateStringcho ra một ngày. Hàm đó trảnullcho giá trị rỗng và giá trị không đọc được, và ngày nó giữ là ngày UTC (src/sync/lib/casts.js:2-11,src/controllers/client/update-profile/validate.js:27-30,src/controllers/client/update-profile/parse-payload.js:14-16).sexđi quamapGender:1hoặc"1"làMALE,2hoặc"2"làFEMALE, mọi thứ khác làUNKNOWN, và response ánh xạUNKNOWNthành0.receive_offersđi quatoBool(src/sync/lib/casts.js:1,14-18,src/controllers/client/update-profile/parse-payload.js:17-18,src/controllers/client/setting/mapper.js:14-18,34).- Handler thay đổi client mà guard đã tải, set
updated_atvà save. Lần save xóa client đã cache (src/controllers/client/update-profile/index.js:17-20,src/models/client.js:158-161). Không có push sang Shukah (docs/plans/2026-07-16-shukah-update-profile-api-local.md:42,140). - Route hồ sơ không đọc
push_enabled(docs/plans/2026-07-16-shukah-update-profile-api-local.md:39,src/controllers/client/update-profile/parse-payload.js:10-19).
Cập nhật setting
Handler cần client_id bằng client của token, rồi push_enabled không được là undefined,
set push_enabled bằng toBool và save. Nó không thay đổi gì khác và không push sang Shukah
(src/controllers/client/setting/index.js:9-24, src/sync/lib/casts.js:1,
docs/plans/2026-07-10-shukah-client-setting-api-local.md:100-106). Một request không có JSON body
đến dưới dạng {}, cho message client_id trước.
Stub device id
Handler trả {id: 920, client_id: 356315, device_id: req.body?.device_id ?? '<sample uuid>'}
và không làm gì khác. Query và header bị bỏ qua
(src/controllers/client/add-device-id/index.js:1-10,
docs/plans/2026-07-15-shukah-add-device-id-api-local.md:15-16,65-69). Một unit test chốt nó
(src/controllers/client/__tests__/add-device-id.test.js:11-35).
Khi tài liệu và code mâu thuẫn (code thắng)
- Design doc 2026-07-16 ghi path cập nhật của Shukah là
PUT /api/v1/clients/{client_id}(docs/plans/2026-07-16-shukah-update-profile-api-local.md:14-19). App gọiPUT /maeda/client/{client_id}. - Lịch sử route của auth service cho thấy một route Shukah
PUT /maeda/api/settingmà service Locate đã thay thế (commitd837492). App không bao giờ gọi nó: công tắc push đi qua route hồ sơ. - Hành vi
sex,receive_offersvàpush_enabledcủa lời gọi hồ sơ trên Shukah không có trong repo nào: Chưa được tài liệu hóa. - 2026-10-02: trang này không có body thành công của Shukah cho update profile và update setting, và không có
body lỗi của Shukah. Giờ chúng đã được capture: cùng hồ sơ 13 field ở cả hai phía, và một mảng lỗi
theo field
422trên Shukah trong khi Locate trả lời400. - 2026-10-02: trang này ghi body
400của Locate là{"status":400,"message":"..."}. Trên dev nó cũng mangstack, một stack trace của server (src/middlewares/error-handler.js:33, được thêm bất cứ khi nàoNODE_ENVkhông phảiproduction). - 2026-10-02: trang này nói Shukah lưu gì cho add-device-id là chưa được tài liệu hóa, và câu trả lời của nó chưa được xác nhận. Shukah lưu một dòng thiết bị mới cho mỗi lời gọi và trả lời bằng id của dòng đó và id của người gọi.
Sources
locate-authentication-service@6757aa4:src/routes/client.js:23-26,src/controllers/client/update-profile/validate.js:4-31,src/controllers/client/update-profile/index.js:11-23,src/controllers/client/update-profile/parse-payload.js:5-19,src/controllers/client/setting/index.js:9-24,src/controllers/client/setting/mapper.js:14-38,src/controllers/client/add-device-id/index.js:1-10,src/controllers/client/__tests__/add-device-id.test.js:11-35,src/sync/lib/casts.js:1-18,40-41,src/models/client.js:158-161,src/middlewares/error-handler.js:12-35- Tài liệu của
locate-authentication-service@6757aa4:docs/api/client-auth-and-address-book.md§10 và §11 (dòng 412-528; thay đổi lần cuối 2026-07-27),docs/plans/2026-07-16-shukah-update-profile-api-local.md:14-19,36-44,138-140,docs/plans/2026-07-10-shukah-client-setting-api-local.md:100-106,docs/plans/2026-07-15-shukah-add-device-id-api-local.md:12-18,63-69 - Snapshot mobile
mobile/locate-client@e960c3a(branchdevelopment, 2026-02-26; code của chính app, không phải Locate):src/entities/user/model/api/services/user.service.ts:20-27,68-74,src/entities/user/model/api/dto/user.dto.ts:58-121,165-171,src/entities/user/model/types/user.server.ts:3-14,src/entities/user/model/constants/user.server.ts:1-6,src/entities/user/model/services/updateUser/updateUser.ts:13-42,src/features/UpdateProfileForm/model/services/updateProfile.ts:80-91,src/features/UpdateProfileForm/model/services/initUpdateProfileForm.ts:13-23,src/features/UpdateProfileForm/ui/UpdateProfileForm/UpdateProfileForm.tsx:42-45,73,155-160,platforms/mobile/products/locate/screens/home/PersonalInfo/ui/PersonalInfo/PersonalInfo.tsx:51,src/features/PushNotificationSettings/model/services/togglePushNotificationEnable.ts:22-26,src/features/PushNotificationSettings/ui/PushNotificationSettings/PushNotificationSettings.tsx:42-50,platforms/mobile/products/locate/screens/home/Settings/ui/Settings/Settings.tsx:37,src/entities/user/model/services/sendDeviceIdentificationData/sendDeviceIdentificationData.ts:18-30,src/entities/user/model/services/init/init.ts:21-23 - Capture dev, 2026-10-02 (parity audit):
update-profile--shukah,update-profile--locate-jwt,update-profile-bad--shukah,update-profile-bad--locate-jwt,update-setting--shukah,update-setting--locate-jwt,add-device-id--shukah,add-device-id--locate-jwt - Capture dev, 2026-10-01:
locate-update-profile-unchanged,locate-update-profile-bad-birth-date,locate-setting-unchanged,locate-setting-mismatched-client,locate-add-device-id,probe-locate-update-profile,probe-locate-setting,probe-locate-add-device-id