การแยกข้อมูล
การแยกระดับแถว — fail-closed
ทุกตารางที่มีขอบเขตแยกตามผู้เช่า (tenant) จะเปิดใช้ PostgreSQL Row-Level Security แบบ FORCE โดยนโยบายจะผูกทุกแถวไว้กับเงื่อนไข "tenant_id = current_setting('app.current_tenant')"
คำขอที่มาโดยไม่ได้ตั้งค่า tenant context จะคืนศูนย์แถว — ไม่ใช่แม้แต่ข้อผิดพลาด แต่ว่างเปล่าอย่างเงียบ ๆ การเห็นข้อมูลของคลินิกหนึ่งด้วยเซสชันของอีกคลินิกเป็นไปไม่ได้ในเชิงสถาปัตยกรรม
การทดสอบการแยกข้ามผู้เช่า (cross-tenant) ต้องผ่านเป็นสีเขียวใน CI เสมอ หากเป็นสีแดง โค้ดจะไม่ถูกรวม
ตัวตนแบบ transaction-local, ธุรกรรมแบบอะตอมมิก
รหัสประจำตัวผู้เช่าจะถูกกำหนดไว้ตั้งแต่จุดเริ่มต้นที่สุดของทุก transaction ที่มีการเขียนข้อมูล และมีผลเฉพาะภายใน transaction นั้นเท่านั้น จึงไม่ติดค้างอยู่ในคอนเนกชันพูล และไม่รั่วไหลไปยังคำขออื่น
ธุรกรรมแบบหลายเอนทิตี (ใบแจ้งหนี้ + รายการ + การชำระเงิน + การตัดสต็อก) เป็นอะตอมมิกภายใน transaction เดียว: เขียนพร้อมกันทั้งหมดหรือไม่เขียนเลย ไม่มีบันทึกที่ค้างคาหรือไม่สอดคล้อง
สิทธิ์ตามบทบาท (RBAC) ถูกบังคับใช้ที่เซิร์ฟเวอร์
การควบคุมสิทธิ์ทำที่ชั้น API ไม่มีวันไว้ใจไคลเอนต์หรือฝั่งหน้าจอ การซ่อนเมนูในเบราว์เซอร์เกี่ยวข้องกับรูปลักษณ์เท่านั้น — การตัดสินใจจริงอยู่ที่เซิร์ฟเวอร์
การกลายพันธุ์ (mutation) ของแกนกลาง (เฟส 1) ถูกปกป้องตามบทบาท admin, พนักงานต้อนรับ และแพทย์ แม้บทบาทที่ไม่มีสิทธิ์จะเรียกเอนด์พอยต์ คำขอก็จะถูกปฏิเสธ
การเขียนแบบ idempotent — ไม่มีการดำเนินการซ้ำ
ทุกคำขอเขียนพก Idempotency-Key การล็อกฝั่งเซิร์ฟเวอร์ป้องกันรายการที่สองที่มากับคีย์เดียวกัน
แม้เมื่อเครือข่ายขาดหรือไคลเอนต์ส่งคำขอเดิมซ้ำ ก็จะไม่เกิดการเก็บเงินหรือออกใบแจ้งหนี้เป็นครั้งที่สอง ผลลัพธ์จะเป็นหนึ่งเดียวและคาดการณ์ได้เสมอ
ความปลอดภัยของคำสั่ง (query)
SQL injection เป็นไปไม่ได้ — คำสั่งแบบมีพารามิเตอร์
คำสั่งฐานข้อมูลทั้งหมดเป็นข้อความที่สร้างในเวลาคอมไพล์ด้วย sqlc และมีพารามิเตอร์อย่างสมบูรณ์ ในโค้ดเบสไม่มีแม้แต่บรรทัดเดียวที่สร้าง SQL ด้วยการต่อสตริงจากอินพุตผู้ใช้ด้วยมือ
สิ่งนี้กำจัดการโจมตีประเภท SQL injection ในเชิงโครงสร้าง — โดยอาศัยวิธีการสร้างคำสั่ง (query) ไม่ใช่ความพยายามในการ "กรอง" หรือ "escape"
การแยกแบบ Loopback — แกนกลางปิดต่อภายนอก
แกน API จะรับฟังเฉพาะที่ 127.0.0.1 (loopback) เท่านั้น ความพยายามผูกกับ 0.0.0.0 หรือ IP สาธารณะจะถูกปฏิเสธตั้งแต่เริ่มต้น แกนหลักจะไม่เปิดสู่อินเทอร์เน็ตไม่ว่ากรณีใด
หน้าสาธารณะเพียงหน้าเดียวคือประตูบางเบา (BFF) ซึ่งไม่เก็บกฎธุรกิจใด ๆ นอกจากเซสชัน การเรนเดอร์ และ CSRF เบราว์เซอร์ไม่สามารถมองเห็นหรือเข้าถึงแกน API โดยตรงได้เลย
รหัสผ่าน argon2id, คีย์เซสชันแบบ opaque
รหัสผ่านถูกแฮชด้วย argon2id ที่เป็นมาตรฐานอุตสาหกรรมและใช้หน่วยความจำหนัก (memory-hard) ไม่มีการใช้แฮชแบบธรรมดาหรืออ่อนแอ
คีย์เซสชันเป็นค่า opaque แบบสุ่มด้วยการเข้ารหัสขนาด 32 ไบต์ เก็บไว้ใน Redis และหมดอายุด้วย TTL เบราว์เซอร์จะได้รับเพียงคุกกี้แบบ HttpOnly + Secure + SameSite เท่านั้น คีย์ไม่เคยเปิดเผยให้ JavaScript เข้าถึง
บันทึกตรวจสอบที่แก้ไขไม่ได้ (append-only)
การดำเนินการสำคัญจะถูกเขียนลงในบันทึกตรวจสอบแบบ append-only ภายใน transaction เดียวกันกับ mutation ที่ทริกเกอร์มัน หากธุรกรรมถูกย้อนกลับ บันทึกตรวจสอบก็จะไม่ถูกเขียน — ทั้งสองแยกจากกันไม่ได้
สิทธิ์ UPDATE/DELETE ถูกเพิกถอนจากตารางบันทึกตรวจสอบ บันทึกจึงไม่สามารถแก้ไขหรือลบภายหลังได้ ประวัติยังคงอยู่ตามเดิม
การปิดบังข้อมูลที่ละเอียดอ่อน
TCKN รหัสผ่าน คีย์เซสชัน และข้อมูลสุขภาพจะไม่เข้าสู่บันทึก (log) ในรูปแบบใด ๆ แม้ในเอาต์พุตดีบัก ฟิลด์เหล่านี้ก็ถูกปิดบัง
เมื่อจำเป็น ฟิลด์ที่ละเอียดอ่อนจะถูกเข้ารหัสในระดับคอลัมน์ ข้อมูลสุขภาพที่มีลักษณะพิเศษได้รับการปกป้องด้วยกฎที่วางไว้ตั้งแต่ต้นในการออกแบบ
ความปลอดภัยของจำนวนเงิน — numeric, การกลับรายการ
จำนวนเงินถูกเก็บเป็น numeric(14,2) ทุกที่ ไม่มีการคำนวณเงินด้วย float การปัดเศษเกิดขึ้นที่จุดเดียวบนเซิร์ฟเวอร์ — จึงไม่เกิดการเคลื่อนของเศษสตางค์หรือความคลาดเคลื่อนจากการปัดเศษ
การยกเลิกและคืนเงินถูกประมวลผลเป็นการกลับรายการ แทนการลบบันทึก ยอดคงเหลือของบัญชีไม่ได้เขียนด้วยมือ แต่คำนวณจากยอดรวมของใบแจ้งหนี้และการชำระเงินเสมอ ประวัติไม่ถูกทำลาย
การส่งออกข้อมูลและความปลอดภัยของเบราว์เซอร์
การรับส่งข้อมูลทั้งหมดผ่าน HTTPS/TLS และเปิด HSTS เบราว์เซอร์สร้างการเชื่อมต่อในรูปแบบเข้ารหัสเท่านั้น
นโยบายความปลอดภัยของเนื้อหา (CSP) ที่เข้มงวดจะบล็อกสคริปต์แบบ inline; X-Frame-Options DENY ป้องกัน clickjacking และ X-Content-Type-Options nosniff ป้องกันการสับสนของชนิดข้อมูล มีการบังคับใช้ Referrer-Policy และ Permissions-Policy ด้วยเช่นกัน