---
url: https://docs.nemo12.com/architecture/sdd-005-interaction.md
description: >-
  Hệ Interaction dùng chung: thread, đối tượng được bình luận, quyền hiển thị và
  hội thoại giữa learner, phụ huynh, mentor.
---

# SDD-005 — Interaction & Conversation System

**Horizontal platform capability** (như Identity, Notification, Evidence) — một Interaction Service dùng chung; cấm mỗi school/module tự xây comment riêng.

## 2. Entities & Targets (REQ-INX-01)

`Interaction: Comment · Reply · Reaction · Mention · Annotation · Activity`.

```text
Comment: comment_id · author_id · target_type · target_id · parent_comment_id
· content · created_at · edited_at · visibility · status
```

`target_type + target_id` áp cho gần như mọi object: Learning Experience, Assessment (vd `assessment_result/asr_28392`), Lab, Question, Recommendation, Learner Report, Learning Package, Goal, Evidence, Mentor Session, Community Post, Media. Ví dụ luồng chuẩn: Parent comment dưới Recommendation → Mentor reply → Learner react/hỏi tiếp — conversation gắn với đúng object đó (REQ-PAR-07).

## 3. Threading (REQ-INX-02)

Data model hỗ trợ nesting đệ quy; UI giới hạn 1–2 cấp.

## 4. Visibility & Permission (REQ-INX-03, REQ-MEN-02)

Levels: `private · learner_parent · mentor_team · school · community · internal_staff`. Mentor note "có dấu hiệu đoán đáp án" = `internal_staff`, learner không thấy. Authorization ở backend theo relationship user↔learner (family, assignment).

## 5. Mentions & Notifications (REQ-INX-04)

`@mentor @parent @learner` → events `CommentCreated, MentionCreated, ReplyCreated, ReactionAdded` → Queue `nemo12-events` → Notification module → in-app, email, push (mobile-ready).

### 5.1 Kênh email — Cloudflare Email Service (SRC-602)

Thư rời hệ thống qua **binding `EMAIL`** của Cloudflare Email Service, không qua nhà cung cấp
ngoài. Chủ dự án chốt 2026-08-26, thay Resend của SRC-452.

Đây là binding chứ không phải secret, nên **không còn khoá API nào để lộ hay phải xoay vòng** —
bớt đúng một thứ trong danh sách bí mật phải quản (REQ-SEC-06, RISK-013).

Điều kiện để thư thật sự đi được, và trạng thái khi chưa đủ:

| Điều kiện | Chưa đủ thì sao |
| --- | --- |
| Tên miền gửi đã onboard vào Email Service | `send` ném `E_SENDER_DOMAIN_NOT_CONFIGURED`; digest ghi `failed`, cron **không** chết |
| Người nhận là **địa chỉ đích đã xác minh** (giới hạn beta) | `send` ném `E_RECIPIENT_NOT_ALLOWED` |
| Worker có binding `EMAIL` | `sendEmail` trả `skipped`; cron vẫn chạy, vẫn ghi log |

**Trạng thái đã dựng (2026-08-26, SRC-602):** `nemo12.com` đã onboard — Status *Enabled*, DNS
*Configured* (MX/SPF/DKIM đều nằm trên `cf-bounce.*`, không đụng email tên miền gốc);
`dac2205@gmail.com` là địa chỉ đích *Verified*; **đã gửi thư thử thành công** qua binding thật
(`wrangler dev --remote`, không deploy). Nghĩa là: chừng nào còn trong beta, thư chỉ tới được
các địa chỉ đã xác minh — với giai đoạn `DIGEST_TEST_RECIPIENT` thì vậy là đủ, còn muốn gửi cho
bố mẹ thật thì phải chờ mở hạn chế này hoặc xác minh từng địa chỉ.

Ba trạng thái `ok · skipped · failed` là cố ý tách: gộp "chưa cấu hình xong" vào "lỗi" sẽ làm mọi
ngày trước khi bật kênh trông như một sự cố, và người trực sẽ học cách bỏ qua cảnh báo.

