# Core `cp-workspace` — Vòng đời & provision workspace

> 07/7/2026 · Repo: **controlplane** · Đánh giá: **✅ Vững cho 1 host · ⚠ scale-out & backup** · Bản HTML: [cp-workspace.html](cp-workspace.html) · [Review tổng core](core-review-2026-07-07.md)

## 1. Vai trò
Provisioner cấp tài nguyên thật cho mỗi workspace: **CREATE DATABASE riêng → migrate schema nền → cấp owner role → spawn PM2 instance** (dải cổng BE 41000–41999 / FE 42000–42999) + routing Caddy on-demand HTTPS.

## 2. Thành phần chính

| Thành phần | Vai trò |
|---|---|
| **Workspace · WorkspaceMembership · WorkspaceCreationRequest** | Danh mục workspace + thành viên + luồng xin tạo |
| **provisioner.js** | DB riêng · migrate one-shot qua RT CLI (env override DB_NAME) · owner role + bump epoch · spawn PM2 |
| **clean-workspace.js · ws-env.js** | Xóa an toàn (từ chối DB dùng chung, idempotent) · xem env instance |
| **caddyApi · workspaceGateService** | Routing FE theo domain (WS_CADDY_ROUTING=1) · gate trạng thái workspace |

## 3. Hiện trạng (đọc từ code)
- Kiến trúc Level 2 (DB-per-workspace) đúng với yêu cầu cô lập dữ liệu pháp lý của trường lái
- Provision không cần instance RT đang chạy (CLI one-shot) — thiết kế sạch
- Script dọn workspace an toàn, idempotent
- ⚠ Gắn chặt 1 host: path cứng `WS_RUNTIME_ROOT`, PM2 local, dải cổng thủ công
- ⚠ Chưa thấy cơ chế **backup/restore per-workspace DB** — dữ liệu hồ sơ là căn cứ pháp lý

## 4. Khuyến nghị — tham chiếu hệ phổ biến

| Tham chiếu | Khuyến nghị |
|---|---|
| **PostgreSQL vận hành chuẩn** | **Ưu tiên cao:** pg_dump định kỳ từng DB workspace + kiểm tra restore — bắt buộc trước khi Vĩnh An go-live (dữ liệu thanh tra được) |
| **Kubernetes operator pattern** | Khi >5–10 workspace: tách provisioner thành reconcile-loop (desired state trong CP, actuator tách riêng) — chưa cần ngay, nhưng đừng thêm logic mới phụ thuộc path local |
| **Odoo.sh / Shopify** | Thêm trạng thái vòng đời workspace rõ ràng (provisioning → active → suspended → archived) gắn với billing/subscription |

## 5. Liên kết trong core
- **cp-identity** — sinh AuthClient/JWT secret per-ws
- **rt-host** — instance được spawn
- **cp-store** — entitlement quyết định module được cài


## Ma trận tác nhân × năng lực

Core không phải module nghiệp vụ — ma trận theo **tác nhân**, kèm cơ chế/quyền gate. R đọc · W thực hiện · A duyệt.

| Năng lực | Cơ chế / quyền gate | SUPER | OWNER/QTHT | DEV | SVC | USER |
|---|---|:--:|:--:|:--:|:--:|:--:|
| Yêu cầu tạo workspace | WorkspaceCreationRequest | A | — | — | — | W (request) |
| Provision / destroy | script + quyền admin CP | W | — | — | — | — |
| Xem trạng thái provisioning | membership | R | R | — | — | — |
| Backup / restore per-WS (P3 — đích) | system.admin.backup.* | W | R (restore theo duyệt) | — | — | — |
| ws:env / scripts vận hành | shell trên host | W | — | — | — | — |

SUPER = super admin CP · OWNER/QTHT = quản trị WS · DEV = developer/publisher · SVC = service-to-service · USER = người dùng cuối. Mục **(đích)** = theo khuyến nghị P1–P5.
