4 นาที

gate ใดของ pull request จากเอเจนต์ที่ควรบล็อกการผสานโค้ด?

ใช้ gate สำหรับ pull request ของเอเจนต์ 7 แบบที่วัดผลได้ เพื่อหยุดโค้ดไม่ปลอดภัย: tests, CodeQL, dependencies, secrets, authorization, migrations และ rollback

gate ใดของ pull request จากเอเจนต์ที่ควรบล็อกการผสานโค้ด?

เอเจนต์อาจสร้าง diff ที่สะอาด คำอธิบายที่น่าเชื่อ และโค้ดที่ผ่านการรีวิวอย่างรวดเร็วได้ แต่แอปพลิเคชันยังอาจมีช่องโหว่หรือกู้คืนไม่ได้ การตัดสินใจผสานโค้ดจึงควรอิงหลักฐานที่รีโพซิทอรีวัดได้ ไม่ใช่อิงน้ำเสียงที่เอเจนต์พูดอย่างมั่นใจหรือขนาดของแพตช์ที่ดูเล็ก

ผมใช้ gate ที่บล็อกอยู่เจ็ดอย่าง ได้แก่ การทดสอบ, CodeQL, การตรวจสอบ dependencies, การสแกน secrets, การตรวจสอบการอนุญาต, การซ้อม migration และการยืนยัน rollback แต่ละอย่างตอบคำถามเรื่องความล้มเหลวคนละแบบ ชุดทดสอบที่ผ่านไม่ได้พิสูจน์ว่าแพ็กเกจใหม่ปลอดภัย และผล static analysis ที่สะอาดก็ไม่ได้บอกว่า database migration จะล็อกตารางที่ใช้งานหนักที่สุดหรือไม่

gate เหล่านี้ใช้กับการเปลี่ยนแปลงจากมนุษย์และเอเจนต์เหมือนกัน การที่เอเจนต์เป็นผู้เขียนเปลี่ยนปริมาณ ความเร็ว และลักษณะของข้อผิดพลาด แต่ไม่ใช่เหตุผลให้มีเส้นทางที่แยกออกมาและอ่อนแอกว่า หากการเปลี่ยนแปลงที่เสนอให้หลักฐานแบบเดียวกับ pull request อื่นไม่ได้ ก็ยังไม่พร้อมผสานโค้ด

gate ต้องให้หลักฐาน ไม่ใช่คำแนะนำ

gate สำหรับผสานโค้ดควรให้ผลผ่านหรือไม่ผ่านที่ทำซ้ำได้ สำหรับ commit เดียวกันที่จะเข้าสู่ protected branch คอมเมนต์ที่บอกว่า "โปรดตรวจสอบ dependency นี้" คือคำแนะนำ ส่วนการตรวจสอบที่จำเป็นซึ่งระบุแพ็กเกจ เวอร์ชัน advisory และเกณฑ์ความรุนแรง คือหลักฐาน

ความต่างนี้สำคัญ เพราะฟีเจอร์ด้านความปลอดภัยจำนวนมากตั้งค่าเริ่มต้นให้รายงานหลังจากจุดตัดสินใจที่มีประโยชน์ผ่านไปแล้ว สแกนเนอร์อาจสร้าง alert ส่งอีเมล หรือเปิด issue ขณะที่ปุ่มผสานโค้ดยังใช้งานได้ ทีมจึงบอกว่าเปิดใช้การสแกนแล้ว ทั้งที่มันหยุดการเปลี่ยนแปลงไม่ได้ สำหรับทุก gate ให้ยืนยันคุณสมบัติสี่ข้อ:

  • มันรันกับ head commit ปัจจุบันของ pull request
  • branch protection บังคับผลลัพธ์ที่ระบุชื่อของมัน
  • งานที่ถูกข้าม หมดเวลา หรือแครช ไม่นับว่าผ่าน
  • ผลลัพธ์บันทึกรายละเอียดเพียงพอที่จะทำซ้ำการตัดสินใจได้

เก็บนโยบายไว้ในรีโพซิทอรี manifest ขนาดเล็กช่วยให้รีวิวง่ายกว่าชุดการตั้งค่าที่มีเพียงผู้ดูแลระบบเท่านั้นที่รู้:

merge_gates:
  tests: required
  codeql: required
  dependency_review: required
  secret_scan: required
  authorization: required
  migration_rehearsal: required_when_changed
  rollback_verification: required

ค่า required_when_changed ไม่ใช่ช่องโหว่ หมายความว่า gate จะตรวจหาไฟล์ที่เกี่ยวข้องก่อน แล้วจึงซ้อมหรือบันทึกผลที่ชัดเจนว่า "ไม่เกี่ยวข้อง" อย่าให้ path filters ทำให้การตรวจสอบที่จำเป็นค้างอยู่ตลอดไป และอย่าให้เอเจนต์ตัดสินเองว่าการเปลี่ยนแปลงที่เสี่ยงของตนได้รับยกเว้น

กำหนดสิทธิ์ของ workflow ให้เหลือเท่าที่แต่ละงานจำเป็น โค้ดใน pull request คืออินพุตที่ไม่น่าเชื่อถือ แม้บรাঞ্চนั้นจะเป็นขององค์กรคุณ gate ที่เผย write token หรือ production secret ให้โค้ดที่กำลังตรวจอยู่ อาจสร้างปัญหาที่แย่กว่าสิ่งที่ตั้งใจจะจับได้

ปกป้องตัวตนของ check ให้รอบคอบพอ ๆ กับตรรกะของมัน กฎของบรাঞ্চมักบังคับชื่อสถานะ ดังนั้น workflow สองรายการที่รายงานชื่อเดียวกันได้ อาจทำให้งานที่อ่อนแอกว่าผ่านกฎนั้น ตั้งชื่อเฉพาะให้ policy job จำกัดผู้ที่แก้ workflow ได้ และบังคับให้เจ้าของไฟล์นั้นรีวิว เมื่อ merge queue สร้าง merge commit ใหม่ ให้รัน gates กับ commit นั้นอีกครั้ง หรือใช้ฟีเจอร์ของแพลตฟอร์มที่ผูกผลลัพธ์กับ revision ในคิว หลักฐานของ head เมื่อวานไม่ใช่หลักฐานของการผสานในวันนี้

