Private Docs

AMLO Screening — Open Concerns (ความเสี่ยงที่ยังเปิดอยู่)

รายการความเสี่ยงที่ยังไม่ปิด ณ วันส่งมอบ data tier — อะไรบล็อก deploy, อะไรบล็อกงานชิ้นถัดไป, อะไรเป็นหนี้ที่รู้ตัวแล้วยอมรับไว้ พร้อมเงื่อนไขปิดของแต่ละข้อ

อัปเดต: 2026-08-21

หน้านี้ไม่ใช่ TODO list — เป็นรายการของที่ “รู้ว่าเสี่ยง แต่ยังไม่ปิด” พร้อมเหตุผลว่าทำไมถึงยังไม่ปิด และต้องเห็นอะไรถึงจะปิดได้ สถานะของที่ลงไปแล้ว → Data Tier Handoff


สรุปตาราง

#เรื่องระดับบล็อกอะไรเจ้าของ
1SSH.NET 2026.0.0 ยังไม่เคยรันจริง🔴 สูงdeploydev ที่ deploy service
2migration ไม่เคยถูก test suite รัน🟡 กลางความมั่นใจของ migration รอบถัดไปdev
3ไม่มี pipeline ไหนรัน migration🟡 กลางทุก deploy (manual step)DevOps / dev
4คีย์จัดกลุ่มยังไม่มีมติจาก Compliance🟡 กลางงานชิ้นถัดไป (ตัวสร้าง generation)Compliance
5read path เดิมยังเทียบ CustCode ดิบ🟢 หนี้ที่รู้ตัวไม่บล็อกdev (แก้ตอนแตะ endpoint)
6ไม่มีทางสร้าง fingerprint เวอร์ชันเก่า🟢 หนี้ที่รู้ตัวไม่บล็อก จนกว่าจะต้อง backfilldev
7SIT ช้ากว่า 3 migration🟢 รับทราบไม่บล็อก (เลิกใช้แล้ว)ทีม
8DB ล้ำหน้า code ที่ deploy🟢 รับทราบไม่บล็อก (migration เพิ่มอย่างเดียว)
9PII / retention ของ snapshot_detail🟡 กลางPhase 2Compliance / Security

1. 🔴 SSH.NET 2026.0.0 ยังไม่เคยรันกับ SFTP จริง — บล็อก deploy

อัปจาก 2024.2.02026.0.0 เพื่อปิด CVE-2026-48798 (path traversal ใน ScpClient) ปัญหาคือ ไม่มี test สักตัวที่แตะ Sftp / SSH / Renci และผู้ใช้เดียวคือ src/Centralized02.Infrastructure/Sftp/SshNetSftpFileSource.cs ⇒ build ผ่านและ test 851 ตัวผ่าน ไม่ได้พิสูจน์อะไรเลยเกี่ยวกับ SFTP

CVE ตัวที่แก้อยู่ที่ ScpClient ซึ่งเราไม่ได้ใช้ (เราใช้ SftpClient) — แต่ระหว่างทางมี behaviour change ที่เห็นได้เฉพาะตอน runtime 2 เรื่อง:

เวอร์ชันเปลี่ยนอะไรกระทบเราตรงไหน
2025.0.0ตัด DSA ออกถ้า host key ของฝั่ง server หรือ private key ใน Key Vault เป็น DSA → พังที่ client.Connect() (~บรรทัด 28)
2025.1.0”Fix SftpFileAttributes file type detection”กระทบ f.IsRegularFile (~บรรทัด 32–33) — เปลี่ยนได้ว่าไฟล์ไหนถูก ingest โดยไม่มี error ให้เห็น
2025.1.0เพิ่มการตรวจ host key algorithm, แยก PrivateKeyFile ตามรูปแบบ keyอาจ reject key ที่เคยรับได้

2025.1.0 → 2026.0.0 ต้นทางระบุว่า breaking change “None known”

