N3 (Co4E) cần gọi tool nhưng Team Hoa chưa bắt đầu. Ba đường: N3 ngồi đợi
(trái nguyên tắc không team nào chặn team nào), N3 tự phỏng đoán (không ai
soi, chắc chắn phải sửa), hoặc viết một bản đề xuất để Hoa duyệt. Chọn cái
thứ ba.
Ranh giới giữ đúng sơ đồ phân hệ trong plan.md: domain/security/ là của
Gamma, application/conversations/tool_policy_gateway.py là của Hoa. Nên Gamma
định nghĩa hình dạng, Hoa cài đặt. Không đụng file nào của họ.
Hình dạng bám vào code đang chạy: SecurityVerdict (allowed/reason/layer) và
hộp thoại xin phép ở chat_panel.py:1312. Khác biệt duy nhất là gộp thành một
câu trả lời ba trạng thái ALLOW/DENY/ASK, thay vì bắt chỗ gọi tự nhớ hỏi hai
nơi.
Hai ràng buộc đưa vào có chủ đích, mỗi cái một test:
- DENY và ASK bắt buộc có reason, ném lỗi ngay lúc dựng. Người dùng cần
biết vì sao bị chặn và audit_log cần ghi lại.
- ASK không phải allowed. Đây là bẫy dễ mắc nhất: coi ASK như ALLOW thì
tool chạy trước khi có ai đồng ý.
Kèm FakeToolPolicyGateway lập trình được theo tên tool hoặc theo hàm, có ghi
lại đã hỏi những gì — test khẳng định được "có hỏi cổng không", không chỉ
"kết quả đúng không".
docs/refactor/GammaTeam_decisions.md thêm quyết định 3, kèm nguyên văn tin
nhắn cần gửi Hoa và ô đánh dấu đã gửi / đã xác nhận.
102 test xanh (96 + 6 mới). CASAN Check 1 sạch. domain/ và application/ có 0
import PySide6 — kiểm bằng AST, vì grep đếm ra 4 mà cả 4 là chữ "PySide6"
nằm trong chính docstring cảnh báo. Check 3 của Team Duy nên phân tích cú
pháp chứ đừng grep.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
6.8 KiB
Hai quyết định chờ nhóm trưởng chốt — Team Gamma
Hai việc này không code được cho tới khi có người quyết. Cả hai đều ảnh hưởng ra ngoài phạm vi một người, nên để đây thay vì chôn trong comment.
Trạng thái: chưa chốt. Hạn: trước khi N1 bắt đầu R02-T05 (26/08).
Quyết định 1 — provider_conf() còn trả api_key hay không
Vì sao phải quyết trước khi code
R02-T05 chuyển API key sang Keyring. Câu hỏi là sau khi chuyển, dict do
provider_conf() trả về còn chứa api_key không.
Có 5 nơi đang đọc trực tiếp — đo trên main ngày 21/08:
| Nơi đọc | Thuộc |
|---|---|
providers/anthropic.py:26 |
Team Duy |
providers/openai_compat.py:36 |
Team Duy |
core/image_gen.py:50 |
Team Duy (routing/model) |
core/ext_connectors.py:98 |
Team Hoa |
ui/ext_connector_dialog.py:87 |
Team Gamma |
Ba trong năm nằm ngoài team. Quyết một mình rồi im lặng là làm vỡ code người khác.
Hai đường
A. Giữ api_key trong dict, ConfigRepository tự lấy từ SecretStore rồi ghép vào
- 5 nơi đọc không phải sửa dòng nào
- Không cần báo team khác, không cần đồng bộ lịch
- Đổi lại: bí mật vẫn đi lang thang trong dict, dễ lọt vào log hoặc màn hình debug
- CASAN Check 1 vẫn PASS vì nó quét file trên đĩa, không quét bộ nhớ
B. Bỏ api_key khỏi dict, ai cần thì gọi secrets.get(provider_key(name))
- Sạch về nguyên tắc: bí mật chỉ xuất hiện đúng chỗ cần
- Đổi lại: 5 nơi phải sửa, 3 trong đó phải chờ team khác xếp lịch
- Rủi ro: quên một chỗ thì mất API key lúc chạy thật, mà test có fake nên không bắt được
Đề xuất
Đường A cho sprint này, đường B ghi vào nợ kỹ thuật.
Lý do: mục tiêu của cổng CASAN là không còn secret nằm trên đĩa, và đường A đạt được điều đó. Đường B giải quyết thêm chuyện secret trong bộ nhớ — đúng nhưng không phải việc của 10 ngày này, và nó kéo hai team khác vào một thay đổi họ không lên kế hoạch.
Nếu chọn B thì phải báo Team Duy và Team Hoa trong hôm nay, không phải lúc đã sửa xong.
Nhóm trưởng chốt: ☐ A ☐ B — ngày ____
Quyết định 2 — số phận 24 checker UI
Vấn đề
tools/check_*.py là bộ kiểm tra giao diện viết trong 2 tuần vừa rồi, hiện
24 file. Chúng bám vào đường dẫn cũ:
| Import | Số chỗ |
|---|---|
cowork_local.config |
34 |
cowork_local.app |
16 |
cowork_local.state |
22 |
cowork_local.ui.* |
~12 |
R08 dời hết những module đó sang presentation/. Nghĩa là cả 24 checker chết
ngay ngày N1 đụng config.py — và đó là lưới an toàn duy nhất cho phần giao
diện, vì pytest không kiểm giao diện (90 test hiện tại là logic).
Ba đường
A. Ai dời file thì cập nhật checker tương ứng, ngay trong PR đó
- Giữ được lưới suốt 10 ngày
- Tốn thêm ~15% thời gian mỗi PR
- Rủi ro: người sửa vội có thể nới lỏng phép kiểm cho nó xanh — đã xảy ra một lần trong quá trình làm UI, khi một checker được sửa thành không thể đỏ
B. Đóng băng: bỏ khỏi CI, sửa một lượt ngày 31/08
- Nhanh nhất trong 10 ngày
- Đổi lại: không có gì canh hồi quy giao diện suốt cả sprint. Refactor là lúc dễ vỡ giao diện nhất
- Rủi ro cuối sprint: sửa 24 file cùng lúc, không ai nhớ cái nào đo gì
C. Bỏ hẳn
Không khuyến nghị. Vứt đi hai tuần công sức kiểm chứng, và ba tài liệu refactor không có gì thay thế cho phần giao diện.
Đề xuất
Đường A, kèm một ràng buộc: PR nào sửa checker phải nói rõ trong mô tả sửa gì và vì sao — để việc nới lỏng phép kiểm không lọt qua review.
tools/check_probes_bite.py đã có sẵn cơ chế chứng minh checker còn cắn được;
chạy nó sau mỗi đợt sửa là bắt được ngay chuyện đó.
Nhóm trưởng chốt: ☐ A ☐ B ☐ C — ngày ____
Quyết định 3 — Gamma viết hộ DTO ToolPolicyGateway cho Team Hoa
Đã làm, chờ Hoa xác nhận. Ngày: 21/08.
Vì sao làm thay
N3 (Co4E) cần gọi tool nhưng Team Hoa chưa bắt đầu. Ba đường:
| Hệ quả | |
|---|---|
| N3 ngồi đợi Hoa | Mất mấy ngày, trái nguyên tắc "không team nào chặn team nào" |
| N3 tự phỏng đoán | Phỏng đoán của một người, không ai soi, sửa lại chắc chắn |
| Gamma viết bản đề xuất | N3 chạy ngay, Hoa có cái cụ thể để duyệt hoặc sửa |
Ranh giới không lấn
Sơ đồ phân hệ trong plan.md giao domain/security/ cho Team Gamma, còn
application/conversations/tool_policy_gateway.py cho Team Hoa.
Nên chia đúng như vậy:
- Gamma định nghĩa hình dạng →
domain/security/tool_policy.py - Hoa cài đặt gateway →
application/conversations/tool_policy_gateway.py, nối vàocore/mcp_client.pyvà tool dựng sẵn
Không đụng file nào của Hoa.
Đã bám vào code đang chạy, không bịa
| Nguồn | Lấy gì |
|---|---|
core/agent_security.py::SecurityVerdict |
allowed · reason · layer |
ui/permission_dialog.py + chat_panel.py:1312 |
trạng thái "hỏi người dùng" |
Khác biệt duy nhất: gộp thành một câu trả lời ba trạng thái
(ALLOW / DENY / ASK) thay vì bắt chỗ gọi tự nhớ hỏi hai nơi.
Hai ràng buộc đưa vào có chủ đích:
DENYvàASKbắt buộc córeason— người dùng cần biết vì sao, vàaudit_logcần ghi lại. Thiếu là ném lỗi ngay lúc dựng, không phải lúc chạy.ASKkhông phảiallowed— bẫy dễ mắc nhất là coi ASK như ALLOW rồi tool chạy mà chưa ai đồng ý. Có test riêng cho chuyện này.
Gửi Hoa cái gì
Bên mình viết trước bản đề xuất
ToolPolicyGatewayởdomain/security/tool_policy.pyvì N3 cần gọi tool mà bên Hoa chưa bắt đầu — để N3 khỏi phải tự đoán. Ba kiểu:ToolCallRequest,PolicyDecision,ToolPolicyGateway. Phần cài đặt vẫn để bên Hoa ởapplication/conversations/tool_policy_gateway.py, bọn mình không đụng. Thấy chỗ nào không hợp thì sửa thẳng file đó, đừng tạo kiểu thứ hai. Đổi bây giờ còn rẻ vì mới mình N3 dùng.
Đã gửi Hoa: ☐ — ngày ____ Hoa xác nhận: ☐ đồng ý ☐ có sửa