ถือว่าการตั้งค่า gate เองเป็นโค้ดที่ละเอียดอ่อน pull request ที่เปลี่ยนเกณฑ์ ลบ path ลดระดับ query pack หรือเพิ่มข้อยกเว้น ย่อมเปลี่ยนความหมายของผลสีเขียวทั้งหมดหลังจากนั้น แสดง diff ของนโยบายให้เด่น และบังคับให้ maintainer ที่เข้าใจ control ที่ได้รับผลกระทบรีวิว เอเจนต์เสนอการเปลี่ยนแปลงเช่นนี้ได้ แต่ต้องไม่ผ่านง่ายขึ้นเพียงเพราะแก้กลไกที่ใช้ตัดสินตัวเอง

การทดสอบบล็อก regression ที่สังเกตได้

gate การทดสอบควรบล็อกทุกการเปลี่ยนแปลงที่ทำให้พฤติกรรมตามข้อกำหนดพังบน runtime และเวอร์ชันฐานข้อมูลที่รองรับ ต้องรันด้วยอินพุตการ build เดียวกับที่ merge commit จะใช้ รวมถึง dependencies ที่ล็อกไว้ ไฟล์ที่สร้างขึ้น feature flags และสถานะ schema

เอเจนต์เก่งเป็นพิเศษในการทำให้ assertion ที่ใกล้ที่สุดผ่าน อาจเพิ่ม fallback ที่ทำให้เทสต์หนึ่งผ่าน แต่ทำให้การจัดการข้อผิดพลาด การแบ่งหน้า concurrency หรือสัญญา API ข้างเคียงพัง บังคับให้ pull request เพิ่มหรือแก้เทสต์เมื่อเปลี่ยนพฤติกรรม แต่อย่าวัดคุณภาพจากจำนวนบรรทัดเทสต์ใหม่ ตรวจว่าเทสต์นั้นจะล้มเหลวหรือไม่ หากลบหรือย้อน implementation ออก

gate การทดสอบที่ดีมีหลายชั้นและตั้งชื่อแยกกัน:

  • Unit tests สำหรับตรรกะเฉพาะจุดและกรณีขอบเขต
  • Integration tests สำหรับสัญญาของฐานข้อมูล queue cache และบริการภายนอก
  • Contract tests สำหรับรูปแบบ request และ response แบบสาธารณะ
  • Smoke test ขนาดเล็กกับ artifact ที่ build แล้ว

จัดการ flaky tests จนถึงต้นเหตุ แทนที่จะให้ retry อัตโนมัติไปจนผ่าน การ retry หนึ่งครั้งอาจเก็บหลักฐานเพื่อวินิจฉัยได้ แต่สถานะสุดท้ายควรแสดงความล้มเหลวครั้งแรก ไม่เช่นนั้นเอเจนต์อาจผสานโค้ดที่พิสูจน์ได้เพียงว่าบางครั้งมันทำงาน

smoke test ควรเริ่ม artifact เรียกใช้ health endpoint และเส้นทางเขียนข้อมูลที่มีความหมายหนึ่งเส้นทาง จากนั้นหยุดอย่างสะอาด การทดสอบซอร์สโค้ดโดยไม่เริ่มแอปที่แพ็กแล้วจะพลาดไฟล์ที่หายไป ค่า environment เริ่มต้นที่ผิด migrations ที่พัง และ startup panics สำหรับเว็บเซอร์วิส อาจบันทึกผลแบบกระชับได้ดังนี้:

{"commit":"abc123","build":"pass","startup_ms":842,"health":200,"write_read_cycle":"pass"}

อย่ากำหนดเปอร์เซ็นต์ coverage แบบเดียวสำหรับทุกที่ให้เป็น gate หลัก Coverage อาจบอกว่าการเปลี่ยนแปลงยังไม่ถูกทดสอบ แต่รีโพซิทอรีอาจได้เปอร์เซ็นต์สูงจาก assertion ที่อ่อนแอ กำหนด gate ตามชุดทดสอบที่บังคับและพฤติกรรมที่เปลี่ยน แล้วใช้การเปลี่ยนแปลง coverage เป็นหลักฐานประกอบการรีวิว

ปกป้องเทสต์จาก implementation ที่มันใช้ตัดสิน หาก pull request ทั้งเปลี่ยนกฎและเขียน assertion ใหม่ให้ยอมรับผลใหม่ ชุดทดสอบอาจผ่านทั้งที่สัญญาเปลี่ยนไปอย่างเงียบ ๆ ให้ผู้รีวิวเปรียบเทียบเทสต์ที่เปลี่ยนกับ public API, issue หรือกฎการยอมรับ สำหรับ parser, validator, ตรรกะการเรียกเก็บเงิน และการตรวจสิทธิ์ ให้เพิ่ม mutation testing หรือชุดอินพุตที่ผิดโดยเจตนาขนาดเล็ก คำถามที่มีประโยชน์คือชุดทดสอบปฏิเสธ implementation ที่ผิดแต่น่าเป็นไปได้หรือไม่ ไม่ใช่เอเจนต์ทำให้ implementation ของตัวเองผ่าน assertion ที่ตัวเองเขียนได้หรือไม่

เก็บ artifacts ของเทสต์เมื่อ gate ล้มเหลว เก็บ seed ที่ทำให้เทสต์สุ่มล้มเหลว image ฐานข้อมูลที่แน่นอน service logs ที่ลบ secrets แล้ว และคำสั่งที่ทำซ้ำการรันได้ สถานะที่ไม่มีข้อมูลทำซ้ำทำให้เอเจนต์หรือวิศวกรคนถัดไปต้องกลับไปเดา กำหนดเวลาการเก็บ artifact ตามกฎข้อมูลของรีโพซิทอรี และอย่าอัปโหลด production snapshot เพียงเพราะทำให้ทำซ้ำความล้มเหลวง่าย

