SDD-053 - Kho ảnh chung, tag, phân phối ảnh, hồ sơ mentor
Chỉ đạo 02.10.2026: trong dolphin cần chỗ quản lý thông tin mentor (xem chi tiết từng người), đưa ảnh chân dung lên (ngang, dọc, vuông, nền đậm, nền sáng, ảnh trong lớp, ảnh với học viên), dùng tag để phân loại theo vài cụm, và một khu riêng để phân phối ảnh lên các trang cụ thể. Album hiện có phải có cùng các cơ chế ấy. Bổ sung 03.10.2026: mỗi mentor có chứng chỉ, thành tích thi, xuất hiện trên báo chí.
Tài liệu này mở rộng SDD-019 (hồ sơ mentor, album) và SDD-009 (Media System). Nó chưa được hiện thực: đây là thiết kế đã chốt, kèm lộ trình bốn giai đoạn ở §9.
1. Hiện trạng đo được (production, 03.10.2026)
| Đối tượng | Số liệu | Hệ quả |
|---|---|---|
Ảnh trong media | 73, trong đó 64 công khai | |
| Ảnh không có kích thước | 50 / 73 | Không biết ảnh ngang hay dọc, nên không lọc được theo hình dạng |
| Ảnh trong album | 62, ở 7 album (3 đã đăng) | |
| Ảnh album chưa có caption | 31 / 62 | |
| Ảnh album chưa có mô tả | 48 / 62 | Alt text tự sinh chỉ còn tên album để dựa vào |
| Ảnh album chưa có thời điểm chụp | 36 / 62 | |
| Alt text còn là tên tệp | 1 / 62 | |
| Hồ sơ mentor | 7, 6 đã đăng | |
| Mentor chưa có ảnh chân dung | 7 / 7 | Mọi thẻ mentor trên nemo12.com đang hiện chữ cái đầu thay cho ảnh |
| Mentor đã kiểm chứng là cựu học sinh trường chuyên | 5 / 7 |
Lượt audit đầu tiên (03.10.2026, skill audit-photos):
- Đo và điền kích thước cho 45 / 45 ảnh công khai còn thiếu: 29 ngang, 14 dọc, 2 vuông; nền 20 tối, 10 sáng, 15 ở vùng giữa (không đoán). Năm ảnh nội bộ (ảnh gia đình) bỏ qua có chủ đích. Hình dạng và nền chưa có cột nên mới chỉ nằm trong báo cáo, chờ giai đoạn 1.
- Dựng lại alt text cho 1 ảnh còn là tên tệp (
Screenshot 2026-07-17 at 23.25.22, album "ABC"). - Còn chờ người: 7 / 7 mentor chưa có ảnh chân dung; ảnh album thiếu caption 31, thiếu mô tả 48, thiếu thời điểm chụp 36; caption "ấdas d" ở album "ABC" trông như chữ gõ thử.
- Rủi ro cần chủ dự án quyết: ba album đã đăng có tên học viên hoặc là lớp học sinh ("Trí Minh (Nemo AI)", "Đàm Anh Tú (Nemo AI)", "Lớp AI Teen 2026", tổng 36 ảnh) trong khi hệ thống chưa có chỗ ghi đồng ý của phụ huynh (§6, giai đoạn 1). Skill không tự gỡ đăng: đó là quyết định của người, đúng lớp ba của §8.
Mô hình hiện tại: mỗi mentor đúng một ô ảnh (mentor_profiles.photo_media_id); ảnh album gắn người ở mức album (photo_album_people) chứ không ở mức từng ảnh; ảnh chưa có tag; chưa có khái niệm "chỗ hiển thị". Tiền lệ phân phối duy nhất là testimonials.placements_json (SRC-676), một mảng tên trang tự do, không ràng buộc.
2. Mười quyết định đã chốt
Chủ dự án chốt cả mười theo đề xuất (03.10.2026).
| # | Câu hỏi | Quyết định | Lý do |
|---|---|---|---|
| Q1 | Một kho ảnh hay hai | Một kho chung. Album chỉ là một cách nhóm ảnh | Tách hai kho thì cùng một tấm ảnh phải tải lên và điền thông tin hai lần |
| Q2 | Các cụm tag | Năm cụm, danh sách đóng (§3) | Tag tự do sinh ra "lớp học", "lop hoc", "classroom" cho cùng một nghĩa, và bộ lọc mất tác dụng |
| Q3 | Nền sáng hay tối | Máy đoán lúc tải lên, người sửa được | Đoán theo độ sáng đúng phần lớn trường hợp, sai với ảnh ngược sáng |
| Q4 | Phân phối theo chỗ | Mỗi chỗ hiển thị tự khai ràng buộc, khu phân phối chỉ gợi ý ảnh hợp | Cách duy nhất để không đặt ảnh ngang vào ô dọc |
| Q5 | Cố định hay xoay vòng | Cố định, có thứ tự | Xoay vòng làm khó kiểm tra trang đang hiện gì, và hỏng SEO ảnh |
| Q6 | Ảnh có học viên | Bắt buộc có đồng ý của phụ huynh, ghi ở từng ảnh; hệ thống chặn phân phối ra trang công khai khi thiếu | Ảnh trẻ em; tiền lệ testimonials đã chặn đăng khi thiếu consent |
| Q7 | Chứng chỉ, thành tích, báo chí | Mục có cấu trúc: tên, năm, đơn vị cấp hoặc tên báo, link nguồn, ảnh, trạng thái "đã kiểm chứng" | Giống danh sách cựu học sinh tiêu biểu: phải kiểm chứng được trước khi đưa lên |
| Q8 | Ảnh chứng chỉ và ảnh báo | Cùng kho ảnh, tag bối cảnh certificate / press | Một bài báo về một mentor hiện được cả ở trang mentor lẫn trang trường |
| Q9 | Ai làm gì | Mentor tự tải và sửa hồ sơ, ảnh, thành tích của mình; phân phối và đánh dấu đã kiểm chứng / đã có đồng ý chỉ staff, admin | Người biết rõ nhất về mình là chính mentor; quyết định đưa gì ra công khai thì cần một người thứ hai |
| Q10 | Skill audit ảnh | Tự điền phần máy đo được, gợi ý không tự ghi phần cần phán đoán, không bao giờ tự đánh dấu đồng ý hay kiểm chứng | §8 |
3. Tag: năm cụm, danh sách đóng
Danh sách sẽ khai trong code (file mediaTags.ts trong module showcase, dự định, chưa dựng ở giai đoạn 1), không ở D1: cùng lập luận với tag đóng của Dory (SDD-024) và đăng ký dashboard (SDD-037). Thêm một giá trị là một dòng code có typecheck, không phải một dòng dữ liệu có thể trỏ sai.
| Cụm | Giá trị | Ai gắn |
|---|---|---|
shape (hình dạng) | landscape · portrait · square | Máy, từ width/height. Tỉ lệ trong khoảng 0,9 tới 1,1 là vuông |
tone (nền) | light · dark · cutout (đã tách nền) | Máy đoán, người sửa; lưu kèm nguồn auto / human |
context (bối cảnh) | portrait · classroom · with_learners · event · outdoor · certificate · press | Người gắn; AI gợi ý |
people (ai trong ảnh) | danh sách mentor và học viên | Người gắn; không phải tag chữ mà là liên kết tới hồ sơ |
quality (mức dùng được) | homepage_ready · internal_only · needs_replacement | Staff, admin |
shape và tone là cột trên media (một ảnh đúng một giá trị); context là nhiều giá trị nên ở bảng media_tags (dự định, chưa dựng); people ở bảng media_people (dự định, chưa dựng).
Tag with_learners và bảng người-trong-ảnh (dự định, chưa dựng) phải khớp nhau. Ảnh có học viên trong bảng đó thì máy tự thêm with_learners. Ngược lại, gắn with_learners mà không chỉ ra học viên nào thì vẫn bị coi là ảnh có trẻ em và vẫn phải qua cổng đồng ý (§6): thiếu thông tin không được trở thành lối thoát khỏi cổng.
4. Mô hình dữ liệu (đề xuất, giai đoạn 1-3)
media + orientation, tone, tone_source, quality, has_learners,
learner_consent, consent_note, consent_by, consent_at
media_tags (media_id, tag) -- cụm context
media_people (media_id, person_type, person_id) -- mentor | learner
media_placements (slot_id, media_id, position, placed_by, placed_at)
mentor_credentials (id, mentor_id, kind, title, issuer, year, source_url,
media_id, verified, verified_by, verified_at,
display_order, status)photo_album_itemsgiữ nguyên và tiếp tục trỏmedia_id. Tag, người trong ảnh, đồng ý đều nằm ởmedia, nên một ảnh album tự có cùng cơ chế với ảnh mentor (yêu cầu "album cũng có các cơ chế tương tự"). Caption theo vùng đọc và mô tả vẫn ởphoto_album_itemsvì chúng thuộc về cách một album kể chuyện, không thuộc về tấm ảnh.photo_album_people(mức album) giữ lại cho tương thích; trang mới đọc người trong ảnh ở mức từng ảnh.mentor_profiles.photo_media_idgiữ lại làm ảnh chân dung mặc định của thẻ mentor. Mọi ảnh khác của mentor là ảnh trong kho cómedia_peopletrỏ tới mentor đó.mentor_credentials.kind∈certificate·competition·press. Danh sách đóng kiểm ở API.
5. Chỗ hiển thị (placement slot): khai trong code, kèm ràng buộc
Mỗi chỗ hiển thị trên nemo12.com là một dòng trong đăng ký placementSlots.ts:
{
id: "mentors.card", // khoá ổn định
page: "/mentors",
label: "Ảnh trên thẻ mentor",
capacity: 1, // mỗi mentor một ảnh
perMentor: true,
require: { shape: ["portrait", "square"], context: ["portrait"], quality: ["homepage_ready"] },
minWidth: 600,
}Danh sách khởi đầu (các chỗ đang dùng ảnh hôm nay):
| Slot | Trang | Số ảnh | Ràng buộc chính |
|---|---|---|---|
mentors.card | /mentors | 1 mỗi mentor | dọc hoặc vuông, bối cảnh chân dung |
mentor.hero | /mentors/:slug | 1 mỗi mentor | ngang, rộng tối thiểu 1600px |
mentor.gallery | /mentors/:slug | tới 8 mỗi mentor | bất kỳ; ảnh có học viên phải có đồng ý |
mentor.credentials | /mentors/:slug | theo số thành tích đã kiểm chứng | bối cảnh certificate hoặc press |
parents.classroom | /for-parents | tới 6 | bối cảnh classroom hoặc with_learners |
students.classroom | /for-students | tới 6 | như trên |
community.strip | /community | tới 12 | bất kỳ đã đủ chuẩn |
home.team | / | tới 4 | chân dung, homepage_ready |
Vì đăng ký nằm trong code, thêm một chỗ hiển thị là thêm một dòng; khu phân phối và trang web đọc cùng một đăng ký nên không lệch nhau (cùng lập luận SDD-037 §2.2).
Phân phối là cố định và có thứ tự (Q5): media_placements.position quyết định thứ tự hiện. Khu phân phối cho kéo thả đổi thứ tự trong một slot.
6. Cổng trước khi lên trang công khai
Một ảnh chỉ được gắn vào một slot công khai khi đủ cả ba:
visibility = 'public'vàmoderation_status = 'approved'(cổng sẵn có của SDD-019 §2).- Thoả ràng buộc của slot (§5): sai hình dạng hay thiếu bối cảnh thì API từ chối, kèm lý do bằng chữ.
- Ảnh có học viên (
has_learners = 1, hoặc tagwith_learners, hoặc cómedia_peoplekiểu learner) thì phảilearner_consent = 1. Đồng ý ghi ở từng ảnh (Q6), kèmconsent_note(kênh và ngày hỏi), và chỉ staff, admin đánh dấu được.
Một thành tích (mentor_credentials) chỉ hiện công khai khi verified = 1 và có source_url.
API công khai đọc media_placements cho từng slot rồi lọc lại theo cổng này lúc trả về, chứ không tin vào trạng thái lúc gắn: đồng ý có thể bị rút sau khi ảnh đã được phân phối.
7. Các khu trong dolphin
Đặt trong cụm "What the public sees" ở trang chủ (SRC-1176), trừ hồ sơ mentor ở cụm "People and schools". Mọi khu theo luật chỉ đọc mặc định (SRC-1178): Edit mới sửa, Save/Cancel đứng đúng chỗ nút Edit (SRC-1181).
| Khu | Đường dẫn | Việc |
|---|---|---|
| Kho ảnh | /photos | Lưới ảnh, lọc theo năm cụm tag; badge "thiếu thông tin" |
| Chi tiết một ảnh | /photos/:id | Hai cột ảnh và thông tin; tag, người trong ảnh, đồng ý, nơi đang được phân phối |
| Thêm ảnh | /photos/upload | Trang riêng; máy đo hình dạng, nền, kích thước ngay khi tải |
| Album | /albums/... | Như hiện tại (SDD-019 §12-14), ảnh album mở ra chính trang chi tiết ảnh của kho |
| Phân phối | /placements | Danh sách slot; mỗi slot hiện ràng buộc, ảnh đang gắn theo thứ tự, và gợi ý ảnh hợp |
| Hồ sơ mentor | /team/:id | Thông tin, ảnh chân dung (chọn từ kho), ảnh khác của mentor, chứng chỉ, thành tích thi, báo chí |
8. Skill audit-photos
.claude/skills/audit-photos/SKILL.md, thuộc họ audit-* và được /audit gọi. Ba lớp hành động, đúng Q10:
| Lớp | Ví dụ | Skill làm gì |
|---|---|---|
| Máy đo được | kích thước, hình dạng, độ sáng nền, alt text còn là tên tệp | Tự điền qua seed-data, kèm SELECT kiểm chứng |
| Cần phán đoán | bối cảnh, ai trong ảnh, caption, mô tả | Gợi ý, ghi vào báo cáo; người duyệt rồi mới ghi |
| Cam kết với người ngoài | đồng ý của phụ huynh, thành tích đã kiểm chứng | Không bao giờ tự đánh dấu; chỉ báo thiếu |
9. Lộ trình
| Giai đoạn | Nội dung | Phụ thuộc |
|---|---|---|
| 1 | Cột mới trên media, media_tags, media_people; máy đo hình dạng và nền lúc tải lên; khu Kho ảnh và Chi tiết ảnh | migration |
| 2 | placementSlots.ts, media_placements, cổng §6, khu Phân phối | 1 |
| 3 | mentor_credentials, hồ sơ mentor mở rộng, quyền mentor tự sửa (Q9) | 1 |
| 4 | nemo12.com đọc ảnh theo slot thay cho photo_media_id và album trực tiếp | 2, 3 |
Trước giai đoạn 1, skill audit-photos đã chạy được trên mô hình hiện tại (đo và điền kích thước, sửa alt text tên tệp, báo phần thiếu); các mục của §3-§6 được báo là "chưa có mô hình".
10. Trace
| SRC | REQ | Hiện thực |
|---|---|---|
| SRC-1215 | REQ-MED-08, REQ-MED-09, REQ-MED-10, REQ-MED-11, REQ-MEN-20, REQ-MEN-21 | Thiết kế; hiện thực theo §9. Skill .claude/skills/audit-photos/SKILL.md |