# Hướng dẫn vận hành TeamBoard MKT

Tài liệu này dành cho Admin vận hành website. Bản áp dụng: `20260816-login-presence-dot-44`.

## 1. Phân quyền tổng quát

Quyền hệ thống được tách khỏi vai trò công việc. Một thành viên có thể mang vai trò công việc như Manager, Planner, Content, Designer hoặc Video Editor; riêng cờ **Admin** mới mở được quyền quản trị hệ thống.

| Cấp tài khoản | Phạm vi chính | Báo cáo / Nhân sự / KPI team | Quản lý vai trò, thành viên | Quản lý mã, hosting | Cài đặt và Cơ sở dữ liệu |
|---|---|---:|---:|---:|---:|
| Admin | Toàn hệ thống | Có | Có | Có | Có |
| Manager | Điều hành team | Có | Có, trừ cấp/hạ quyền Admin | Không | Không |
| Planner | Lập kế hoạch, điều phối | Có | Có, trừ cấp/hạ quyền Admin | Không | Không |
| Content | Công việc nội dung | Theo quyền vai trò | Không | Không | Không |
| Designer | Công việc thiết kế | Theo quyền vai trò | Không | Không | Không |
| Video Editor | Công việc video | Theo quyền vai trò | Không | Không | Không |

Các quyền nghiệp vụ như giao task, chỉnh deadline, chỉnh mức ưu tiên và khóa ngày nhận task được cấu hình theo từng vai trò tại **Cài đặt → Quản lý vai trò & phân quyền**.

Manager và Planner được mở **Cài đặt** để quản lý vai trò, hạng mục và thành viên. Họ không thể tạo một Admin mới, cấp/hạ quyền Admin, xóa tài khoản Admin hoặc xem các khối vận hành hệ thống.

Hai quyền sau luôn thuộc Admin và không xuất hiện dưới dạng quyền có thể cấp cho Manager/Planner:

- Quản lý mã, build, cấu hình hosting và tích hợp.
- Mở Cài đặt, kiểm tra/kéo/lưu Supabase, xuất/nhập backup và reset dữ liệu.

Lưu ý bảo mật: việc ẩn menu và chặn thao tác trong giao diện giúp đúng luồng sử dụng. Với môi trường production cần bảo vệ dữ liệu ở Supabase bằng Auth + RLS. Kiến trúc quan hệ và policy tương ứng nằm trong `supabase/schema_relational_rls.sql`.

## 2. Tạo và thêm thành viên

### Bước A — tạo tài khoản đăng nhập trên Supabase

1. Đăng nhập Supabase và mở đúng project của TeamBoard.
2. Vào **Authentication → Users → Add user**.
3. Nhập email theo quy ước hiện tại: `<username>@mkt.minhkhanhwp.com`.
4. Đặt mật khẩu tạm có ít nhất 6 ký tự và chọn tạo user.
5. Gửi riêng email đăng nhập và mật khẩu tạm cho thành viên; không ghi mật khẩu vào task hoặc tài liệu public.

### Bước B — tạo hồ sơ thành viên trong TeamBoard

1. Đăng nhập TeamBoard bằng tài khoản Admin.
2. Vào **Cài đặt → Quản lý thành viên**.
3. Nhập Họ tên, Chức danh và Username. Username phải trùng phần trước `@` của email Supabase.
4. Chọn Vai trò công việc.
5. Chọn Quyền:
   - **Thành viên** cho Manager, Planner và các nhân sự thông thường.
   - **Admin** chỉ cho người chịu trách nhiệm mã nguồn, hosting và cơ sở dữ liệu.
6. Bấm **Thêm** và chờ thông báo lưu thành công.
7. Đăng xuất, dùng cửa sổ ẩn danh đăng nhập thử tài khoản mới để kiểm tra menu và phạm vi dữ liệu.