Nhà cung cấp được gói trong đúng một hàm (`modules/email/channel.ts`), nên lần đổi này chỉ phải
sửa hàm đó cộng khai báo binding — hợp đồng `SendResult` giữ nguyên, `run.ts` và test không phải
biết ai đang chuyển thư.

### 5.2 Template thư — `modules/email/templates.ts` (SRC-605)

Chủ dự án 2026-08-26: mọi thư gửi đi phải là HTML đẹp cùng ngôn ngữ biển sâu. Một layout chung
(`renderLayout`) + 5 template: **báo cáo tuần theo từng con** (weeklyReport — template đầu bảng),
xác nhận đăng ký sự kiện, nhắc buổi học thử, con nghỉ học nhiều ngày, chào mừng bố mẹ mới.

Ba luật của mọi thư (kiểm bằng test, không kiểm pixel): tiêu đề + câu mở tự đứng được; không
chấm điểm con, không màu đỏ (REQ-UX-03) — "cần để mắt" là hổ phách; **đúng một nút hành động
mỗi thư**. Kỹ thuật: style inline 100%, layout bằng `<table>`, không ảnh ngoài, không webfont —
Gmail cắt `<style>`, Outlook render bằng Word engine, nên file này không import gì từ design
system mà là bản dịch tay của cùng bảng màu. Dãy ô mức vững (`masteryCells`) giữ đúng ẩn dụ
MasteryBar của web. Đã gửi thử cả 5 thư với dữ liệu giả định, nhận đủ trong Inbox (2026-08-26).

Nợ này đã trả: `modules/email/digestContent.ts` (thư tổng kết hằng ngày) nay đi qua cùng
`renderLayout`, và `weeklyReport` chạy trên truy vấn thật chứ không còn dữ liệu giả định. Từ
SRC-744 mọi file thư nằm trong một thư mục duy nhất — xem bản đồ trong [ref.emails](../reference/emails/rules.md).

## 6. Moderation — K12 bắt buộc (REQ-INX-05)

Profanity/abuse/spam/inappropriate detection (AI classify qua AI Gateway) + report/hide/block + moderation queue + audit log. Quyết định nghiêm trọng: lưu evidence + human review. Pattern `hidden_at` (soft-hide) kế thừa sutucon.

## 7. Activity Stream (REQ-INX-06)

Mọi interaction tạo Activity Event → **Learner Activity Timeline** (Parent commented, Mentor replied, Learner completed lab, Recommendation acknowledged…) — feed cho Learner Model & Parent Model (SDD-002), và telemetry (login/page_view/course_open — FEAT-050) nhập cùng dòng behavior evidence.

## 8. Forum (REQ-COM-03) — specialization của Interaction

Forum là hiện thân đầu tiên của Interaction System (kế thừa `lab_topics/replies/votes` chuyenchon):

```text
forum_topics (id, scope_type[subject|school|general], scope_id, title, body,
              author_user_id, author_role, status[open|hidden|locked], reply_count,
              vote_score, created_at, last_activity_at)
interactions (id, target_type, target_id, parent_id, author_user_id, author_role,
              content, visibility, status[visible|hidden|blocked], hidden_at, created_at)
interaction_votes (interaction_target, user_id, value[-1|1])   -- upvote/downvote
```

* **Topic = target** (`target_type='forum_topic'`); **reply = interaction** trên topic. Threading 1 cấp (SDD-005 §3).
* **Vote** up/down trên topic và reply (`vote_score`), sắp xếp theo mới nhất / nhiều vote.
* **Visibility** mặc định `community` (mọi user Nemo12); scope theo subject (Toán/Anh/Văn) hoặc school để đúng ngữ cảnh học.
* **Moderation K12** (SDD-005 §6): lọc từ cấm cơ bản khi tạo; report → moderation queue; author/staff `hide`; audit. AI classify qua AI Gateway là nâng cấp sau.
* **Authz**: mọi authenticated learner/parent tạo được; chỉ author hoặc staff `hide`/`lock`.

Vote + mentor-featured exemplars trên submissions (REQ-INX-07) dùng chung `interaction_votes`.

## Trace

| REQ | Mục |
| --- | --- |
| REQ-INX-01..06 | §2–§7 |
| REQ-PAR-07 | §2 |
| REQ-MEN-02 | §4 |