CodeQL บล็อกเส้นทางโค้ดที่รู้ว่าไปสู่ช่องโหว่

gate CodeQL ควรบล็อก findings ใหม่ที่มีความเชื่อมั่นสูง ในภาษาและ artifacts ที่สร้างขึ้นซึ่ง CodeQL วิเคราะห์จริง ไม่ควรทำให้เข้าใจว่าผลสะอาดพิสูจน์ว่าแอปทั้งหมดปลอดภัย

GitHub อธิบายว่า CodeQL คอมไพล์โค้ดเป็นฐานข้อมูลที่ใช้ query ได้ แล้วรัน queries บนฐานข้อมูลนั้น โมเดลนี้มีประโยชน์เพราะติดตามข้อมูลผ่านโค้ด แทนการจับเพียงข้อความที่น่าสงสัย แต่ก็มีขอบเขตจากภาษาที่รองรับ ความสำเร็จของ build การเลือก query และโค้ดที่มีอยู่ขณะวิเคราะห์ หากการสร้างฐานข้อมูลตัด service ออกอย่างเงียบ ๆ ผลสีเขียวก็ครอบคลุมน้อยกว่าที่ผู้รีวิวคิด

ใช้ workflow ที่ระบุภาษาอย่างชัดเจนและมีนโยบาย query ที่คงที่:

name: codeql
on: [pull_request]
permissions:
  contents: read
  security-events: write
jobs:
  analyze:
    strategy:
      matrix:
        language: [javascript-typescript, go]
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
          queries: security-extended
      - uses: github/codeql-action/autobuild@v3
      - uses: github/codeql-action/analyze@v3

ในรีโพซิทอรีจริง ให้ pin third party actions กับ commit digests ที่รีวิวแล้ว Tags ทำให้ตัวอย่างอ่านง่าย แต่ tag ที่เปลี่ยนได้ขยายขอบเขตความเชื่อถือของงานความปลอดภัยที่บังคับ

ตัดสินว่าอะไรต้องบล็อกก่อน alert แรกจะปรากฏ โดยปกติผมบล็อก findings ใหม่ตามเกณฑ์ความรุนแรงและความแม่นยำที่รีโพซิทอรีตกลงกัน ส่วนหนี้เดิมยังคงมองเห็นได้ใน baseline การบล็อกผลในอดีตทุกอันตั้งแต่วันแรกผลักให้เกิดการ dismiss ครั้งใหญ่ การละเลยผลเดิมทั้งหมดตลอดไปสร้างจุดบอดถาวร ให้มอบหมายเจ้าของและกำหนดวันครบกำหนดแก่ baseline แทน

ตรวจสอบชุดไฟล์ที่วิเคราะห์เมื่อ services, ภาษา หรือคำสั่ง build เปลี่ยน pull request ที่เพิ่ม mobile client ใหม่ generated resolver หรือ backend แยกต่างหาก อาจต้องใช้ analyzer หรือขั้นตอน build เพิ่มเติม คำว่า "CodeQL ผ่าน" มีความหมายก็ต่อเมื่อผู้รีวิวบอกได้ว่า CodeQL ตรวจอะไรบ้าง

แยกความล้มเหลวในการวิเคราะห์ออกจากการวิเคราะห์ที่สะอาด หาก autobuild คอมไพล์แพ็กเกจไม่ได้ งานต้องรายงานความล้มเหลวด้าน infrastructure หรือการตั้งค่า ไม่ใช่ zero findings เก็บ log การสร้างฐานข้อมูลและจำนวนไฟล์ซอร์สที่วิเคราะห์ตามภาษา เปรียบเทียบจำนวนเหล่านี้กับ base branch แล้วแจ้งเตือนหากลดลงมากโดยไม่มีคำอธิบาย วิธีนี้จับความล้มเหลวทั่วไปได้: การแก้ build ตัดโมดูลที่มีช่องโหว่ออก การวิเคราะห์เร็วขึ้น และ check ความปลอดภัยเป็นสีเขียวเพราะเห็นโค้ดน้อยลง

รีวิวการ dismiss เหมือนการเปลี่ยนนโยบาย ไม่ใช่งานเก็บกวาด false positive ต้องมีคำอธิบายที่เฉพาะเจาะจงและผูกกับเส้นทางโค้ดและ query suppression comments ควรแคบ มีเจ้าของ และมองเห็นได้ใน diff ของ pull request การยกเว้นทั้งรีโพซิทอรีสำหรับไฟล์ที่สร้างขึ้นอาจเหมาะสม แต่ก่อนอื่นต้องยืนยันว่าไม่มี templates ที่ดูแลเองหรืออินพุตของ generator อยู่ในไดเรกทอรีนั้น

การตรวจสอบ dependencies หยุดความเสี่ยงก่อนติดตั้ง

การตรวจสอบ dependencies ควรบล็อก pull request เมื่อ dependency diff ของมันเพิ่มแพ็กเกจหรือเวอร์ชันที่ละเมิดนโยบายที่ระบุชัด นโยบายนั้นอาจรวมความรุนแรงของ advisory ที่ทราบ licenses ที่ห้าม แหล่งแพ็กเกจที่ไม่คาดคิด และ direct dependencies ที่เพิ่มโดยไม่มีเจ้าของ

gate นี้ต่างจาก vulnerability alert ของรีโพซิทอรี Alert บอกว่ามี dependency ที่มีช่องโหว่ในบรাঞ্চ การตรวจสอบ dependencies ถามว่า pull request นี้ทำให้ dependency graph แย่ลงหรือไม่ GitHub dependency review เปรียบเทียบ manifests และ lockfiles ข้าม pull request จึงตัดสินใจได้ทันเวลาและระบุที่มาได้

