Bỏ qua

Nền giao diện

Nền quản trị · nhóm 5 · 14 story · 🟡 chưa viết xong · còn 18 mốc

Chưa viết xong: còn 18 mốc

Phần chưa viết hiển thị tiêu chí dự kiến từ kế hoạch (đã qua cổng PO duyệt) và mốc chờ agent làn docs.

Story Service Thứ tự Ghi chú
E-001/5.1 Nền token và thành phần cho admin-fe admin-fe 19 cap/admin-console-ui · UX-DR1, 10, 11, 12
E-001/5.2 Nền token và thành phần cho portal-fe portal-fe 20 cap/tpp-portal-ui · ~~AD-13 nên viết lại~~ đã archive — giữ nguyên; từ 09/09 story sau kế thừa được
E-001/5.3 Sàn trợ năng cho admin-fe admin-fe 21 cap/admin-console-ui · UX-DR2, 3 · focus-visible không phải focus
E-001/5.4 Sàn trợ năng và responsive cho portal-fe portal-fe 22 cap/tpp-portal-ui · UX-DR2, 3, 4
E-001/5.5 Khung màn danh sách cho admin-fe admin-fe 23 cap/admin-console-ui · UX-DR6, 8, 9
E-001/5.6 Khung màn danh sách cho portal-fe portal-fe 24 cap/tpp-portal-ui · UX-DR6, 8, 9
E-001/5.7 Màn đăng nhập admin-fe admin-fe 25 cap/admin-console-ui · PO tách 09/09 (P1): CHỈ còn màn đăng nhập, quản trị người dùng sang 5.11, vai/quyền sang 5.12 · ⛔ PO chốt 07/09: CHỈ tên đăng nhập + mật khẩu; nút «tài khoản MSB» và bước mã xác thực KHÔNG render (giai đoạn 2) — xem docs/style.md §3 và gói design/ui_kits/admin/ (AdminLogin, index.html:46)
E-001/5.8 Hạ tầng phiên cho admin-fe admin-fe 26 cap/admin-console-ui · đăng xuất · đổi mật khẩu trong phiên · trang 404 và 403 toàn màn
E-001/5.9 Đăng nhập và hạ tầng phiên cho portal-fe portal-fe 27 cap/tpp-portal-ui · khoá tạm sau N lần sai · quên mật khẩu dùng câu trung lập · đăng xuất · đổi mật khẩu · 404 và 403 · PO chốt 09/09 (P7): áp tiền lệ port của 5.8 — dựng màn và cổng phiên trên hợp đồng của E-004/2.8, ⛔ màn tự khai là giữ chỗ tới khi BE lên
E-001/5.10 Vỏ ứng dụng admin-fe — Sidebar và Topbar theo gói design admin-fe 28 cap/admin-console-ui · design/components/navigation/Sidebar.jsx, Topbar.jsx · sidebar trắng 228px, nhóm có nhãn, mục đang mở nền cam nhạt, nút thu gọn · topbar breadcrumb + ngôn ngữ + avatar · thay nav giữ chỗ ở App.tsx · danh sách mục tiêm từ ngoài (nếp D1 của 5.5), ẩn theo quyền là dữ liệu đầu vào · ⛔ icon tự host (UX-DR10)
E-001/5.11 Màn người dùng MSB admin-fe 29 cap/admin-console-ui · tách từ 5.7 09/09 (P1) · danh sách + tạo tài khoản nội bộ; gói design AccountList lọc Loại = Nội bộAccountCreateModal · ✅ ĐO LẠI 11/09 — gói ĐÃ TÁCH hai màn, ghi chú cũ («gói chỉ có một màn Tài khoản chung hai loại ⇒ dừng và hỏi») HẾT HIỆU LỰC và ⛔ không còn chặn: AccountList({scope}) vào gói từ lượt CCS 09/09 bc770cd — hai tập dữ liệu, cột riêng, lọc riêng, màn TPP ⛔ không có nút Tạo mới. ✅ Hai lệch nghiệp vụ của gói PO đã chốt 11/09, ghi trong thân issue OAPI-140 (admin-fe#25): tạo tài khoản TPP được, qua quyền · màn ⛔ không nói «tài khoản AD». Luật chung ở docs/style.md §1: gói là nguồn hình ảnh, ⛔ không phải nguồn nghiệp vụ. ⚠️ AC năm cột GIỮ NGUYÊN (PO chốt 11/09) — nhưng ba cột Tên đăng nhập · Đơn vị · Vai trò ⛔ chưa có nguồn ở bất kỳ tầng nào (app.internal_user V6 chỉ có email · ho_ten · disabled_at) ⇒ lượt thi công đầu tạm bỏ, phần bỏ đi là NỢ, issue con của OAPI-140. ⛔ Nguồn dữ liệu của màn là story mới E-001/2.6 · gán vai không thuộc story này (ở 5.12) · ~~PO chốt 11/09 tối: tạo · vô hiệu · mở lại qua duyệt 3.1 ⇒ trạng thái «chờ duyệt»~~ ⚠️ PO SỬA 12/09 (gói design/roles/): BỎ «chờ duyệt» — change man-nguoi-dung-msb đã dựng bộ từ ba giá trị @ 0cab81f, gỡ lại trong cùng change (story chưa archive): bộ từ còn Đang hoạt động · Ngưng hoạt động, tạo/vô hiệu/mở lại hiệu lực ngay, không nút duyệt · thêm theo gói: nhấp một hàng mở hộp thoại Gán vai (AssignRoleModal — thân hộp thoại thuộc 5.12, đây chỉ là cửa vào) khi người đang đăng nhập là super admin; người khác thấy hộp cảnh báo «Không đủ quyền gán vai» đầu trang và hàng không nhấp được · ⛔ câu «tài khoản AD» của gói vẫn không theo (PO 11/09) · ✅ PO chốt 11/09 (xác nhận lại với làn platform cùng ngày): thêm cột Ngày tạo — nguồn app.internal_user.created_at (V6), gói AccountList có vẽ; AC năm cột ở epics.md ⛔ không sửa ngược (⛔G1), hàng này là nơi ghi ⇒ màn có sáu cột. Nối API là nợ OAPI-145 (admin-fe#27)
E-001/5.12 Màn vai và quyền theo chức năng admin-fe 30 cap/admin-console-ui · tách từ 5.7 09/09 (P1) · gói design RoleList · PermissionList · RoleCreateModal · ⛔ K3: «quyền duyệt» là lớp riêng trong bảng quyền, hiển thị tách, ⛔ không trộn vào quyền chức năng; maker ≠ checker trên cùng một việc do engine E-001/3.1 thi hành, ⛔ không phải cấu hình; gán quyền duyệt tự nó qua duyệt (FR-004) · ~~⚠️ gói chưa vẽ lớp quyền duyệt trong RoleCreateModal~~ hết hiệu lực: gói có APPROVAL_PERMS @ screens.jsx:1294 (đo 11/09) · ✅ PO chốt 11/09 tối (mở issue, UU-TIEN-GD1 §G): đi như 5.11màn trước trên nguồn mẫu + tự khai TuKhaiChuaNoi, nối API 2.4 là nợ có tên; áp tiền lệ port P7 ⇒ M:2.4Đ:2.4, điều kiện đóng story vẫn là 2.4 archive · phạm vi thêm theo 2.4: màn CRUD danh mục quyền (PermissionList + tạo/sửa/ngưng, lớp đặc quyền hiển thị tách) · ⚠️ PO SỬA 12/09 — nguồn hình ảnh là gói design/roles/ (Phân quyền - Admin.dc.html + README.md), ⛔ KHÔNG «chờ duyệt», nút chính là «Lưu», hiệu lực ngay; ba màn + bốn hộp thoại: Quyền (lọc đối tượng/lớp, gom theo đối tượng, phân trang số) · Biểu mẫu quyền (mã tự sinh chỉ đọc; chọn lớp đặc quyền ⇒ hành động đổi nhóm + hai trường hệ quả) · Vai trò (7 cột) · Tạo/Sửa vai (ma trận 13 đối tượng × 4 hành động, chọn cả hàng/tất cả; khối Đặc quyền duyệt tự sinh từ danh mục — ⛔ không gõ cứng) · Gán vai (bảng vai với ngày cấp · Đã cấp/Đã thu hồi/Chưa cấp · nút Thu hồi ghi mốc, ô đã thu hồi khoá không bỏ tick · khối lịch sử) · Xác nhận ngưng hoạt động · 403 hai dạng (toàn trang khi mở URL trực tiếp, hộp trong card) · sidebar lọc theo quyền: mục không được cấp không render, nhóm rỗng không render (dữ liệu tiêm vào vỏ 5.10, nếp D1) · ~~7 mục gói còn thiếu~~ gói 12/09 đã lấp; còn lại ở bản kê CCS 12/09
E-001/5.13 Nối bốn màn xác thực của portal-fe vào portal-be thật portal-fe 33 cap/tpp-portal-ui · mở 11/09/2026 tối (PO chốt — §G) · nhà của issue có sẵn OAPI-107 (portal-fe#20) và của change đang thi công noi-xac-thuc-vao-portal-be — trước 11/09 change này chạy không có hàng story ⇒ epic-status mù · bỏ máy chủ giả lập src/features/auth/may-chu-gia-lap.ts, gọi POST /api/v1/tpp-sessions · DELETE …/current · PUT /api/v1/tpp-users/current/password · «quên mật khẩu» vẫn màn giữ chỗ tới khi OAPI-127 trả · ⚠️ số 5.13 trống vì P3 hết đối tượng (5.6 đã gộp vỏ portal)
E-001/5.14 Màn hàng đợi chờ duyệt admin-fe 34 cap/admin-console-ui · mở 11/09/2026 tối (PO chốt — UU-TIEN-GD1 §C «lỗ thật», chọn MÀN RIÊNG) · liệt kê yêu cầu người đang đăng nhập duyệt được, lọc theo loại (GĐ1: hồ sơ tổ chức · yêu cầu đăng ký · cấu hình luồng — ⛔ không vai/quyền/gán vai/tài khoản nội bộ, PO 12/09 + 13/09), bấm hàng đi tới màn đối tượng để duyệt/từ chối kèm lý do · ⛔ K3: người tạo yêu cầu ⛔ không thấy nút duyệt của chính mình (engine 3.1 thi hành, màn chỉ phản ánh) · ⚠️ gói design/roles/ 12/09 màn Hàng đợi (tab Vai/Quyền/Gán vai, khối «trước → sau») nhưng đó là biến thể maker/checker cho phân quyền — PO đã bỏ ở GĐ1 ⇒ lấy hình dạng (bảng + chi tiết trước/sau), đổi loại sang hồ sơ tổ chức · yêu cầu đăng ký · cấu hình luồng; ghi bản kê CCS 12/09 để vẽ đúng loại

Vì sao làm — BRD

→ Mục tiêu và giá trị nghiệp vụ nằm ở Tổng quan epic. Ở đây chỉ ghi mỗi story góp gì vào mục tiêu đó.

E-001/5.1 Nền token và thành phần cho admin-fe — admin-fe

Góp gì vào mục tiêu epic. Mọi màn hình của F1 (quản trị người dùng, phân quyền) và F3 (hàng đợi chờ duyệt, maker/checker) sẽ mọc trên nền này. Story chưa dựng màn nghiệp vụ nào; nó chốt cách bề mặt quản trị nói với mắt người, và chốt bằng cổng máy chứ không bằng lời dặn.

  • Làm BÂY GIỜ chứ không sau vài màn hình, vì một lý do đo được: gói design mang năm sửa đổi tương phản rút từ một đợt đo trong đó 13/28 cặp màu trượt ngưỡng WCAG. Nạp token sau khi đã có mã dùng màu nghĩa là đi sửa ngược từng chỗ — và chỗ nào sót thì không cổng nào thấy.
  • Trạng thái không được mã hoá chỉ bằng màu. Với một hàng đợi phê duyệt thì đây không phải yêu cầu trợ năng cho một nhóm thiểu số: đọc nhầm trạng thái là duyệt nhầm hồ sơ. Change ghim nó vào kiểu dữ liệu — nhãn trạng thái không có chữ thì tsc đỏ, không phải reviewer phải nhớ.
  • Phân trang nói đúng ngôn ngữ hợp đồng API. AD-28 đánh trang từ 1, còn Spring Data mặc định đánh từ 0. Nếu front-end cũng nghĩ 0-gốc thì hai lỗi ngược nhau triệt tiêu nhau ở màn đầu tiên và chỉ lộ ra ở màn thứ hai — loại lỗi đắt nhất để truy. Ghim 1-gốc vào kiểu của thành phần biến sai lệch thành lỗi biên dịch.
  • Icon nằm trong repo, không CDN — mở rộng cổng «tự chứa» mà story khung đã dựng (UX-DR10, AD-23). Bề mặt này không có đường ra Internet, nên một icon tải từ ngoài là màn hình hỏng lặng lẽ ở môi trường thật.
  • Hiển thị ngày giờ tách khỏi định dạng trao đổi (UX-DR12): back-end nói yyyy-MM-ddTHH:mm:ssZ, người Việt đọc ngày–tháng–năm theo giờ Việt Nam. Chuỗi sai profile thì báo lỗi, không hiển thị theo phỏng đoán — đoán sai một mốc thời gian trên hồ sơ phê duyệt là đoán sai một dữ kiện pháp lý.

Vị trí trong hàng đợi. E-001/5.3 (sàn trợ năng), 5.5 (khung màn danh sách), 5.7 (màn đăng nhập và quản trị người dùng), rồi E-002/1.2, 1.4, 1.7 — tất cả đứng sau. E-001/5.2 đã dựng nền tương ứng cho portal-fe viết lại riêng, không nhập lại từ đây. ⚠️ Căn cứ lúc đó là AD-13; PO bỏ vế cấm ấy 09/09/2026 — story sau kế thừa được, chỉ ⛔ không được phụ thuộc build vào nhau.

E-001/5.2 Nền token và thành phần cho portal-fe — portal-fe

Góp gì vào mục tiêu epic. Đây là nền hình ảnh của bề mặt công khai — mọi màn hình nhóm F9 (đăng ký, nộp hồ sơ, khai ứng dụng, lấy khoá) mọc lên trên nó. Không có nền này thì mỗi story tự đặt màu, tự dựng nút, đúng loại phân kỳ mà gói design tồn tại để chặn.

  • Story này ĐÃ viết lại RIÊNG, không nhập gì từ admin-fe. ⚠️ Căn cứ lúc đó là AD-13; PO bỏ vế cấm chia sẻ mã ngày 09/09/2026 — nay chép được, chỉ phụ thuộc build là không, nên đoạn này ghi việc đã làm chứ ⛔ không phát biểu luật. Đây là lần thứ hai dự án trả giá cho luật đó một cách có ý thức: E-001/5.1 đã dựng nền tương đương cho bề mặt quản trị. Đổi lại, một lỗ hổng ở bề mặt công khai không kéo theo bề mặt nội bộ.
  • Sửa một lỗi tương phản THẬT của gói ngay khi chép. Thành phần Button biến thể chính dùng chữ trắng trên nền cam — UX-DR11 đo được 2.77–3.68, dưới ngưỡng WCAG AA. Bản trong repo đọc token thay vì màu cứng. Đây không phải chuyện thẩm mỹ: nút hành động chính không đọc được trên cổng công khai của một ngân hàng là lỗi ai cũng gặp, mỗi ngày, và không ai báo.
  • Dọn 20/22 chỗ màu viết cứng thành token. Chúng đúng màu nhưng sai cơ chế — màu cứng chặn đường chế độ tối (UX-DR5). Hai chỗ còn lại gói không có token nên giữ, có miễn trừ ghi lý do trong cổng, không im lặng bỏ qua.
  • Ngân sách kích thước gói tĩnh có cổng máy (AD-29 mục 3 giao đích danh story này). Bề mặt này ra Internet: gói phình là chi phí trả bằng thời gian chờ của người dùng bên thứ ba, ở đường truyền mà ngân hàng không kiểm soát.
  • Icon tự host, SVG nội tuyến, ⛔ không CDN (UX-DR10) — cùng luật với admin-fe nhưng ở đây lý do là toàn vẹn chuỗi cung ứng cho một bề mặt công khai, không phải «tải không được».

⚠️ Một lệch nguồn — nay ĐÃ XỬ XONG ở nguồn. Mật độ lấy theo GÓI — control 48px, chữ thân 15px, đệm card 28px (PO chốt 07/09/2026) — trong khi DESIGN.md ghi 44/14/24. Ngày 09/09/2026 PO bỏ hẳn bộ artifact UX: DESIGN.md không còn tồn tại, tiêu chuẩn giao diện nay ở một nguồn duy nhấtdocs/style.md của repo hoạch định. ⇒ Số đang chạy là số của gói, và ⛔ không còn tài liệu thứ hai nói số khác.

E-001/5.3 Sàn trợ năng cho admin-fe — admin-fe

Góp gì vào mục tiêu epic. Đây là sàn trợ năng của bề mặt quản trị — nơi nhân viên ngân hàng duyệt hồ sơ TPP, gán vai, đọc hàng đợi maker/checker. Câu chốt của nguồn nói rõ mức kỳ vọng: «Đây là sàn, không phải mục tiêu phấn đấu.»

  • Trên một bề mặt PHÊ DUYỆT, thao tác được bằng bàn phím và tên đọc được không phải tiện nghi. F3 là hàng đợi chờ duyệt: người dùng đọc trạng thái rồi bấm duyệt hoặc từ chối. Một nút chỉ có icon mà không có tên đọc được, hay một phần tử không tới được bằng bàn phím, biến thao tác có hậu quả pháp lý thành thao tác đoán. FR-020 bắt checker chỉ duyệt hoặc từ chối — mô hình đó chỉ chặt bằng đúng độ rõ của giao diện.
  • Gói design gốc KHÔNG có focus-visible và KHÔNG có một thuộc tính aria- nào. PO đưa cả hai vào giai đoạn 1 ngày 05/09/2026 — tức đây là phần thêm vào so với gói, không phải phần gói cho sẵn mà đội chỉ việc dùng.
  • AD-29 mục 4 bác việc nâng cổng trợ năng thành quy ước ở spine, «vì nó đã có nhà» — nhà đó chính là story này. Hệ quả trực tiếp: story phải giao cả cổng máy, không chỉ mã. Nếu chỉ giao mã thì luật trợ năng không có chỗ nào cưỡng chế, và spine đã cố ý không nhận việc đó.

Vị trí trong hàng đợi. E-001/5.5 (khung màn danh sách) và 5.7 (màn đăng nhập, quản trị người dùng), rồi mọi màn E-002E-007 của bề mặt quản trị đều dựng trên sàn này. Dựng sau khi đã có màn hình nghĩa là đi sửa ngược từng màn — và chỗ nào sót thì không cổng nào thấy.

E-001/5.4 Sàn trợ năng và responsive cho portal-fe — portal-fe

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.5 Khung màn danh sách cho admin-fe — admin-fe

Góp gì vào mục tiêu epic. Story này không giao màn hình nào cho nghiệp vụ, nhưng nó là vật mang của cả ba luồng ưu tiên (PO chốt 08/09/2026): mọi màn danh sách của F1 (quản trị người dùng, phân quyền), F3 (hàng đợi chờ duyệt) và của E-002E-007 đều mọc trên khuôn PageHeader → SearchInput → Table → Pagination mà nó dựng. Nó đứng trước, không phải việc rẽ ngang.

  • Danh sách của cổng này không tải hết được, nên «sắp xếp» là chuyện của máy chủ chứ không phải của trình duyệt. NFR-010 đếm 1.069 API. Một bảng tự sắp xếp mảng nó đang cầm thì chỉ sắp trang đang xem — và đó là kết quả sai mà trông đúng: người duyệt thấy bảng đã sắp, không có dấu hiệu nào để nghi ngờ. Vì vậy story chốt luật ở tầng khung, một lần, thay vì dặn từng màn.
  • URL là công cụ làm việc, không phải chi tiết kỹ thuật. Nhân viên ngân hàng gửi nhau đường dẫn «xem hàng đợi này». Nếu tham số không nằm trên URL — hoặc tệ hơn, URL nói một đằng màn hiển thị một nẻo — thì thứ được gửi đi là một đường dẫn nói dối, và người nhận không có cách nào biết. UX-DR8 đòi mọi tham số danh sách nằm trên URL; story này biến đòi hỏi đó thành cơ chế có cổng.
  • Trên bề mặt PHÊ DUYỆT, «không đủ quyền» là kết quả ĐÚNG THEO THIẾT KẾ, không phải sự cố. Mô hình phân quyền sinh ra để một số người không xem được một số màn. Đăng xuất họ ở đó là biến một thiết kế đang chạy đúng thành cái trông như lỗi hệ thống — và người dùng sẽ đi hỏi vòng quanh thay vì đọc lời giải thích. UX-DR9 tách ba trạng thái này ra khỏi «lỗi» chung chính vì thế.

Vị trí trong hàng đợi. Đứng ngay sau sàn trợ năng E-001/5.3, và đứng trước E-001/5.7 (màn đăng nhập, quản trị người dùng) cùng E-004/1.4 (màn hồ sơ tổ chức) — hai story đầu tiên có màn nghiệp vụ thật. E-001/5.6 là bản song song cho portal-fe, và nó đã được viết lại riêng. ⚠️ ⛔ Nay không còn ràng buộc phải thế: PO bỏ vế cấm chia sẻ mã của AD-13 ngày 09/09/2026 — chép được, chỉ phụ thuộc build là không.

E-001/5.6 Khung màn danh sách cho portal-fe — portal-fe

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.7 Màn đăng nhập admin-fe — admin-fe

Góp gì vào mục tiêu epic. Đây là cửa vào của toàn bộ bề mặt quản trị. Mọi story F1F8 đều giả định có một người đã đăng nhập; trước story này bề mặt quản trị ⛔ không có cửa nào.

  • Story được giao làm HAI nhịp, và nhịp một cố ý chưa dùng được. PO chốt 09/09/2026 «giao màn trước, cắm sau»: lượt đầu giao màn đăng nhập hoàn chỉnh đứng trên một cổng phiên ⛔ không nối đi đâu, vì điều kiện để nối — phiên có trạng thái ở admin-be (E-001/2.3) — lúc ấy chưa có. Người bấm «Đăng nhập» nhận đúng câu «Đường đăng nhập chưa mở ở bản này».
  • Cái giá của nhịp đó là một bản chạy được mà ⛔ không làm được việc — và nó chỉ an toàn vì màn nói thẳng ra thay vì im lặng. Đây là chỗ dễ nhất để một trang tài liệu nói sai: mô tả thao tác đăng nhập trong khi thao tác ấy chưa nối, và ⛔ không lộ ra lúc soát bài vì ảnh chụp vẫn đẹp, câu chữ vẫn đúng hình dạng của màn.
  • Nhịp hai không phải «nối một hàm». Hợp đồng phiên tạm do front-end tự đặt lúc chưa có hợp đồng thật; nhịp này thay hình dạng tạm bằng hình dạng thật, ⛔ không cắm một lớp dịch giữa hai hình dạng — hai hình dạng cạnh nhau đúng là thứ «hai nguồn trôi khỏi nhau» mà dự án đã cấm ở bốn chỗ khác.

Vị trí trong hàng đợi. Story đã tách ba ngày 09/09: 5.7 nay chỉ còn màn đăng nhập; quản trị người dùng nội bộ sang 5.11, vai và quyền sang 5.12. Nó tiêu thụ E-001/2.3 phía máy chủ và E-001/5.8 hạ tầng phiên, rồi mở đường cho mọi màn nghiệp vụ phía sau.

E-001/5.8 Hạ tầng phiên cho admin-fe — admin-fe

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.9 Đăng nhập và hạ tầng phiên cho portal-fe — portal-fe

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.10 Vỏ ứng dụng admin-fe — Sidebar và Topbar theo gói design — admin-fe

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.11 Màn người dùng MSB — admin-fe

Góp gì vào mục tiêu epic. Trang quản trị trước story này có vỏ, có đăng nhập thật, và ⛔ không có một màn nghiệp vụ nào: cây điều hướng bày 13 mục, tất cả dẫn tới trang không tồn tại. Đây là màn nghiệp vụ đầu tiên — mục «Tài khoản» là mục đầu tiên đi tới nơi.

  • Nó đặt khuôn cho 12 màn sau, ⛔ không chỉ giao một bảng. Lượt đầu tiên áp bố cục theo miền nghiệp vụ (AD-29 mục 6) vào một màn thật: chỗ đặt mã, cách nối dữ liệu, cách khai ra phần chưa có. Màn sau chép khuôn này chứ không tự nghĩ lại.
  • Nó là màn A2 của lộ trình ưu tiên giai đoạn 1 — ngay sau A1 (đăng nhập). Và nó gặp đúng tình huống §F của lộ trình: hai điểm cuối của admin-be chưa có (liệt kê người dùng, tạo tài khoản). Lộ trình nói làn ⛔ không dừng: dựng màn trên nguồn tiêm từ ngoài, //TODO đúng chỗ sẽ nối, nợ có điều kiện trả, và màn tự khai đang chạy trên dữ liệu mẫu.
  • Giá trị nghiệp vụ nằm ở ba quyết định PO gỡ khỏi gói design. Gói vẽ Tên đăng nhập · Đơn vị · Vai trò và câu chữ về «tài khoản AD»; bảng thật (app.internal_user) không có cột nào như hai cột đầu, vai thì chưa có story. PO chốt 11/09: định danh là thư điện tử, bỏ đơn vị, vai chờ E-001/2.4. Sáu trong mười chỗ phải sửa là câu chữ nấp trong helper, placeholder, chú thích — đúng loại lỗi mà docs/style.md §1 cảnh báo: gói là nguồn hình ảnh, ⛔ không phải nguồn nghiệp vụ.

Vị trí trong hàng đợi. Thứ tự 29, tách từ E-001/5.7 ngày 09/09. Đứng trên khung màn danh sách E-001/5.5 và vỏ E-001/5.10. Để lại ba nợ có tên: điểm cuối phía admin-be (OAPI-141), ba cột AC chưa có nguồn (OAPI-142), nối API danh sách + tạo (OAPI-145). Gán vai là E-001/5.12; duyệt là màn hàng đợi E-001/5.14; người dùng bên thứ ba là E-004/1.9.

E-001/5.12 Màn vai và quyền theo chức năng — admin-fe

Góp gì vào mục tiêu epic. Đây là màn nghiệp vụ thứ hai của trang quản trị (A4 của lộ trình ưu tiên, ngay sau màn người dùng) và là chỗ người quản trị nhìn thấy mô hình phân quyền của cả cổng. Hai mục điều hướng «Vai trò» · «Quyền» hiện dẫn tới trang không tồn tại.

  • Nó hiện thực một quyết định PO đổi bản chất của quyền. PO chốt 11/09, nguyên văn: «danh mục quyền là cái cấu hình được, xem thêm sửa xoá được, anh cần nó control được qua admin» — tức quyền là dữ liệu, ⛔ không phải hằng số trong mã, và trang quản trị là nơi cấu hình nó. Mã quyền theo khuôn <đối tượng>.<hành động>; ⛔ không xoá, chỉ ngưng hoạt động (AD-11).
  • Nó làm lộ ra thứ K3 bắt phải lộ. Quyền có hai lớp — chức năng và đặc quyền duyệt — và lớp đặc quyền phải hiển thị tách hẳn. Gói design vẽ danh mục quyền ba cột không phân biệt lớp; một danh mục không cho biết quyền nào là đặc quyền là danh mục giấu đúng thứ K3 bảo phải lộ. Change thêm hai cột có nguồn (Lớp · Trạng thái) từ trường dữ liệu, ⛔ không vẽ hình học mới.
  • Nó giữ luật «mọi thay đổi vai/quyền qua phê duyệt hai người» (FR-004, AD-9): nút chính của biểu mẫu tạo vai là «Gửi duyệt», ⛔ không «Tạo mới» như gói — ngôn ngữ là chỗ style.md thắng gói. Và người soạn không duyệt được chính hồ sơ mình soạnluật máy, ⛔ không phải một ô cấu hình vai — câu này đặt ngay trong khối đặc quyền.

Vị trí trong hàng đợi. Đứng trên khung danh sách E-001/5.5, hộp thoại của E-001/5.11, và vỏ E-001/5.10. Điểm cuối chưa có: admin-be chưa có bảng vai/quyền, E-001/2.4 chưa mở issue ⇒ đi tiếp theo §F như 5.11 (nguồn mẫu tiêm từ ngoài, màn tự khai, nợ nối có tên, điều kiện trả: 2.4 archive). Phần AC gói chưa vẽ (biểu mẫu quyền, sửa/ngưng vai, gán vai) là tạm bỏ có tên chờ CCS — ⛔ không tự vẽ, ⛔ không cắt phạm vi. Gán vai cho người dùng thuộc màn Tài khoản (5.11), ⛔ không phải màn này. Màn hàng đợi duyệt là 5.14.

E-001/5.13 Nối bốn màn xác thực của portal-fe vào portal-be thật — portal-fe

Góp gì vào mục tiêu epic. E-001/5.9 đã dựng bốn màn xác thực thật cùng tầng phiên cho cổng bên thứ ba — nhưng chúng nói chuyện với một máy chủ giả lập nằm trong gói tĩnh. Nghĩa là tới hôm nay bề mặt TPP ⛔ không có đường vào thật: đăng nhập được là vì tệp giả lập nói được, ⛔ không phải vì có ai xác thực. Story này là lượt đầu tiên cổng có đường vào.

  • Mốc đã tới, và đây là chỗ nối. E-004/2.8 (xác thực và phiên cho bên thứ ba) đã merge ở portal-be với đủ điểm cuối đăng nhập · đăng xuất · đổi mật khẩu. Không nối thì hai nửa đều «xong» mà người dùng vẫn không vào được.
  • Nó vạch ra một lỗ hợp đồng đang nằm im, ⛔ không cổng nào bắt. portal-fe gắn mã phiên vào tiêu đề riêng X-Session-Token; portal-be khai Authorization: Bearer. Mỗi repo tự nó nhất quán, ca kiểm hai bên đều xanh, và ⛔ không ai so hai bên. Đây là ca mẫu của bệnh «cổng xanh mà bất biến đã hỏng» giữa các repo tách rời (AD-13) — lượt nối đầu tiên là lúc nó vỡ, và thà vỡ ở đây hơn trên môi trường thật.
  • Với người dùng, ba điều mới xuất hiện mà trước không tồn tại: tài khoản là tài khoản do portal-be cấp; sai nhiều lần thì bị khoá tạm với số lần và thời hạn do máy chủ nói; đổi mật khẩu thì phiên khác bị đăng xuất. ⛔ Không thao tác nào mới — ba màn cũ đổi kết quả.

Vị trí trong hàng đợi. Thứ tự 33; mở 11/09 tối để change noi-xac-thuc-vao-portal-be — trước đó thi công không có hàng story ⇒ bảng tiến độ mù. Đứng sau E-001/5.9 (bốn màn) và E-004/2.8 (điểm cuối). Màn quên mật khẩu ở lại giả lậpportal-be gỡ nhánh đặt lại mật khẩu khỏi phạm vi vì chưa có cổng gửi thư; nợ trả theo sự kiện (lượt đầu portal-be có điểm cuối ấy, OAPI-127).

E-001/5.14 Màn hàng đợi chờ duyệt — admin-fe

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

Ai dùng, dùng thế nào — URD

Một hành trình cho cả nhóm, kể từ bề mặt người dùng chạm vào. Nhóm này có hai bề mặt — bên thứ ba và ngân hàng — nên hành trình đi xuyên cả hai.

E-001/5.2 Nền token và thành phần cho portal-fe — portal-fe

Chưa có màn hình nghiệp vụ nào — bên thứ ba vẫn chưa có gì để làm trên cổng; đăng ký, nộp hồ sơ, lấy khoá thuộc nhóm F9. Nhưng khác story khung, ở đây đã có thứ nhìn được và bấm được: bộ thành phần dùng lại.

Người chạm vào giai đoạn này là người dựng màn hình saungười nghiệm thu giao diện. Những gì người nghiệm thu tự kiểm được, không cần chờ màn nghiệp vụ:

  1. Nhìn nút hành động chính. Chữ trên nền cam không được là trắng, và tỉ số tương phản phải đạt ngưỡng WCAG AA cho chữ thường. Đây là chỗ gói gốc sai, nên là chỗ phải nhìn trước tiên.
  2. Dựng lại trong môi trường KHÔNG có thư mục gói design. Bản dựng vẫn phải thành công và vẫn đúng màu — chứng minh token đã thật sự nằm trong repo, không phải tham chiếu ra ngoài.
  3. Cắt đường ra Internet rồi tải lại. Icon hiển thị đầy đủ: không ô trống, không tài nguyên tải hỏng.
  4. Xem một mốc thời gian. Hiện theo quy tắc hiển thị, không phải chuỗi trao đổi nguyên bản. Đưa vào một mốc sai định dạng ⇒ giao diện hiện dấu hiệu thiếu dữ liệu, ⛔ không ném lỗi và ⛔ không hiện chuỗi rác — hai chiều đều phải đúng.
  5. Truyền một giá trị sai kiểu cho thuộc tính của một thành phần ⇒ cổng kiểm kiểu đỏ. Đây là lý do 19 thành phần của gói được chuyển sang .tsx khi chép: giữ .jsx là mở một lỗ trong cổng kiểu tĩnh mà AD-24 bắt buộc.
  6. Đo kích thước gói tĩnh. Trong ngưỡng ⇒ in số đo; vượt ngưỡng cộng biên độ ⇒ thoát khác 0 và nêu cả số đo thật lẫn ngưỡng, không chỉ nói «vượt».

⇒ Story này không sinh trang hướng dẫn người dùng cuối; cả hai change đều đã khai docs: khong-can. Hướng dẫn cho bên thứ ba viết khi màn hình nhóm F9 có thật, theo mốc PO gọi và trên môi trường tích hợp đã deploy.

E-001/5.4 Sàn trợ năng và responsive cho portal-fe — portal-fe

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.6 Khung màn danh sách cho portal-fe — portal-fe

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.9 Đăng nhập và hạ tầng phiên cho portal-fe — portal-fe

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.13 Nối bốn màn xác thực của portal-fe vào portal-be thật — portal-fe

Lượt đầu tiên người thật đăng nhập được vào cổng bên thứ ba bằng tài khoản thật. ⛔ Không có màn mới — ba màn cũ giờ đi tới máy chủ, nên có thể thất bại vì máy chủ, vì mạng, hay vì bị khoá.

Người nghiệm thu kiểm được bằng tay (cần một tài khoản do portal-be cấp — ⛔ không còn tài khoản mẫu nào nằm trong trang):

  1. Đăng nhập đúng ⇒ vào ứng dụng, tới đúng đích đang chờ (địa chỉ đang mở trước khi bị đẩy ra, nếu có). Đích chỉ nhận đường dẫn nội bộ; địa chỉ ngoài bị thay bằng đích mặc định.
  2. Đăng nhập sai ⇒ một thông điệp chung (⛔ không nói sai email hay sai mật khẩu) kèm số lần thử còn lại đúng như máy chủ trả — ⛔ không phải con số giao diện tự đếm. Bấm gửi hai lần liên tiếp ⛔ không đốt hai lượt thử: nút vô hiệu trong lúc chờ, ở cả ba biểu mẫu.
  3. Sai tới mức khoá tạm ⇒ màn nói đang khoá tạm cùng thời điểm mở lại, biểu mẫu vô hiệu. ⚠️ Nếu máy chủ không cho biết mốc ⇒ màn chỉ nói đang khoá, ⛔ không nêu mốc nào — đó là chủ đích, ⛔ không phải thiếu.
  4. Đăng xuất ⇒ máy chủ được báo chấm dứt phiên, mã phiên xoá khỏi trình duyệt, về màn đăng nhập. Đăng xuất khi mất mạng ⇒ mã phiên vẫn xoá, vẫn về màn đăng nhập.
  5. Đổi mật khẩu — gõ sai mật khẩu hiện tại ⇒ báo lỗi tại ô mật khẩu hiện tại, người dùng vẫn đang đăng nhập, vẫn ở màn đó, các ô khác giữ nguyên. ⛔ Không bị đẩy ra màn đăng nhập. Thông điệp ⛔ không tiết lộ gì về mật khẩu đúng.
  6. Đổi mật khẩu thành công ⇒ màn kết quả nói rõ các phiên khác bị đăng xuấtkhoá truy cập của ứng dụng không đổi; phiên đang dùng vẫn sống.
  7. Phiên chết ngay lúc đang đổi mật khẩu ⇒ về màn đăng nhập, ⛔ không nhận thông điệp «mật khẩu hiện tại sai».
  8. Không thao tác 15 phút ⇒ phiên hết, lượt gọi kế bị từ chối ⇒ về màn đăng nhập, đích được giữ.

⚠️ Hai điều ⛔ ĐỪNG kỳ vọng ở bản này: - Quên mật khẩu chưa dùng được. Màn vẫn hiện, vẫn nhận email, vẫn trả lời trung lập — nhưng ⛔ không có thư nào được gửi: portal-be chưa có điểm cuối đặt lại mật khẩu. Một màn nhận email rồi trả lời trung lập trông y hệt màn đang chạy đúng; người viết hướng dẫn phải nói rõ kẻo người dùng ngồi chờ thư. - Số lần thử và thời hạn khoá ⛔ không phải hằng số của giao diện. Trang hướng dẫn ⛔ không được ghi số cứng («sai 3 lần», «khoá 15 phút») — hai giá trị ấy portal-be cấu hình, giao diện chỉ hiển thị lại; ghi số là đẻ nguồn thứ hai sẽ trôi.

E-001/5.1 Nền token và thành phần cho admin-fe — admin-fe

Vẫn chưa có người dùng nghiệp vụ nào — nhân viên ngân hàng chưa đăng nhập được (E-001/5.7, mà nó còn chờ E-001/2.2). Nhưng khác hai story khung ở nhóm 0, story này đã có thứ nhìn được và bấm được: bộ thành phần dùng lại.

Người chạm vào ở giai đoạn này là người dựng màn hình saungười nghiệm thu giao diện. Những gì người nghiệm thu tự kiểm được, không cần chờ màn nghiệp vụ:

  1. Đi bằng bàn phím qua mọi thành phần tương tác được: mỗi điểm dừng phải có chỉ báo tiêu điểm hai lớp — khe hở sát viền rồi vòng ngoài màu đậm — và nó chỉ hiện khi đi bằng bàn phím (:focus-visible), không nhấp nháy khi bấm chuột.
  2. Nhìn chữ trên nền cam. Phải là màu mực đậm, không phải trắng. Đây là một trong năm sửa đổi tương phản; đổi về trắng thì cổng kiểm phải đỏ chứ không phải mắt người phải bắt.
  3. Đọc một nhãn trạng thái. Luôn có chữ, không chỉ có màu.
  4. Bấm phân trang. Trang đầu là 1, không phải 0; và không chọn được trang ngoài khoảng hợp lệ.
  5. Đi trong trình thuật sĩ. Lùi về bước đã đi qua thì được; nhảy tới bước chưa tới thì không.
  6. Bỏ trống một trường bắt buộc. Thông báo lỗi phải nối với ô nhập bằng quan hệ mà trình đọc màn hình đọc được — không phải một dòng chữ đỏ trôi nổi cạnh ô.
  7. Xem một mốc thời gian. Hiển thị ngày–tháng–năm rồi giờ phút, theo giờ Việt Nam. Đưa vào một chuỗi sai profile trao đổi ⇒ báo lỗi, không hiển thị đại.
  8. Cắt đường ra Internet rồi tải lại. Icon vẫn hiển thị đủ — chúng nằm trong repo.

⇒ Story này không sinh trang hướng dẫn người dùng cuối; link.yaml của change đã khai docs: khong-can. Hướng dẫn cho nhân viên ngân hàng viết khi màn hình nghiệp vụ đóng, từ UI thật.

E-001/5.3 Sàn trợ năng cho admin-fe — admin-fe

Vẫn chưa có màn hình nghiệp vụ nào — nhân viên ngân hàng chưa đăng nhập được (E-001/5.7, còn chờ E-001/2.2). Cái story này giao là cơ chế, không phải màn hình.

Nhưng đây là story kiểm bằng người dùng thật rõ nhất từ đầu epic tới giờ: toàn bộ nó là hành vi quan sát được bằng bàn phím. Người nghiệm thu tự kiểm được ngay:

  1. Bấm Tab một lần từ đầu trang. Phần tử nhận tiêu điểm phải là liên kết bỏ qua điều hướng (skip link) — không phải một mục menu nào đó.
  2. Đi hết giao diện bằng bàn phím. Mọi phần tử tương tác có tên đọc được không rỗng; nút chỉ có icon phải mang nhãn chỉ-cho-trình-đọc.
  3. Rà chỉ số tiêu điểm.Không phần tử nào được mang chỉ số dương — thứ tự bàn phím phải theo thứ tự tài liệu, không theo số ai đó gán tay.
  4. Bấm / khi tiêu điểm ở NGOÀI ô nhập ⇒ nhảy vào ô tìm kiếm. Bấm / khi đang GÕ trong một ô nhập ⇒ ký tự / được nhập bình thường, tiêu điểm không chuyển đi. Chiều thứ hai mới là chiều dễ hỏng, và là chiều người dùng gặp mỗi ngày.
  5. Mở nhiều lớp phủ chồng nhau rồi bấm Escchỉ lớp trên cùng đóng, không đóng sạch.
  6. Chạy một tiến trình bất đồng bộ ⇒ vùng sống động đổi nội dung thành thông điệp tương ứng. Rà giao diện: đúng MỘT vùng sống động ở tầng ứng dụng, và nó ở mức lịch sự.

⚠️ Một hành vi cố ý không «thông minh»: nếu có nhiều hơn một phần tử mang dấu hiệu đích tìm kiếm, giao diện báo lỗi nêu rõ tình trạng chứ ⛔ không tự chọn một trong số đó. Tự chọn là đúng ngẫu nhiên hôm nay và sai ngẫu nhiên ngày mai, không ai lần ra.

⇒ Story này không sinh trang hướng dẫn người dùng cuối — nó không thêm màn hình nào. Hướng dẫn cho nhân viên ngân hàng viết khi màn nghiệp vụ có thật, theo mốc PO gọi.

E-001/5.5 Khung màn danh sách cho admin-fe — admin-fe

Vẫn chưa có màn hình nghiệp vụ nào. Cái story này giao là khung cộng một màn trình diễn chạy trên nguồn dữ liệu giả — đủ để nhìn thấy và bấm được, chưa phải màn để làm việc.

Nhưng phần lớn giá trị của nó lại kiểm được bằng tay, không cần đọc mã:

  1. Mở màn bằng một URL mang từ khoá, cột sắp xếp và số trang hợp lệ ⇒ màn hiển thị đúng các giá trị đó, URL không đổi.
  2. Sửa URL cho hỏng (số trang là chữ, hoặc cột sắp xếp không có trong bảng) ⇒ màn dùng giá trị mặc định VÀ URL tự viết lại cho khớp thứ đang hiển thị. ⛔ Không được có cảnh «URL vẫn hỏng, màn vẫn chạy» — đó chính là đường dẫn nói dối.
  3. Ngay sau đó bấm nút quay lại của trình duyệt ⇒ về màn trước, ⛔ không quay về chính cái URL hỏng vừa được sửa. Đây là chiều dễ hỏng nhất và là chiều người dùng gặp thật.
  4. Sao chép URL đang xem, gửi cho người khác mở ⇒ họ thấy đúng bộ tham số đó.
  5. Đổi trang hoặc gõ tìm kiếm trên màn đã có dữ liệu ⇒ dữ liệu cũ còn trên màn ở trạng thái mờ; ⛔ khung xương không hiện lại. Khung xương chỉ thuộc về lần tải đầu.
  6. Xoá hết nội dung ô tìm kiếm ⇒ danh sách trở về đầy đủ, ⛔ không phải trạng thái rỗng.
  7. Lọc ra không kết quả ⇒ câu thông báo khác câu «chưa có dữ liệu», và có nút xoá bộ lọc. Hai tình huống khác nhau thì không dùng chung một câu.
  8. Bấm tiêu đề một cột sắp xếp được ⇒ thứ tự các dòng đang hiển thị không đổi cho tới khi dữ liệu mới về. Bảng gửi yêu cầu đi, nó không tự xếp lại.
  9. Bấm / khi tiêu điểm nằm TRONG vùng màn danh sách ⇒ vào ô tìm kiếm. Bấm / khi tiêu điểm ở NGOÀI vùng đó ⇒ ⛔ không ăn. Cả hai chiều đều phải đúng.

⚠️ Người nghiệm thu cần biết giới hạn của những gì mình vừa bấm. Dữ liệu trên màn trình diễn đến từ nguồn giả, vì admin-be chưa có điểm cuối danh sách nào cho admin-fe. Ba trạng thái mới (không đủ quyền · mất kết nối · hết phiên) được chứng minh bằng nguồn giả ném đúng loại lỗi, ⛔ không phải bằng một mã lỗi thật từ máy chủ. Đường mạng thật được chốt ở E-001/5.7.

⇒ Story này không sinh trang hướng dẫn người dùng cuối — nó không thêm màn nghiệp vụ nào. Hướng dẫn cho nhân viên ngân hàng viết khi màn thật có mặt, theo mốc PO gọi.

E-001/5.7 Màn đăng nhập admin-fe — admin-fe

Đây là story đầu tiên của bề mặt quản trị có thứ để một người thật bấm — nhưng phải đọc kỹ nó đang ở nhịp nào.

Trên bản đang chạy ở nhánh chính, người nghiệm thu thấy một màn đăng nhập đầy đủ: ô thư điện tử, ô mật khẩu, nút hiện/ẩn, nút Đăng nhập, thông báo lỗi tử tế. ⛔ Nhưng bấm Đăng nhập thì chưa đi tới đâu — màn trả lời «Đường đăng nhập chưa mở ở bản này». Đó là nhịp một, và câu trả lời ấy là đúng thiết kế, ⛔ không phải lỗi.

Sau nhịp hai (change đang mở), người nghiệm thu kiểm được bằng tay:

  1. Tải lại một địa chỉ thuộc phiên ⇒ nếu máy chủ xác nhận còn phiên, vỏ ứng dụng hiện ra và người dùng ở lại đúng màn đang xem; nếu không còn phiên ⇒ về màn đăng nhập, và địa chỉ đang mở được giữ làm đích quay về.
  2. Ngắt mạng rồi tải lại ⇒ trang xử như không có phiên và ⛔ không bày vỏ ứng dụng ra. Đây là chiều dễ hỏng: đoán sai chiều này là lộ khung màn quản trị cho người chưa đăng nhập.
  3. Đi qua nhiều màn mà không tải lại trang ⇒ ⛔ không phát thêm lượt hỏi trạng thái phiên nào.
  4. Đăng xuất ⇒ về màn đăng nhập. Đăng xuất khi mất mạng ⇒ vẫn xoá dữ liệu phiên phía trình duyệt và vẫn về màn đăng nhập, kèm cho biết chưa chắc đã thu hồi được ở máy chủ. Đăng xuất khi phiên đã đóng từ trước ⇒ về màn đăng nhập ⛔ không kèm cảnh báo nào.
  5. Mở màn đổi mật khẩu ⇒ màn cho biết đường ấy chưa mở, và phần còn lại của màn vẫn hiện đầy đủ, vẫn thao tác được.

⚠️ Ba câu người nghiệm thu ⛔ ĐỪNG kỳ vọng, vì chúng là thiết kế chứ không phải thiếu sót: mọi ca đăng nhập thất bại cho cùng một thông điệp (ràng buộc chống dò tài khoản) · tài khoản khoá tạm tự mở lại kèm mốc, ⛔ không phải đi xin quản trị viên · ⛔ không có đếm ngược hạn phiên ở phía trình duyệt — màn học rằng phiên hết bằng cách bị máy chủ từ chối.

E-001/5.8 Hạ tầng phiên cho admin-fe — admin-fe

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.10 Vỏ ứng dụng admin-fe — Sidebar và Topbar theo gói design — admin-fe

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.11 Màn người dùng MSB — admin-fe

Màn nghiệp vụ đầu tiên người thật mở được — nhưng phải đọc đúng nó đang ở nhịp nào: đây là giao diện hoàn chỉnh chạy trên dữ liệu mẫu, và màn tự nói ra điều đó.

Người nghiệm thu kiểm được bằng tay:

  1. Vào mục «Tài khoản» từ cây điều hướng ⇒ tới màn danh sách người dùng nội bộ (⛔ không còn trang không tồn tại). Màn có một dòng khai rằng dữ liệu đang hiển thị là dữ liệu mẫu — dòng ấy nằm trong luồng đọc, trình đọc màn hình đọc được, và không trông như thông báo lỗi.
  2. Bảng có đúng BỐN cột: Họ và tên · Thư điện tử · Ngày tạo · Trạng thái. ⛔ Không có Tên đăng nhập, Đơn vị, Vai trò — thiếu là chủ đích (chưa có nguồn dữ liệu), ⛔ không phải sót.
  3. Trạng thái đọc được bằng chữ, ⛔ không chỉ bằng màu, và là bộ từ đóng ba giá trị: Đang hoạt động · Ngưng hoạt động · Chờ duyệt. Hàng «Chờ duyệt» ⛔ không hiện như đã có hiệu lực, và trên màn ⛔ không có nút duyệt nào — duyệt ở màn hàng đợi.
  4. Ô tìm kiếm chỉ hứa tìm theo họ tên hoặc thư điện tử — ⛔ không hứa tìm theo thứ không có (tên đăng nhập, đơn vị). Ô là đích của phím tắt tìm kiếm, và chỉ một ô như thế.
  5. Bấm «Tạo mới» ⇒ biểu mẫu mở trong hộp thoại phủ lên danh sách, tiêu điểm vào tiêu đề hộp. Biểu mẫu có ba ô: Họ và tên · Thư điện tử · Trạng thái. ⛔ Không có ô «Loại tài khoản» — loại suy ra từ màn đang đứng.
  6. Bàn phím trong hộp thoại: Tab từ phần tử cuối quay về phần tử đầu, ⛔ không thoát ra trang sau; trang phía sau ⛔ không nhận thao tác. Esc khi chưa gõ gì ⇒ đóng, tiêu điểm trả về nút «Tạo mới».
  7. Gõ dở rồi đóng (Esc, nút ✕, bấm nền, Huỷ) ⇒ hộp hỏi «Bỏ dữ liệu vừa nhập?» ngay trong hộp. Esc lần nữa là QUAY LẠI NHẬP, dữ liệu còn nguyên — chỉ bấm «Bỏ» mới bỏ. ⚠️ Người viết hướng dẫn ⛔ không được viết «bấm Esc hai lần để đóng».
  8. Bấm gửi ⇒ màn nói lượt gửi chưa nối tới máy chủ, ⛔ không báo đã tạo xong. Đó là đúng thiết kế ở nhịp này.
  9. Ba trạng thái của khung danh sách (đang tải · rỗng · lỗi có đường thử lại) vẫn dùng lại từ E-001/5.5 — kiểm bằng cách tiêm nguồn tương ứng, ⛔ không phải bằng dữ liệu thật.

⚠️ Ba điều người nghiệm thu ⛔ ĐỪNG kết luận vội: «bỏ ô Loại tài khoản» ⛔ không nghĩa là quản trị viên không tạo được tài khoản bên thứ ba — năng lực còn, đi qua quyền, ở màn người dùng bên thứ ba · «bảng chỉ bốn cột» ⛔ không phải AC bị cắt — AC giữ năm cột, ba cột là nợ có điều kiện trả từng cột · «Chờ duyệt» ⛔ không suy được từ dữ liệu người dùng — nguồn là engine phê duyệt, tức trên bản này nó chỉ xuất hiện ở hàng mẫu.

E-001/5.12 Màn vai và quyền theo chức năng — admin-fe

Hai màn mới và một hộp thoại, chạy trên danh mục MẪU và tự nói ra điều đó — cùng nhịp với màn người dùng: giao diện hoàn chỉnh, đường dữ liệu thật chưa có.

Người nghiệm thu kiểm được bằng tay:

  1. Mục «Quyền» ⇒ màn danh mục quyền, năm cột: Tên · Mã · Mô tả · Lớp · Trạng thái. Mã đọc theo khuôn <đối tượng>.<hành động> (ví dụ nguoi-dung.read). Hàng thuộc lớp đặc quyền duyệt mang nhãn «Đặc quyền» bằng chữ, ⛔ không chỉ bằng màu. Màn có một dòng khai rằng danh mục đang hiển thị là mẫu — sinh từ cây điều hướng, ⛔ không phải danh mục thật.
  2. Trên màn Quyền ⛔ KHÔNG có nút Tạo mới, ⛔ không thao tác trên hàng, ⛔ không biểu mẫu quyền — gói design chưa vẽ; thiếu là chủ đích có tên, ⛔ không phải sót.
  3. Mục «Vai trò» ⇒ màn danh sách vai, sáu cột: Tên · Mã · Mô tả · Trạng thái · Ngày tạo · Ngày cập nhật. Trạng thái là bộ từ đóng Đang hoạt động · Ngưng hoạt động · Chờ duyệt; hàng «Chờ duyệt» ⛔ không hiện như đã có hiệu lực. Một ô tìm kiếm, là đích của phím tắt.
  4. Bấm tạo vai ⇒ hộp thoại (cùng bốn hành vi bàn phím như hộp thoại của màn người dùng): Tên vai · Mã vai · Mô tả · Trạng thái · bảng chọn quyền chức năng (có Chọn tất cả, tìm theo tên/mã) · và khối «Đặc quyền duyệt» tách riêng nền cảnh báo, liệt kê đúng những quyền có lớp đặc quyền trong danh mục, kèm câu «Người soạn một hồ sơ không duyệt được chính hồ sơ ấy — hệ thống chặn, không phụ thuộc vào vai».
  5. «Chọn tất cả» ở bảng quyền chức năng ⇒ chọn hết quyền chức năng, ⛔ không quyền đặc quyền nào bị chọn theo.
  6. Ô Mã vai có câu gợi ý hình dạng nhưng ⛔ không chặn — gõ gì cũng gửi được; quy tắc mã do máy chủ phán. ⛔ Đừng kết luận «thiếu kiểm tra».
  7. Nút chính là «Gửi duyệt», ⛔ không phải «Tạo mới» / «Lưu». Gửi thiếu tên hoặc mã ⇒ báo đúng ô thiếu, ⛔ không gửi. Gửi đủ ⇒ màn nói lượt gửi chưa nối tới máy chủ, ⛔ không báo đã tạo, ⛔ không xuất hiện hàng mới.
  8. Ba trạng thái của khung (tải · rỗng · lỗi có thử lại) kiểm bằng cách tiêm nguồn.

⚠️ Bốn điều ⛔ ĐỪNG kỳ vọng ở bản này, vì đều là chủ đích: sửa hay ngưng hoạt động vai · thêm/sửa/ngưng quyền · gán vai cho người dùng (ở màn Tài khoản, và cũng chưa nối) · ẩn/hiện menu, nút theo quyền của người đang đăng nhập — phiên chưa mang dữ liệu vai; thi hành phân quyền là việc của lượt nối E-001/2.4. ⚠️ Và không có «xoá» ở đâu cả — vai và quyền chỉ ngưng hoạt động.

E-001/5.14 Màn hàng đợi chờ duyệt — admin-fe

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

Hệ làm gì, ràng buộc gì — PRD

Mỗi story một mục, phần máy chủ trước, giao diện sau. Story chưa đóng hiển thị tiêu chí dự kiến từ epics.md.

E-001/5.1 Nền token và thành phần cho admin-fe — admin-fe

Nguồn hồ sơ. admin-fe @ origin/main — change đã đóng; hồ sơ bản cuối ở openspec/changes/archive/2026-09-07-ui-tokens-primitives/ (proposal.md · design.md · specs/admin-console-ui/spec.md · tasks.md). Issue OAPI-11-nen-token-va-thanh-phan-cho-admin-fe (thangvv111/admin-fe#3); link.yaml khai docs: khong-can.

Bản thảo này viết từ nhánh origin/ui-tokens-primitives 59b3e86, và change được archive trong lúc viết. Đã đối chiếu bốn tệp proposal · design · spec · tasks giữa 59b3e86 và bản archive: giống hệt ⇒ nội dung dưới đây là hồ sơ bản cuối, không phải bản giữa chừng.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Token là một nguồn duy nhất Mọi màu, thang chữ, khoảng cách, bo góc, bóng khai ở đúng một nơi; mã giao diện tham chiếu theo tên, ⛔ không viết giá trị màu trực tiếp; ⛔ không thêm token màu ngoài bảng của gói Quét src/ thấy mã màu viết thẳng ngoài nơi khai token ⇒ thoát khác 0, nêu tên file. Gọi tên token không tồn tại ⇒ kiểm kiểu thất bại
Năm sửa đổi tương phản cưỡng chế bằng phép đo ink-500 thay ink-400 cho chữ mờ · active đậm hơn một nấc · vòng tiêu điểm ink-900 · chữ trên nền cam là ink-900 · primaryText = #C23D1A Cổng tính tỉ số tương phản từ chính giá trị token, khẳng định từng cặp — ⛔ không tin vào việc giá trị được chép đúng. Đổi chữ trên nền cam về trắng ⇒ cổng đỏ và nêu tỉ số đo được
Cam giữ nguyên vai trò nền Giá trị màu cam nền không đổi so với gói; chỉ màu chữ đặt trên được đổi So token với gói design
Bốn thành phần gói không có Pagination · Textarea · WizardSteps · Field; ⛔ không nhập từ repo front-end khác Phân trang phát số trang 1-gốc, nhận đúng ba tên của hợp đồng API, chặn trang ngoài khoảng · thuật sĩ cho lùi, không cho nhảy tới · Field nối lỗi với ô nhập bằng quan hệ trình đọc màn hình đọc được
Trạng thái không mã hoá chỉ bằng màu Nhãn trạng thái luôn mang chữ; kiểu của thành phần không cho phép tạo nhãn chỉ có màu Tạo nhãn không truyền chữ ⇒ kiểm kiểu thất bại
Chỉ báo tiêu điểm luôn nhìn thấy được Hai lớp, dùng :focus-visible; ⛔ không có khai báo bỏ chỉ báo mà không thay bằng chỉ báo khác Quy tắc kiểu bỏ chỉ báo mặc định không kèm thay thế ⇒ cổng thoát khác 0
Icon nằm trong repo Tham chiếu bằng đường dẫn nội bộ; kết quả dựng không chứa tham chiếu icon ra mạng ngoài Quét kết quả dựng
Hiển thị ngày giờ tách khỏi trao đổi Đọc đúng profile trao đổi, hiển thị ngày–tháng–năm giờ Việt Nam; giá trị sai profile bị từ chối thay vì đoán Hai ca ngược chiều — hợp lệ ⇒ chuỗi đúng thứ tự; sai profile ⇒ báo lỗi, không trả chuỗi nào
Giao diện không dùng biểu tượng cảm xúc ⛔ Không ký tự emoji trong mã giao diện Cổng quét mã nguồn

Quyết định và cái phải trả

  • Token khai bằng biến CSS; TypeScript chỉ ĐỌC TÊN, không chép giá trị. Hai bảng giá trị là hai nguồn, mà gói design mới là nguồn. Một bảng trong repo là đủ; thêm bảng thứ hai chỉ để tiện cho TypeScript là tự tạo chỗ trôi. Kiểu TypeScript vì thế chỉ là union các tên token — gọi sai tên thì tsc đỏ.
  • Năm sửa đổi tương phản đi kèm PHÉP ĐO, không chỉ đi kèm giá trị. Chép năm giá trị mới vào thì dễ; giữ chúng đúng qua nhiều tháng mới khó. Người sau nhìn một token chữ-trên-cam màu mực đậm rất dễ «sửa cho đẹp» thành trắng, và không gì đỏ cả. Nên công thức WCAG nằm trong phép thử: đọc token thật, tính tỉ số, khẳng định từng cặp. Ngưỡng lấy từ bảng đo của gói design:
Cặp Ngưỡng Đo được
ink-900 trên primary #E85431 ≥ 4.5 4.88
ink-900 trên đầu nhạt gradient #F07A45 ≥ 4.5 6.44
primaryText #C23D1A trên primarySoft ≥ 4.5 4.58
primaryText trên trắng ≥ 4.5 5.28
ink-500 trên trắng (nhãn trường) ≥ 4.5 4.76
vòng tiêu điểm ink-900 trên mọi nền của hệ ≥ 3.0
  • Icon viết thẳng thành component TSX trong repo. Không icon font (kéo theo file font thứ hai và vấn đề trợ năng), không một request mỗi icon, không thư viện kéo cả nghìn icon để dùng mươi cái. ⚠️ Bản đầu của quyết định này viết «nhập .svg qua plugin của công cụ dựng» và đã bị BỎ — chính hồ sơ an ninh của change nêu rủi ro thêm một phụ thuộc vào đường dựng, nơi mã của nó chạy với quyền người dựng. Viết thẳng TSX đạt cùng mục tiêu mà không thêm phụ thuộc nào. Cái phải trả, ghi ra để không ai tưởng là bữa trưa miễn phí: thêm icon là viết TSX chứ không thả file vào thư mục, và dữ liệu đường vẽ viết tay không có ai kiểm — không cổng nào so hình vẽ với bản thiết kế.
  • Icon thừa hưởng màu chữ, nhờ đó không bao giờ cần một token màu riêng — và cổng «không mã màu ngoài nơi khai token» không phải mở ngoại lệ nào.

⛔ Cố ý KHÔNG có trong story này

  • Sàn trợ năng đầy đủ — điều hướng bàn phím, vùng sống động, phím tắt — thuộc E-001/5.3. Ở đây chỉ có phần trợ năng dính liền với token: vòng tiêu điểm hai lớp, vì nó là một giá trị màu trong bảng chứ không phải một hành vi.
  • Khung màn danh sách (E-001/5.5); mọi màn hình nghiệp vụ F1F8.
  • portal-feE-001/5.2 đã viết lại riêng (căn cứ lúc đó là AD-13, vế cấm ấy PO bỏ 09/09/2026). Không đụng admin-be: story này không gọi API nào.

E-001/5.3 Sàn trợ năng cho admin-fe — admin-fe

Nguồn hồ sơ. admin-fe @ origin/accessibility-floor 8197a92openspec/changes/accessibility-floor/ (proposal.md · design.md · specs/admin-console-ui/spec.md · tasks.md). Issue OAPI-32-san-tro-nang-cho-admin-fe (thangvv111/admin-fe#7). Change CHƯA đóng ⇒ bản thảo; dấu duyệt ghim sha7 bản cuối.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Mọi hành động làm được bằng chuột đều làm được bằng bàn phím Mỗi phần tử tương tác có tên đọc được không rỗng; phần tử không có chữ nhìn thấy phải mang nhãn chỉ-cho-trình-đọc; ⛔ không chỉ số tiêu điểm dương; Tab lần đầu rơi vào liên kết bỏ qua điều hướng Liệt kê mọi phần tử tương tác đã render, rà từng điều kiện
Thay đổi bất đồng bộ được thông báo đúng một vùng sống động ở tầng ứng dụng, ở mức lịch sự; tiến trình bất đồng bộ báo kết quả ⇒ nội dung vùng đó đổi Rà giao diện đã render + chạy một tiến trình thật
Hai phím tắt của bề mặt quản trị / ngoài ô nhập ⇒ vào ô tìm kiếm · / trong ô nhập ⇒ gõ bình thường, không chuyển tiêu điểm · Esc khi nhiều lớp phủ chồng ⇒ chỉ lớp trên cùng đóng · nhiều hơn một đích tìm kiếm ⇒ báo lỗi, ⛔ không tự chọn Bốn ca, trong đó hai ca là chiều nghịch

Phần đã có, change này chỉ XÁC NHẬN và canh bằng cổng

Ship từ E-001/5.1 (OAPI-11): vòng tiêu điểm hai lớp :focus-visible · Field nối nhãn và các thuộc tính mô tả/không-hợp-lệ/bắt-buộc · Pagination có vùng điều hướng đặt tên và vùng sống động riêng · WizardSteps đánh dấu bước hiện tại · Badge luôn có chữ và chấm · icon có nhãn hoặc được ẩn khỏi trình đọc.

⇒ Giá trị của change này với phần đó không phải viết lại, mà là đặt cổng máy để chúng không trôi mất ở story sau. Đây đúng tinh thần bài học đã trả giá trong epic: «gỡ cơ chế này ra thì ca nào ĐỎ?»

Phần dựng mới — CƠ CHẾ, không phải màn hình

Liên kết bỏ qua điều hướng · vùng sống động ở tầng ứng dụng kèm một API mệnh lệnh để nơi khác gọi (trước đó chỉ Pagination tự có vùng riêng, thay đổi bất đồng bộ nói chung không có chỗ thông báo) · bộ điều phối phím tắt · tiện ích văn bản chỉ-cho-trình-đọc · cổng máy trợ năng.

⛔ Cố ý KHÔNG có trong story này

Không đổi API công khai của bảy thành phần đã có — sàn trợ năng không được là cái cớ để sửa hợp đồng thành phần. Màn hình nghiệp vụ F1F8; khung màn danh sách (E-001/5.5); sàn trợ năng của portal-fe (E-001/5.4, đã viết riêng — căn cứ AD-13 lúc đó, vế cấm nay đã bỏ).

⚠️ Người duyệt cần biết — còn kịp sửa một chỗ

link.yaml của change này đang khai docs: RỖNG. Change chưa đóng, nên đây là chỗ duy nhất trong ngày còn sửa được tại nguồn: khoá đó bỏ trống không được hiểu là «không cần» — docs-gate coi là chưa khai và fail-closed, còn archive thì bất biến (PO chốt 07/09/2026), nên đóng rồi là kẹt vĩnh viễn trong mục [D3]. Bảy change đã rơi vào đó hôm nay.

Quan điểm làn docs: khai docs: khong-can — story này giao cơ chế, không thêm màn hình nào người dùng cuối nhìn thấy. Việc khai thuộc làn admin-fe; làn docs không sửa repo service.

E-001/5.5 Khung màn danh sách cho admin-fe — admin-fe

Nguồn hồ sơ. admin-fe @ origin/mainopenspec/changes/archive/2026-09-08-list-screen-shell/ (proposal.md · design.md · specs/admin-console-ui/spec.md · tasks.md · test-cases.md · security.md), SHA artifact cuối 885fd82. Issue OAPI-46-khung-man-danh-sach (thangvv111/admin-fe#9). Ba quyết định nền lấy từ AD-29 mục 5, 6, 7 (spine 91ee92f). Change đã đóng và archive ngày 08/09/2026 — bản thảo này viết khi change còn mở, đã soát lại theo hồ sơ bản cuối.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Tham số danh sách nằm trên URL và không bao giờ lệch với màn Từ khoá · bộ lọc · cột và chiều sắp xếp · số trang · số dòng mỗi trang đều trên URL. Tham số hỏng ⇒ dùng mặc định VÀ ghi lại URL; lượt ghi đó thay thế mục lịch sử, ⛔ không đẩy mục mới Ca lưới cả hai chiều: nhận đúng từ chối sai; cộng ca «bấm quay lại sau khi URL được sửa»
Bản đồ trạng thái là một nguồn duy nhất Đúng chín từ trạng thái nghiệp vụ → biến thể nhãn, từng cặp khớp bảng trạng thái của tiêu chuẩn giao diện; trục môi trường là bản đồ riêng, ⛔ không trộn; giá trị ngoài bản đồ ⇒ báo lỗi thấy được, ⛔ không rơi xuống mặc định Cổng đếm đủ chín khoá và đối chiếu từng cặp
Màn danh sách phủ đủ bảy trạng thái Bốn cơ bản (đang tải · có dữ liệu · rỗng · lỗi) cộng ba của UX-DR9 (không đủ quyền · mất kết nối · hết phiên). Khung xương chỉ lần tải đầu; tải lại ⇒ giữ dữ liệu cũ và làm mờ. Rỗng ⇒ phân biệt «chưa có dữ liệu» với «lọc không ra kết quả», ca sau có nút xoá lọc. Không đủ quyền ⇒ giải thích trong khung, ⛔ không kết thúc phiên. Hết phiên ⇒ xoá phiên, sang màn đăng nhập, giữ URL đích. Mất kết nối ⇒ tự thử lại tối đa một lầnchỉ thao tác đọc Bảy ca render, mỗi trạng thái một ca; cộng ca «khung xương không hiện ở lần tải lại»
Bảng ⛔ không sắp xếp phía trình duyệt Table nhận trạng thái sắp xếp từ ngoài và phát yêu cầu đổi; ⛔ không đụng thứ tự mảng nó nhận (NFR-010) Cổng quét mã Table, ĐỎ nếu thấy phép sắp xếp
Mỗi màn đúng một ô tìm kiếm là đích phím tắt SearchInput mang data-phim-tat="tim-kiem"; gọi từ ký tự đầu, chờ 300ms sau khi ngừng gõ, Enter gọi ngay; ô rỗng ⇒ danh sách đầy đủ Rà màn đã render: đúng một phần tử mang dấu hiệu
Phím tắt sống trong phạm vi thành phần đang có tiêu điểm SC 2.1.4 giải bằng lối (3) — listener gắn vào container của màn, ⛔ không gắn document; hàm nhận container là tham số bắt buộc, ⛔ không nhánh rơi Ca lưới cả hai chiều (trong vùng ăn · ngoài vùng không ăn), cộng bite gắn ngược về document

Phần dựng mới

Lớp đọc-và-chuẩn-hoá tham số URL (trả hai thứ: giá trị đã chuẩn hoá danh sách tham số bị từ chối) · bản đồ chín trạng thái dưới dạng dữ liệu, không phải nhánh rẽ · bốn thành phần PageHeader, SearchInput, Table, EmptyState (repo trước đó chỉ có Pagination) · bảy trạng thái màn · một màn trình diễn để khung có vật thật · chín cổng máy kèm bảy bite đỏ-trước / xanh-sau chứng minh từng cổng thật sự bắt được.

Cộng react-router 8.3.1phụ thuộc npm đầu tiên thêm vào repo kể từ khi dựng. Bản số đo từ package-lock.json ⛔ không lấy từ package.json (hai thứ lệch nhau khi khoảng bản cho phép trôi). Lượt cài này kích hoạt đường chặn của OAPI-25: nếu gói kéo theo khuyến cáo mức high thì CI của chính lượt này ĐỎ — ⛔ đó là hành vi mong muốn, cách xử là nâng hoặc thay gói, không nới ngưỡng.

⛔ Cố ý KHÔNG có trong story này

Không gọi back-end thật — khung nhận hàm tải dữ liệu tiêm từ ngoài; ⛔ không dựng điểm cuối giả trong repo (nó là thứ sẽ phải xoá, và nó làm cổng «không lời gọi mạng nào trong src/**» mất nghĩa). ⛔ Không dựng màn nghiệp vụ — danh sách người dùng thuộc E-001/5.7, hồ sơ tổ chức thuộc E-004/1.4. ⛔ Không dựng Modal, Toggle, Stepper, InfoField, dải hoàn tác — chúng có chủ khác. ⛔ Không chốt lại quy ước: AD-29 mục 6 khai đây là khuôn tối thiểu và vài chi tiết sẽ phải sửa sau lượt đầu; sửa thì đề nghị ở spine, không sửa trong change.

⚠️ Người duyệt cần biết — hai chỗ

1. Một chênh ĐÃ ĐO giữa hai văn bản — và nguồn đã XOÁ chênh đó đi sau khi bản thảo này viết. Lúc thi công, hợp đồng trải nghiệm mô tả ca hết phiên bằng một hộp đăng nhập lại chồng lên màn để giữ nội dung đang nhập; AD-29 mục 7 (PO chốt 08/09/2026) nói chuyển sang màn đăng nhập, giữ URL đích. Change theo spine vì nó mới hơn và là văn bản ràng buộc — và lựa chọn đó nay đúng hẳn: ngày 09/09/2026 PO bỏ bộ artifact UX, gộp tiêu chuẩn giao diện về một nguồn (docs/style.md), và chính chênh này được nêu đích danh là lý do phải gộp.

⇒ ⛔ Người duyệt không cần đi tìm văn bản kia nữa: nó không còn tồn tại. Story có biểu mẫu dài (E-004/1.4) vì thế cũng không còn phải hỏi lại — chỉ còn một nguồn để theo.

2. Khoá docs: đã được khai trước khi đóng — story này ⛔ KHÔNG rơi vào mục change thiếu khoá. Bản thảo lúc change còn mở ghi khoá đang bỏ trống; làn admin-fe đã điền trước khi archive, trỏ huong-dan-admin/man-danh-sach.md — đúng quy ước thư mục của repo docs.

⚠️ Nhưng trang đó chưa viết được, và người duyệt nên biết vì sao. Story giao khung cộng một màn trình diễn chạy nguồn giả; màn nghiệp vụ thật đầu tiên nằm ở E-001/5.7. Trang hướng dẫn phải bám UI thật, nên nó chờ tới khi có màn — cùng nếp PO chốt 08/09/2026 cho trang nhật ký hệ thống: nghĩa vụ đã khai thì để nguyên trong sổ, không xoá cho gọn sổ.

E-001/5.7 Màn đăng nhập admin-fe — admin-fe

Nguồn hồ sơ. Story này giao bằng hai change:

  • admin-fe @ origin/mainopenspec/changes/archive/2026-09-10-man-dang-nhap/, issue OAPI-101-man-dang-nhap-admin-fe (thangvv111/admin-fe#14). Đã đóng — giao màn.
  • admin-fe @ origin/cam-cong-phien-vao-api da9557dopenspec/changes/cam-cong-phien-vao-api/, issue OAPI-108-cam-dang-nhap-vao-api-that (thangvv111/admin-fe#17). CHƯA đóng — trả nợ cắm đường thật.

⇒ Phần dưới mô tả story khi cả hai nhịp xong; chỗ nào chỉ đúng sau nhịp hai thì nói rõ.

Yêu cầu và cách đo — nhịp hai

Yêu cầu Ràng buộc Đo bằng
Hỏi máy chủ về phiên trước khi quyết định render Tải lại địa chỉ thuộc phiên ⇒ còn phiên thì giữ nguyên màn, hết phiên thì về đăng nhập giữ đích quay về. ⛔ Lượt hỏi không tới được máy chủ ⇒ xử như không có phiên, ⛔ không bày vỏ ứng dụng Ba ca render; cộng ca đi nhiều màn ⇒ ⛔ không phát thêm lượt hỏi nào
Lời gọi ra máy chủ đi qua đúng một mô-đun Mô-đun vận chuyển là tệp duy nhất gọi mạng, và nó ⛔ không mang lược đồ, tên máy hay số cổng — mọi đường là đường tương đối dưới tiền tố API. Đưa vào một đường mang tên máy ⇒ mô-đun từ chối phát ⛔ Cổng cũ «không tệp nào gọi mạng» được SIẾT thành «đúng một tệp» — ⛔ không nới
Năng lực chưa có đường thật phải nói ra, ⛔ không giả lập Gửi biểu mẫu của thao tác chưa có đường ⇒ màn cho biết đường chưa mở, ⛔ không treo im lặng, ⛔ không báo lỗi kỹ thuật; phần còn lại của màn vẫn dùng được Ca render một màn có năng lực chưa mở
Kết thúc phiên theo ý người dùng Đăng xuất ⇒ báo máy chủ, xoá dữ liệu phía trình duyệt, về màn đăng nhập. Mất mạng ⇒ vẫn xoá và vẫn về, kèm cho biết chưa chắc thu hồi được. Phiên đã đóng từ trước ⇒ về màn đăng nhập ⛔ không kèm cảnh báo Ba ca, trong đó hai ca là đường hỏng
Đổi mật khẩu trong phiên Chính sách đọc được ⇒ hiện trước khi người dùng gõ; đọc ⛔ không được ⇒ màn vẫn dùng được, vi phạm nói rõ sau khi gửi. Đổi xong ⇒ cho biết các phiên khác còn hiệu lực hay không ⚠️ Máy chủ ⛔ chưa có đường đổi mật khẩu ⇒ nhánh đang chạy là ca «chưa mở»
Màn đăng nhập ⛔ không tự gọi ra ngoài Màn nhận hàm từ ngoài; ⛔ không tự dựng lời gọi Rà mã của màn

⛔ Cố ý KHÔNG có trong story này

Không dựng điểm cuối giả để lấp chỗ — hợp đồng máy chủ ⛔ không có đường cho đổi mật khẩu và đọc chính sách, nên hai hàm ấy khai chưa có và màn nói ra. ⛔ Không đếm ngược, ⛔ không đoán hạn phiên ở phía trình duyệt — màn học bằng lượt bị từ chối. ⛔ Không thêm cờ gửi kèm thông tin đăng nhập hay cờ gọi chéo nguồn: cùng-origin qua proxy thì trình duyệt tự gửi, thêm hai cờ ấy là che đúng loại lỗi vừa vá. ⛔ Không đưa mã người dùng, vai hay quyền vào danh tính của vỏ — vỏ ⛔ không được là nơi thứ hai quyết định chuyện quyền. ⛔ Không vẽ lại giao diện.

⚠️ Người duyệt cần biết — bốn chỗ

1. ⛔ BA tên trang hướng dẫn cho CÙNG một chủ đề — đây là lỗi đang lớn dần. Ba change khai ba đường dẫn khác nhau: huong-dan-admin/dang-nhap-va-tai-khoan.md (OAPI-101, đã archive) · huong-dan-admin/quan-tri-he-thong/nguoi-dung.md (OAPI-109 của admin-be, đã archive) · huong-dan-admin/dang-nhap-va-phien.md (OAPI-108, change còn mở). Theo hệ đặt tên PO chốt 10/09/2026 — tên theo nhóm nghiệp vụ của epic, khai docs: phải trỏ tên đã có trong khung — thì trang đúng là quan-tri-he-thong/nguoi-dung.md. ⇒ OAPI-108 còn sửa được tại nguồn; hai change kia đã archive nên là lỗ. Nếu không thống nhất, một chủ đề sẽ có ba trang rỗng.

2. Bản trên nhánh chính hôm nay vẫn CHƯA đăng nhập được. Đo 11/09/2026: src/** của origin/main0 lời gọi mạng, và nguồn phiên vẫn là tệp giả. Nợ OAPI-108 còn mở. ⇒ Mọi câu mô tả thao tác đăng nhập chỉ đúng sau khi nhánh kia merge.

3. Một cổng máy được SIẾT chứ không được nới — đáng ghi nhận. Khi phải thêm lời gọi mạng đầu tiên, đường dễ là nới cổng «không tệp nào gọi mạng» cho rộng ra. Change không làm vậy: nó đổi cổng thành «đúng một tệp, và tệp ấy không được mang tên máy». Cổng sau chặt hơn cổng trước.

4. Đổi mật khẩu là năng lực CHƯA CÓ ở máy chủ, không phải chưa làm ở giao diện. Trang hướng dẫn ⛔ không được mô tả thao tác đổi mật khẩu như một việc làm được — màn hiện có nói «chưa mở», và đó là trạng thái đúng cho tới khi có story máy chủ.

E-001/5.8 Hạ tầng phiên cho admin-fe — admin-fe

Chờ hồ sơ. Tiêu chí dự kiến từ kế hoạch:

  • Đăng xuất: gọi cổng phiên, xoá trạng thái phía client, đưa về màn đăng nhập — không để lại dữ liệu màn cũ trong bộ nhớ ứng dụng.
  • Đổi mật khẩu trong phiên: biểu mẫu riêng, không dùng lại luồng đăng nhập; đúng AdminChangePasswordModal của gói design.
  • Trang 404403 toàn mànUX-DR9 chốt «không đủ quyền» xử ở màn đích, không ẩn lặng.
  • Cổng phiên gom một chỗ để lúc nối E-001/2.3 chỉ phải sửa một nơi; E-001/5.10 gọi đúng cổng này cho hành động đăng xuất trên Topbar.
  • ⚠️ Story archive trước Đ:E-001/5.7Đ:E-001/2.3 nên check-thu-tu.sh báo XANH GIẢ — đó là trạng thái đã biết, không phải lỗi mới.

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.10 Vỏ ứng dụng admin-fe — Sidebar và Topbar theo gói design — admin-fe

Chờ hồ sơ. Tiêu chí dự kiến từ kế hoạch:

  • Sidebar trắng cố định 228px: logo trên cùng, nhóm menu có nhãn 12px in hoa, mục đang mở nền #FAECE8 chữ cam kèm thanh chỉ báo, nút Thu gọn ở chân — đúng design/components/navigation/Sidebar.jsx.
  • Topbar: breadcrumb theo tuyến hiện tại, chọn ngôn ngữ, avatar hai chữ cái nền cam nhạt có hành động đăng xuất gọi cổng phiên của E-001/5.8.
  • Danh sách mục điều hướng tiêm từ ngoài (nếp D1 của 5.5): vỏ không biết miền nghiệp vụ nào; ẩn mục không có quyền là dữ liệu đầu vào, không phải logic của vỏ (UX-DR9 «không đủ quyền» vẫn xử ở màn đích).
  • Thay thanh nav giữ chỗ của màn trình diễn trong App.tsx; AdminLogin vẫn là nhánh chưa xác thực, Sidebar/Topbar chỉ ở nhánh đã xác thực.
  • Điều hướng bàn phím đầy đủ, phím tắt / mở tìm kiếm (UX-DR3); icon tự host, ghim phiên bản (UX-DR10, AD-23).

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.11 Màn người dùng MSB — admin-fe

Nguồn hồ sơ. admin-fe @ origin/main e8a0816openspec/changes/archive/2026-09-11-man-nguoi-dung-msb/ (proposal.md · design.md · specs/admin-console-ui/spec.md · tasks.md · test-cases.md · security.md · review.md · docs.md · uat.md). Issue OAPI-140-man-nguoi-dung-msb (thangvv111/admin-fe#25). Change ĐÃ đóng (archive 11/09/2026) ⇒ đây là bản cuối; sha7 cho dấu duyệt lấy bằng docs-gate.sh sha man-nguoi-dung-msb ở repo admin-fe.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Màn danh sách người dùng nội bộ trên khung chung Dùng khung màn danh sách (E-001/5.5) và vỏ (E-001/5.10); bảy trạng thái của khung dùng lại, ⛔ không dựng lại Ca tiêm nguồn: có dữ liệu · rỗng (nói rõ chưa có, ⛔ không bảng trống câm) · lỗi (có đường thử lại)
Bốn cột, ⛔ không cột nào thiếu nguồn thật Họ và tên (ho_ten) · Thư điện tử (email) · Ngày tạo (created_at, PO thêm 11/09) · Trạng thái (disabled_at + engine duyệt). ⛔ Không Tên đăng nhập, Đơn vị (bảng không có cột), ⛔ không Vai trò (E-001/2.4 chưa mở) — một cột không nguồn là chỗ chờ người ta điền dữ liệu bịa Đếm cột trên màn = 4; ⛔ không cột ngoài bốn trường
Trạng thái là bộ từ đóng ba giá trị, ⛔ không mã hoá chỉ bằng màu Đang hoạt động · Ngưng hoạt động · Chờ duyệt. Hàng có yêu cầu tạo/vô hiệu/mở lại đang chờ ⇒ Chờ duyệt, ⛔ không hiện như đã có hiệu lực; màn ⛔ không có thao tác duyệt Hàng chờ duyệt ghi «chờ duyệt» bằng chữ; ⛔ không nút duyệt
Một ô tìm kiếm, chỉ hứa thứ có thật Ô mang dấu hiệu đích phím tắt, đúng một ô; placeholder «tìm theo họ tên hoặc thư điện tử» — ⛔ không «username», ⛔ không «đơn vị» Đếm phần tử mang dấu hiệu = 1
Loại tài khoản đến từ màn, ⛔ không từ ô trong biểu mẫu Bỏ ô «Loại tài khoản» của gói; màn nội bộ tạo nội bộ, màn bên thứ ba (E-004/1.9) tạo bên thứ ba ⇒ biểu mẫu có một bộ ràng buộc Mở biểu mẫu từ màn này ⇒ ⛔ không ô chọn loại; ⛔ không ô nào đổi nghĩa theo lựa chọn khác
Biểu mẫu tạo mở trong hộp thoại với bốn hành vi Esc đóng · tiêu điểm ⛔ không rời hộp, trang sau inert · đóng ⇒ tiêu điểm về phần tử đã mở · có dữ liệu chưa gửi ⇒ hỏi trước khi đóng; bấm nền đi cùng đường với Esc; đang hỏi mà yêu cầu đóng nữa ⇒ huỷ câu hỏi, dữ liệu còn nguyên; hộp là dialog có tên với công nghệ trợ giúp Tab từ cuối ⇒ về đầu; Esc chưa gõ ⇒ đóng + tiêu điểm về nút mở; gõ rồi Esc ⇒ hỏi; Esc lần nữa ⇒ về ô đang nhập, dữ liệu nguyên
Màn chạy trên dữ liệu mẫu phải tự khai Chưa có đường lấy dữ liệu thật ⇒ màn nói rõ đang là dữ liệu mẫu; lời khai đọc được bằng trợ giúp, trong luồng đọc, ⛔ không nhầm với lỗi. Thao tác ghi chưa có đường ⇒ ⛔ không báo thành công Mở màn ⇒ có lời khai; gửi biểu mẫu ⇒ «chưa nối tới máy chủ», ⛔ không «đã tạo»
Gửi khi đã có đường ghi (hợp đồng cho lượt nối) Thành công ⇒ đóng hộp mà ⛔ không hỏi bỏ dữ liệu; từ chối ⇒ báo không gửi được, giữ dữ liệu, ⛔ không lộ chi tiết máy chủ; ⛔ không gửi đôi, ⛔ không đóng giữa lúc gửi Ca với hàm gửi tiêm: thành công / từ chối / đang gửi

⛔ Cố ý KHÔNG có trong story này

Không gán vaiE-001/5.12, và gán vai phải qua phê duyệt (FR-004). ⛔ Không màn người dùng bên thứ ba — E-004/1.9. ⛔ Không dựng điểm cuối giả dưới bất kỳ hình thức nào. ⛔ Không tự vẽ bề mặt gói chưa có. ⛔ Không dựng sẵn nhánh biểu mẫu cho bên thứ ba. ⛔ Không nút duyệt trên hàng — E-001/5.14. ⛔ Không dọn shared/lib, ⛔ không tách App.tsx (OAPI-139 — lượt này chỉ trả một phần ba: dựng src/features/).

⚠️ Người duyệt cần biết — sáu chỗ

1. Đây là giao diện hoàn chỉnh chạy trên DỮ LIỆU MẪU — và điều đó là thiết kế, ⛔ không phải nửa vời. Hai điểm cuối phía admin-be (liệt kê, tạo) chưa tồn tại (đo openapi.yaml: bốn đường, ba đường phiên và một đường di trú). Lộ trình §F cho đi tiếp với ba điều kiện — nguồn tiêm từ ngoài, //TODO đúng chỗ, màn tự khai — và change làm đủ ba. Một bảng người dùng trông như thật trên dữ liệu mẫu tệ hơn bảng rỗng: người vận hành sẽ đếm bảy tài khoản mẫu thành bảy tài khoản thật. ⚠️ Trang hướng dẫn ⛔ không được chụp màn này rồi gọi là «danh sách người dùng của bạn».

2. «Tạo tài khoản» vướng thứ NẶNG hơn thiếu đường HTTP. Vai ứng dụng của admin-be chỉ đọc bảng băm mật khẩu — ⛔ không đường nào trong mã sản xuất đặt mật khẩu. Tức «tạo tài khoản» ⛔ không thể là một POST thẳng; nó cần cơ chế đặt mật khẩu ban đầu (thư mời, mã một lần, hay vai riêng) mà chưa ai thiết kế. PO chốt 11/09: giao diện dựng trước, cơ chế do admin-be đề xuất (OAPI-98), phần nối là nợ OAPI-145. §F ⛔ không cho đi tắt qua đây — nó áp cho chức năng và mắt xích ngoài, ⛔ không áp cho cách ghi dữ liệu và vết.

3. Ba cột bị gỡ là NỢ, ⛔ không phải cắt phạm vi — và bản đầu của change viết ngược. Số đo đúng (bảng không có username/don_vi, quét 0 kết quả), nhưng bước từ «dữ liệu không tồn tại» sang «⇒ không phải nợ» là quyết định phạm vi, thuộc PO. PO chốt: AC giữ năm cột, lượt đầu tạm bỏ ba, nợ OAPI-142 với điều kiện trả riêng từng cột. Khác án lệ E-001/5.7 (đơn vị bị bỏ hẳn vì AC không đòi): ở đây AC đòi nên hoãn, ⛔ không bỏ. Thứ phân biệt hai kết cục là AC, ⛔ không phải số đo.

4. Chỗ dễ đọc nhầm nhất: bỏ ô «Loại tài khoản» ⛔ KHÔNG phải bỏ năng lực tạo tài khoản bên thứ ba. PO nguyên văn: «Design thì dùng nhưng logic thì không theo. Admin / người dùng tạo tài khoản TPP khi được cấp quyền.» Năng lực giữ; thứ đổi là chỗ chọn: từ một trường dữ liệu sang ngữ cảnh màn. Lý do kỹ thuật: một biểu mẫu hai nhánh có hai bộ ràng buộc và một nút gửi — phép kiểm phải hỏi «nhánh nào» trước khi hỏi «hợp lệ không», đó là chỗ một nhánh im lặng đi lọt; và quyền tạo hai loại là hai quyền khác nhau, tách theo màn thì quyền quyết ở tầng tuyến trước khi biểu mẫu hiện. PO khai sẽ báo CCS sửa gói.

5. Hộp thoại đầu tiên của trang quản trị — và bốn hành vi của nó là bề mặt trợ năng, ⛔ không phải một cái hộp. Bản đầu mở biểu mẫu tại chỗ để né dựng thành phần dùng chung ngoài task; PO chốt 11/09 «dựng Modal, làm giống design». Sau lens review, bốn chỗ hở đã vá: Esc/✕/nền lần nữa khi đang hỏi là huỷ câu hỏi (bản đầu: Esc giữ phím = mất sạch dữ liệu) · trang sau inert + khoá cuộn · bấm nền chỉ đóng khi nhấn thả đều ở nền (bôi chọn chữ ⛔ đóng) · đổi ô Trạng thái tính là «có thay đổi». ⚠️ Hướng dẫn phải tả đúng: Esc lần nữa là quay lại nhập, ⛔ không «bấm Esc hai lần để đóng».

6. Trạng thái «Chờ duyệt» trả ngay trong change, nhưng nguồn của nó chưa có. PO chốt 11/09 tối: tạo · vô hiệu · mở lại người dùng nội bộ đều qua duyệt ⇒ màn mang trạng thái chờ trên hàng, ⛔ không nút duyệt. Làn chọn trả ngay (rẻ hơn mở nợ: một giá trị vào bộ từ đóng, một hàng mẫu, một ca thử). Nhưng cho-duyet ⛔ không suy được từ disabled_at — nguồn là engine phê duyệt qua đường liệt kê E-001/2.6, đã ghi vào nợ OAPI-145. Biểu mẫu tạo vẫn gửi «đang hoạt động» (thứ maker yêu cầu); trạng thái chờ do máy chủ gán.

Nợ mở khi đóng change: OAPI-141 (admin-be: API + createdAt + trạng thái chờ) · OAPI-142 (ba cột AC) · OAPI-145 (nối API danh sách + tạo; cơ chế mật khẩu ban đầu, chủ OAPI-98) · OAPI-66 (khung: cột ⛔ sắp được lên URL). Cổng review độc lập ⛔ không qua (axes-gate rc 0 — không chạm trục nhạy cảm); lens review 11/09 @ 0cab81f: 27 vá, 2 hoãn, 1 bác.

E-001/5.12 Màn vai và quyền theo chức năng — admin-fe

Nguồn hồ sơ. admin-fe @ origin/man-vai-va-quyen 1f4576copenspec/changes/man-vai-va-quyen/ (proposal.md · design.md · specs/admin-console-ui/spec.md · tasks.md · test-cases.md · security.md · review.md · docs.md · uat.md). Issue OAPI-162-man-vai-va-quyen (thangvv111/admin-fe#28). Gói design đo @ platform 61494f7 (RoleList · PermissionList · RoleCreateModal · APPROVAL_PERMS). Change CHƯA thi công ⇒ bản thảo; cổng docs-gate phe-duyetadmin-fe đang ở mức block ⇒ thi công chỉ bắt đầu sau khi trang này được duyệt đúng SHA artifact.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Màn danh mục quyền — quyền là dữ liệu cấu hình được Năm cột: Tên · Mã (<đối tượng>.<hành động>, dẫn xuất, ⛔ lưu riêng) · Mô tả · Lớp (chức năng / đặc quyền duyệt) · Trạng thái. Hình dạng theo PO chốt cho E-001/2.4 (doi_tuong · hanh_dong · ten · mo_ta · lop · trang_thai, UNIQUE(doi_tuong, hanh_dong)); ⛔ không theo permRows của gói (chép từ ảnh SIT cũ). Nguồn mẫu sinh từ 13 mục điều hướng × 4 hành động chuẩn + 6 đặc quyền đúng gói; màn tự khai là mẫu Đếm cột = 5; hàng lớp đặc quyền có nhãn «Đặc quyền» bằng chữ; rỗng/lỗi nói rõ
Màn danh sách vai Sáu cột: Tên · Mã · Mô tả · Trạng thái · Ngày tạo · Ngày cập nhật; đúng một ô tìm kiếm mang dấu hiệu phím tắt; vai có yêu cầu chờ ⇒ «Chờ duyệt», ⛔ không «Đang hoạt động» Đếm cột = 6; đếm ô phím tắt = 1
Biểu mẫu tạo vai trong hộp thoại, khối đặc quyền tách riêng, SINH từ dữ liệu Dùng Modal của 5.11 (bốn hành vi). Tên · Mã · Mô tả · Trạng thái · bảng quyền chức năng phẳng (giữ bố cục gói) · khối đặc quyền lọc từ danh mục theo lop === 'dac-quyen', ⛔ không gõ cứng 6 quyền như gói — quyền duyệt cấu hình sau phải tự xuất hiện. Khối mang câu về K3 viết theo UX-DR7 Mở hộp ⇒ khối đặc quyền = đúng tập quyền có lớp đặc quyền trong nguồn tiêm; «Chọn tất cả» ⛔ không kéo theo đặc quyền
⛔ Biểu mẫu không kiểm hình dạng mã vai Helper của gói (in hoa, số, _, ., ≤ 64) là luật hình dạng của máy chủ — giao diện ⛔ mang bản sao (⛔ regex, ⛔ số 64); giữ câu gợi ý, máy chủ (2.4) phán Gõ mã sai khuôn ⇒ vẫn gửi được
Nút gửi là «Gửi duyệt» FR-004 · AD-9: tạo vai, đổi tập quyền, gán vai đều là yêu cầu phê duyệt ⇒ lượt gửi ⛔ bao giờ «tạo xong», kể cả khi có API; sau máy chủ nhận ⇒ hàng «Chờ duyệt». Gửi thiếu tên/mã ⇒ báo đúng ô, ⛔ gửi Nhãn nút; ca gửi thiếu ô
Điểm cuối chưa có ⇒ §F, nếp 5.11 tai_vai · tai_quyen · gui_vai tiêm từ ngoài; vắng ⇒ nguồn mẫu + lời tự khai role="status"; gửi ⇒ tự khai chưa nối, ⛔ báo đã tạo; // TODO(OAPI-<nợ>) tại prop. Nợ nối mở khi đóng change, điều kiện trả: 2.4 archive Gửi biểu mẫu ⇒ «chưa nối», ⛔ «đã tạo»
Bộ từ và badge theo luật chung UX-DR7 bộ từ đóng; UX-DR6 badge qua bản đồ, badge Đặc quyền = biến thể cảnh báo ⛔ chấm; UX-DR9 bảy trạng thái khung dùng lại; UX-DR13 biểu mẫu là hộp thoại Ca khung: tải · rỗng · lỗi

⛔ Cố ý KHÔNG có trong story này

Không thi hành phân quyền ở giao diện (ẩn menu/nút theo quyền, kiểm quyền ở tầng tuyến) — phiên chưa mang vai; thuộc lượt nối E-001/2.4. ⛔ Không biểu mẫu thêm/sửa/ngưng quyền, ⛔ không sửa/ngưng vai, ⛔ không gán vai — gói chưa vẽ (bản kê 7 mục PO đã gửi CCS); là tạm bỏ có tên, cùng khuôn OAPI-142, ⛔ không phải cắt phạm vi; gán vai còn thuộc màn Tài khoản chứ ⛔ không phải màn này. ⛔ Không dựng điểm cuối giả; ⛔ không bịa danh mục là thật. ⛔ Không màn hàng đợi (5.14). ⛔ Không «xoá» vai hay quyền ở bất kỳ đâu (AD-11). ⛔ Không đụng OAPI-139.

⚠️ Người duyệt cần biết — năm chỗ

1. «Ma trận quyền» của admin-be (E-001/1.2) ⛔ KHÔNG phải RBAC người dùng — đừng nhầm hai thứ. Ma trận ấy là quyền của tiến trình admin_app trên bảng CSDL. Story này là quyền của người trên chức năng; admin-be origin/main @ 26cbbf6 chưa có bảng role/permission/user_role lẫn đường API — E-001/2.4 chưa mở issue. ⇒ Mọi thứ trên màn là mẫu cho tới khi 2.4 lên.

2. Hai cột gói chưa vẽ được thêm vào — có nguồn, và có lý do K3. Gói vẽ danh mục quyền ba cột; PO chốt quyền có loptrang_thai. Thêm cột Lớp là để lộ đặc quyền duyệt đúng như K3 đòi; thêm bằng thành phần có sẵn (Badge), ⛔ không vẽ hình học mới. Bản kê đã xin CCS bản vẽ chính thức; nếu gói sau này bỏ cột Lớp thì đó là câu hỏi cho PO, ⛔ không theo gói mù (Open Question 1).

3. Khối đặc quyền của gói GÕ CỨNG 6 quyền — change cố ý ⛔ không theo. Vì quyền là dữ liệu, khối phải lọc từ danh mục theo lớp; một quyền duyệt cấu hình sau phải tự xuất hiện. Đây là chỗ một lượt «dựng đúng theo gói» sẽ tạo ra danh sách chết. Câu «Nguyên tắc bốn mắt» của gói giữ vì khớp nghiệp vụ đã chốt (K3/AD-9), viết lại theo UX-DR7: hệ thống chặn, không phụ thuộc vào vai — quyền duyệt chỉ quyết định ai được duyệt.

4. Hai chỗ ngôn ngữ mà style.md thắng gói, người duyệt xác nhận khi review màn. Nút «Gửi duyệt» thay «Tạo mới» (Open Question 2) — vì lượt gửi là yêu cầu phê duyệt, không phải tạo. Và ô Mã vai ⛔ không kiểm khuôn — AGENTS.md cấm giao diện mang bản sao luật máy chủ; câu gợi ý ⛔ phải phép kiểm.

5. Trục nhạy cảm T_authz khai [N/A] — có lý do, và người duyệt nên thấy nó hợp lý. Change ⛔ thi hành phân quyền nào: không ẩn menu theo quyền, không kiểm ở tầng tuyến, không gán vai. Nó chỉ hiển thị danh mục mẫu và một biểu mẫu chưa nối. Cái chạm thật tới T_authz là lượt nối 2.4. ⚠️ Trang hướng dẫn: nói khuôn mã quyền, ⛔ liệt kê danh mục (do người quản trị cấu hình); ⛔ chụp màn rồi gọi là danh mục thật; ⛔ mô tả tạo vai như «bấm Lưu là có hiệu lực».

E-001/5.14 Màn hàng đợi chờ duyệt — admin-fe

Chờ hồ sơ. Tiêu chí dự kiến từ kế hoạch:

  • Hình theo gói design/HANDOFF.md §«Hàng đợi chờ duyệt dùng chung»: một màn chung cho mọi loại, ⛔ không mỗi loại một màn/tab. Danh sách: pill trạng thái (Chờ duyệt mặc định · Đã duyệt · Từ chối · Tất cả, kèm số đếm) · ô tìm + select loại có số đếm · bảng 8 cột (chọn · Mã · Đối tượng · Nội dung · Hành động · Người gửi · Thời gian · Trạng thái) · nhãn «Yêu cầu của bạn». Chi tiết: stepper 3 bước · 5 InfoField (Loại · Đối tượng · Hành động · Người gửi · Ảnh hưởng) · khối Trước → Sau hai cột với dòng thêm/bỏ/đổi · nút Từ chối (bắt buộc lý do) · Phê duyệt · «Duyệt và sang kế tiếp». Màn riêng có URL; điều hướng theo docs/style.md §3 (PO chốt 13/09 chọn B): một mục cấp cao «Hàng đợi chờ duyệt» + huy hiệu đếm, sau Trang chủ, ⛔ không tạo nhóm «Phê duyệt» như gói.
  • Loại đối tượng KHÔNG lấy từ gói (gói không phải nguồn nghiệp vụ). Gói vẽ 8 loại; GĐ1 chỉ có loại có nguồn thật: hồ sơ tổ chức (E-004/1.3) · yêu cầu đăng ký sản phẩm (E-005, khi có) · cấu hình luồng phê duyệt (E-001/3.2). ⛔ Không: vai trò · quyền · gán vai · tài khoản nội bộ — PO chốt 12/09 (K3 lệch có chủ ý cho bốn thao tác phân quyền, docs/backlog-tuan-thu.md §2; hàng 3.3) và nhắc lại 13/09. Bộ lọc loại chỉ liệt loại có nguồn; ⛔ không hiện loại rỗng giả. Loại mới = một dòng danh mục + module nộp before/after — không thêm màn.
  • Nguồn dữ liệu = API E-001/3.3 (M:): hợp đồng một yêu cầu theo khuôn gói (id · kind · target/targetCode · action · by/at · impact · title · before[]/after[]); hình dạng do 3.3 chốtopenapi.yaml của admin-be, màn phản ánh, ⛔ không tự bịa trường. Chưa có API ⇒ đi trước bằng port + màn giữ chỗ theo tiền lệ 5.12/5.9, nối là nợ có tên.
  • K3 (⛔R3): người tạo yêu cầu ⛔ không thấy nút duyệt của chính mình — engine 3.1 thi hành, màn chỉ phản ánh (hộp đỏ theo gói, hai nút vô hiệu, nội dung vẫn đọc). ⛔ Không dựng đường «tự duyệt» của gói (hộp vàng super admin): K3 chỉ lệch cho bốn thao tác phân quyền, mà chúng ⛔ không đi qua hàng đợi ⇒ không có ca nào cần nó; «PO chốt» trong gói là giả định của CCS. Mục «Hàng đợi chờ duyệt» chỉ render khi tài khoản có bất kỳ đặc quyền <đối tượng>.approve (sổ ánh xạ loại → đặc quyền là việc của 3.3).
  • Duyệt hàng loạt (khoá cùng loại, ẩn «chọn tất cả» khi lọc Tất cả) chỉ khi API 3.3 có thao tác hàng loạt; không có thì không vẽ nút — ⛔ không tự lặp gọi đơn.
  • Bảng rộng: responsive theo điều kiện đo được ở docs/style.md §8.4 (min-width: 1240px của gói là giá trị hình, không phải điều kiện). Sàn trợ năng UX-DR2/UX-DR3.
  • Xong = change archive với ca hành vi cho: lọc theo loại chỉ có loại GĐ1 · người tạo không duyệt được yêu cầu của mình · từ chối không lý do bị chặn · bấm hàng tới đúng màn đối tượng; ca UAT E-001/5.14; trang hướng dẫn huong-dan-admin/ khai ở docs:.

⟨CẦN NGƯỜI VIẾT — agent làn admin-fe viết khi đóng change⟩

E-001/5.2 Nền token và thành phần cho portal-fe — portal-fe

Nguồn hồ sơ. portal-fe @ origin/main — story này có HAI change, cả hai đã đóng: openspec/changes/archive/2026-09-07-nen-token-va-thanh-phan/ (chính) và .../2026-09-07-keo-goi-design-2026-09-07/ (kéo gói design). Cả hai khai docs: khong-can.

⚠️ Bản thảo này viết sau khi change đã archive, không phải song song thi công: change rời [D1] của làn docs ngay khi đóng, nên trang vẫn còn mốc mà không còn xuất hiện trong danh sách việc. Xem mục cuối.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Token là nguồn duy nhất của màu, chữ, khoảng cách ⛔ Không mã màu viết trực tiếp ngoài token; token chép vào repo và ghim phiên bản, không tham chiếu ra ngoài Quét toàn bộ mã thành phần · dựng trong môi trường KHÔNG có thư mục gói design vẫn thành công và đúng màu
Nút chính đọc được Tương phản chữ/nền cam đạt WCAG AA cho chữ thường, và chữ KHÔNG phải màu trắng Đo từ chính giá trị token
Bộ thành phần kiểm kiểu tĩnh đầy đủ Lệnh kiểm kiểu phủ toàn bộ mã thành phần Truyền giá trị sai kiểu ⇒ cổng thoát khác 0 (đo hai chiều)
Icon không phụ thuộc mạng ngoài SVG nội tuyến, tự host, ghim phiên bản Phục vụ trong môi trường không ra Internet: không ô trống, không tài nguyên hỏng
Hiển thị tách khỏi trao đổi Mốc đúng định dạng ⇒ hiện theo quy tắc hiển thị; mốc sai định dạngdấu hiệu thiếu dữ liệu, ⛔ không ném lỗi, ⛔ không chuỗi rác Hai ca ngược chiều
Ngân sách gói tĩnh có cổng máy Vượt ngưỡng + biên độ ⇒ thoát khác 0 và nêu số đo thật cùng ngưỡng; trong ngưỡng ⇒ thoát 0 và in số đo AD-29 mục 3 giao đích danh story này

Quyết định và cái phải trả

  • Chép 19 thành phần của gói vào repo và chuyển .jsx.tsx. Giữ .jsx là mở một lỗ trong cổng kiểu tĩnh mà AD-24 bắt buộc — cổng có mà thủng một mảng thì tệ hơn cổng không có, vì nó mua sự yên tâm.
  • Sửa lỗi tương phản của gói NGAY LÚC CHÉP, không hoãn. Bản trong repo đọc token thay vì màu cứng. Đã báo ngược lên gói. Cái phải trả: bản repo và bản gói lệch nhau ở một điểm cho tới khi gói sửa — lệch có chủ đích, đã ghi, không phải trôi.
  • Hai chỗ màu cứng được GIỮ, kèm miễn trừ ghi lý do trong cổng (viền danger, bóng Toggle) — gói không có token tương ứng. ⛔ Không im lặng bỏ qua, và cũng không bịa token mới: UX-DR11 cấm tự thêm token màu ngoài bảng của gói.
  • Chế độ tối (UX-DR5) BỊ CHẶN tới khi có logo SVG gốc — nêu tên để không ai tưởng là bỏ sót. Việc dọn màu cứng thành token ở đây chính là dọn đường cho nó.

⛔ Cố ý KHÔNG có trong story này

Màn hình nghiệp vụ (nhóm F9) · sàn trợ năng (E-001/5.4) · khung màn danh sách (E-001/5.6) · chế độ tối.

⚠️ Người duyệt cần biết

  • Mật độ lệch nguồn. Repo theo GÓI (control 48px · chữ thân 15px · đệm card 28px, PO chốt 07/09/2026); DESIGN.md ghi 44/14/24. ⚠️ Đã xử ở nguồn 09/09/2026: PO bỏ hẳn bộ artifact UX, DESIGN.md không còn tồn tại, tiêu chuẩn giao diện nay ở docs/style.md. Số đang chạy là số của gói.
  • Bản thảo này viết muộn, và đó là một lỗ của quy trình chứ không phải của làn. [D1] chỉ kê change đang mở; change archive xong là rơi khỏi danh sách, dù trang vẫn còn mốc. Đây là lần thứ hai trong ngày 07/09 (lần đầu: E-001/0.1). Đã báo — cổng đo bằng «mốc còn lại của story» thì thấy, nhưng [D1] thì không.

E-001/5.4 Sàn trợ năng và responsive cho portal-fe — portal-fe

Chờ hồ sơ. Tiêu chí dự kiến từ kế hoạch:

  • Như E-001/5.3, cộng ba dải responsive; bảng thành thẻ dưới 768px, không cuộn ngang (UX-DR4).

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.6 Khung màn danh sách cho portal-fe — portal-fe

Chờ hồ sơ. Tiêu chí dự kiến từ kế hoạch:

  • Như E-001/5.5, viết lại cho portal-fe.

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.9 Đăng nhập và hạ tầng phiên cho portal-fe — portal-fe

Chờ hồ sơ. Tiêu chí dự kiến từ kế hoạch:

  • Màn đăng nhập của cổng bên thứ ba: khoá tạm sau N lần sai (N là cấu hình, ⛔ không phải hằng số trong mã), quên mật khẩu dùng câu trung lập — không tiết lộ email có tồn tại hay không.
  • Đăng xuất · đổi mật khẩu trong phiên · trang 404403 toàn màn, đối xứng E-001/5.8 của bề mặt admin.
  • PO chốt 09/09/2026 (P7) — áp tiền lệ port của 5.8: dựng màn và cổng phiên trên hợp đồng của E-004/2.8, ⛔ mỗi màn tự khai là giữ chỗ cho tới khi back-end lên. Vì thế Đ:E-004/2.8 là điều kiện đóng, không phải điều kiện mở.
  • Tầng phiên gom vào một mô-đun để lượt nối máy chủ thật chỉ sửa một chỗ.
  • ⚠️ docs/style.md §6 chốt 401 xử ở MỘT chỗ duy nhất, ⛔ không màn nào tự xử 401 của riêng nó ⇒ story này gom nhánh hết phiên lên tầng vỏ/định tuyến.

⟨CẦN NGƯỜI VIẾT — agent làn portal-fe viết khi đóng change⟩

E-001/5.13 Nối bốn màn xác thực của portal-fe vào portal-be thật — portal-fe

Nguồn hồ sơ. portal-fe @ origin/noi-xac-thuc-vao-portal-be 165757eopenspec/changes/noi-xac-thuc-vao-portal-be/ (proposal.md · design.md · specs/tpp-portal-ui/spec.md · tasks.md · test-cases.md · security.md · review.md · docs.md · uat.md). Issue OAPI-107-noi-xac-thuc-vao-portal-be (thangvv111/portal-fe#20). Hợp đồng đọc từ portal-be/openapi.yaml @ 46bc45d (⛔ đọc để viết mã, ⛔ không sinh mã — AD-13). Change CHƯA đóng ⇒ bản thảo; dấu duyệt ghim sha7 bản cuối.

Yêu cầu và cách đo

Yêu cầu Ràng buộc Đo bằng
Ba màn nói chuyện với máy chủ thật qua đường tương đối Đăng nhập POST /api/v1/tpp-sessions · đăng xuất DELETE …/current · đổi mật khẩu PUT /api/v1/tpp-users/current/password; ⛔ gói tĩnh không chứa tài khoản, mật khẩu, bộ đếm. ⛔ Không nướng địa chỉ back-end vào gói (AD-26 mục 4) Quét src/features/ ⇒ ⛔ không chỗ nào còn gọi thuDangNhap của giả lập
Mã phiên đi trong tiêu đề uỷ quyền chuẩn Authorization: Bearer <mã>, ⛔ không tiêu đề tự đặt; đổi ở portal-fe vì bên lệch chuẩn là bên sửa Ca kiểm khẳng định cả tiền tố Bearer, ⛔ không chỉ đếm «có gửi tiêu đề»
Số lần thử còn lại và mốc mở khoá lấy của máy chủ X-Login-Attempts-Remaining · Retry-After (giây); mốc = bây giờ + giây, tính một lần. ⛔ Không tự đếm. Retry-After vắng ⇒ nói đang khoá mà ⛔ không nêu mốc, ⛔ không dùng hằng cũ làm mặc định Sai còn lượt ⇒ hiện đúng số máy chủ trả; khoá không mốc ⇒ ⛔ không nêu mốc nào
401 thôi mang một nghĩa — cổng đọc code trong thân, ⛔ không đọc mã trạng thái PRT.0008 (mật khẩu hiện tại sai) ⇒ ⛔ không xoá phiên, trả về màn gọi; mọi ca còn lại (PRT.0006, thân không đọc được, không có code, rỗng) ⇒ xoá phiên — fail-closed. Danh sách là không-xoá-phiên, ⛔ không phải xoá-phiên. Đọc thân bọc try (401 có thể trả HTML từ proxy). Cổng ⛔ vẫn không tự điều hướng Từ chối không khai lý do ⇒ đi đường xoá phiên; PRT.0008 ⇒ phiên còn, ở lại màn
Đổi mật khẩu — mật khẩu hiện tại sai ⇒ báo tại chỗ, giữ phiên (PO chốt C1) Lỗi tại ô mật khẩu hiện tại; giữ các ô khác; ⛔ không đăng xuất, ⛔ không rời màn; thông điệp ⛔ không tiết lộ gì về mật khẩu đúng Ca gửi sai mật khẩu hiện tại ⇒ vẫn đăng nhập, vẫn ở màn
Đăng xuất luôn xoá mã phiên phía trình duyệt Báo máy chủ trước; máy chủ không trả lời (lỗi mạng) ⇒ mã phiên vẫn xoá, vẫn về màn đăng nhập Ca đăng xuất khi mạng hỏng
Trạng thái «đang gửi» quan sát đượcchặn gửi lặp Gọi mạng thật có khoảng chờ ⇒ bấm hai lần là đốt hai lượt thử của máy chủ; nút gửi vô hiệu trong lúc chờ ở cả ba biểu mẫu Ca bấm gửi hai lần ⇒ một lượt gọi
Phiên hết hạn 15 phút không hoạt động; đích quay về chỉ nhận đường dẫn nội bộ Giữ từ E-001/5.9, đi cùng đường xoá phiên Ca không thao tác quá hạn; ca đích giả mạo ⇒ về mặc định

⛔ Cố ý KHÔNG có trong story này

Không nối màn quên mật khẩuportal-be không có điểm cuối (gỡ khỏi OAPI-71 vì chưa có cổng gửi thư); màn giữ giả lập, nợ trả theo sự kiện (OAPI-127). ⛔ Không sinh client từ openapi.yaml của portal-be (AD-13, ⛔R5). ⛔ Không thêm thư viện gọi mạng (fetch + cổng goiCoPhien đủ). ⛔ Không đụng docker/, .env.example (PORTAL_BE_UPSTREAM có sẵn). ⛔ Không làm mới mã phiên (refresh) — hợp đồng không có đường ấy. ⛔ Không xoá may-chu-gia-lap.ts — teo lại còn phần phục vụ màn quên mật khẩu, ⛔ không để lại mã «phòng khi cần».

⚠️ Người duyệt cần biết — năm chỗ

1. Hai repo lệch tên tiêu đề phiên mà cả hai lưới đều xanh — đây là loại lỗi kiến trúc tách repo sinh ra, ⛔ không phải lỗi một làn. AD-13 cấm phụ thuộc build xuyên repo nên không cổng nào so hai bên; lỗ chỉ lộ ở lượt nối đầu tiên. Người duyệt nên coi đây là bằng chứng cho việc cần một phép so hợp đồng ở tầng tích hợp (UAT) — change này chỉ vá ca cụ thể.

2. Ngoại lệ CÓ PHẠM VI của luật «401 xử ở một chỗ» — ⛔ không phải bỏ luật. Phạm vi: đúng một mã (PRT.0008), trên đúng một đường (đổi mật khẩu), và vẫn xử tại cùng một chỗ — cổng quyết, ⛔ không phải màn tự quyết. portal-be ghi ngoại lệ đối xứng ở phía họ: luật «một mã cho mọi lý do» sinh cho bề mặt chưa xác thực; đường này chỉ tới được khi đã cầm phiên sống. ⚠️ Fail-closed đặt đúng chiều: mã lạ ⇒ xoá phiên (phiền nhưng ⛔ không hỏng bảo mật), ⛔ không phải giữ phiên.

3. Retry-After — hợp đồng của portal-be mô tả trong VĂN XUÔI nhưng ⛔ không khai trong headers:. Mã của họ có gửi thật (có ca kiểm), nhưng một máy khách sinh từ hợp đồng sẽ không biết tiêu đề ấy tồn tại. Làn portal-fe đã báo portal-be, ⛔ không sửa file của họ. Đây là lý do ca «khoá mà không mốc» ⛔ không hiếm như nó có vẻ — và là lý do màn ⛔ không được bịa mốc.

4. Chốt C2 (câu chữ màn quên mật khẩu là của giao diện) vẫn hiệu lực dù màn chưa nối. Màn cố ý bỏ trường thông điệp máy chủ trả, kể cả sau này khi có điểm cuối — vì ca kiểm «không tiết lộ» nằm ở giao diện, câu chữ phải do giao diện làm chủ mới kiểm được. ⚠️ Người sau đọc thấy «không đọc trường của máy chủ» rồi «sửa» là làm ca kiểm mất chỗ bám.

5. Trang hướng dẫn: hai chỗ dễ viết sai. (a) Quên mật khẩu chưa dùng được — mục ⛔ không được bỏ: màn nhận email rồi trả lời trung lập trông y hệt màn đang chạy đúng. Khi portal-be có điểm cuối, mục này hết đúng và người mở change ấy phải gỡ. (b) ⛔ Không ghi số cứng cho «sai mấy lần» / «khoá bao lâu» — portal-be cấu hình, giao diện chỉ hiển thị lại. link.yaml khai docs: hai trang huong-dan-portal/dang-nhap.md · tai-khoan.md — cùng hai trang E-001/5.9 đã khai, chưa tồn tại trong repo docs, dựng khi PO gọi mốc.