465 lines
37 KiB
Markdown
465 lines
37 KiB
Markdown
# KẾ HOẠCH 18 — Governed Chat Console (Chat-as-Loop qua Control Plane)
|
||
|
||
> Status 2026-07-09b: **✅ Chat capability uplift (items 1–5) done+test.**
|
||
> **(1) ANALYSIS mode**: router phân loại ý định suy luận/so sánh (`analyze/compare/
|
||
> evaluate/trade-off…`) → `ANALYSIS` (read-only, no side-effect), synthesis dùng
|
||
> prompt lập luận `role=analysis`. **(2) Multi-turn memory**: `chat-readonly.load_history`
|
||
> dựng lại lịch sử **per-chat/per-tenant** từ H5 audit (chỉ preview đã H4-scan, không
|
||
> raw msg), nén qua Plan-08 `context-compress`, nạp vào prompt; cross-chat/cross-tenant
|
||
> không rò. **(3) Streaming**: `ask --stream` phát NDJSON 2 pha — draft `UNCERTIFIED`
|
||
> (deterministic, whitelist-only, no side-effect) rồi final certified; injection → deny
|
||
> trước khi có draft. Control Panel: `POST /api/v1/chat/ask/stream` (spawn NDJSON) + UI
|
||
> toggle Stream + draft banner. **(4) CODEGEN full model-router**: `chat-turn._model_codegen_body`
|
||
> sinh code qua `model-router.sh` (offline-first, fallback scaffold), vẫn artifact-scan +
|
||
> loop-cert, draft-only; injection trong code sinh → artifact-scan BLOCK. **(5) Cloud
|
||
> live-smoke**: `chat-cloud-smoke.sh` chạy synthesis cloud thật khi có key, SKIP khi
|
||
> không (không nằm trong unit gate). Test: `phase-chat-advanced` **8/0** + `phase-chat-model-synthesis`
|
||
> **7/0**; toàn bộ chat suites **74/0 (WSL)**, nối `ci-harness-gate.sh`; Control Panel TS sạch.
|
||
>
|
||
> Status 2026-07-09: **✅ Track M (Model Provider Binding) — model-optional grounded synthesis done+test.**
|
||
> Read-only Ask CASAN giờ tổng hợp câu trả lời tự nhiên **có trích dẫn** khi
|
||
> `CASAN_CHAT_MODEL_MODE=model` (RAG: whitelist sources → `model-router.sh --role
|
||
> generate`), giữ **offline-first**: mặc định/CI vẫn deterministic (không phụ thuộc
|
||
> model). Fail-SAFE: model lỗi/không sẵn sàng → fallback deterministic, không crash,
|
||
> không bịa. Cloud provider → ép `CASAN_PREFLIGHT=1` (PII→cloud guard). Model output
|
||
> vẫn qua H4 output scan (secret → DENY fail-closed). H6 ghi real token + provider
|
||
> cost_source. Config: `packages/casan-harness/config/model-providers.yaml`. Test
|
||
> `phase-chat-model-synthesis` **7/0 (WSL)**, nối `ci-harness-gate.sh`; UI `/chat`
|
||
> hiện badge `model:<provider>`/`deterministic`. **Còn:** ANALYSIS synthesis + multi-turn
|
||
> memory + streaming read-only + CODEGEN full model-router path + cloud live-smoke (key thật).
|
||
>
|
||
> Status 2026-07-08: **✅ MVP-0 + MVP-1 + MVP-2 + MVP-3 done+test.**
|
||
> Đã 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. **CODEGEN-as-loop** đã có draft-only artifact scan +
|
||
> loop certification. **Track 8.1/8.2/8.3/8.4** đã có replay/verify-chain
|
||
> foundation, Command Center Chat/Loop widget đọc chat audit/replay evidence thật,
|
||
> và escalation vào approvals inbox.
|
||
> **Track 9/MVP-3** đã partition chat state theo tenant, guard explicit paths,
|
||
> ghi encrypted audit snapshot, và scope kill-switch/quota theo tenant.
|
||
> 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`/`model_role` binding + routing theo role; synthesis gọi `model-router.sh --role generate` | `config/model-providers.yaml` + `chat-readonly.py synthesize_answer` | `phase-chat-model-synthesis`: model mode → provider `local`, answer có citations |
|
||
| 18.M.2 | 🟡 Data policy `local/internal/cloud`: cloud → ép `CASAN_PREFLIGHT=1` (harness-preflight PII→cloud C3). Live cloud test cần key thật | nối `harness-preflight.sh` | offline: model output secret → H4 output scan DENY fail-closed (test 5) |
|
||
| 18.M.3 | ✅ Credential ngoài repo: chỉ `key_env` name trong config, key đọc từ env qua `model-call.py`; cloud key unset → fallback deterministic (không bịa) | `model-providers.yaml` + `model-call.py` | key unset → `reason=cloud_key_unset` |
|
||
| 18.M.4 | ✅ Provider token/cost telemetry → H6: real `input/output_tokens` + `cost_source` per backend + `synthesis_mode` | `chat-readonly.py record_metrics` | test: H6 metric `ollama_local_real_tokens`, tokens 42/17 |
|
||
|
||
### 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 | `chat-turn.py` + `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 | 🟡 agent/skill picker theo RBAC + delegation-level + loop certification badges + replay/evidence surfaces đã có; nút **loop-breaker** trực tiếp vẫn là target UI follow-up | Control Plane UI | picker hiện locked agent, backend DENY agent ngoài quyền; OPERATOR/CODEGEN 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) | `chat-turn.py` + `approval-inbox.py` + `/approvals` | 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** | `tenant-store.sh` + chat audit/replay paths | tenant A không đọc/ghi state B |
|
||
| 18.9.2 | ✅ per-tenant encrypt at-rest (MT-02 offline snapshot) | `tenant-crypt.sh` | admin/tenant B không decrypt audit A |
|
||
| 18.9.3 | ✅ quota / kill-switch scope theo tenant (MT-03) | `kill-switch.sh` + `cost-spike-detect.sh` | 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`, `phase-chat-approval-tests.sh`,
|
||
`phase-chat-codegen-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.
|
||
- [x] CODEGEN draft path binds `codegen-draft`/`sourcegen-draft`, proves `artifact-scan` + `tool-output-scan` in allowlist, blocks injected generated artifacts, and certifies draft-only artifact through Plan-17 loop-run. Verify: `phase-chat-codegen` 4/0, `phase-chat-prompt-router` 9/0.
|
||
|
||
**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.
|
||
|
||
**MVP-2 Track 8.4 (Approvals / escalation):**
|
||
- [x] Delegation escalation (`REQUIRES_APPROVAL`) from chat creates an `ESCALATED` ChatTurn and pending `chat.escalate` proposal in `approval-inbox.py`.
|
||
- [x] Approval inbox keeps SoD and reason requirements; strict mode / supplied approval JWT calls `approval-verify.sh` and fake JWT is denied before proposal mutation.
|
||
- [x] Control Panel `/approvals` can pass an approval JWT for strict review; dev mode remains backward-compatible.
|
||
- [x] Verify: `phase-chat-approval` 4/0, `phase-chat-agent-select` 8/0, `phase-chat-replay` 4/0, `console:test` 28/0, `console:build` xanh.
|
||
|
||
**MVP-3 Track 9 (Multi-tenant hardening):**
|
||
- [x] Non-default tenant chat turns write audit/head/agent-binding/metrics/artifacts/loop state under `tenant-store.sh` partitions; default single-tenant path remains backward-compatible.
|
||
- [x] `chat-replay.py` and explicit chat audit overrides are guarded by tenant-store, so tenant A cannot point replay at tenant B's audit path.
|
||
- [x] Chat audit writes create per-tenant encrypted `.enc` snapshots via `tenant-crypt.sh`; tenant B cannot decrypt tenant A's snapshot.
|
||
- [x] Chat entry checks tenant-scoped kill-switch and tenant cost quota before work; tenant A halt/quota does not halt tenant B.
|
||
- [x] Verify: `phase-chat-tenant` 8/0, `console:test` 29/0, `console:build` xanh.
|
||
|
||
**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ụ.
|
||
- [x] 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 + MVP-3] — ✅ done+test.**
|
||
Ask CASAN read-only, Operator registered actions, agent/skill governance foundation,
|
||
CODEGEN draft-as-loop, OPERATOR chat-as-loop/draft-hold, replay/verify-chain foundation,
|
||
Command Center Chat/Loop widget, approvals escalation đã có harness CLI + Control Panel
|
||
API/UI. Multi-tenant chat state, replay guard, encrypted audit snapshot, tenant kill-switch,
|
||
và tenant quota đã có test đối kháng.
|
||
- **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)._
|