# 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 เต็มรูปแบบ
