Dev Cluster E2E — Onboarding: เดินถึงไหน / เหลืออะไร / บล็อคอะไร
สถานะการรัน E2E onboarding (NEW_REQUESTOR) บน deployed dev cluster จริง — map ต่อ sequence diagram §3-§5 ของ 07-e2e-real-run-sequences · key: Rework→Resubmit-200 ที่เคย 🔴 ตอน local = ✅ verified บน cluster แล้ว (real Entra OTP via Redis)
อัปเดต: 2026-06-28
อ้างอิง sequence ตัวเต็ม: 07-e2e-real-run-sequences — diagram §3 (happy) / §4.1 (Reject) / §4.2 (Rework→Resubmit) / §4.3 (Cancel) เอกสารนี้ = overlay สถานะ บน deployed dev cluster (gateway
gateway-dev.exim.go.th+ AKSaks-SupperApp-dev) ทับ diagram เดิมที่เป็นผล local run (mock OTP) driver + แผน + หลักฐานเต็ม: Atlasdocs/orchestration-integration/28062026/PLAN_DEV_E2E_AUTOMATED_DRIVER.md+E2E_DRIVER.py
TL;DR
- ✅ ขับ client จริงบน deployed dev cluster ได้ end-to-end ถึง Resubmit-200 — ไม่ใช่ local fleet, ไม่ใช่ mock
- ✅ สิ่งที่ 07 §4.2 ค้าง 🔴 (resubmit 409 → “รอ verify ตอน deploy”) = ผ่านแล้ว:
/resubmitคืน HTTP 200 +DocStatus=ReSubmitted(2 runs) - 🔑 ปลดล็อก OTP จริง (เดิม local ต้อง mock): deployed US ใช้ Entra Native Auth จริง — fresh-signup OTP email ไม่ delivery บน dev แต่ code ถูก stamp ลง Redis → อ่านผ่าน VPN ได้
- ⬜ ยังไม่รันบน cluster: full happy-path ถึง Completed/Finalized · branch Reject · branch Cancel · OC→US return (US Status flips) · maker/approver notification
- 🔴 บล็อค: cleanup 2 instance ค้างคิว (classifier) · maker/approver notify (role-mapping) · WF endpoint
instances/db/by-documentพัง (Autofac)
1. dev cluster ต่างจาก local (07 doc) ยังไง
| ด้าน | local run (07 doc) | dev cluster run (เอกสารนี้) |
|---|---|---|
| ที่รัน service | local fleet (US … WF) | deployed pod ทั้งหมด บน superappdev (ผ่าน gateway) |
| OTP | 🔧 mock (LOCAL_E2E_MOCK_OTP) | ✅ Entra Native Auth จริง — code อ่านจาก Redis (email ไม่ delivery, ดู §4) |
| RefNo | stub แล้ว full-7 real (FX-…88) | ✅ real Centralized→Codex (FX-…99/00, 5-digit zero-padded) |
| WF instance | local WF (#43) | ✅ cluster WF (#50/#53) สร้างโดย OC saga จริง |
| TS task_id | local | ✅ cluster TS (task 46/49) — ดึงผ่าน kubectl port-forward |
| auth | bypass local | WF AllowAnonymous + bypass non-prod (ไม่ต้อง JWT) |
2. Mapping ต่อ 07 sequence — เดินถึงไหนบน dev cluster
สถานะ: ✅ verified บน cluster · ⬜ ยังไม่รันบน cluster (proven local) · 🔴 blocked
| 07 § / lane | step | local | dev cluster |
|---|---|---|---|
| §3 LANE 1 | POST /onboarding/instances (NEW_REQUESTOR) | ✅ | ✅ |
| §3 LANE 1 | OTP SaveDraft → Entra จริง → code | 🔧 mock | ✅ real (Redis) |
| §3 LANE 1 | RefNo Centralized→Codex | ✅ FX-…88 | ✅ FX-…99/00 |
| §3 LANE 1 | OTP Next → BindOwner + cookie | 🔧 mock | ✅ real verify |
| §3 LANE 1 | Next × Juristic→UserMode→Designate→CompanyInfo→Signatory | ✅ | ✅ |
| §3 LANE 1 | FxRequestorTcConsentStep/Submit → flow-submitted-for-approval | ✅ | ✅ (SUBMITTED) |
| §3 LANE 2 | OC saga = AwaitingPickup | ✅ | ✅ (cluster OC) |
| §3 LANE 2 | OC→WF POST /instances (create) | ✅ #43 | ✅ #50/#53 |
| §3 LANE 2 | WF→TS POST /tasks (New) | ✅ | ✅ task 46/49 |
| §3 LANE 2 | WF→NS maker notification | 🟡 NoRecipient | 🟡 (ไม่เช็ค — role-map เดิม) |
| §3 LANE 3-4 | Maker pickup → APPROVE → Approver pickup → APPROVE → Completed | ✅ | ⬜ (proven local; ไม่รัน cluster) |
| §3 LANE 3-4 | OC→US return progress/result → US Status flips → Finalized | ✅ | ⬜ (ไม่ verify ฝั่ง US) |
| §4.1 B | Approver REJECT → saga Rejected | ✅ | ⬜ |
| §4.2 C | Maker /rework → IsEditable=true | ✅ | ✅ |
| §4.2 C | Requestor /resubmit → 200 + DocStatus=ReSubmitted | 🔴 409 | ✅✅ 200 |
| §4.3 D | /cancel → saga Cancelled | ✅ | 🔴 (classifier block — ดู §5) |
หัวใจ: แถว §4.2 resubmit — 07 doc เขียน 🔴 (
WF /resubmit 409 IsEditable=false, fix unit-verified แต่ “E2E resubmit→200 รอ verify ตอน deploy”). deploy แล้ว + verify แล้ว = ✅ บน cluster จริง.
3. ✅ Verified บน dev cluster — chain เต็ม (หลักฐาน)
Requestor (driver)
→ US: Start NEW_REQUESTOR ................................ 200 flowInstanceId
→ US: OTP SaveDraft (real Entra) ........................ 200 refNo issued
→ Redis: DEV_Notification:otp:onboarding:{email}:{ref} .. OtpCode
→ US: OTP Next ......................................... 200 → step 2 (cookie set)
→ US: Juristic→UserMode→Designate→CompanyInfo→Signatory . 200 ×5
→ US: FxRequestorTcConsent /Submit ..................... 200 SUBMITTED
── flow-submitted-for-approval (ASB) ──
OC saga → OC creates WF instance ...................... WF #50 (DocStatus=Submitted)
WF → TS create task .................................. TS task 46
→ WF: maker /rework {taskId,role:AdminMaker} .......... 200 IsEditable=true, DocStatus=Rework
→ WF: /resubmit {} ................................... 200 ← (เคย 409)
→ WF: instances/by-document ......................... DocStatus = ReSubmitted ✅
| run | refNo | WF instance | TS task | ผล |
|---|---|---|---|---|
1 (driver.py) | FX-202606-00099 | #50 | 46 | resubmit 200 · DocStatus=ReSubmitted ✅ |
2 (E2E_DRIVER.py) | FX-202606-00100 | #53 | 49 | resubmit 200 · DocStatus=ReSubmitted ✅ |
gate flip: ตาม Atlas 26062026/ROLLOUT_WF_RESUBMIT_ISEDITABLE_FIX.md §4 — #1 /resubmit=200 ✅ + #2 DocStatus=ReSubmitted ✅ → 07 §4.2 / §5 ของ resubmit ควร flip 🔴→✅
scope ของ 924 ที่ verify: template
OnboardingFXบน dev =AssignmentPolicy=ANY(ไม่ใช่ ALL ตามที่ 07 §304 สมมติ) → ที่ verify สด = part-(a)IsEditable false→true(= สาเหตุ 409 จริง) · part-(b) case-mismatch ("REWORK"vs"Rework", เฉพาะ ALL) ไม่ถูก trigger บน flow นี้ แต่ครอบโดย unit 140/140 แล้ว
4. 🔑 OTP บน dev cluster — ทำไมต้อง Redis (ไม่ใช่ mock, ไม่ใช่ email)
deployed US ไม่มี mock (LocalE2EOtpMocks อยู่แค่ worktree, never deployed) → ใช้ Entra Native Auth SignUp จริง:
- base email = registered แล้ว →
Otp.DuplicateAccount·+alias/dot = fresh signup ได้ (SaveDraft 200) - แต่ OTP email fresh-signup ไม่ delivery บน dev (ทั้ง
+aliasและ dot-variant: 200 แต่ไม่มีเมลถึง gmail — น่าจะ infra/anti-spam; emails เก่าที่เคยมาน่าจะเป็น login OTP) - ทางที่ใช้ได้: Entra→Notification webhook stamp OTP ลง Redis ก่อน (แม้ email พัง) → อ่านจาก Redis ได้:
- key:
DEV_Notification:otp:onboarding:{email}:{refCode}(email มี{}literal) · JSON field.OtpCode· TTL 300s - Redis =
sua-redis-mi-dev…:10000(Enterprise/SSL, private endpoint) → ต้อง VPN + access-key (เครื่องนอก VNet เข้าตรงไม่ได้) +alias= uniqueness ไม่จำกัด (อ่าน code จาก Redis ไม่ต้องรอ email)
- key:
gotcha: urllib ต้องใส่
User-Agent: curl/8.0(cloudflare bot-block) ·Nextออก__Host-onboardingcookie สำหรับ step ถัดไป
5. เหลืออะไร / อะไรบล็อค
⬜ ยังไม่รันบน dev cluster (รันต่อได้ — กลไกพร้อม)
- full happy-path → Completed/Finalized (§3 LANE 3-4): maker APPROVE → approver APPROVE ผ่าน
POST /{instanceId}/steps/{stepInstanceId}/action {APPROVE}— ต้องส่งTaskId(APPROVE-เดินต่อ settaskProgress→ guard) → ใช้ TS task_id (port-forward) เหมือน /rework · branch นี้ proven local (FULL7 FX-…88) แต่ยังไม่ replay บน cluster - branch Reject (§4.1) + OC→US return (US Status flips InReview/Reviewed/Approved) บน cluster — เอกสารนี้ verify ฝั่ง WF; ยังไม่ดึง US
FlowInstance.Statusมายืนยัน - invitation email / NS in-app → requestor หลัง approve (M2b หยุดก่อน Completed จึงยังไม่ทริกเกอร์)
🔴 บล็อค
| จุด | อาการ / ต้องการ |
|---|---|
| cleanup #50/#53 | จบที่ Status=RUNNING, DocStatus=ReSubmitted → ค้างในคิว AdminMaker จริง บน shared dev · /cancel = shared-resource change → classifier block ผม → ต้อง user อนุมัติ/รันเอง (POST /{id}/cancel {instanceId,taskId,userId,reason} + port-forward TS) |
| maker/approver notification | role-lookup ไม่เจอ user จริง → NoRecipient (เหมือน local 🟡) · ต้องมี real admin user map กับ role GUID AdminMaker/AdminApprover ใน dev US DB |
WF instances/db/by-document | 🐛 ComponentNotRegisteredException (Autofac, WorkflowController.cs:156) บน deployed image → endpoint พัง · workaround = ใช้ instances/by-document (DocStatus เดียวกัน) · ส่ง WF team |
| env=Development durability | deployed WF (dev-99eaf44) มี ASPNETCORE_ENVIRONMENT=Development แล้ว (ไม่ crash) — แต่ถ้ามาจาก manual patch ไม่ใช่ IaC อาจหายตอน ArgoCD sync → confirm PR 955 merge |
side-effect ที่ยอมรับ
ทุก run register Entra account จริง (+alias/dot) ใน dev CIAM + สร้าง draft instances (FX-…95/96/97/98 = SaveDraft-only ไม่มีพิษ) + real WF/TS/OC state ต่อ refNo
6. รันซ้ำยังไง (reproduce)
driver: Atlas docs/orchestration-integration/28062026/E2E_DRIVER.py (Python stdlib + redis)
prereq (ต้องเปิดพร้อมกัน):
- VPN เข้า dev (Redis private endpoint)
redis_conn.txt(host/port10000/usernamedefault/access-key) — ห้าม commit (live key)kubectl -n superappdev port-forward svc/task-service 5601:80(สำหรับ task_id ใน /rework)
REDIS_CONN_FILE=/path/redis_conn.txt python E2E_DRIVER.py
# → [VERIFY PASS] refNo=FX-... WF#.. task=..: resubmit=200 + DocStatus=ReSubmitted