Nếu đã tạo user Supabase nhưng chưa tạo hồ sơ TeamBoard, người dùng chưa được ánh xạ đúng vào dữ liệu ứng dụng. Nếu đã tạo hồ sơ nhưng chưa tạo Supabase Auth user, người dùng không đăng nhập được ở chế độ hosting.

## 3. Kết nối và cập nhật dữ liệu lên Supabase

### Cấu hình frontend

Mở `assets/js/config.js` và kiểm tra:

```js
dataMode: 'supabase',
authMode: 'supabase',
supabaseUrl: 'https://<project-ref>.supabase.co',
supabaseAnonKey: '<publishable-or-anon-key>',
siteUrl: 'https://ten-mien-cua-ban/',
```

Chỉ dùng **publishable/anon key** ở frontend. Tuyệt đối không đưa `service_role` key vào `config.js`, file ZIP, hosting public hoặc Git repository.

### Khởi tạo database hiện app đang dùng

Frontend hiện tại vẫn đọc/ghi row JSON `public.teamboard_state` để tương thích bản đang chạy. Với project mới:

1. Mở Supabase **SQL Editor**.
2. Chạy toàn bộ `supabase/schema_state.sql`.
3. Tạo Supabase Auth users.
4. Chạy `supabase/schema_auth_security.sql` để bỏ policy anonymous và yêu cầu đăng nhập.
5. Không chạy `supabase/deprecate_json_state_after_cutover.sql` khi frontend vẫn dùng `teamboard_state`.

### Kiểm tra kết nối trong website

1. Đăng nhập bằng Admin.
2. Vào **Cài đặt → Cơ sở dữ liệu**.
3. Bấm **Kiểm tra kết nối**. Trạng thái đúng là Supabase đang hoạt động.
4. Bấm **Kéo dữ liệu mới** trước khi bắt đầu một đợt chỉnh sửa quản trị lớn.
5. Sau khi thay đổi, bấm **Lưu lên Supabase** nếu cần đồng bộ ngay; ứng dụng cũng tự lưu và live sync theo chu kỳ cấu hình.
6. Kiểm tra `updated_at` của row `main` trong Supabase đã thay đổi.

Manager và Planner chỉ nhìn thấy các phần quản lý vai trò, hạng mục và thành viên trong trang Cài đặt. Hai khối **Cơ sở dữ liệu** và **Hướng dẫn vận hành** không hiển thị; các lệnh kiểm tra/kéo/lưu database cũng bị chặn nếu gọi ngoài luồng giao diện. Họ vẫn có thể sử dụng dữ liệu công việc được ứng dụng đồng bộ theo quyền nghiệp vụ.

### Nâng cấp bảo mật theo bảng quan hệ

Row JSON chung không thể phân quyền chi tiết từng task/chat ở mức database. Khi chuyển production đầy đủ, thực hiện theo thứ tự trong `docs/SUPABASE_SQL_RUN_ORDER.md`:

1. Chạy `supabase/schema_relational_rls.sql`.
2. Chạy `supabase/verify_relational_schema.sql`.
3. Backup, sau đó chạy `supabase/migrate_state_json_to_relational.sql`.
4. Chuyển adapter frontend sang các bảng quan hệ và kiểm thử đầy đủ.
5. Chỉ sau khi frontend đã cut-over mới chạy `supabase/deprecate_json_state_after_cutover.sql`.

## 4. Build và đưa website lên hosting

### Tạo bản bàn giao

Tại thư mục dự án:

```text
npm run check
npm run build
```

Thư mục `dist/` sau build là gói cần upload. Bản build đã kèm `assets/` và `docs/`; thư mục SQL `supabase/` chỉ lưu trong bộ mã nguồn quản trị và không cần public trên hosting.

### Upload shared hosting / cPanel