บังคับความสอดคล้องของ lockfile หากเอเจนต์แก้ package.json แต่ไม่แก้ lockfile หรือแก้ lockfile โดยไม่มีการแก้ manifest ที่สอดคล้องกัน งานควรล้มเหลว คำสั่งติดตั้งที่ resolve เวอร์ชันใหม่ระหว่าง CI ทำให้ผลไม่แน่นอน และอาจทดสอบ graph ที่ต่างจากที่ผู้รีวิวเห็น

นโยบายแบบกระชับอาจเป็นดังนี้:

dependency_policy:
  fail_on_severity: high
  deny_licenses:
    - AGPL-3.0
  allow_sources:
    - registry.npmjs.org
    - proxy.golang.org
  require_owner_for_direct_additions: true

รายการ license ที่แน่นอนไม่ใช่ค่าที่ควรคัดลอกโดยไม่คิด เป็นการตัดสินใจด้านกฎหมายและผลิตภัณฑ์ ส่วนที่มีประโยชน์คือรีโพซิทอรีประกาศไว้ และ check พิมพ์แพ็กเกจที่ทำให้เกิดผลนั้น

อย่าอนุมัติแพ็กเกจอัตโนมัติเพียงเพราะชื่อคล้ายกับไลบรารีที่แนะนำ เอเจนต์อาจหลอนชื่อแพ็กเกจ เลือก fork ที่ถูกทิ้ง หรือเพิ่ม client ขนาดใหญ่เพื่อ helper เล็กน้อยหนึ่งตัว ผลการรีวิวควรแสดงแพ็กเกจ direct และ transitive ที่เพิ่ม registry ต้นทาง เวอร์ชันที่ resolve, license และสถานะ advisory จากนั้นผู้รีวิวถามได้ว่าโค้ดที่มีอยู่หรือ dependency ที่เล็กกว่าจัดการปัญหานี้ได้แล้วหรือไม่

ให้ล้มเหลวแบบปิด หากบริการ dependency สร้าง diff ไม่ได้ advisory feed ที่ใช้งานไม่ได้อาจเป็นเหตุให้ชะลอการผสาน ไม่ใช่เปลี่ยนความไม่แน่นอนเป็น check สีเขียว ขั้นตอนฉุกเฉินอาจอนุญาตให้ maintainer ที่ระบุชื่อข้ามอย่างมีเอกสาร โดยแนบเหตุผลไว้กับ commit

ตรวจพฤติกรรมการติดตั้งในงานแยกที่จำกัด network access ไว้เฉพาะ registries ที่อนุมัติ Lifecycle scripts และ build plugins รันโค้ดระหว่างติดตั้ง ดังนั้นแพ็กเกจอาจอันตรายได้แม้แอปไม่ import มันเลย บันทึกว่า dependency ใหม่เพิ่ม install scripts, native binaries หรือ registry ที่ไม่คุ้นเคยหรือไม่ อย่ารันงานนั้นด้วย publishing credentials, cloud tokens หรือ package cache ที่เขียนได้และแชร์กับ builds ที่เชื่อถือได้

โค้ดที่ vendored และ container images ควรอยู่ในการตัดสินใจเดียวกัน แม้ manifest review ปกติอาจไม่พบ เปรียบเทียบ image digests, ชื่อ base image, Git submodules และ archives ที่เช็กอิน บังคับใช้ immutable digests สำหรับอินพุตของรีลีส tag ที่เป็นมิตร เช่น latest ทำให้ pull request ทำซ้ำภายหลังไม่ได้ เพราะ bytes เปลี่ยนได้โดยไม่มี diff ใหม่

การสแกน secrets ต้องตรวจ diff และประวัติ

ให้ผู้ตรวจเห็น diff ที่แท้จริง
Koder.ai ส่งออกซอร์สโค้ดเพื่อให้รีโพซิทอรีของคุณใช้การตรวจสอบที่บังคับก่อนผสานโค้ดได้

การสแกน secrets ควรบล็อกเมื่อ pull request เพิ่มรูปแบบ credential หรือ secret ที่ยืนยันว่าใช้งานได้ แม้สตริงนั้นจะอยู่ใน test fixture, ไฟล์ที่ลบแล้ว generated bundle หรือ commit ก่อนหน้าใน pull request

Push protection และการสแกน pull request แก้ปัญหาที่เกี่ยวข้องกันแต่ต่างกัน Push protection อาจหยุด secret ที่รู้จักก่อนถึง remote gate ของ pull request ตรวจสิ่งที่มาถึงแล้ว และอาจครอบคลุมผู้ร่วมพัฒนาหรือ token types ที่ push protection พลาด Alert ที่ไม่มี branch protection ไม่ได้บล็อกการผสาน

สแกนช่วง commit ทั้งหมดเทียบกับ base branch ไม่ใช่เฉพาะ filesystem สุดท้าย เอเจนต์อาจเพิ่ม token ใน commit หนึ่งแล้วลบใน commit ถัดไป token ยังอยู่ในประวัติ Git และอาจไปถึง logs หรือ caches แล้ว ให้ถือว่ามันถูกเปิดเผย หมุนเวียนหรือเพิกถอน credential ลบออกจากประวัติที่เสนอ และรัน check อีกครั้ง

ใช้ synthetic fixtures ที่ยืนยันตัวตนไม่ได้ fixture ควรระบุตัวเองอย่างชัดเจน และตรงกับ test pattern ที่กำหนดไว้ในเครื่อง แทนการคัดลอกรูปแบบ cloud key จริง allowlists ที่กว้างอันตราย เพราะทั้งผู้โจมตีและอุบัติเหตุจะพบไดเรกทอรีที่ถูกละเว้นในที่สุด เก็บข้อยกเว้นให้ตรงจุด ผ่านการรีวิว และอยู่ใกล้กับการตั้งค่าตัวตรวจจับ

