# Role Permission Matrix วันที่จัดทำ: 2026-07-07 ## Summary เอกสารนี้กำหนดโครงสร้าง role และ permission model ใหม่สำหรับระบบ Training Management System เพื่อใช้แทนแนวทางเดิมที่พึ่งพา: - `systemRole` - `membership.role` - `businessRole` แบบกระจายหลายชั้นและ hard-code ตาม feature เป้าหมายของโมเดลใหม่คือ: - แยก `system-level access` ออกจาก `organization-level access` - ใช้ `permissions` เป็นตัวตัดสินสิทธิ์จริงที่ระดับ API/server - รองรับ workflow ที่ซับซ้อนขึ้น เช่น approve, publish, schedule, archive, revision - ลดการพึ่งพา `businessRole` ให้เหลือ compatibility layer ชั่วคราว ## Access Model ระบบใหม่ควรมี 3 ชั้น: | Layer | Purpose | Example | | --- | --- | --- | | `system_role` | สิทธิ์ระดับ platform | `super_admin`, `support`, `standard` | | `organization_role` | บทบาทหลักในแต่ละองค์กร | `owner`, `org_admin`, `hrd_manager`, `hrd_staff`, `employee` | | `permissions[]` | สิทธิ์ละเอียดระดับ feature/action | `announcement:publish`, `users:manage` | ## System Roles | System Role | Meaning | | --- | --- | | `super_admin` | เข้าถึงทุกองค์กรและทุกฟังก์ชันได้ | | `support` | เข้าถึงเพื่อ support หรือ diagnose ได้ตาม policy ที่กำหนด | | `standard` | ใช้สิทธิ์ตาม role ในองค์กรเป็นหลัก | ## Organization Roles | Organization Role | Meaning | | --- | --- | | `owner` | เจ้าขององค์กร จัดการทุกอย่างในองค์กร | | `org_admin` | ผู้ดูแลองค์กร จัดการ users, master data, reports, workflow ได้ | | `hrd_manager` | อนุมัติ, publish, schedule, archive workflow ฝั่ง HRD ได้ | | `hrd_staff` | สร้าง, แก้ draft, submit ได้ แต่อนุมัติและ publish ไม่ได้ | | `employee` | ผู้ใช้ทั่วไป เห็นเฉพาะข้อมูล public และข้อมูลของตัวเอง | ## Permission Catalog ### Platform / Organization | Permission | Meaning | | --- | --- | | `organization:manage` | จัดการข้อมูลองค์กร | | `organization:switch` | สลับ active organization | | `membership:manage` | จัดการสมาชิกในองค์กร | | `roles:assign` | เปลี่ยน role ให้สมาชิก | | `permissions:assign` | กำหนด permission รายคนหรือราย role | ### Users / Employee Directory | Permission | Meaning | | --- | --- | | `users:read` | ดูรายการผู้ใช้ | | `users:create` | สร้างผู้ใช้ | | `users:update` | แก้ผู้ใช้ | | `users:delete` | ลบหรือปิดผู้ใช้ | | `users:manage` | จัดการผู้ใช้ทั้งหมด | | `employee_directory:read` | ดู employee directory | | `employee_directory:write` | แก้ employee directory | | `employee_import:run` | import พนักงาน | | `employee_master_review:approve` | อนุมัติ master data จาก import | ### Courses / Training Policy / Training Matrix | Permission | Meaning | | --- | --- | | `courses:read` | ดูหลักสูตร | | `courses:write` | จัดการหลักสูตร | | `training_policy:read` | ดูนโยบาย | | `training_policy:write` | จัดการนโยบาย | | `training_matrix:read` | ดู training matrix | | `training_matrix:write` | จัดการ training matrix | ### Training Records | Permission | Meaning | | --- | --- | | `training_record:self_read` | ดูประวัติอบรมของตัวเอง | | `training_record:self_write` | สร้างหรือแก้ draft ของตัวเอง | | `training_record:read_all` | ดูข้อมูลทั้งองค์กร | | `training_record:write_all` | สร้างหรือแก้แทนคนอื่นในองค์กร | | `training_record:submit` | ส่งตรวจสอบ | | `training_record:review` | อนุมัติหรือขอแก้ไข | | `training_record:delete_draft` | ลบ draft | | `training_record:manage_attachments` | จัดการไฟล์แนบ | ### Announcements | Permission | Meaning | | --- | --- | | `announcement:read_public` | ดูประกาศที่เผยแพร่แล้ว | | `announcement:read_all` | ดูประกาศทุกสถานะ | | `announcement:create` | สร้างประกาศ | | `announcement:edit_draft` | แก้ draft หรือ revision | | `announcement:delete_draft` | ลบ draft | | `announcement:submit` | ส่งอนุมัติ | | `announcement:approve` | อนุมัติ | | `announcement:reject` | ตีกลับ | | `announcement:publish` | เผยแพร่ทันที | | `announcement:schedule` | ตั้งเวลาเผยแพร่ | | `announcement:unpublish` | ยกเลิกการเผยแพร่ | | `announcement:archive` | เก็บถาวร | | `announcement:revision` | สร้าง draft revision จาก version ที่เผยแพร่แล้ว | | `announcement:preview` | preview ได้ | ### Online Lessons | Permission | Meaning | | --- | --- | | `online_lesson:read_public` | ดูบทเรียนที่เผยแพร่แล้ว | | `online_lesson:read_all` | ดูบทเรียนทุกสถานะ | | `online_lesson:create` | สร้างบทเรียน | | `online_lesson:edit_draft` | แก้ draft หรือ revision | | `online_lesson:delete_draft` | ลบ draft | | `online_lesson:submit` | ส่งอนุมัติ | | `online_lesson:approve` | อนุมัติ | | `online_lesson:reject` | ตีกลับ | | `online_lesson:publish` | เผยแพร่ทันที | | `online_lesson:schedule` | ตั้งเวลาเผยแพร่ | | `online_lesson:unpublish` | ยกเลิกการเผยแพร่ | | `online_lesson:archive` | เก็บถาวร | | `online_lesson:revision` | สร้าง draft revision | | `online_lesson:preview` | preview ได้ | ### Reports / Audit / Notifications | Permission | Meaning | | --- | --- | | `reports:self_read` | ดูรายงานของตัวเอง | | `reports:organization_read` | ดูรายงานทั้งองค์กร | | `reports:export` | export รายงาน | | `audit_logs:read` | ดู audit logs | | `notifications:read` | ดู notifications | | `notifications:manage` | จัดการ notification flows หรือ templates | ## Recommended Role-Permission Matrix | Permission Group | owner | org_admin | hrd_manager | hrd_staff | employee | | --- | --- | --- | --- | --- | --- | | `organization:*` | Y | Y | N | N | N | | `membership:manage` | Y | Y | N | N | N | | `roles:assign` | Y | Y | N | N | N | | `permissions:assign` | Y | Y | N | N | N | | `users:*` | Y | Y | N | N | N | | `employee_directory:read` | Y | Y | Y | Y | N | | `employee_directory:write` | Y | Y | Y | Y | N | | `employee_import:run` | Y | Y | Y | N | N | | `employee_master_review:approve` | Y | Y | Y | N | N | | `courses:read` | Y | Y | Y | Y | N | | `courses:write` | Y | Y | Y | Y | N | | `training_policy:read` | Y | Y | Y | N | N | | `training_policy:write` | Y | Y | Y | N | N | | `training_matrix:read` | Y | Y | Y | Y | N | | `training_matrix:write` | Y | Y | Y | Y | N | | `training_record:self_*` | Y | Y | Y | Y | Y | | `training_record:read_all` | Y | Y | Y | Y | N | | `training_record:write_all` | Y | Y | Y | Y | N | | `training_record:submit` | Y | Y | Y | Y | Y | | `training_record:review` | Y | Y | Y | N | N | | `announcement:create/edit_draft/delete_draft/submit/preview` | Y | Y | Y | Y | N | | `announcement:approve/reject/publish/schedule/unpublish/archive/revision` | Y | Y | Y | N | N | | `online_lesson:create/edit_draft/delete_draft/submit/preview` | Y | Y | Y | Y | N | | `online_lesson:approve/reject/publish/schedule/unpublish/archive/revision` | Y | Y | Y | N | N | | `reports:self_read` | Y | Y | Y | Y | Y | | `reports:organization_read` | Y | Y | Y | N | N | | `reports:export` | Y | Y | Y | N | N | | `audit_logs:read` | Y | Y | N | N | N | | `notifications:read` | Y | Y | Y | Y | Y | | `notifications:manage` | Y | Y | Y | N | N | ## Page Access Matrix | Page / Module | owner | org_admin | hrd_manager | hrd_staff | employee | | --- | --- | --- | --- | --- | --- | | Dashboard Overview | Y | Y | Y | Y | Y | | Notifications | Y | Y | Y | Y | Y | | Training Records | Y | Y | Y | Y | Y | | Pending Review | Y | Y | Y | N | N | | Announcements | Y | Y | Y | Y | Y, public-only content | | Online Lessons | Y | Y | Y | Y | Y, public-only content | | Users | Y | Y | N | N | N | | Employee Directory | Y | Y | Y | Y | N | | Courses | Y | Y | Y | Y | N | | Training Policy | Y | Y | Y | N | N | | Training Matrix | Y | Y | Y | Y | N | | Reports | Y | Y | Y | N | Y, self-only | | Audit Logs | Y | Y | N | N | N | ## Special Rules ### Employee visibility Employee-facing queries ต้องถูกจำกัดที่ server-side เสมอ: - content ต้องใช้ `status = published` - versioned content ต้องใช้ `is_current = true` - training records ต้อง self-scope หรือผ่าน employee mapping ที่อนุญาต ### HRD staff HRD staff ต้อง: - สร้าง content ได้ - แก้ draft ได้ - submit ได้ แต่ต้องไม่มีสิทธิ์: - approve - publish - schedule publish - unpublish - archive ### HRD manager HRD manager ต้อง: - approve / reject ได้ - publish ได้ - schedule ได้ - archive ได้ - preview ได้ ### Super admin `super_admin` เป็น system override: - bypass organization-level permission checks ได้ - แต่ควรยังใช้ organization context เดิมในการ query/write เพื่อให้ audit trail ชัดเจน ## Design Notes For Current Repo สำหรับ repo ปัจจุบัน: - `systemRole` ยังควรเก็บไว้ - `memberships.role` ควรถูกย้ายจาก `owner/admin/member` ไปสู่ role model ใหม่ หรือเพิ่ม layer mapping ใหม่ - `businessRole` ควรถูกลดบทบาทเหลือ compatibility layer ระหว่าง migration - server-side checks ต้องย้ายจาก `isHRD()` / `isIT()` ไปเป็น `hasPermission()` / `requirePermission()` ## Recommended Rollout 1. เพิ่ม permission catalog กลางใน `src/lib/auth` 2. เพิ่ม helper: - `hasPermission()` - `hasAnyPermission()` - `requirePermission()` 3. เปลี่ยน route handlers ให้เช็ก permission ก่อน 4. เปลี่ยน nav/page visibility ให้ใช้ permission matrix 5. คง `businessRole` ไว้ชั่วคราวเพื่อไม่ให้ feature เดิมพัง 6. ค่อยทยอย refactor feature ให้ใช้ permission-first model เต็มรูปแบบ