เงื่อนไขปิด — smoke test กับ endpoint จริงของ dev/uat ด้วย key จริงจาก Key Vault:

  • Connect() ผ่าน
  • ListDirectory คืนรายการไฟล์เท่าเดิมกับที่ 2024.2.0 เคยคืน (ข้อนี้สำคัญที่สุด — ถ้าไฟล์หายไปเงียบๆ จะกลายเป็น “ไม่มีไฟล์ใหม่” ซึ่งระบบถือว่าปกติ)
  • ReadAllText อ่านไฟล์ได้ครบ
  • ยืนยันว่า host key และ client key ไม่ใช่ DSA

ℹ️ ข้อนี้ไม่เกี่ยวกับ migration ที่ลง DEV/UAT ไปแล้ว — ตารางเปล่ายังไม่มีใครเขียน จะ rollback หรือรอได้โดยไม่กระทบอะไร


2. 🟡 migration ไม่เคยถูก test suite รัน

tests/Centralized05.Tests/TestSupport/SqliteAuthDbContext.cs ใช้ EnsureCreated() ซึ่ง สร้าง schema จาก model ตรงๆ ข้าม migration ทั้งหมด ⇒ test 851 ตัวพิสูจน์ว่า model ถูก ไม่ได้พิสูจน์ว่า migration ถูก

has-pending-model-changes = none ก็ตอบแค่ว่า model กับ migration ล่าสุดตรงกัน ไม่ได้ตอบว่า migration รันผ่าน

รอบนี้ชดเชยด้วยการรันกับ Postgres จริงบน DEV/UAT แล้วยิงทดสอบพฤติกรรม 10 ข้อ (Handoff §5) — แต่เป็นการทำมือ ไม่ได้อยู่ใน CI

เงื่อนไขปิด: มี integration test ที่รัน Database.Migrate() กับ Postgres จริง (Testcontainers) อย่างน้อย 1 ตัว — หรือยอมรับว่าทุก migration ต้องทำ manual verification แล้วเขียนไว้ใน definition of done

ℹ️ ผลข้างเคียงที่แก้ไปแล้วระหว่างทาง: connection string ของ SQLite เดิมไม่ได้ระบุ Foreign Keys=True ⇒ test เรื่อง cascade เคยผ่านแบบไร้ความหมาย ตอนนี้เปิดแล้ว


3. 🟡 ไม่มี pipeline ไหนรัน migration

ตรวจแล้วทั้ง ci.yml, ci-sit.yml, ci-orchestrate.ymlไม่มี step รัน migration ทุก env ต้องมีคนรัน script เอง

ผลที่ตามมาคือ env drift แบบที่เห็นอยู่ตอนนี้: DEV/UAT อยู่ที่ migration ล่าสุด ส่วน SIT ช้ากว่า 3 ตัว (ข้อ 7)

เงื่อนไขปิด: ตัดสินใจอย่างใดอย่างหนึ่ง — เพิ่ม step ลง pipeline หรือประกาศให้ชัดว่าเป็น manual runbook แล้วเขียน runbook ไว้ (ตอนนี้อยู่ที่ Handoff §7 ซึ่งเป็นเอกสาร sprint ไม่ใช่ runbook ถาวร)


4. 🟡 คีย์จัดกลุ่มยังไม่มีมติ — บล็อกงานชิ้นถัดไป

ตัวสร้าง generation เขียนไม่ได้จนกว่าจะรู้ว่าจัดกลุ่มด้วยคีย์อะไร ข้อเสนอจากฝั่ง dev คือ (CustCode, RecordGuid) พร้อมหลักฐานวัดจากไฟล์จริงแล้วที่ Phase 1 §3.2 แต่เป็นคำถามของ Compliance ไม่ใช่ของ dev

schema รองรับได้ทุกทางเลือกแล้ว (เก็บ RecordGuid, SubjectId, CtlId ครบ) จึงไม่บล็อก data tier — บล็อกเฉพาะโค้ดที่จัดกลุ่ม

คำถามพ่วงที่ต้องถามพร้อมกัน: การเปลี่ยนบทบาท (CustTypeDesc) ถือเป็นหลักฐานใหม่ที่ต้องทบทวนหรือไม่ — มีผลกับ EvidenceFingerprint โดยตรง ซึ่งแปลว่ามีผลกับการ revoke สิ่งที่อนุมัติไปแล้ว