รวม pattern detectors กับ entropy checks และการยืนยัน credential ในกรณีที่ผู้ให้บริการรองรับอย่างปลอดภัย Pattern matching มีความเสี่ยงด้าน network และการเปิดเผยน้อยกว่า แต่พลาด tokens แบบกำหนดเองได้ การยืนยันช่วยลดความไม่แน่นอนได้ แต่ส่งส่วนหนึ่งของ candidate secret ไปยังบริการอื่น และห้ามรันกับ endpoint ที่ไม่น่าเชื่อถือซึ่ง pull request ระบุไว้โดยเด็ดขาด บันทึกว่า detectors ใดตรวจยืนยัน ตัวใดอยู่ในเครื่อง และข้อมูลใดออกจาก CI

สแกนรูปแบบที่เข้ารหัสทั่วไปและ outputs ที่สร้างขึ้น โดยไม่ทำเหมือนทุกสตริงสุ่มคือ credential Base64, URL encoding และ bundles ที่ minify แล้วอาจซ่อน secret ที่ปรากฏอย่างชัดเจนในขั้นตอนซอร์ส กำหนดเกณฑ์การบล็อกจาก fixtures ที่ทดสอบแล้ว แล้วรีวิวการอัปเดต detector เหมือนการเปลี่ยนนโยบายอื่น สแกนเนอร์ที่ส่งเสียงเตือนมากเกินไปฝึกให้ maintainer dismiss ผล ส่วนสแกนเนอร์ที่เงียบสร้างความมั่นใจปลอม

ผลลัพธ์ของ gate ต้องบอกตำแหน่งโดยไม่เปิดเผย:

{"result":"fail","detector":"generic-api-token","commit":"abc123","path":"config/dev.env","line":7,"fingerprint":"sha256:8f2c..."}

อย่าพิมพ์ค่าที่ตรงกันทั้งหมดลง CI logs หรือคอมเมนต์ใน pull request การ mask หลังสแกนเนอร์ส่ง output อาจช้าเกินไป เพราะระบบ log การแจ้งเตือน และ job artifacts อาจคัดลอกมันไปแล้ว

การสแกน secrets ไม่ได้แทนการรีวิวสิทธิ์ของรีโพซิทอรี workflow อาจอ่าน production credential โดยไม่ใส่ใน diff และเอเจนต์อาจแก้ deployment job เพื่อขโมยมัน เก็บ secrets ออกจากงาน pull request จำกัดสิทธิ์ของ workflow และบังคับ human review สำหรับการแก้ CI definitions

การตรวจสอบการอนุญาตพิสูจน์ว่าการกระทำที่ห้ามยังคงถูกห้าม

gate การอนุญาตควรพิสูจน์ว่าทุก protected operation ปฏิเสธ actor ที่ไม่ควรทำได้ และอนุญาต actor ที่ควรทำได้ที่ขอบเขตของ service เทสต์ login อย่างเดียวไม่ได้ทดสอบการอนุญาต

ทีมมักปะปน authentication, authorization และการมองเห็นใน user interface Authentication ระบุว่าใครส่ง request มา Authorization ตัดสินว่าตัวตนนั้นทำ action นี้กับ object นี้ได้หรือไม่ การซ่อนปุ่ม admin ใน React ไม่ได้เปลี่ยนการตัดสินใจใดบน Go API หาก backend ยอมรับ request แอปยังมีช่องโหว่

สร้าง permission matrix สำหรับ endpoints และ business actions ที่เปลี่ยน ให้เล็กพอรีวิวได้ แต่รวมขอบเขต ownership และ tenant:

read_private_project:
  anonymous: deny
  member: deny
  other_tenant: deny
  owner: allow
  admin: allow
update_project:
  anonymous: deny
  other_tenant: deny
  owner: allow

สร้างเทสต์จาก matrix นี้ หรือเขียน table driven cases ที่เทียบเท่าในภาษา service ทุกกรณี deny ควรเรียก handler จริงด้วย identifiers ที่เหมือนจริง Mocks ที่แทน authorization middleware พิสูจน์ได้ว่า route ทำงาน แต่ข้าม control ที่กำลังทดสอบ

ทดสอบการเข้าถึงระดับ object ไม่ใช่เฉพาะ roles ผู้ใช้สองคนอาจมี role member เหมือนกัน แต่เป็นคนละองค์กร เปลี่ยน resource identifier และ tenant identifier แยกกันเพื่อจับ insecure direct object references ทดสอบ bulk endpoints, exports, background jobs และ GraphQL resolvers ด้วย ซึ่งมักข้าม checks ที่เขียนไว้สำหรับ REST handlers ปกติ

ให้ gate ล้มเหลวเมื่อ protected route ใหม่ไม่มี policy mapping วิธีนี้เปลี่ยน authorization ที่ขาดหายจากการคาดเดาของผู้รีวิวให้กลายเป็นข้อบกพร่องที่วัดได้ ให้ค่าเริ่มต้นบน server เป็น deny กฎ allow ที่ชัดเจนตรวจสอบง่ายกว่าโค้ดกระจัดกระจายที่ปฏิเสธเพียงกรณีไม่ดีบางส่วนที่รู้จัก

เอเจนต์มักนำ handler ใกล้เคียงมาใช้ซ้ำ และคง happy path ไว้ แต่ทิ้ง ownership check ไป permission matrix ทำให้การตกหล่นนี้มองเห็นได้ และให้สัญญาที่เสถียรแก่ผู้รีวิวเมื่อ roles หรือกฎ tenant เปลี่ยนในภายหลัง

ทดสอบ authorization หลัง input normalization การแปลงตัวพิมพ์ รูปแบบ identifier ทางเลือก duplicate query parameters และ nested object references อาจส่ง requests ที่เทียบเท่ากันผ่านเส้นทางโค้ดต่างกัน ทดสอบ endpoint ตรงและ batch หรือ import route ที่ไปถึง operation เดียวกัน หาก background worker เป็นผู้เขียนขั้นสุดท้าย ให้ส่งต่อบริบท actor และ tenant เข้า job แทนการมอง worker เป็น trusted user ที่มีอำนาจทุกอย่าง

