diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 186496f..40a5735 100755 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -76,7 +76,7 @@ docker compose up -d backend-api backend-scheduler frontend | `tulinh` | Write | | `namcunguyen` | Write | -> ⚠️ **2026-07-03 — Security incident**: mật khẩu của các user trên từng bị lưu ở dạng plaintext ngay trong bảng này và đã bị commit vào git. Toàn bộ mật khẩu đã cần được rotate — xem [SECURITY_INCIDENT_GITEA_CREDENTIALS.md](SECURITY_INCIDENT_GITEA_CREDENTIALS.md) để biết chi tiết xử lý và tình trạng hiện tại. **Không bao giờ lưu mật khẩu/secret trong file tài liệu** — dùng password manager hoặc secret vault. +> ✅ **2026-07-03 — Security incident (đã đóng)**: mật khẩu của các user trên từng bị lưu ở dạng plaintext ngay trong bảng này và đã bị commit vào git. Đã rotate toàn bộ mật khẩu và rewrite lịch sử git để xoá sạch giá trị cũ — xem [SECURITY_INCIDENT_GITEA_CREDENTIALS.md](SECURITY_INCIDENT_GITEA_CREDENTIALS.md) để biết chi tiết. **Không bao giờ lưu mật khẩu/secret trong file tài liệu** — dùng password manager hoặc secret vault. **Nginx config:** `/opt/ai-agent/nginx/conf.d/hermes.conf` (bind mount vào nginx_proxy) diff --git a/SECURITY_INCIDENT_GITEA_CREDENTIALS.md b/SECURITY_INCIDENT_GITEA_CREDENTIALS.md index 2f75089..01771bc 100644 --- a/SECURITY_INCIDENT_GITEA_CREDENTIALS.md +++ b/SECURITY_INCIDENT_GITEA_CREDENTIALS.md @@ -1,8 +1,9 @@ # Security Incident — Gitea passwords leaked via ARCHITECTURE.md > **Phát hiện:** 2026-07-03, trong quá trình review toàn bộ dự án. +> **Đóng sự cố:** 2026-07-03. > **Mức độ:** Nghiêm trọng — mật khẩu thật ở dạng plaintext, đã nằm trong lịch sử git của repo dùng chung. -> **Trạng thái:** 🟢 Mật khẩu đã rotate xong cả 4 tài khoản; lịch sử git đã redact xong, chỉ còn 1 lệnh force-push của bạn để hoàn tất. +> **Trạng thái:** ✅ **Đã xử lý xong toàn bộ.** --- @@ -17,64 +18,38 @@ Commit `c734e3d` ("docs: thêm Gitea + Infrastructure vào kiến trúc hệ th | `tulinh` | Write | | `namcunguyen` | Write | -File này nằm trong repo private `hanlap/trading-portal` tại `git.dangloica.org`, đã được push lên `origin/master`. Bảng mật khẩu đã được gỡ khỏi phiên bản mới nhất của file (xem commit sửa `ARCHITECTURE.md` kèm theo đánh giá này), **nhưng giá trị cũ vẫn còn nguyên trong lịch sử git** — bất kỳ ai có quyền đọc repo (hoặc từng clone repo về máy, kể cả sau khi bị thu hồi quyền) đều có thể lấy lại mật khẩu bằng `git log -p` hoặc `git show c734e3d`. +File này nằm trong repo private `hanlap/trading-portal` tại `git.dangloica.org`, đã được push lên `origin/master`. Bất kỳ ai có quyền đọc repo (hoặc từng clone repo về máy, kể cả sau khi bị thu hồi quyền) đều có thể lấy lại mật khẩu bằng `git log -p` hoặc `git show c734e3d`. -## 2. Vì sao mình không tự xử lý toàn bộ +## 2. Xử lý đã thực hiện -- **Rotate mật khẩu**: cần đăng nhập vào Gitea (`git.dangloica.org`) với quyền admin — mình không có quyền truy cập hệ thống đó. -- **Rewrite lịch sử git** (xoá hẳn secret khỏi mọi commit cũ): đây là thao tác phá huỷ lịch sử dùng chung. Sau khi rewrite, tất cả 5 người (`tien`, `hanlap`, `nguyendao`, `tulinh`, `namcunguyen`) đều phải re-clone hoặc reset cứng lại repo local — nếu ai đó đang có commit chưa push dựa trên history cũ, họ sẽ mất hoặc phải rebase thủ công rất phức tạp. Đây là quyết định cần bạn xác nhận và thông báo trước cho cả team, không phải việc nên tự động thực hiện. +1. **Gỡ bảng mật khẩu khỏi bản hiện tại của `ARCHITECTURE.md`** — chặn đứng việc lộ thêm cho ai clone mới từ thời điểm đó. +2. **Rotate toàn bộ 4 mật khẩu** trên Gitea (`hanlap`, `nguyendao`, `tulinh`, `namcunguyen`) — vô hiệu hoá giá trị đã lộ. +3. **Rewrite toàn bộ lịch sử git** bằng [`git filter-repo`](https://github.com/newren/git-filter-repo), thay cả 4 mật khẩu bằng `***REMOVED***` trong mọi commit — verify bằng `git log -p | grep ` cho kết quả 0 lần xuất hiện. +4. **Force-push lịch sử đã rewrite vào `master`** — hoàn tất bởi bạn (`tien`) ngày 2026-07-03. Do team vẫn tiếp tục push code trong lúc chờ (2 lần: hotfix TypeScript của `hanlap`, và 2 commit CI/deploy workflow), nhánh rewrite tạm phải được tạo lại **4 lần** để không làm mất các commit đó — lần cuối dựa trên tip `d4abeac` của `master`. +5. Team đã được thông báo để `git fetch && git reset --hard origin/master` (không `git pull` thường, vì sẽ xung đột với lịch sử cũ). -## 3. Việc cần làm — theo thứ tự ưu tiên +**Kết quả cuối:** `origin/master` hiện tại không còn chứa mật khẩu thật ở bất kỳ commit nào trong lịch sử. -### Bước 1 — Rotate mật khẩu (làm ngay, không cần chờ bước 2) +## 3. Bài học rút ra -Đây là bước **quan trọng nhất**. Một khi mật khẩu cũ bị vô hiệu hoá, giá trị còn sót trong lịch sử git chỉ còn là dữ liệu chết — không cần rewrite lịch sử một cách gấp gáp nữa. +- **Không bao giờ lưu secret (mật khẩu, API key, token) trong file `.md`/doc** — dùng password manager (Bitwarden, 1Password...) hoặc secret vault (Vault, Doppler...) và chỉ ghi *cách lấy* secret trong tài liệu, không ghi giá trị thật. +- **Rewrite lịch sử git trên nhánh đang hoạt động (`master`) là một cuộc chạy đua với thời gian**: mỗi commit mới push lên trong lúc chuẩn bị force-push đều làm bản rewrite bị lỗi thời. Lần sau nếu cần làm việc này, nên báo team tạm dừng push vào nhánh đích trong một khung giờ ngắn *trước khi* bắt đầu chuẩn bị rewrite, thay vì chuẩn bị xong rồi mới xin tạm dừng. +- Cân nhắc thêm hook `pre-commit` chạy [gitleaks](https://github.com/gitleaks/gitleaks) hoặc [trufflehog](https://github.com/trufflesecurity/trufflehog) để chặn commit chứa secret trước khi nó vào lịch sử git — phòng hơn chữa. -1. Đăng nhập Gitea bằng tài khoản `tien` (admin). -2. Vào **Admin Panel → Users**, hoặc yêu cầu từng người tự đổi mật khẩu qua **Settings → Account**. -3. Đổi mật khẩu cho cả 4 tài khoản: `hanlap`, `nguyendao`, `tulinh`, `namcunguyen`. -4. Khuyến nghị đổi luôn mật khẩu của `tien` (dù không bị lộ trực tiếp) — vệ sinh bảo mật tốt cho tài khoản admin. -5. Nếu bất kỳ ai trong 4 người dùng lại mật khẩu đã lộ ở nơi khác (email, hệ thống nội bộ khác...), **nhắc họ đổi luôn ở những nơi đó** — thói quen dùng lại mật khẩu là rủi ro thực tế phổ biến nhất sau một vụ lộ như thế này. -6. Nếu Gitea hỗ trợ, bật 2FA cho các tài khoản có quyền ghi vào repo. - -### Bước 2 — Rewrite lịch sử git — ✅ Đã chuẩn bị xong, chỉ còn 1 bước của bạn - -Đã dùng [`git filter-repo`](https://github.com/newren/git-filter-repo) để thay thế cả 4 mật khẩu bằng `***REMOVED***` trong **toàn bộ lịch sử git** (đã verify: 0 lần xuất hiện qua `git log --all -p`). Lịch sử đã rewrite được đẩy lên nhánh tạm `history-rewrite-2026-07-03` trên origin (không đụng tới `master`) để bạn kiểm tra trước: - -`https://git.dangloica.org/hanlap/trading-portal/src/branch/history-rewrite-2026-07-03` - -> Lưu ý: nhánh này đã được tạo lại **3 lần** do `master` tiếp tục có commit mới trong lúc chờ xử lý (lần 1 dựa trên `dca7a49`, lần 2 dựa trên `d9afca4` sau hotfix của `hanlap`, lần 3 — hiện tại — dựa trên `6707d03`, tip mới nhất của `master` tính đến 2026-07-03). Bản mới nhất (tip `9d0a32c`) là bản cần force-push, các bản cũ hơn không còn dùng nữa. - -**Việc còn lại — chỉ bạn chạy được** (force-push vào `master` nằm ngoài phạm vi Claude được phép tự động thực hiện): - -```bash -git push origin history-rewrite-2026-07-03:master --force -git push origin --delete history-rewrite-2026-07-03 # dọn nhánh tạm sau khi xong -``` - -> ⚠️ **Nên chạy sớm**: mỗi lần có commit mới lên `master` trước khi force-push, nhánh rewrite lại bị lỗi thời và cần làm lại. Nếu team đang tích cực push code, tốt nhất tạm dừng push vào `master` cho đến khi force-push xong, để tránh phải lặp lại bước này lần nữa. - -Sau khi force-push, **thông báo ngay cho `hanlap`, `nguyendao`, `tulinh`, `namcunguyen`**: họ phải chạy (không được `git pull` bình thường vì sẽ tạo merge conflict với history cũ): - -```bash -git fetch origin -git reset --hard origin/master -``` - -hoặc đơn giản nhất là xoá bản clone cũ và clone lại từ đầu. - -## 4. Khuyến nghị dài hạn - -- Không bao giờ lưu secret (mật khẩu, API key, token) trong file `.md`/doc — dùng password manager (Bitwarden, 1Password...) hoặc secret vault (Vault, Doppler...) và chỉ ghi *cách lấy* secret trong tài liệu, không ghi giá trị thật. -- Cân nhắc thêm hook `pre-commit` chạy [gitleaks](https://github.com/gitleaks/gitleaks) hoặc [trufflehog](https://github.com/trufflesecurity/trufflehog) để chặn commit chứa secret trước khi nó vào lịch sử git. - -## 5. Trạng thái xử lý +## 4. Việc còn lại (không khẩn cấp) | Việc | Trạng thái | |---|---| -| Gỡ bảng mật khẩu khỏi ARCHITECTURE.md (bản hiện tại) | ✅ Đã làm (2026-07-03, cùng đợt review này) | -| Rotate mật khẩu `namcunguyen` | ✅ Đã đổi (2026-07-03) | -| Rotate mật khẩu `hanlap`, `nguyendao`, `tulinh` | ✅ Đã đổi (2026-07-03) — cả 4 tài khoản bị lộ giờ đều có mật khẩu mới | -| Rewrite lịch sử git (filter-repo, verify 0 mật khẩu còn sót) | ✅ Đã làm (2026-07-03, lần 3), đẩy lên nhánh `history-rewrite-2026-07-03` (tip `9d0a32c`) | -| Force-push nhánh rewrite đè `master` + báo team resync | ⏳ Chờ bạn chạy (xem Bước 2 ở trên) — làm sớm để tránh phải rebuild nhánh lần nữa | -| Bật 2FA cho các tài khoản ghi | ⏳ Chờ bạn thực hiện | +| Bật 2FA cho các tài khoản có quyền ghi (`hanlap`, `nguyendao`, `tulinh`, `namcunguyen`, `tien`) | ⏳ Khuyến nghị, chưa bắt buộc | +| Dọn object cũ còn sót trong các bản clone local (không ảnh hưởng repo dùng chung) | ⏳ Tuỳ chọn — mỗi người tự chạy `git gc --prune=now` nếu muốn | + +## 5. Lịch sử xử lý + +| Ngày | Việc | Người thực hiện | +|---|---|---| +| 2026-07-03 | Phát hiện sự cố, gỡ mật khẩu khỏi bản hiện tại | Claude | +| 2026-07-03 | Rotate mật khẩu `namcunguyen` | tien | +| 2026-07-03 | Rewrite lịch sử git (lần 1-4, cập nhật theo commit mới của team) | Claude | +| 2026-07-03 | Rotate mật khẩu `hanlap`, `nguyendao`, `tulinh` | tien | +| 2026-07-03 | Force-push lịch sử đã rewrite vào `master` | tien | +| 2026-07-03 | Verify sạch mật khẩu trên `origin/master`, đóng sự cố | Claude | diff --git a/theo_doi_trading-portal_v5.md b/theo_doi_trading-portal_v5.md new file mode 100644 index 0000000..989759a --- /dev/null +++ b/theo_doi_trading-portal_v5.md @@ -0,0 +1,84 @@ +# Theo dõi đánh giá dự án Trading Portal — v5 + +> **Ngày đánh giá gốc:** 2026-07-03 +> **Cập nhật v1-v4:** xem các file `theo_doi_trading-portal_v1.md`…`v4.md` +> **Cập nhật v5 (lần này):** 2026-07-03 — **đóng hoàn toàn sự cố (a)**: rotate xong 4/4 mật khẩu Gitea, rewrite + force-push lịch sử git thành công +> **Người thực hiện:** Claude (Sonnet 5), theo yêu cầu của tien.a.le@accenture.com +> **Quy ước đặt tên:** Mỗi lần có thay đổi lớn → tạo bản mới `theo_doi_trading-portal_v6.md`, ... giữ nguyên các bản cũ làm lịch sử. + +--- + +## 1. Tổng quan dự án + +(Không đổi — xem [theo_doi_trading-portal_v2.md](theo_doi_trading-portal_v2.md) mục 1.) + +--- + +## 2. Cập nhật quan trọng nhất trong v5: sự cố (a) đã đóng + +**a. Mật khẩu Gitea bị commit thẳng vào Git** — ✅ **ĐÃ ĐÓNG HOÀN TOÀN (2026-07-03)** + +Tóm tắt toàn bộ quá trình xử lý (chi tiết đầy đủ ở [SECURITY_INCIDENT_GITEA_CREDENTIALS.md](SECURITY_INCIDENT_GITEA_CREDENTIALS.md)): + +1. Gỡ bảng mật khẩu khỏi bản hiện tại của `ARCHITECTURE.md`. +2. Rotate cả 4 mật khẩu bị lộ (`hanlap`, `nguyendao`, `tulinh`, `namcunguyen`) trên Gitea. +3. Dùng `git filter-repo` rewrite toàn bộ lịch sử git, thay 4 mật khẩu bằng `***REMOVED***`. +4. Force-push lịch sử đã rewrite vào `master` — do team tiếp tục push code trong lúc chờ (hotfix TypeScript của hanlap + 2 commit CI/deploy), bước rewrite phải lặp lại **4 lần** để không làm mất các commit hợp lệ đó, trước khi force-push cuối cùng thành công. +5. Verify: `git log -p` trên `origin/master` cho **0 lần xuất hiện** cả 4 mật khẩu cũ. +6. Team đã resync theo hướng dẫn (`git fetch && git reset --hard origin/master`). + +**Bài học quy trình** (đã ghi vào SECURITY_INCIDENT doc mục 3): rewrite lịch sử trên nhánh đang hoạt động là cuộc chạy đua với thời gian — lần sau nên xin team tạm dừng push *trước khi* bắt đầu chuẩn bị, không phải sau khi chuẩn bị xong. + +**Việc còn lại, không khẩn cấp:** bật 2FA cho các tài khoản ghi (khuyến nghị, chưa bắt buộc). + +--- + +## 3. Toàn bộ nhược điểm & rủi ro — trạng thái tổng hợp đến v5 + +| # | Vấn đề | Trạng thái | +|---|---|---| +| a | Mật khẩu Gitea lộ trong lịch sử git | ✅ Đóng hoàn toàn | +| b | RBAC thiếu ở `/orders/place` | ✅ Đã xử lý + có test | +| c | Hardcode sàn "mexc" trong order routing | ✅ Đã xử lý + có test | +| d | AES-CBC không xác thực toàn vẹn | ✅ Đã chuyển sang AES-GCM + có test | +| e | Thiếu test suite/CI | 🟢 122 test, CI workflow đã thêm (chưa xác nhận runner) | +| f | Mật khẩu DB không đồng bộ trong docker-compose | ✅ Đã xử lý | +| g | CORS fallback `*` | ✅ Đã fail-closed + có test | +| h | God files (`signal_service.py`, `indicator_service.py`) | ⏳ Chưa xử lý | +| i | Frontend thiếu tầng data-fetching thống nhất | ⏳ Chưa xử lý | +| j | AnalyticsPage dùng data giả | ⏳ Chưa xử lý | +| k | Inline CSS-in-JS không design system | ⏳ Chưa xử lý | +| l | Cache in-memory single-instance | ⏳ Chưa xử lý | +| m | Rủi ro overfitting hệ thống tín hiệu | ⏳ Chưa xử lý | +| n | Không có backup/restore Postgres | ⏳ Chưa xử lý | +| o | Quản lý secrets không nhất quán | ⏳ Chưa xử lý | +| p | Eviction dùng nhầm giá cross-symbol | ✅ Đã xử lý + có test | +| q | RSI sai giá trị khi giá đi ngang | ⏳ Ghi nhận, chờ quyết định | +| r | MFI wraparound index (tác động ~0) | ⏳ Ghi nhận, không ưu tiên | +| s | Sự cố quy trình: replace_all bỏ sót 1 vị trí | ✅ Đã vá, rút kinh nghiệm | + +--- + +## 4. Đề xuất ưu tiên tiếp theo + +| Ưu tiên | Việc cần làm | +|---|---| +| Ngắn hạn | Xác nhận Gitea Actions/runner đã bật để CI thực sự chạy | +| Ngắn hạn | Bật 2FA cho các tài khoản ghi trên Gitea | +| Trung hạn | Quyết định có sửa quirk RSI (q) hay không | +| Trung hạn | Tách nhỏ `signal_service.py` (h), hợp nhất API client frontend (i) | +| Trung hạn | Gắn nhãn/ẩn AnalyticsPage demo (j) | +| Dài hạn | Backtest walk-forward trước khi tin vào win-rate để chỉnh Kelly sizing (m) | + +--- + +## 5. Lịch sử phiên bản + +| Phiên bản | Ngày | Thay đổi | +|---|---|---| +| v0 | 2026-07-03 | Đánh giá tổng thể lần đầu | +| v1 | 2026-07-03 | Fix (b), (c), (f) | +| v2 | 2026-07-03 | Test cho (b)/(c), fix (d) AES-GCM, fix (g) CORS, hướng dẫn (a) | +| v3 | 2026-07-03 | Test risk_manager/trade_executor/signal_service (81 test), CI Gitea Actions, phát hiện (p) | +| v4 | 2026-07-03 | Rewrite lịch sử git (a) chuẩn bị xong, fix (p), test indicator_service + async signal_service (122 test), phát hiện (q)/(r), ghi nhận sự cố quy trình (s) | +| v5 | 2026-07-03 | **Đóng hoàn toàn sự cố (a)** — rotate xong 4/4 mật khẩu, force-push lịch sử đã rewrite thành công, verify sạch |