برنامهریزی، تحلیل و عملیات پلتفرم · فصل ۱ — Message، Identity، Contact، Opportunity و Obligation · 192
Unified Inbox و Channel-normalized Messages
داده و event دارد اما آنها را به مدل تصمیم، attention، experiment یا platform policy قابل توضیح تبدیل نمیکند. موضوع جاری: «Unified Inbox و Channel-normalized Messages». میتواند برای «Unified Inbox و Channel-normalized Messages» model، signal و guardrail لازم را در یک workflow محدود تعریف و ارزیابی کند.
خلاصهٔ درس
داده و event دارد اما آنها را به مدل تصمیم، attention، experiment یا platform policy قابل توضیح تبدیل نمیکند. موضوع جاری: «Unified Inbox و Channel-normalized Messages».
میتواند برای «Unified Inbox و Channel-normalized Messages» model، signal و guardrail لازم را در یک workflow محدود تعریف و ارزیابی کند.
خروجی این درس
میتواند برای «Unified Inbox و Channel-normalized Messages» model، signal و guardrail لازم را در یک workflow محدود تعریف و ارزیابی کند.
پیشنیازها
1. مسئله واقعی: Inbox واحد بدون حفظ منبع، امن نیست
یک Email، Web Form و Chat ممکن است درباره یک خرید واحد باشند، اما شناسه، زمان، Thread و Attachment آنها یک semantics مشترک ندارند. هدف این درس ساختن یک Normalized Message قابلممیزی است؛ نه یکیکردن هویت افراد. هر رکورد باید بتواند به رویداد خام خودش برگردد و هر تصمیم dedupe یا parse باید از شواهد قابلمشاهده دفاع شود.
2. مرز مالکیت درس
PLN-001 فقط Channel Normalization را مالک است: Raw Message را به یک Envelope پایدار تبدیل میکند و provenance، dedupe و parse state را نگه میدارد. تشخیص اینکه دو handle متعلق به یک Person هستند در PLN-002 است. بنابراین participant_handles را حفظ میکنیم، اما canonical_person_id تولید نمیکنیم.
3. CloudEvents چه چیزی به ما میآموزد
CloudEvents یک قالب vendor-neutral برای Event تعریف میکند و چهار context attribute اجباری id، source، specversion و type دارد. همچنین source + id مرز مفیدی برای تشخیص duplicate در همان context است. ما از این ایده برای طراحی envelope الهام میگیریم، ولی schema Inbox خود MAKNOW را به CloudEvents نسبت نمیدهیم.
4. Provenance باید از UI مستقل بماند
W3C PROV نشان میدهد provenance باید بین سیستمها قابل نمایش و تبادل باشد. در این درس provenance_pointer یعنی مسیری که نشان میدهد این Envelope از کدام Raw Event، Adapter و Normalization Version آمده است. اگر UI عوض شود، این lineage نباید گم شود.
5. Envelope پایدار را از فیلدهای ضروری شروع کن
حداقل فیلدهای عملی این درس عبارتاند از: channel، raw_message_ref، external_message_id، source_system، occurred_at، received_at، participant_handles، body_ref، attachment_refs، normalization_version، provenance_pointer، dedupe_key، parse_state، unsupported_fields و ingest_decision. thread_hint ممکن است منبعهای متفاوتی داشته باشد و نباید جعل شود.
6. occurred_at و received_at یکی نیستند
occurred_at زمان رخداد نزد منبع است؛ received_at زمان دریافت در Inbox. Retry میتواند received_at تازه داشته باشد ولی همان رویداد قبلی باشد. حذف یکی از این دو زمان، تشخیص تأخیر، replay و ترتیب رویدادها را ضعیف میکند.
7. Raw Ref و External Message ID هر دو لازماند
external_message_id شناسهای است که Provider یا Source System میدهد. raw_message_ref مسیر بازیابی payload خام یا snapshot آن است. یکی جای دیگری را نمیگیرد: External ID برای correlation و dedupe مفید است؛ Raw Ref برای audit، replay و بازتفسیر نسخههای بعدی Normalizer لازم است.
8. Dedupe Key باید Channel-scoped و Context-scoped باشد
یک dedupe key خوب باید حداقل context منبع را حفظ کند. در Lab از ترکیب workspace_scope + channel + source_system + external_message_id استفاده میکنیم. این policy فقط برای fixture آموزشی است، اما اصل مهم روشن است: همان External ID در workspace دیگری نباید بهصورت خام با رکورد قبلی collision کند.
9. Replay را با «پیام جدید» اشتباه نگیر
اگر Provider همان event را دوباره با received_at جدید تحویل دهد، Envelope میتواند دوباره ساخته شود، اما dedupe_state=REPLAY باید downstream action را به SUPPRESS_REPLAY ببرد. تغییر زمان دریافت بهتنهایی دلیل ساختن Message جدید نیست.
10. Thread Hint شاهد است، نه حقیقت کانونی
بعضی channelها thread ID صریح دارند؛ Email ممکن است فقط reply headers داشته باشد؛ Form ممکن است اصلاً thread نداشته باشد. thread_hint باید منبع خودش را نشان دهد. اگر provider thread ID حذف شد ولی reply header معتبر باقی ماند، میتوان hint را از همان header ساخت، بدون جعل شناسه Provider.
11. Parse State باید Partial و Unsupported را تحمل کند
یک Attachment با content type ناشناخته نباید خودکار باعث از دسترفتن Body معتبر شود. parse_state=PARTIAL_UNSUPPORTED و unsupported_fields امکان میدهد پیام اصلی Normalized بماند، درحالیکه بخش نامفهوم برای پردازش بعدی علامتگذاری میشود. اما کمبود فیلدهای حیاتی مانند Raw Ref یا Provenance میتواند کل ingest را به QUARANTINED ببرد.
12. Normalization حق Merge هویت ندارد
وجود Email، Chat و Form در یک Inbox ثابت نمیکند handleهای آنها یک شخصاند. اگر Adapter فیلدی مانند resolved_person_id یا دستور Merge قطعی وارد کند، Normalizer باید آن را بهعنوان عبور از مرز scope تشخیص دهد؛ نه اینکه بیصدا آن را Canonical کند.
13. Worked Example: Email با Attachment
فرض کنید Email با External ID m-204، Raw Ref پایدار، زمان رخداد و دریافت، participant handles، Body Ref و Attachment Ref میرسد. با provenance کامل و content type شناختهشده، Envelope NORMALIZED است، dedupe key از context منبع ساخته میشود و identity همچنان unresolved میماند.
14. Failure Probeهای قطعی
چهار probe را اجرا کن: همان event با received_at جدید باید Replay تشخیص داده شود؛ نبود provider thread ID با reply header معتبر نباید جعل ID ایجاد کند؛ External ID یکسان در workspace دیگر نباید collision بسازد؛ Attachment ناشناخته باید typed unsupported state تولید کند. Raw Ref یا Provenance مفقود نیز باید از happy path خارج شود.
15. Transfer: Thread ID حذف شده، Reply Header باقی است
در Transfer، Provider دیگر thread ID نمیدهد ولی Email reply header و تمام source references باقیاند. Envelope را از شواهد جدید دوباره بساز: thread_hint را با source مشخص از reply header استخراج کن، dedupe key را از context واقعی محاسبه کن و Identity را unresolved نگه دار. نتیجه نباید از baseline کپی شود.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
F1 retrieval
F2 diagnosis
S1 application
S2 diagnosis
S3 decision
S4 transfer
ملاکهای ارزیابی (rubric)
| Dimension | Sufficient evidence | Blocking failure |
|---|---|---|
| Boundary | Channel normalization is owned; person identity stays unresolved | Normalization silently merges identity |
| Source fidelity | Raw reference, external ID, source and provenance remain visible | Canonical envelope destroys source traceability |
| Dedupe/replay | Dedupe key is context-scoped and replay is explicit | Later received_at is treated as a new message without evidence |
| Parse uncertainty | Unsupported/partial states remain typed | Unknown attachment or missing evidence is coerced into success |
| Transfer | Thread hint and dedupe evidence are recomputed from changed input | Baseline result or provider thread ID is copied/fabricated |
منابع و تازگی
مطالعهٔ موارد (case studies)
تصاویر درس
فایلهای آزمایشگاه
Use only the supplied synthetic records. Implement normalize(case) in starter.py. Preserve source references and provenance, derive a context-scoped dedupe key, keep replay/unsupported states explicit, and never perform cross-channel identity merge.
Run python run_checks.py. The learner checker validates output shape and boundary safety only; expected labels and reference logic remain outside learner-publishable paths.