บันทึกการตัดสินใจที่คาดหวังและกฎนโยบายที่ให้ผลนั้น แต่เลี่ยงการเผยข้อมูล object ส่วนตัวใน logs ความล้มเหลวที่ดีระบุ actor class, action, object class และ status ที่คาดหวัง ไม่ dump access token หรือ record เต็ม หลักฐานนี้ช่วยให้ผู้รีวิวแยก test fixture ที่พังออกจากการเปลี่ยนสิทธิ์จริงได้

การซ้อม migration วัด locks และการย้อนกลับได้

ทดสอบการกู้คืนก่อนรีลีส
การดีพลอย สแนปช็อต และการย้อนกลับของ Koder.ai รองรับการซ้อมกู้คืนที่ด่านผสานโค้ดต้องการ

gate migration ควรใช้ schema change ที่เสนอทั้งหมดกับสำเนาที่มีลักษณะใกล้ production รัน compatibility probes และบันทึกระยะเวลา locks และพฤติกรรม rollback ก่อนผสาน migration ที่สำเร็จบนฐานข้อมูลทดสอบว่างเปล่าพิสูจน์ได้น้อยมาก

ใช้ snapshot ที่ผ่านการล้างข้อมูล หรือชุดข้อมูลที่สร้างขึ้นซึ่งมีขนาดตาราง indexes, constraints และ skew ใกล้เคียงกัน ข้อมูล production จริงไม่ควรอยู่ใน infrastructure ของ pull request เป้าหมายคือสร้างแรงกดดันด้านการปฏิบัติการโดยไม่คัดลอกข้อมูลส่วนบุคคลหรือข้อมูลลับ

ซ้อมลำดับการดีพลอยจริง หาก application instances รุ่นเก่ายังทำงานระหว่าง migration ให้ทดสอบโค้ดเก่ากับ schema ใหม่ และโค้ดใหม่กับ schema ระยะเปลี่ยนผ่าน การเพิ่ม nullable column มักเข้ากันได้ การเปลี่ยนชื่อ column ในขั้นตอนเดียวอาจทำให้ทุก instance เก่าที่ยังให้บริการอยู่พัง

บันทึกหลักฐานเป็นผลที่เครื่องอ่านได้:

{"migration":"20260727_add_project_state","apply_ms":18420,"max_lock_ms":310,"old_app_probe":"pass","new_app_probe":"pass","down":"pass"}

กำหนด thresholds ตามฐานข้อมูลและประเภทตาราง lock 300 milliseconds อาจไม่กระทบกับตารางหนึ่ง แต่รบกวนอีกตารางหนึ่ง ผู้รีวิวควรเห็น limit ที่เลือกข้างผลที่วัดได้ พร้อมเวอร์ชันฐานข้อมูลที่ใช้ซ้อม

สำหรับ PostgreSQL ให้ตรวจ operations ที่ rewrite table, validate constraint หรือ build index ระหว่างบล็อกการเขียน ควรเปลี่ยนแบบ expand and contract: เพิ่มรูปแบบใหม่ ดีพลอยโค้ดที่ใช้ได้ทั้งสองรูปแบบ backfill เป็น batches ที่ควบคุมได้ สลับการอ่าน แล้วค่อยลบรูปแบบเก่าในการเปลี่ยนครั้งถัดไป pull request เพิ่มอีกหนึ่งครั้งมีต้นทุนต่ำกว่าการด้นสดระหว่าง outage

ไม่ใช่ทุก migration จะมี down ที่ปลอดภัย การลบ column ทำให้ข้อมูลสูญหาย และการย้อน transformation อาจกำกวม ในกรณีเหล่านี้ gate ควรบังคับมีขั้นตอนกู้คืนไปข้างหน้าและจุดคืนค่าแบ็กอัปที่ทดสอบแล้ว การเรียก irreversible migration ว่า "rollback safe" เพียงเพราะมี down file ไม่ซื่อตรง

ทดสอบ retries และ partial failure การดีพลอยอาจหยุดหลังสร้าง index แต่ก่อนบันทึกว่า migration เสร็จ และความพยายามครั้งถัดไปต้องไม่ทำให้สถานะเสียหายหรือล้มเหลวตลอดไป หยุดการซ้อมที่ขอบเขตที่ควบคุมได้ รันซ้ำ และยืนยันว่า schema กับ migration ledger ตรงกัน สำหรับ backfill ที่ยาว ให้พิสูจน์ว่า batches ทำต่อจาก cursor ที่บันทึกไว้ และการรัน batch ซ้ำไม่ทำให้ข้อมูลซ้ำหรือหาย

ตรวจผลต่อ disk และ replication รวมถึงเวลาที่ผ่านไป table rewrite อาจใช้พื้นที่ชั่วคราว ขยาย write ahead logs และทำให้ replicas ล่าช้าหลัง primary operation ดูเหมือนเสร็จแล้ว gate ไม่ต้องพยากรณ์ production ได้สมบูรณ์ แต่ควรบันทึกปริมาณเหล่านี้บนชุดข้อมูลที่ซ้อมและเปรียบเทียบกับ limits ที่เจ้าของฐานข้อมูลเลือก หากไม่มีหลักฐานนี้ migration ในเครื่องที่เร็วอาจทำให้ production volume เต็มได้

การยืนยัน rollback ต้องรันเส้นทางกู้คืน

เก็บรักษาสถานะดีที่ยืนยันแล้ว
สแนปช็อตของ Koder.ai ให้จุดกู้คืนที่จับต้องได้สำหรับการตรวจสอบการย้อนกลับ แทนคำสัญญาที่เขียนไว้