เงื่อนไขปิด: Compliance ยืนยันคีย์เป็นลายลักษณ์อักษร → บันทึกเป็น ADR → เก็บคีย์ไว้เป็น constant/config จุดเดียว ห้าม hardcode กระจาย


5. 🟢 read path เดิมยังเทียบ CustCode ดิบ

AmloScreeningMatchRepository (~บรรทัด 36) ยังเทียบ x.CustCode == custCode ตรงๆ ⇒ GET /v1/amlo-screening/{custCode} ตอบ NotFound ให้ " abc123 " ทั้งที่ amlo_screened_company จับคู่ได้

ทำไมยังไม่แก้: ตารางนั้นคือ staging ซึ่งอยู่คนละชั้นกับ ADR 0007 และการแก้จะเปลี่ยนพฤติกรรมของ endpoint ที่มีคนใช้อยู่ — ควรแก้พร้อม test เทียบก่อน/หลัง ไม่ใช่แถมมากับ migration

เงื่อนไขปิด: แก้ตอนแตะ endpoint นั้นรอบหน้า พร้อม test ว่า " abc123 " กับ ABC123 ให้ผลเดียวกัน · บันทึกไว้แล้วที่ Phase 1 §7 และใน ADR 0007


6. 🟢 สร้าง fingerprint เวอร์ชันเก่าไม่ได้แล้ว

ADR 0008 บังคับให้ Create ปั๊ม FingerprintVersion จาก CurrentVersion เสมอ — โดยตั้งใจ เพื่อกันแถวที่ label ไม่ตรงสูตร

ผลข้างเคียงคือ backfill หรือการคำนวณย้อนหลังทำผ่าน Create ไม่ได้ ห้ามแก้โดยเปิดให้ Create รับ version กลับมา (จะย้อนกลับไปหาปัญหาที่ ADR 0008 ปิดไปทันที) ต้องทำเป็นทางเข้าแยกที่มีเจตนาชัดเจน

เงื่อนไขปิด: เมื่อมี requirement backfill จริง — ยังไม่มี


7. 🟢 SIT ช้ากว่า 3 migration

SIT_CentralizedDb อยู่ที่ 20260608112601_RenameDocumentNumberTables ทีมยืนยันว่าเลิกใช้ SIT แล้ว จึงไม่ migrate ให้

บันทึกไว้เพื่อกันคนกลับมาเปิด SIT ใหม่แล้วคิดว่ามันพร้อมใช้ — ต้องไล่ migration 3 ตัวก่อน ไม่ใช่แค่ deploy service


8. 🟢 DB ล้ำหน้า code ที่ deploy อยู่

DEV/UAT มีตาราง 3 ตัวแล้วแต่ยังไม่มี service เวอร์ชันที่รู้จักมัน — ปลอดภัยเพราะ migration เพิ่มอย่างเดียว ไม่มี ALTER/DROP ของเดิม และตารางว่างเปล่า

บันทึกไว้เพราะเวลาไล่ปัญหาแล้วเจอตารางที่ code ไม่ได้ใช้ จะได้ไม่คิดว่าเป็นขยะที่ลบทิ้งได้


9. 🟡 PII และ retention ของ snapshot_detail

snapshot_detail เก็บ ชื่อบุคคลที่สาม (ไทย/อังกฤษ) เป็น text ธรรมดา ไม่เข้ารหัส และยังไม่มี retention policy

ADR 0006 ตั้งใจให้ snapshot เป็นที่เดียวที่ต้องคุยเรื่อง retention (staging ลบได้) แต่ยังไม่มีใครตอบว่า เก็บนานเท่าไหร่ และ ต้องเข้ารหัสไหม

กฎที่บังคับไว้แล้วระหว่างที่ยังไม่มีคำตอบ: คอลัมน์ชื่อ ห้ามโผล่ใน API response หรือ log ใดๆ — เป็นเงื่อนไขรับงานข้อหนึ่งของ Phase 1

เงื่อนไขปิด: Compliance/Security ตอบ retention + การเข้ารหัส → ทำเป็น ADR