Skip to content

GitLab

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • H happy-qa
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 11
    • Issues 11
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Metrics
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Infrastructure Registry
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Pornpavit Tantilavasute
  • happy-qa
  • Issues
  • #4

Closed
Open
Created Sep 23, 2026 by Pornpavit Tantilavasute@joe_qaMaintainer0 of 7 tasks completed0/7 tasks

[QA Brain MVP] T4: Case-Insensitive Substring/Keyword Search Baseline & Query Service

สรุปงาน (Summary)

พัฒนา QA Brain Query Service สำหรับการค้นหาและเรียกดู Gotchas โดยวางโครงสร้าง Pre-Query Authorization Filtering ที่รัดกุม, การแยก Semantics ของพารามิเตอร์ projectId เป็น 3 รูปแบบอย่างชัดเจน, การปิดกั้นข้อมูล DRAFT เป็นค่าตั้งต้น (Strict DRAFT Boundary Isolation), การรองรับ includeDeprecated, และใช้ระบบค้นหา Substring/Keyword (ILIKE) ที่ครอบคลุมทั้ง title, what, tags และ evidenceRef เป็น MVP Baseline

อ้างอิงข้อกำหนดสถาปัตยกรรม: Canonical RFC v4.1 (Section 2.1, 2.4, 2.5, 5.2, 5.3)
ลำดับการทำงาน (Dependency): ขึ้นต่อกับ T1 (ต้องมี Data Model)


ขอบเขตและงานที่ต้องทำ (Scope of Work)

1. นิยามความหมายของ projectId 3 รูปแบบอย่างชัดเจน (3-Tier Project Semantics)

เพื่อป้องกันความคลุมเครือระหว่างการค้นหาทั่วทั้งเวิร์กสเปซกับการค้นหารายโปรเจกต์ ให้สร้าง Where Clause ตามพารามิเตอร์ที่ส่งเข้ามาดังนี้:

รูปแบบพารามิเตอร์ projectId ความหมายและพฤติกรรมการค้นหา เงื่อนไข SQL Where Clause
1. ไม่ส่ง (Omitted / Undefined) ค้นหา Gotcha ส่วนกลางของ Workspace รวมกับ ทุกโปรเจกต์ที่ Caller ถือ Grant อยู่ workspace_id = :wsId AND (project_id IS NULL OR project_id IN (:authorizedProjectIds))
2. ส่งค่า null อย่างชัดแจ้ง (projectId: null) ค้นหา เฉพาะ Gotcha ส่วนกลางระดับ Workspace เท่านั้น (ไม่ดึงข้อมูลของโปรเจกต์ใดเลย แม้จะมีสิทธิ์) workspace_id = :wsId AND project_id IS NULL
3. ระบุ ID โปรเจกต์ (projectId: "proj-123") ตรวจสอบว่า Caller มี Grant ใน proj-123 หรือไม่ (หากไม่มี ให้ตอบกลับ HTTP 403 FORBIDDEN) $\rightarrow$ ค้นหา Gotcha ของโปรเจกต์นั้น รวมกับ Gotcha ส่วนกลางระดับ Workspace workspace_id = :wsId AND (project_id = 'proj-123' OR project_id IS NULL)
  • ข้อกำหนดสำคัญ: ห้าม ทำ Post-query in-memory filtering เพื่อป้องกันปัญหา Information Leakage และ Pagination Keyset เคลื่อน

2. DRAFT & DEPRECATED Boundary Isolation

  • สำหรับคำสั่งค้นหา (query):
    • ค่าตั้งต้น (includeDraft = false, includeDeprecated = false): ต้องกรอง status = 'VERIFIED' เท่านั้น
    • กรณีส่ง includeDraft = true: ผู้เรียกต้องมีบทบาทระดับ QA_EDITOR+ ในโปรเจกต์นั้น (หรือ WORKSPACE_EDITOR+ สำหรับ Workspace Draft) หากไม่มีสิทธิ์ ให้ปฏิเสธหรือเพิกเฉย
    • กรณีส่ง includeDeprecated = true: ยอมให้ผลลัพธ์รวมบทเรียนสถานะ DEPRECATED มาด้วย (สำหรับ Web UI แท็บ Deprecated) โดยยังคงซ่อน DRAFT ไว้ตามเดิม
  • สำหรับคำสั่งเรียกดูรายข้อ (get_entry):
    • หาก Gotcha ที่ขอมีสถานะเป็น DRAFT และผู้เรียกไม่ได้ส่ง includeDraft = true หรือไม่มีสิทธิ์ Editor ให้ตอบกลับ HTTP 404 NOT_FOUND เพื่อป้องกัน Resource Enumeration
    • หาก Gotcha เป็น DEPRECATED ต้องส่ง includeDeprecated = true (และมีสิทธิ์ QA_EDITOR+) จึงจะอ่านได้

3. MVP Substring / Keyword Search Engine (รวม evidenceRef)

  • ใช้ Case-Insensitive Substring Matching (ILIKE) บน PostgreSQL:
    • ทำการตัดคำค้นหา (Query Tokens) ด้วยช่องว่าง
    • จับคู่ค้นหาใน 4 ฟิลด์หลัก: title, what, evidenceRef, และสมาชิกใน tags Array
    • รองรับการค้นหาคำสำคัญทั้งภาษาไทยและภาษาอังกฤษ
  • มีคำเตือนมาตรฐาน (disclaimer) แนบในผลลัพธ์: "Search uses case-insensitive keyword matching baseline. Complex semantic queries may require exact terms."

4. Cursor-Based Pagination

  • รองรับพารามิเตอร์ limit (1 ถึง 20, ค่าตั้งต้น 5)
  • ใช้ Keyset / Cursor Pagination อิงตามคู่ (createdAt, id)
  • ส่งคืน nextCursor ที่ปลอดภัย (Base64 encoded) และ totalMatches

เกณฑ์การตรวจรับ (Acceptance Criteria)

  • Explicit Null Scope Test: เมื่อส่ง projectId: null ระบบต้องส่งคืนเฉพาะ Gotcha ที่ projectId IS NULL เท่านั้น ไม่ปน Gotcha ของโปรเจกต์ใดเลย
  • Omitted Scope Test: เมื่อไม่ส่ง projectId ระบบส่งคืน Gotcha ของทุกโปรเจกต์ที่ผู้ใช้มีสิทธิ์ รวมกับ Gotcha ส่วนกลาง
  • Explicit ID Scope Test: ส่ง projectId = "proj-A" ได้เฉพาะ Gotcha ของ proj-A + ส่วนกลาง; หากส่ง ID โปรเจกต์ที่ไม่มีสิทธิ์ ได้รับ HTTP 403 FORBIDDEN
  • DRAFT Immunity Test: การเรียกค้นหาแบบปกติจะไม่เห็น Gotcha สถานะ DRAFT เด็ดขาด
  • EvidenceRef Search Test: ค้นหาด้วย Run ID หรือ Commit Hash ใน evidenceRef แล้วได้ผลลัพธ์ถูกต้อง
  • Deprecated Filter Test: เมื่อส่ง includeDeprecated = true ได้รับ Gotcha สถานะ Deprecated ปรากฏในผลลัพธ์
  • Unverified Get Rejection: การยิง get_entry ขอ ID ของบทเรียน DRAFT โดยไม่ส่งสิทธิ์ Editor ต้องได้รับผลลัพธ์ NOT_FOUND
Edited Sep 24, 2026 by Pornpavit Tantilavasute
Assignee
Assign to
Time tracking