1. Trước khi ghi đè, tải backup website đang chạy và xuất backup JSON trong **Cài đặt → Cơ sở dữ liệu**.
2. Mở File Manager của hosting và vào web root, thường là `public_html/` hoặc thư mục domain.
3. Upload toàn bộ **nội dung bên trong** `dist/` vào web root.
4. Đảm bảo `index.html` nằm trực tiếp ở web root, không bị lồng thành `public_html/dist/index.html`.
5. Ghi đè đầy đủ `index.html`, `assets/`, `.htaccess`, `favicon.ico` và `VERSION.txt`.
6. Bật HTTPS và kiểm tra domain trong `assets/js/config.js` khớp URL thật.
7. Purge cache của hosting/CDN, sau đó mở cửa sổ ẩn danh hoặc hard refresh.

### Kiểm tra sau deploy

- Đăng nhập Admin và kiểm tra build hiển thị trong thẻ Cơ sở dữ liệu.
- Mở/thu gọn sidebar; reload trang và xác nhận trạng thái được giữ trên thiết bị.
- Kiểm tra bộ lọc Tổng quan, Kanban, Nhân sự, Báo cáo, Lịch task và KPI đều dùng cùng bố cục hai hàng.
- Tạo một task thử, đổi trạng thái, reload và kiểm tra dữ liệu còn tồn tại.
- Mở hai trình duyệt khác nhau để kiểm tra live sync.
- Đăng nhập Manager và Planner: quản lý được vai trò/thành viên nhưng không thấy Hướng dẫn vận hành hoặc Cơ sở dữ liệu, không thể cấp quyền Admin.
- Đăng nhập một thành viên thông thường: chỉ thấy dữ liệu đúng phạm vi.

## 5. Quy trình cập nhật phiên bản an toàn

1. Xuất backup JSON và ghi lại build đang chạy.
2. Chỉnh mã nguồn ở thư mục dự án, không chỉnh trực tiếp file trong `dist/`.
3. Tăng version trong `VERSION.txt`, `assets/js/config.js` và query version trong `index.html`.
4. Chạy `npm run check` rồi `npm run build`.
5. Upload `dist/`, purge cache và kiểm tra theo checklist trên.
6. Nếu lỗi, phục hồi gói hosting và backup JSON trước đó.

## 6. Xử lý lỗi thường gặp

### Website mở nhưng giao diện cũ

- Purge cache/CDN và hard refresh.
- Kiểm tra query `?v=` của CSS/JS trong `index.html` có đúng build mới.
- Kiểm tra hosting đã ghi đè đúng thư mục `assets/`.

### Supabase báo `Failed to fetch`

- Kiểm tra Internet, `supabaseUrl` và publishable/anon key.
- Kiểm tra SQL schema đã chạy đúng project.
- Kiểm tra Supabase Auth session còn hiệu lực.
- Kiểm tra RLS policy và domain HTTPS.
- Không chuyển sang `service_role` key để chữa tạm lỗi frontend.

### Thành viên không đăng nhập được

- Kiểm tra Auth user tồn tại và email đúng quy ước.
- Kiểm tra username hồ sơ TeamBoard trùng phần trước `@`.
- Kiểm tra user chưa bị disable và mật khẩu không có khoảng trắng thừa.

### Manager/Planner nhìn thấy Cài đặt

- Kiểm tra tài khoản có bị bật cờ Admin hay không.
- Đổi quyền về Thành viên, đăng xuất và đăng nhập lại.
- Nếu vẫn sai, xóa session/cache trình duyệt và kiểm tra build đang chạy.

## 7. Checklist bàn giao Admin

- Có ít nhất hai Admin dự phòng thuộc hai người chịu trách nhiệm khác nhau.
- Chỉ Admin giữ quyền truy cập mã nguồn, hosting, Supabase Dashboard và backup.
- Manager/Planner không được cấp cờ Admin chỉ để xem báo cáo.
- Mật khẩu Supabase/hosting dùng password manager và bật MFA nếu nhà cung cấp hỗ trợ.
- Backup trước mọi migration, import hoặc reset dữ liệu.
- Không gửi `service_role` key qua chat, email hoặc ảnh chụp màn hình.