gate rollback ควรดีพลอย candidate ไปยัง environment แยก สร้างสถานะตัวแทน เรียกวิธี rollback ที่รองรับ และพิสูจน์ว่าเวอร์ชันก่อนหน้ายังให้การอ่านและเขียนที่ถูกต้องได้ แผน rollback ที่เขียนไว้ไม่ใช่การยืนยัน

แยก application rollback ออกจาก data rollback การสลับ traffic กลับไปยัง binary ก่อนหน้าอาจใช้เวลาไม่กี่วินาที แต่การย้อน schema ที่ทำลายข้อมูลหรือ data transformation อาจทำไม่ได้ gate ควรรายงานทั้งสองอย่าง หากแอปเก่ารันกับ schema ใหม่ไม่ได้ ให้ระบุ candidate ว่าย้อนกลับไม่ได้ และบังคับใช้แผนดีพลอยแบบเป็นขั้น

ลำดับที่ใช้งานได้จริงคือ:

  1. ดีพลอย main commit ปัจจุบันและ seed records ที่เป็นตัวแทน
  2. อัปเกรดเป็น artifact ของ pull request และทดสอบ paths ที่เปลี่ยน
  3. สร้าง records ใหม่ในสถานะที่อัปเกรดแล้ว
  4. คืน artifact หรือ snapshot ก่อนหน้าด้วย control ที่ระบุไว้
  5. รัน probes สำหรับการอ่าน การเขียน queue และ background jobs

check ควรเก็บ artifact identifiers, snapshot identifiers, timestamps และผล probes ไม่ควรเก็บ credentials หรือข้อมูลลูกค้าที่คัดลอกมา วัดเวลาการกู้คืนเพื่อเป็นหลักฐานตามเป้าหมายการปฏิบัติการของคุณเอง ไม่ใช่คำสัญญาสากล

Snapshots มีประโยชน์ก็ต่อเมื่อมีคนพิสูจน์ว่าครอบคลุมทุกอย่างที่แอปต้องใช้ Files, object storage, queue state, schema changes และ external side effects อาจอยู่นอก server snapshot ให้ระบุขอบเขตเหล่านั้นในผลลัพธ์ การชำระเงิน อีเมล หรือ webhook ที่ส่งไปแล้ว ดึงกลับไม่ได้ด้วยการคืนฐานข้อมูล

ทำ rollback probe ให้เข้มกว่า health check อ่าน record ที่สร้างก่อนอัปเกรด อ่าน record ที่สร้างหลังอัปเกรด อัปเดตทั้งสองเมื่อ compatibility อนุญาต และประมวลผล queued job ที่สร้างโดยแอปแต่ละเวอร์ชัน เปรียบเทียบผลลัพธ์ที่ผู้ใช้เห็น ไม่ใช่เพียง status codes เซิร์ฟเวอร์ที่คืน 200 แต่ทิ้ง field ใหม่หรืออ่าน enum ผิด ยังไม่ได้กู้คืน

ทดสอบ control ที่ผู้รับเวรใช้ หาก production rollback ต้องเลือก artifact คืน snapshot หรือเปลี่ยน traffic การซ้อมแยกควรใช้อินเทอร์เฟซและเส้นทางสิทธิ์เดียวกัน สคริปต์ส่วนตัวบนแล็ปท็อปของวิศวกรคนหนึ่งไม่ใช่ operational control หลักฐานควรแสดงว่า operator role ที่ระบุทำการกู้คืนได้โดยไม่ต้องได้ permanent administrator access

Koder.ai รองรับการส่งออกซอร์ส การดีพลอยและโฮสติ้ง สแนปช็อต และ rollback ดังนั้นแอปที่สร้างบนแพลตฟอร์มนั้นจึงใช้ artifacts เหล่านี้ใน gate ได้ แทนที่จะมองการกู้คืนเป็นย่อหน้าใน pull request กฎเดียวกันใช้ได้กับทุกแพลตฟอร์ม: รัน recovery control แล้ว probe แอปที่คืนค่าแล้ว

required check เดียวควรสรุปทั้งเจ็ด

การตัดสินใจผสานขั้นสุดท้ายควรบังคับ policy check ที่มีชื่อคงที่เพียงหนึ่งเดียว ซึ่งยืนยันผลพื้นฐานทั้งเจ็ดสำหรับ head commit ที่ตรงกัน ชื่องานเดี่ยวเปลี่ยนได้ matrix jobs เพิ่มจำนวน และ optional paths ข้ามงานได้ aggregator ขนาดเล็กช่วยป้องกัน branch protection หลุดจากนโยบาย

ให้แต่ละ gate ส่งผลลัพธ์ที่ลงลายมือชื่อหรือแพลตฟอร์มรับรอง ซึ่งมี commit, policy version, outcome และตำแหน่งหลักฐาน aggregator ปฏิเสธผลที่หายไป ล้าสมัย เป็นกลาง หรือถูกยกเลิก และต้องไม่อนุมานว่าผ่านจากงานที่ไม่รายงาน

{
  "commit": "abc123",
  "policy": "merge-gates-v3",
  "results": {
    "tests": "pass",
    "codeql": "pass",
    "dependency_review": "pass",
    "secret_scan": "pass",
    "authorization": "pass",
    "migration_rehearsal": "not_applicable",
    "rollback_verification": "pass"
  },
  "decision": "allow"
}

กำหนดเส้นทาง override ที่แคบ เพราะเหตุฉุกเฉินเกิดขึ้นได้ ต้องมี maintainer ที่ระบุชื่อ ผู้อนุมัติคนที่สอง เหตุผลที่เขียนไว้ วันหมดอายุ และ issue ติดตามผล อย่าให้เอเจนต์ขอหรืออนุมัติข้อยกเว้นของตนเอง รายงาน overrides ไว้ที่เดียวกับผล gate ปกติ เพื่อให้ยังมองเห็นหลังเหตุการณ์ผ่านไป

