Files
CASAN/docs/plans/CASAN_PLAN_18_CHAT_CONSOLE.md
T

416 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# KẾ HOẠCH 18 — Governed Chat Console (Chat-as-Loop qua Control Plane)
> Status 2026-07-08: **🟡 MVP-0 + MVP-1 done+test; MVP-2 Track 4 + Operator Track 5/6 + Track 8.1/8.2/8.3 done — target architecture còn planned.**
> Đã implement **Ask CASAN — Read-only Evidence Assistant** qua harness + Control
> Panel (`/api/v1/chat/ask`, `/chat` UI): Prompt Router deterministic
> `READ_ONLY/OPERATOR/BLOCK/NOT_SUPPORTED`, context whitelist, H4 scan in/out, H5
> chat audit hash-chain, H6 token telemetry, answer kèm evidence sources. **MVP-1
> Operator** đã có registered actions `run tests` / `build pack` / `verify pack`
> qua `action-gate`, không free-command, kết quả có artifact provenance. **MVP-2
> Track 4 foundation** đã có `agent-registry.yaml`, agent/skill resolver, RBAC
> gate chọn agent, delegation hold, tool allowlist block, Control Panel agent picker.
> **Operator Track 5/6** đã bind mỗi side-effect turn vào Plan-17 `loop-run.sh`,
> verify trace/replay, H4 preflight/context/tool-output scan, và chỉ release action
> sau khi draft được certify. **Track 8.1/8.2/8.3** đã có replay/verify-chain
> foundation và Command Center Chat/Loop widget đọc chat audit/replay evidence thật.
> Mục tiêu
> tổng thể vẫn là thêm **cửa sổ chat** vào Control Plane (Plan-13) như một
> **bề mặt tương tác của core harness** — mỗi lượt chat là **một loop-run được
> governance** (Plan-17), đi qua đúng H1→H7, không có đường vòng. Đây **không** phải
> một chatbot; nó là **governed agent console**.
>
> Nhãn trạng thái: xem legend ở `CASAN_BACKLOG_STATUS.md`.
> Phụ thuộc: **17** (Loop Contract — turn = loop-run; budget/convergence/verify/trace) ·
> **13** (Control Plane — API bọc harness, HITL inbox §3.4, Command Center §8.6) ·
> **14** (RBAC — ai được chat/chọn agent nào) · **16** (fail-closed, approval JWT thật,
> secure-by-default, tamper-evidence — Plan-18 PHẢI tuân) · **03/02** (model-router +
> skill/agent) · **08** (nén context giữa vòng) · **07** (H5 audit, C4 approval, C7
> kill-switch). **Chặn cứng multi-user:** SEC-23 (tenant-partition) — chat state là
> per-tenant, không được dùng file chung.
>
> **⚠️ Scope note (chống lan man — đọc trước khi implement):** file này mô tả **target
> architecture** cho Governed Chat Console production. **KHÔNG implement toàn bộ một
> lần.** MVP đầu tiên chỉ là **Ask CASAN — Read-only Evidence Assistant**: Prompt
> Router chỉ `READ_ONLY/BLOCK/NOT_SUPPORTED`, context whitelist (Evidence Pack/reports/
> docs), H4 scan in/out, H5 audit chat, H6 token tracking, trả lời **kèm nguồn
> evidence**. Operator/Codegen/Agent-selection/Chat-as-loop/tenant-hardening làm **theo
> phase sau** (xem §1b). Thứ tự bắt buộc: **MVP-0 → MVP-1 → MVP-2 → MVP-3**; không mở
> khoá phase sau khi phase trước chưa xanh CI.
---
## 1. Bối cảnh — vì sao là "chat", vì sao qua harness
CASAN đã là **loop-engineering** (Plan-17): `observe→act→verify→correct` với gate mỗi
vòng, budget, hội tụ, leo thang cho người. Nhưng bộ máy đó hiện **chạy batch/CLI** —
con người không "ngồi trong vòng lặp". **Chat console** biến vòng lặp đó thành một
**bề mặt hội thoại**: người nhập ý định → agent chạy một loop-run được governance →
người thấy từng bước, duyệt khi cần, bấm dừng khi muốn.
**Ranh giới quyết định (nếu vi phạm thì đừng làm):**
| Chatbot thường (❌ không làm) | Governed Chat Console (✅ plan này) |
|---|---|
| Input → model → stream thẳng ra | Input → **H4 preflight/injection** → route → **act qua action-gate** → **H3/H4 verify** → mới lộ |
| Tool call tự do | Mọi tool-call qua `action-gate` + `tool-exec` sandbox + tool-allowlist theo agent |
| Chọn agent = tiện ích UI | Chọn agent = **quyết định routing được RBAC + approval + audit** |
| Lịch sử = 1 file/log chung | Lịch sử **per-tenant** (SEC-23), hash-linked, replay được |
| "Model nói xong là xong" | `DONE` chỉ hợp lệ khi verify đạt **success-criteria** (Plan-17 §3) |
> **Một câu:** chat không phải kênh mới để *né* harness; chat là **cửa để harness trở
> nên hữu hình**. Giá trị nằm ở chỗ mỗi lượt đều **verify được, replay được,
> click-to-evidence được**.
### Bám tư tưởng (FPT §4.3/§4.4/§14 · tư tưởng CASAN)
- **Human-led, AI-first** hiện thân trực tiếp: chat là nơi con người **nhìn thấy &
hành động** trong vòng lặp (nối Plan-13 §3.4 approvals inbox + delegation L0–L5).
- **Core harness là lõi, không phải source-gen:** chat là **vỏ mỏng** trên harness
core (single-source governance) — nó **không** thêm quyền phán quyết mới, không tái
hiện gate. Ưu tiên vẫn là củng cố core (Index P1); chat đứng **sau** Plan-17.
- **Governance-first, không "wow rỗng":** mọi số trên UI có provenance envelope
(Plan-13 §8.6) — đọc từ artifact thật, không vanity.
---
## 1b. Lát cắt MVP & thứ tự thực thi (bắt buộc — chống scope-creep)
> Plan-18 = **target architecture**. Để làm gần mà không ngợp, cắt thành **4 lát**,
> mỗi lát tự đứng được (shippable) và **không** mở khoá lát sau nếu lát trước chưa
> xanh CI. Đây là phần chống "càng làm càng nhiều chức năng".
| MVP | Tên | Làm gì | KHÔNG làm | Phụ thuộc thêm | Tracks |
|---|---|---|---|---|---|
| **MVP-0** | **Ask CASAN** (Read-only Evidence Assistant) | Chat panel đọc **whitelist** (Evidence Pack/reports/docs); Prompt Router `READ_ONLY/BLOCK/NOT_SUPPORTED`; H4 scan in/out; H5 audit; H6 token; trả lời **kèm nguồn** | Không command · không file-write · không skill/agent exec · không tenant/RBAC nặng | **Không cần Plan-17/14/SEC-23** — chỉ H4/H5/H6 (đã có) + model-router read-only | 0 (rút gọn), 1, 2, M (tối thiểu), 7 (UI tối thiểu) |
| **MVP-1** | **Operator** (registered actions) | Whitelist hành động an toàn: `run tests` / `build pack` / `verify pack` qua `action-gate` | Không codegen · không agent tự chọn · không loop tự chủ · không free-command | +Plan-07 action-gate/kill-switch | 3 |
| **MVP-2** | **Chat-as-Loop + Agent/Skill** | Turn = loop-run (Plan-17); agent/skill selection (RBAC+allowlist); codegen qua H4; streaming draft-hold | Không multi-tenant production | **+Plan-17 (T1–T3), +Plan-14 RBAC** | 4, 5, 6, 8 |
| **MVP-3** | **Multi-tenant governed production** | tenant-partition (SEC-23), per-tenant encrypt, approvals inbox đầy đủ, replay/verify-chain KMS | — | **+SEC-23, +Plan-07 TIER-2** | 9, 8 (đầy đủ) |
> **Quy tắc cổng:** MVP-0 **không** phụ thuộc Plan-17/14/SEC-23 ⇒ làm được ngay trên
> nền hiện có. Loop-core (Plan-17) + RBAC (14) chỉ cần từ **MVP-2**; tenant-partition
> (SEC-23) chỉ cần ở **MVP-3**. Một tính năng chỉ "thật" khi có test đối kháng xanh.
---
## 2. Nguyên tắc (bắt buộc — kế thừa Plan-16 + Plan-17)
1. **Không đường vòng.** Chat input là input-vector trực tiếp ⇒ đi qua **cùng**
`harness-preflight` (PII→cloud), `security-check`/H4, `context-assemble-scan`,
`tool-output-scan` như mọi luồng khác. UI/API **không** được bypass gate.
2. **Single-source governance.** Chat backend gọi lại `.specify/**` harness core (đúng
mô hình "API bọc harness" của Plan-13). **Cấm** reimplement verdict ở tầng chat.
3. **Secure-by-default = L1.** Mặc định người duyệt mọi hành động có side-effect;
tăng tự chủ (L→L+1) là **security-sensitive** ⇒ approval JWT thật + SoD + versioned
+ rollback (bài học ARCH-03/SEC-07). Profile `prod` bật enforce mặc định.
4. **Fail-closed toàn diện.** Gate lỗi/timeout/không đọc được policy ⇒ **chặn lượt**
(không "cứ trả lời"). Kế thừa SEC-04/SEC-09.
5. **Tenant-partition từ ngày đầu.** `chat_id`/lịch sử/loop-trace phân vùng theo
`tenant_id` + quyền FS; không file chung (MT-01/SEC-23). RBAC ở **cả tầng dữ liệu**,
không chỉ API.
6. **Streaming có kỷ luật.** Được stream **draft** nhưng gắn nhãn `UNCERTIFIED` tới khi
H3/H4 pass; **side-effect/tool-call bị giữ** cho tới lúc pass (xem §3c).
7. **Mọi lượt replay được.** Turn = loop-run ⇒ ghi vào loop-trace hash-linked (Plan-17
Track 4). Không nhúng secret (chỉ `*_ref`).
---
## 3. Định nghĩa — "Chat Turn = Loop Run"
Một **chat** là chuỗi **turn**. **Mỗi turn = một loop-run của Plan-17** (không định
nghĩa vòng lặp riêng — tái dùng Loop Contract §3 của Plan-17). Bản ghi bất biến:
```
ChatTurn = {
chat_id, tenant_id, turn_id, actor,
user_msg_ref, # tham chiếu (không nhúng PII/secret thô)
agent_selected, skill_selected,
tool_allowlist, delegation_level, # bind theo agent (§3c)
loop_run_id, # NỐI Plan-17: turn chạy như 1 loop-run
preflight_verdict, # H4: PII→cloud / injection (PASS|DENY)
iterations[], # từng Iteration theo Loop Contract (Plan-17 §3)
output_ref, certified, # certified=false ('UNCERTIFIED') tới khi H3/H4 PASS
decision # ANSWERED | ESCALATED | HALTED | DENIED
}
```
**Điều kiện kết thúc turn** (ánh xạ thẳng Plan-17 §3):
- `ANSWERED` — verify đạt success-criteria ⇒ output `certified=true`.
- `ESCALATED(human)` — gate DENY nghiêm trọng / stall rủi ro cao ⇒ vào approvals inbox
(Plan-13 §3.4).
- `HALTED` — budget governor (Plan-17 T1) / convergence (T2) / loop-breaker người bấm.
- `DENIED` — RBAC/preflight chặn ngay từ đầu.
### 3a. Kiến trúc luồng một turn
```mermaid
flowchart TD
U["User msg + chọn agent/skill"] --> RB{"RBAC (14):<br/>được chat + chọn agent này?"}
RB -- no --> DEN["DENIED + lý do (audit)"]
RB -- yes --> BIND["bind tool-allowlist + delegation_level (§3c)"]
BIND --> PF{"H4 preflight:<br/>PII→cloud, injection scan"}
PF -- DENY --> DEN
PF -- PASS --> H1["H1 context assemble + compress (Plan-08, must-keep)"]
H1 --> RT["model-router --role + agent (03/02)"]
RT --> LOOP["loop-run.sh (Plan-17): observe→act→verify→correct"]
LOOP --> ACT["act: tool-call → action-gate + tool-exec sandbox<br/>(chỉ tool trong allowlist)"]
ACT --> VG{"loop-gate verify (Plan-17 T3):<br/>H3 eval + H4 security"}
VG -- FAIL --> CORR["structured correction (bounded, T1)"] --> ACT
VG -- DENY/sensitive --> ESC["ESCALATE → approvals inbox (13 §3.4)"]
VG -- PASS --> REVEAL["reveal output (certified=true)"]
LOOP -. draft .-> DRAFT["stream UNCERTIFIED (side-effect giữ) (§3c)"]
REVEAL --> TR["loop-trace record (T4) + H5 audit (per-tenant)"]
TR --> GOV{"budget governor (T1) + convergence (T2)"}
GOV -- continue --> H1
GOV -- DONE/HALT --> END["kết thúc turn (replayable)"]
style VG fill:#fff3cd,stroke:#8a6d3b,stroke-width:2px
style RB fill:#d0e8ff,stroke:#2c3e91,stroke-width:2px
```
### 3b. Điểm căng đã quyết: **Streaming vs Verify-before-output**
- **Read-only agent (L0):** cho **stream trực tiếp** (không side-effect) — vẫn qua
preflight, output vẫn đi qua H3/H4 rồi mới `certified=true`.
- **Agent có side-effect (≥L1):** **stream draft `UNCERTIFIED`** cho UX, nhưng **mọi
tool-call/ghi file/exec bị GIỮ** đến khi `loop-gate` PASS; nếu DENY → draft bị thu
hồi, không có tác dụng phụ nào xảy ra.
- **Bất biến:** draft **không bao giờ** được thực thi tool trước gate. "Nhìn thấy" ≠
"đã làm".
### 3c. Chọn skill/agent = **routing được governance** (không phải dropdown tự do)
- `agent-registry.yaml` (managed qua Control Plane, versioned + audit): mỗi agent khai
báo `tool_allowlist`, `max_delegation_level`, `roles_allowed`, `model_role`.
- Chọn agent ⇒ **bind** `tool_allowlist` + `delegation_level` cho turn đó; RBAC (14)
quyết ai được chọn agent nào; chọn agent tự chủ cao hơn mức cho phép = **security-
sensitive** ⇒ approval JWT thật + SoD.
- Skill (code-gen) chạy **trong** allowlist của agent + vẫn qua H4 artifact-scan như
Plan-02. Không có skill nào "thoát" gate.
### 3d. Prompt Mode Router (rule-first, model-assisted) — cổng phân loại TRƯỚC loop
> Không phải chat nào cũng cần một loop-run nặng. **Router phân loại ý định TRƯỚC**,
> rồi mới quyết mức xử lý — read-only thì nhẹ, operator/codegen mới nặng. Đây là lý do
> MVP-0 không cần Plan-17: `READ_ONLY` không kích hoạt loop-run.
| Mode | Ý nghĩa | Cho phép | Gate / mức | MVP |
|---|---|---|---|:--:|
| `READ_ONLY` | Hỏi–đáp trên evidence/doc whitelist | đọc context whitelist | H4 in/out, không side-effect | 0 |
| `ANALYSIS` | Suy luận/tổng hợp không side-effect | đọc rộng hơn + reasoning | H4 in/out, L0 | 0/1 |
| `OPERATOR` | Chạy hành động đã đăng ký | run/build/verify pack | action-gate + approval theo mức | 1 |
| `CODEGEN` | Sinh/sửa mã | skill trong allowlist | H4 artifact-scan + loop-gate | 2 |
| `ADMIN`/`GOVERNANCE` | Đổi settings/policy/delegation | control-plane-settings | approval JWT + SoD (security-sensitive) | 2/3 |
| `BLOCK`/`NOT_SUPPORTED` | Injection / ngoài phạm vi / nguy hiểm | — | DENY + audit | 0 |
**Nguyên tắc router:**
- **Rule-first, deterministic:** phân loại theo *requested-capabilities* + *denied-verbs*
+ *bypass-terms* (regex/keyword), **không** phụ thuộc model.
- **Model-assisted chỉ cho ca mơ hồ**, và **rule thắng nếu rủi ro cao hơn** (model nói
`READ_ONLY` nhưng rule thấy `rm -rf`/`deploy`/`chmod` ⇒ giữ mức cao / `BLOCK`).
- **Preview cho người:** UI hiện `mode phát hiện + risk + gates + có cần approval`.
- **Fail-closed:** router lỗi / không đọc được policy ⇒ `BLOCK`; kết quả phân loại ghi
vào H5 audit.
---
## 4. Tasks theo track (gắn nhãn MVP)
> Thứ tự đọc = thứ tự làm: **Router → Read-only → session/audit → operator → agent →
> loop → streaming → API/UI → replay → tenant.** Mỗi track gắn nhãn MVP; **không** làm
> track của MVP sau khi MVP trước chưa xanh CI. Tất cả verify trong **WSL** (deterministic).
### Track 0 — Prompt Mode Router `[MVP-0 rút gọn → đầy đủ ở MVP-1/2]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.0.1 | ✅ Định nghĩa modes + policy map `READ_ONLY/OPERATOR/BLOCK/NOT_SUPPORTED` | `packages/casan-harness/config/prompt-modes.yaml` | schema validate; thiếu/corrupt policy → BLOCK |
| 18.0.2 | ✅ Classifier **deterministic**: requested-capabilities + denied-verbs + bypass-terms | `packages/casan-harness/scripts/bash/prompt-mode-router.py` | `rm -rf`/injection → BLOCK; `deploy` → NOT_SUPPORTED |
| 18.0.3 | ✅ Model-assisted **skip-aware**; MVP-0 không cần model | cùng file | không model → vẫn phân loại bằng rule |
| 18.0.4 | ✅ **Rule thắng model** khi rule rủi ro cao hơn | cùng file | model=READ_ONLY + rule=BLOCK/NOT_SUPPORTED → giữ rule |
| 18.0.5 | ✅ Preview `{mode, risk, gates, needs_approval}` cho UI | cùng file | payload đúng cho từng mode |
| 18.0.6 | ✅ Kết quả router được ghi trong ChatTurn H5; fail-closed lỗi policy → BLOCK | `chat-readonly.py` | router lỗi → BLOCK + audit turn |
### Track 1 — Read-only Ask CASAN (Evidence Assistant) `[MVP-0]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.1.1 | ✅ Context **whitelist**: Evidence Pack + reports + docs (đọc-only, chặn path ngoài whitelist) | `packages/casan-harness/scripts/bash/chat-readonly.py` | hỏi ngoài whitelist → không lộ |
| 18.1.2 | ✅ Trả lời **kèm nguồn** (`answer + sources[]`, provenance envelope) | cùng file | mỗi câu trả lời có ≥1 source ref |
| 18.1.3 | ✅ H4 scan **input + output**; H6 token tracking mỗi lượt | nối `security-check.sh` + metrics jsonl | injection → DENY; token ghi H6 |
| 18.1.4 | ✅ Cấm tuyệt đối side-effect ở mode này (no command/no write/no skill) | router guard | side-effect → NOT_SUPPORTED/BLOCK |
### Track 2 — Chat session + audit trace `[MVP-0]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.2.1 | ✅ Schema phiên `chat_id/turn_id/actor` (tenant-ready; MVP-0 single-tenant OK) | `packages/casan-harness/config/chat-session.schema.json` | schema validate |
| 18.2.2 | ✅ Ghi `ChatTurn` (§3) append-only, hash-linked H5 (không nhúng PII/secret, chỉ hash/ref/preview) | `chat-readonly.py verify-audit` | N turn → chain liên tục; secret không lộ |
| 18.2.3 | ✅ Không lưu raw message; audit lưu hash/ref/preview đã scan | cùng file | msg có secret token → audit không lộ raw secret |
### Track M — Model Provider Binding `[MVP-0 tối thiểu → lớn dần]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.M.1 | `provider_id` per agent + `model_role` per skill; routing theo mode (nối Plan-03/02) | mới `config/model-providers.yaml` | mode → provider đúng |
| 18.M.2 | Data policy `local/internal/cloud`: **PII/secret → cloud phải qua C3 guard** | nối `data-exfil-guard.sh` (C3) | PII→cloud không guard → BLOCK |
| 18.M.3 | Credential ngoài repo (env/secret store), không commit | nối `secrets-scan.sh` | key trong repo → scan FAIL |
| 18.M.4 | Provider-call audit + token/cost telemetry → H6 | nối H6 | mỗi call → có bản ghi cost |
### Track 3 — Operator mode (registered actions) `[MVP-1]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.3.1 | ✅ Whitelist hành động: `run tests` / `build pack` / `verify pack` (đăng ký, **không** free-command) | `packages/casan-harness/config/operator-actions.yaml` | lệnh ngoài whitelist → DENY |
| 18.3.2 | ✅ Mỗi action qua `action-gate` (ALLOW/WARN/REQUIRE_APPROVAL/BLOCK) | `chat-operator.py` + `action-gate.sh` | dangerous → BLOCK; network → REQUIRE_APPROVAL |
| 18.3.3 | ✅ Kết quả action là artifact có provenance, hiển thị lại trong chat | `chat-operator.py` + `/chat` UI | action → evidence link |
### Track 4 — Agent/Skill selection governance `[MVP-2]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.4.1 | ✅ `agent-registry.yaml` versioned (tool_allowlist, max_delegation, roles_allowed, model_role) + resolver bind theo turn | `packages/casan-harness/config/agent-registry.yaml` + `chat-agent-resolver.py` | chọn agent → allowlist đúng |
| 18.4.2 | ✅ RBAC gate chọn agent (14): role không đủ → DENY; vượt `max_delegation` → security-sensitive → approval hold | nối `rbac-check.py` (`chat:select_agent`) | role thấp chọn agent tự chủ → DENY |
| 18.4.3 | ✅ Tool-call runtime chỉ tool **trong allowlist**; ngoài → BLOCK trước runtime | `chat-agent-resolver.py` | tool ngoài allowlist → BLOCK |
| 18.4.4 | ⏳ Skill code-gen chạy trong allowlist + H4 artifact-scan (Plan-02) trước output | nối `artifact-scan.sh` | skill sinh mã có injection → BLOCK |
### Track 5 — Chat-as-loop pipeline `[MVP-2]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.5.1 | 🟡 OPERATOR path done: preflight → router → agent bind → `loop-run.sh` → trace/replay → action release (**gọi harness core, không reimplement**). CODEGEN/full model-router path còn pending | `chat-turn.py` | bỏ gate/draft injection → test FAIL |
| 18.5.2 | 🟡 OPERATOR turn = loop-run: budget governor + convergence + verify-contract (Plan-17 T1/T2/T3) | nối Plan-17 `loop-run.sh`/`loop-trace.py` | operator turn có `loop_run`, trace verify + replay OK |
| 18.5.3 | ✅ Preflight bắt buộc cho OPERATOR: `harness-preflight` + `context-assemble-scan` + `tool-output-scan`, fail-closed | nối H4 | injection trong msg → DENY, side-effect không chạy |
### Track 6 — Streaming / verify reconciliation `[MVP-2]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.6.1 | ✅ OPERATOR draft-hold: draft artifact `UNCERTIFIED` giữ side-effect tới khi `loop-run` PASS | `chat-turn.py` + API | side-effect trước gate → không xảy ra |
| 18.6.2 | ✅ DENY sau draft/preflight → draft held, turn `DENIED/HALTED`, audit; không action | cùng | draft bị DENY → không tác dụng phụ |
| 18.6.3 | ✅ L0 read-only stream thẳng; ≥L1 OPERATOR bắt buộc draft-hold | resolver + `chat-turn.py` | L1 operator không stream-exec thẳng |
### Track 7 — Chat API (NestJS) + UI (React) trên Command Center `[MVP-0 tối thiểu → lớn dần]`
| Task | Việc | File | Verify |
|---|---|---|---|
| 18.7.1 | ✅ Chat API (NestJS) **bọc** harness (MVP-0/1: read-only + operator; single-source, không verdict riêng) | `packages/casan-control-panel/backend/src/chat/*` | API gọi `chat-turn.py`; `console:test` xanh |
| 18.7.2 | ✅ Chat panel React + hiển thị **evidence sources**, registered actions, action-gate + badge `mode/risk` | `packages/casan-control-panel/frontend/src/pages/Chat.tsx` | `console:build` xanh |
| 18.7.3 | 🟡 (MVP-2 partial) agent/skill picker theo RBAC + delegation-level + loop certification badges đã có; còn nút **loop-breaker** và replay drawer khi Track 8 mở | Control Plane UI | picker hiện locked agent, backend DENY agent ngoài quyền; OPERATOR hiện `loop_run` |
| 18.7.4 | Fail-loud: API/telemetry chết → UI `STALE/503` (tái dùng D3 `/healthz`) | nối Plan-07 D3 | ngắt backend → UI báo stale |
### Track 8 — Replay / Evidence / Command Center widgets `[MVP-2 → MVP-3]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.8.1 | ✅ **Replay** một turn (verify lại artifact đã ghi) phát hiện tamper/non-determinism | `chat-replay.py` + `loop-trace.py replay` | sửa artifact turn → replay lệch |
| 18.8.2 | ✅ `verify-chain` lịch sử chat (tamper-evidence, SEC-01/02; KMS khi TIER-2 là follow-up) | `chat-replay.py verify-chain` | sửa 1 turn → chain BREAK |
| 18.8.3 | ✅ Widget **Chat/Loop** trên Command Center (13 §8.6): ticker per-iteration, budget gauge, click → Evidence drawer | `GET /api/v1/command` + `/command` | số khớp fixture; click → evidence |
| 18.8.4 | **Approvals/Escalation panel**: turn `ESCALATED` vào approvals inbox (13 §3.4), duyệt/từ chối (JWT + SoD + lý do) | nối Plan-13 §3.4 | escalate → pending; JWT giả → DENY |
### Track 9 — Multi-tenant hardening `[MVP-3]`
| Task | Việc | File | Verify (WSL) |
|---|---|---|---|
| 18.9.1 | tenant-partition state + quyền FS (SEC-23); RBAC ở **cả tầng dữ liệu** | store per-tenant | tenant A không đọc/ghi state B |
| 18.9.2 | per-tenant encrypt at-rest (MT-02) | nối KMS | admin A không đọc audit B |
| 18.9.3 | quota / kill-switch scope theo tenant (MT-03) | nối kill-switch | 1 tenant burn budget không ảnh hưởng tenant khác |
---
## 5. Red-team / test (kế thừa phong cách adversarial-harness)
| Test | Kỳ vọng |
|---|---|
| Injection trong chat msg (VI/JA/split/base64) | preflight/H4 → DENY, không tới model context |
| Prompt Router: model=READ_ONLY nhưng msg có `rm -rf`/`deploy` | **rule thắng** → OPERATOR/BLOCK, không READ_ONLY |
| Read-only hỏi tài liệu ngoài whitelist | không lộ nội dung ngoài whitelist |
| PII/secret → cloud provider không qua C3 | BLOCK trước khi gọi provider |
| Bypass-attempt: gọi API bỏ qua preflight | pipeline từ chối (không có đường vòng) |
| Agent ngoài quyền (RBAC) | DENIED trước khi chạy |
| Chọn delegation vượt mức (không approval) | security-sensitive → DENY tới khi có JWT + SoD |
| Tool-call ngoài allowlist của agent | action-gate BLOCK |
| Streaming abuse: side-effect trước gate | GIỮ; không tác dụng phụ; DENY → thu hồi draft |
| Cross-tenant: chat A đọc lịch sử B | chặn ở tầng dữ liệu (SEC-23) |
| Runaway chat (loop vô hạn) | HALT(budget) (Plan-17 T1) |
| Self-declared done (model nói xong, verify fail) | KHÔNG `ANSWERED/certified` |
| Replay tamper (sửa turn đã ghi) | replay lệch + chain BREAK |
**File test (theo MVP):** MVP-0 — `phase-chat-prompt-router-tests.sh`,
`phase-chat-readonly-tests.sh`, `phase-chat-session-audit-tests.sh`; MVP-1 —
`phase-chat-operator-tests.sh`; MVP-2 — `phase-chat-agent-select-tests.sh`,
`phase-chat-pipeline-tests.sh`, `phase-chat-stream-hold-tests.sh`,
`phase-chat-replay-tests.sh`; MVP-3 — `phase-chat-tenant-tests.sh`. Chạy **WSL**
(deterministic, mock model; nhánh live cần Ollama SKIP-aware). Nối `ci-harness-gate.sh`;
cập nhật tổng test ở `CASAN_HARDENING_STATUS.md`.
---
## 6. Tiêu chí hoàn thành (Definition of Done)
**MVP-0 (Ask CASAN read-only) — cổng ship đầu tiên:**
- [x] Prompt Router phân loại `READ_ONLY/BLOCK/NOT_SUPPORTED` deterministic; **rule thắng model**; router lỗi → BLOCK.
- [x] Chat chỉ đọc **whitelist**; hỏi ngoài whitelist không lộ; **không** command/write/skill.
- [x] H4 scan input+output; H5 audit mỗi lượt; H6 token tracking. PII→cloud full provider policy vẫn thuộc Track M/Plan-15 khi bật model provider thật.
- [x] Trả lời **kèm ≥1 nguồn evidence**; UI hiện sources + badge mode/risk.
- [x] Suite MVP-0 xanh và nối CI; không đụng OKR app. Verify: `phase-chat-prompt-router` 6/0, `phase-chat-readonly` 5/0, `phase-chat-session-audit` 3/0, `console:test` 23/0, `console:build` xanh.
**MVP-1 (Operator registered actions):**
- [x] Registered action whitelist có `run-chat-tests`, `build-evidence-pack`, `verify-evidence-pack`; không chạy free-command.
- [x] Mọi action đi qua `action-gate`; BLOCK/REQUIRE_APPROVAL không thực thi command.
- [x] Kết quả action ghi artifact có provenance và được hiển thị lại trong `/chat`.
- [x] Suite MVP-1 xanh và nối CI. Verify: `phase-chat-operator` 8/0, prompt-router 8/0, read-only 5/0, session-audit 3/0, `console:test` 24/0, `console:build` xanh.
**MVP-2 Track 4 foundation (Agent/Skill selection governance):**
- [x] Agent registry versioned có `tool_allowlist`, `max_delegation_level`, `roles_allowed`, `model_role`.
- [x] Agent resolver bind theo turn, ghi audit hash-chain, fail-closed khi registry lỗi.
- [x] RBAC gate `chat:select_agent`; role thấp chọn agent tự chủ → DENY; cross-tenant → DENY.
- [x] Delegation vượt agent max → `REQUIRES_APPROVAL`; tool ngoài allowlist → BLOCK trước runtime.
- [x] Control Panel `GET /api/v1/chat/agents`, `/chat` agent/skill/delegation picker, response có `agent_binding`. Verify: `phase-chat-agent-select` 8/0, RBAC 12/0, SEC-23 RBAC 6/0, `console:test` 25/0, `console:build` xanh.
**MVP-2 Track 5/6 OPERATOR slice (Chat-as-loop + draft-hold):**
- [x] OPERATOR turns create an `UNCERTIFIED` draft artifact, run `harness-preflight`, `context-assemble-scan`, `loop-run.sh`, `loop-trace verify-chain`, and `loop-trace replay` before action release.
- [x] Side effects are held until `loop_run.draft_certified=true`; denied drafts keep `side_effect_released=false` and do not execute the registered action.
- [x] Tool output is scanned with `tool-output-scan.sh` before returning the operator result to chat.
- [x] Control Panel response includes `loop_run`; `/chat` displays loop certification/replay status. Verify: `phase-chat-pipeline` 4/0, `phase-chat-stream-hold` 2/0, `phase-chat-operator` 8/0, `console:test` 25/0, `console:build` xanh.
**MVP-2 Track 8.1/8.2 (Replay / verify-chain foundation):**
- [x] `chat-replay.py verify-chain` recomputes chat audit hash-chain and fails closed on edited records.
- [x] `chat-replay.py replay` verifies recorded evidence artifact hashes and replays OPERATOR loop traces via `loop-trace.py replay`.
- [x] Control Plane `GET /api/v1/chat/replay` wraps harness replay; no verdict reimplementation in NestJS.
- [x] Tampered operator evidence artifact → `DRIFT`; tampered chat audit → `BREAK`. Verify: `phase-chat-replay` 4/0, `console:test` 25/0, `console:build` xanh.
**MVP-2 Track 8.3 (Command Center Chat/Loop widget):**
- [x] `GET /api/v1/command` exposes `chat_loop` widget backed by `.specify/logs/chat/chat-turns.jsonl` and harness `chat-replay.py`.
- [x] Widget metrics include turns, answered/action-completed counts, loop-run count, replay records, replayed loops, and token budget gauge from real chat metrics.
- [x] `/command` renders the Chat/Loop card in the existing evidence drawer flow; ticker includes recent chat/loop turns.
- [x] Fixture test proves counts and budget gauge match evidence. Verify: `console:test` 26/0, `console:build` xanh, `phase-chat-replay` 4/0.
**Full (target architecture) — DoD tổng:**
- [ ] Turn chạy **đúng như một loop-run Plan-17** (không định nghĩa vòng lặp riêng).
- [ ] **Không đường vòng:** test chứng minh bỏ bất kỳ gate nào (preflight/verify) → FAIL.
- [ ] Chọn agent/skill qua **RBAC + allowlist**; nâng delegation cần **approval JWT + SoD**.
- [ ] Streaming: side-effect **luôn** sau gate; draft DENY → thu hồi, không tác dụng phụ.
- [ ] Chat state **per-tenant**; test cross-tenant bị chặn ở tầng dữ liệu.
- [ ] Turn **replay được** + `verify-chain` phát hiện tamper.
- [ ] API chỉ **bọc** harness (không verdict riêng); UI đọc **artifact thật** + click-to-evidence.
- [ ] Không đụng OKR app; core harness giữ nguyên số test + thêm suite chat.
---
## 7. Ghi chú trung thực & Non-goals (không lan man)
- **[MVP-0 + MVP-1 + MVP-2 Track 4 + Operator Track 5/6 + Track 8.1/8.2/8.3] — 🟡 done+test.**
Ask CASAN read-only, Operator registered actions, agent/skill governance foundation,
OPERATOR chat-as-loop/draft-hold, replay/verify-chain foundation, và Command Center
Chat/Loop widget đã có harness CLI + Control Panel API/UI. Các phase CODEGEN-as-loop /
approvals escalation / multi-tenant production vẫn chưa mở.
- **MVP-first (chống lan man):** **MVP-0 (Ask CASAN read-only) KHÔNG phụ thuộc Plan-17/
14/SEC-23** — làm được ngay trên nền H4/H5/H6 hiện có. Chỉ **MVP-2 trở đi** (chat-as-
loop + agent) mới cần Plan-17 (T1–T3) + Plan-14 RBAC; **MVP-3** mới cần SEC-23 tenant.
Thứ tự bắt buộc: **MVP-0 → MVP-1 → MVP-2 → MVP-3**, không nhảy cóc.
- **Phụ thuộc cứng Plan-16:** enforcement chỉ "thật" khi approval JWT thật (SEC-07),
fail-closed (SEC-04/09), secure-by-default (SEC-17), tamper-evidence (SEC-01/02) đã vá.
- **Non-goals (KHÔNG làm trong plan này):**
- Không làm chatbot đa mục đích/khách hàng cuối; đây là **ops/dev console** nội bộ.
- Không thêm quyền phán quyết mới ở tầng chat (single-source harness).
- Không tự sinh agent/skill mới ngoài `agent-registry` đã governance.
- Không stream side-effect; không autonomous-by-default.
- Không thay thế core harness track — chat là **vỏ mỏng**, đứng sau core (Index P1).
- **Rẻ + verify offline trước:** bắt đầu **Track 0 (18.0.x Prompt Router)** + **Track 1
(18.1.x Read-only Ask CASAN)** + **Track 2 (18.2.x session/audit)** — thuần bash/python,
deterministic, mock model, WSL; không cần Plan-17/14/infra. Đây chính là **MVP-0**.
- **Giá trị định vị:** biến core harness thành **bề mặt hội thoại có governance** —
câu chuyện "wow thực chất": mỗi lượt chat **verify được, replay được, click-to-
evidence được**, và là hiện thân trực tiếp của **Human-led, AI-first**.
---
_Liên quan: `CASAN_PLAN_17_LOOP_ENGINEERING.md` (Loop Contract — turn = loop-run) ·
`CASAN_PLAN_13_CONTROL_PLANE.md` (§3.4 HITL inbox, §8.6 Command Center, API bọc harness) ·
`CASAN_PLAN_14_RBAC.md` (ai được chat/chọn agent) · `CASAN_PLAN_16_SECURITY_AUDIT_REMEDIATION.md`
(fail-closed, approval JWT thật, tamper-evidence, SEC-23 tenant-partition) ·
`CASAN_PLAN_03_CLOUD_PATCH.md` + `CASAN_PLAN_02_LLM_SOURCEGEN.md` (model-router + skill/agent) ·
`CASAN_PLAN_08_CONTEXT_COMPRESSION.md` (nén context giữa vòng) ·
`CASAN_PLAN_07_PRODUCTION_HARDENING.md` (H5 audit, C4 approval, C7 kill-switch, D3 fail-loud)._