checks เหล่านี้จะเพิ่มเวลาหลายนาทีให้ pull requests บางรายการ และนานกว่านั้นมากสำหรับการเปลี่ยน migration ซึ่งยอมรับได้เมื่อเวลานั้นแลกกับหลักฐานที่เฉพาะเจาะจง รัน gates ราคาถูกก่อน ยกเลิก commits ที่ถูกแทนที่ แคช build inputs ที่เชื่อถือได้ และสงวนการซ้อม environment เต็มรูปแบบให้ paths ที่เกี่ยวข้อง อย่าทำ gate อ่อนลงเพียงเพื่อให้แดชบอร์ดเป็นสีเขียวเร็วขึ้น

เริ่มจากทำให้พฤติกรรมปัจจุบันสังเกตได้ ใส่ชื่อทั้งเจ็ดใน policy file เดียว เชื่อมแต่ละชื่อกับผลที่บังคับ และบังคับให้งานที่ถูกข้ามอธิบายตัวเอง pull request แรกจากเอเจนต์ที่ให้บันทึกนั้นไม่ได้ จะพบรูในระบบส่งมอบก่อนพบรูใน production.

คำถามที่พบบ่อย

Pull request จากเอเจนต์ควรมีกฎเข้มงวดกว่าของมนุษย์หรือไม่?

ใช้หลักฐานที่บังคับเหมือนกันสำหรับทั้งสองกรณี เอเจนต์อาจทำให้ควรเพิ่มการตรวจสอบอัตโนมัติ เพราะสร้างการเปลี่ยนแปลงได้เร็วกว่า แต่ diff ที่มนุษย์เขียนก็อาจเผยความลับ บั๊กการอนุญาต หรือการย้ายข้อมูลที่ไม่ปลอดภัยได้เช่นกัน

ผู้ตรวจที่เป็นมนุษย์สามารถข้าม merge gate ที่ล้มเหลวได้หรือไม่?

ได้ แต่ต้องผ่านข้อยกเว้นที่แคบ มีการบันทึก มีผู้รับผิดชอบสองคน เหตุผล และวันหมดอายุ เอเจนต์ที่สร้างการเปลี่ยนแปลงต้องห้ามอนุมัติข้อยกเว้นของตนเอง

CodeQL ผ่านแล้วแปลว่า pull request ปลอดภัยหรือไม่?

ไม่ได้ ผลผ่านหมายถึงคิวรีที่เลือกไม่พบผลลัพธ์ที่ต้องบล็อกในโค้ดที่ CodeQL วิเคราะห์สำเร็จเท่านั้น ยังต้องมีหลักฐานแยกต่างหากสำหรับ dependencies, การอนุญาตขณะรัน, secrets, การตั้งค่า และการกู้คืนระบบ

ควรทำอย่างไรเมื่อสแกนเนอร์ที่จำเป็นใช้งานไม่ได้?

การตรวจสอบควรล้มเหลวแบบปิด หรือคงสถานะบล็อกไว้ หากเป็นการเปลี่ยนแปลงฉุกเฉิน ให้ใช้ขั้นตอนการข้ามที่บันทึกไว้ แทนการเปลี่ยนผลที่ไม่ทราบให้กลายเป็นผ่าน

การสแกน secrets ควรตรวจสอบ commit ที่ถูกลบหรือไม่?

ควรตรวจสอบช่วง commit ทั้งหมดของ pull request ความลับที่เพิ่มแล้วลบภายหลังยังอยู่ในประวัติ และควรหมุนเวียนก่อนยอมรับการเปลี่ยนแปลงที่ล้างแล้ว

จะทดสอบการอนุญาตใน pull request ได้อย่างไร?

เรียกใช้ service handler จริงด้วยเมทริกซ์ของตัวตน บทบาท tenant วัตถุ และการกระทำ รวมกรณีที่ต้องปฏิเสธและการเปลี่ยนเจ้าของวัตถุ เพราะการล็อกอินสำเร็จและการซ่อนปุ่มในหน้าจอไม่ได้พิสูจน์ว่าเซิร์ฟเวอร์อนุญาตถูกต้อง

Database migration ทุกอันต้องมี down script หรือไม่?

ไม่จำเป็น การเปลี่ยนแปลงแบบทำลายข้อมูลบางอย่างไม่สามารถย้อนกลับได้อย่างซื่อตรง ให้บังคับมีขั้นตอนกู้คืนไปข้างหน้าหรือคืนค่าจากแบ็กอัปที่ทดสอบแล้ว และระบุว่าการเปลี่ยนแปลงนี้ย้อนกลับไม่ได้

การวางแผน rollback ต่างจากการตรวจสอบ rollback อย่างไร?

การวางแผนอธิบายขั้นตอนการกู้คืนที่ตั้งใจทำ การตรวจสอบจะรันขั้นตอนเหล่านั้นกับ artifact ที่จะนำไปใช้และสถานะตัวแทน จากนั้นบันทึกว่าเวอร์ชันก่อนหน้ายังอ่านและเขียนได้ถูกต้องหรือไม่

ทีมจะไม่ให้เจ็ด gate ทำให้ทุก pull request ช้าลงได้อย่างไร?

รันการตรวจราคาถูกก่อน ยกเลิกงานของ commit ที่ถูกแทนที่ แคชอินพุตที่เชื่อถือได้ และซ้อม migration เฉพาะเมื่อการเปลี่ยนแปลงเกี่ยวข้อง ทุก gate ต้องมีผลผ่านหรือไม่เกี่ยวข้องที่ชัดเจน

Branch protection ควรบังคับใช้ผลลัพธ์ใด?

บังคับใช้ผลนโยบายที่มีชื่อคงที่เพียงผลเดียว ซึ่งรวมทั้งเจ็ด gate สำหรับ head commit ที่ตรงกัน ต้องปฏิเสธผลที่หายไป ล้าสมัย ถูกข้าม ถูกยกเลิก หรือเป็นกลาง แทนการเดาว่าผ่าน

Related posts