Metadata-Version: 2.4
Name: gofile-tool
Version: 0.2.1
Summary: CLI, Python SDK và MCP server cho Gofile với truyền file có kiểm chứng
License-Expression: Apache-2.0
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
License-File: LICENSES/MIT-original.txt
Requires-Dist: requests<3,>=2.31
Requires-Dist: PySocks<2,>=1.7.1
Requires-Dist: requests-toolbelt<2,>=1.0
Requires-Dist: rich<15,>=13.7
Provides-Extra: mcp
Requires-Dist: mcp<1.31,>=1.30; python_version >= "3.10" and extra == "mcp"
Provides-Extra: browser
Requires-Dist: playwright<2,>=1.45; extra == "browser"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=7; extra == "dev"
Requires-Dist: coverage>=7.10; extra == "dev"
Requires-Dist: hypothesis>=6; extra == "dev"
Requires-Dist: build>=1; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Requires-Dist: jsonschema>=4; extra == "dev"
Dynamic: license-file

> Bản mô tả tiếng Việt được tạo từ README.md. Bản tiếng Anh README.en.md và các tài liệu tham chiếu đi kèm source distribution; các link file nội bộ được hiển thị dạng tên tài liệu trên PyPI.

# gofile-tool — CLI, Python SDK và MCP server cho Gofile

[![PyPI version](https://img.shields.io/pypi/v/gofile-tool.svg)](https://pypi.org/project/gofile-tool/)
[![Python](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://pypi.org/project/gofile-tool/)
[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE)

**Tiếng Việt (mặc định)** · English · Chỉ mục tài liệu

**Phiên bản: `0.2.1` · Python ≥ 3.9 · Apache-2.0 · kênh ổn định (stable).**

`gofile-tool` là bộ công cụ tải xuống, upload, quản lý nội dung Gofile **thuộc quyền
sở hữu của bạn**, với kết quả JSON ổn định để tích hợp chương trình và agent. Lệnh
viết tắt được ưu tiên là **`gft`**; **`gofile-tool`** và **`gf`** là các tên đầy đủ
cùng một implementation. Kèm theo **Python SDK** (`import gofile_tool`) và
**MCP stdio server** (`gft-mcp`, optional).

> **Trạng thái hỗ trợ:** CLI, SDK và MCP stdio đã hoạt động. Native Windows/macOS,
> Docker và các bài endurance dài **chưa được kiểm chứng trong bản phát hành này** —
> CI có sẵn matrix 3 hệ điều hành × Python 3.9–3.14 để kiểm chứng khi chạy.
> JSON output / JSON Schema là **hợp đồng tích hợp**; hỗ trợ Model Context Protocol
> nằm ở `gft-mcp`.

---

## Mục lục

1. [Tên dự án và phạm vi](#1-tên-dự-án-và-phạm-vi)
2. [Tính năng và giới hạn](#2-tính-năng-và-giới-hạn)
3. [Yêu cầu môi trường](#3-yêu-cầu-môi-trường)
4. [Cài đặt và cập nhật](#4-cài-đặt-và-cập-nhật)
5. [Làm quen nhanh](#5-làm-quen-nhanh)
6. [Token, quyền sở hữu, mật khẩu và proxy](#6-token-quyền-sở-hữu-mật-khẩu-và-proxy)
7. [Tải xuống, lọc và batch](#7-tải-xuống-lọc-và-batch)
8. [Upload file và thư mục](#8-upload-file-và-thư-mục)
9. [Journal, resume và chống trùng](#9-journal-resume-và-chống-trùng)
10. [Băng thông, retry, timeout và hủy](#10-băng-thông-retry-timeout-và-hủy)
11. [Các lệnh quản lý](#11-các-lệnh-quản-lý)
12. [JSON, exit code, ngôn ngữ và agent](#12-json-exit-code-ngôn-ngữ-và-agent)
13. [Python SDK](#13-python-sdk)
14. [MCP stdio server](#14-mcp-stdio-server)
15. [Bảo mật và dữ liệu nhạy cảm](#15-bảo-mật-và-dữ-liệu-nhạy-cảm)
16. [Cấu trúc dự án](#16-cấu-trúc-dự-án)
17. [Test và kiểm chứng](#17-test-và-kiểm-chứng)
18. [Build và phát hành PyPI](#18-build-và-phát-hành-pypi)
19. [Xử lý lỗi thường gặp](#19-xử-lý-lỗi-thường-gặp)
20. [Tài liệu và giấy phép](#20-tài-liệu-và-giấy-phép)

---

## 1. Tên dự án và phạm vi

| Tên | Ý nghĩa |
|---|---|
| `gofile-tool` | Distribution trên PyPI; lệnh CLI đầy đủ |
| `gft` / `gf` | Lệnh viết tắt; `gf` là alias tương thích cũ |
| `gofile_tool` | Namespace Python khi import |
| `gft-mcp` | Entrypoint MCP stdio server (optional extra `[mcp]`) |

Dự án là **client không chính thức**, không được Gofile bảo trợ hay chứng nhận.
Công cụ không vượt quyền private, password, Premium, frozen hay giới hạn tài khoản
của dịch vụ — các hàng rào truy cập do **server quyết định**.

Các chuỗi `CONTENT_ID`, `FILE_ID`, `FOLDER_ID`, `ROOT_FOLDER_ID`, `LINK_ID` trong
ví dụ là placeholder; không chạy lệnh có tác động remote khi chưa xác định rõ đối tượng.

## 2. Tính năng và giới hạn

### Tính năng chính

| Nhóm | Khả năng |
|---|---|
| Download | Streaming, kiểm tra size/MD5, nhiều file song song (`--workers` 1–32), partial download có identity manifest, kiểm tra Range/collision, publish atomic |
| Upload file | Streaming multipart, mở nguồn có kiểm soát (no-follow, anchored), hash trước/sau, **không bao giờ tự replay mutation** |
| Upload thư mục | Kế hoạch offline (`--dry-run`), lọc file, tạo thư mục lồng nhau, executor tuần tự với journal bền vững |
| Job upload | Journal atomic, khóa process, resume đã xác minh, từ chối replay mutation chưa rõ kết quả (`inflight`) |
| Chống trùng | Trong cùng job: rehash local + xác minh metadata remote trước khi bỏ qua file hoàn tất |
| Băng thông | Bộ lập lịch byte dùng chung mỗi client (`--limit-rate`), kiểm tra deadline/hủy khi chờ |
| Refresh link | Opt-in (`--refresh-links`), tối đa một lần/file sau 401/403, giữ nguyên credential và định danh file |
| CLI | Alias, JSON envelope versioned cho automation, output Rich trên terminal, shell completion, watchdog deadline |
| Quản lý | Account/servers, mkdir/rename/set/copy/move/import/search, direct link, restore/recycle theo quyền dịch vụ |
| i18n | Thông báo lỗi/cảnh báo **tiếng Việt hoặc tiếng Anh** (`--lang vi`, `GFT_LANG`); mã lỗi giữ nguyên tiếng Anh |
| MCP | Stdio server với tool scope tường minh: plan upload, job status, info/download khi được cấp quyền |

### Giới hạn được công bố

- MCP chỉ có stdio; chưa có HTTP/SSE, multi-tenant hay remote mutation tools.
- Không có history/dedup toàn cục, incremental sync, hay download-job queue.
- Upload thư mục hiện **tuần tự**; `--workers` chỉ điều khiển download.
- Không tự đối soát/replay mutation ở trạng thái chưa rõ kết quả — đây là thiết kế.
- Không cam kết throughput trên mạng/Gofile thực tế.
- Native Windows/macOS, Docker và soak dài **chưa được kiểm chứng** trong bản phát hành này.
- Coverage 100% không chứng minh phần mềm không còn lỗi.

## 3. Yêu cầu môi trường

- Python **3.9 trở lên** (MCP cần **3.10+** và extra `[mcp]`).
- Dung lượng đĩa cho dữ liệu tải, file `.part`, journal.
- Quyền đọc nguồn upload, quyền ghi thư mục output/job — thư mục tải trên POSIX
  phải thuộc sở hữu của bạn và **không group/world-writable**.
- Mạng tới dịch vụ cho thao tác remote; `upload --dry-run`, `job-status`, `verify`,
  `schema`, `completion` là thao tác **local**.
- Xác thực browser (mặc định) cần extra `browser`, Chromium và OS dependencies.

`--auth-mode api` bỏ qua browser signing provider nhưng **không phải cách vượt hạn
chế truy cập** — endpoint/tài khoản vẫn có thể cần quyền hoặc gói dịch vụ khác
(thông báo `error-notPremium` là hàng rào phía máy chủ).

Công cụ không tự chạy `pip`/`apt`/`brew`, không tự nâng quyền, không tự bật/tắt
Tor, không tự tắt Chromium sandbox.

## 4. Cài đặt và cập nhật

### 4.1. Từ PyPI (khuyến nghị)

```bash
python -m pip install --upgrade 'gofile-tool[browser]'
python -m playwright install chromium   # chỉ cần khi dùng --auth-mode browser (mặc định)
gft --version                           # kỳ vọng: gft 0.2.1
```

Không cần cài `[browser]` nếu bạn chỉ lập kế hoạch local, dùng `--auth-mode api`
phù hợp, hoặc chạy MCP không network. Cập nhật bằng `pip install -U gofile-tool`
(không cần `--pre`; distribution name không đổi thành `gft`).

Trên Linux, nếu Chromium thiếu thư viện hệ thống (operator chủ động):

```bash
python -m playwright install-deps chromium   # có thể cần quyền quản trị
```

### 4.2. Từ wheel local

```bash
python -m venv .venv
source .venv/bin/activate        # Windows PowerShell: .\.venv\Scripts\Activate.ps1
python -m pip install 'gofile_tool-0.2.1-py3-none-any.whl[browser]'
python -m playwright install chromium
gft --help
```

### 4.3. Cho phát triển

```bash
cd gofile-tool
python -m pip install -e '.[browser,dev,mcp]'
python -m pytest -q             # 408 tests, không cần mạng
```

Sau khi di chuyển checkout, cài lại editable package (`.pth`/shebang có thể chứa
đường dẫn cũ).

## 5. Làm quen nhanh

```bash
# Metadata nội dung được phép truy cập
gft info CONTENT_ID --json

# Tải xuống với kiểm tra MD5
gft dl CONTENT_ID -o ./downloads --workers 4 --json

# Cây nội dung và danh sách link
gft tree CONTENT_ID --json
gft links CONTENT_ID --json

# Kế hoạch upload local — không gửi byte nào lên dịch vụ
gft upload ./photos --recursive --dry-run --include '*.jpg' --json

# Chẩn đoán cấu hình (không chết khi thiếu browser — tự báo cáo)
gft doctor --json
```

Alias: `i`/`ls` → `info`, `dl` → `download`, `up` → `upload`, `rm` → `delete`.

## 6. Token, quyền sở hữu, mật khẩu và proxy

### Owner token

Ưu tiên `GOFILE_TOKEN` qua secret manager; `--token` được hỗ trợ nhưng argv có thể
hiện trong process list. Không ghi token vào source/log/issue. Các lệnh
`account`, mutation quản lý và upload thư mục cần **owner token**; có token không
nghĩa sở hữu mọi folder — server quyết định quyền thực tế.

### Guest upload một file

```bash
gft upload ./document.pdf --export-token ./guest.token --json
```

- Guest upload **bắt buộc** `--export-token FILE` để giữ credential quản lý file
  đã upload (file create-only, mode 0600 trên POSIX).
- Chạy lại cùng lệnh khi file token đã tồn tại sẽ nhận `COLLISION` kèm hướng dẫn:
  xóa file, đổi đường dẫn, hoặc thêm **`--force`** để chủ động ghi đè.
- Credential được ghi **sớm** khi account được tạo, không chỉ khi lệnh kết thúc.
- `upload --dry-run` không tạo file token (có warning trong envelope).
- Upload thư mục (`--recursive`) cần owner token, không tự tạo guest.

### Password nội dung

```bash
gft info CONTENT_ID --password-env GOFILE_FOLDER_PASSWORD --json
```

Truyền **tên biến** môi trường, không truyền password literal. Đây là hash theo
metadata protocol của dịch vụ, không phải mã hóa phía client.

### Proxy

`--proxy`/`GOFILE_PROXY` với scheme HTTP/HTTPS/SOCKS5/SOCKS5H, host và port tường
minh. Proxy explicit là tuyến **độc quyền** — không âm thầm fallback. Không có
proxy explicit, Requests có thể dùng cấu hình environment của hệ thống.

## 7. Tải xuống, lọc và batch

```bash
gft download CONTENT_ID -o ./downloads --workers 4 --json

# Bộ lọc
gft dl CONTENT_ID -o ./downloads \
  --include '*.jpg' --exclude '*thumbnail*' \
  --min-size 1024 --max-size 10485760 --max-files 500 --json
```

| Flag | Ý nghĩa |
|---|---|
| `--include` / `--exclude` | Một glob mỗi flag trên đường dẫn tương đối POSIX (`fnmatchcase`, phân biệt hoa/thường) |
| `--min-size` / `--max-size` | Kích thước tối thiểu/tối đa (byte) |
| `--max-files` | Giới hạn số file chọn (mặc định 100.000; vượt quá → lỗi rõ ràng) |
| `--no-verify` | Giảm kiểm tra xuống size-only — chủ động chấp nhận rủi ro |
| `--refresh-links` | Làm mới link bị 401/403 tối đa một lần/file, có kiểm tra định danh |
| `--dry-run` | Vẫn gọi metadata (có thể cần auth) nhưng không tải nội dung |

Công cụ reserve đường dẫn (kể cả va chạm `a.part`/`a`), lock destination, xử lý
partial/Range, xác minh size + MD5 khi server cung cấp, publish atomic. File đích
khác nội dung **không bị ghi đè âm thầm** (`COLLISION`). Server không có MD5 →
cảnh báo kiểm tra size-only.

### Batch

```bash
gft batch ./targets.txt -o ./downloads --workers 4 --json
```

`targets.txt` UTF-8: mỗi dòng một URL/code, `#` là comment. Giới hạn 1.000 target,
2.048 ký tự/dòng (dòng đúng 2.048 ký tự được chấp nhận). Mỗi target có thư mục
output riêng; job lỗi nằm trong `data.jobs` — không giả vờ cả batch thành công.

## 8. Upload file và thư mục

### Một file

```bash
gft upload ./document.pdf --folder-id FOLDER_ID --json
gft upload ./photo.jpg --public --json      # publish tường minh, có thể kèm parent
```

Nguồn được mở có kiểm soát (regular file, no-follow) và kiểm tra identity/hash
trước/sau. Nếu nguồn thay đổi giữa chừng → `INTEGRITY_ERROR`, không tự gửi lại.
`--public` là lựa chọn tường minh; `public=null` trong kết quả **không** khẳng định
file chắc chắn private.

### Kế hoạch thư mục (offline)

```bash
gft up ./photos --recursive --dry-run --include '*.jpg' --max-files 500 --json
```

Plan báo file, path, size, source identity, danh sách thư mục, tổng byte. Scan tối
đa 100.000 entry, độ sâu 64; symlink/special file bị từ chối.

### Upload thư mục thật (durable job)

```bash
gft up ./photos --recursive --folder-id FOLDER_ID \
  --job-dir ./transfer-jobs/photos --limit-rate 1048576 --json
```

1. Bắt buộc owner token; `--folder-id` là **bắt buộc** với `--recursive`.
2. `--job-dir` phải nằm **ngoài source**; job mới không ghi đè job cũ (dùng `--resume`).
3. Mọi file được hash preflight trước mutation đầu tiên; tối đa 10.000 file/job.
4. Thư mục lồng nhau/rỗng được giữ; upload tuần tự; `--public` bị từ chối khi đệ quy.

**Không tự bỏ qua `.env`, private key hay dữ liệu nhạy cảm.** Chọn source hẹp,
xem dry-run, dùng filter rõ ràng.

## 9. Journal, resume và chống trùng

```bash
gft job-status --job-dir ./transfer-jobs/photos --json
gft up ./photos --recursive --folder-id FOLDER_ID \
  --job-dir ./transfer-jobs/photos --resume --json
```

Journal: `JOB_DIR/state.part.json` (atomic write, schema versioned, không lưu
token/password). Binding gồm source/plan/content/account/destination.

| Tình huống | Hành vi |
|---|---|
| File đã commit, journal ghi nhận | Hash lại local + xác minh remote → skip |
| Chết sau checkpoint commit | Resume dùng checkpoint đã xác minh |
| Chết trong cửa sổ mutation | Giữ `inflight` → dừng để đối soát, **không replay** |
| Nguồn/plan/account/destination đổi | Từ chối reuse job |
| Remote file mất/đổi identity | Dừng, không tự tạo bản thay thế |
| Journal hỏng/quá lớn | Báo lỗi rõ ràng thay vì đoán |

Không xóa journal hay sửa `inflight` để ép chạy tiếp; đối soát thủ công khi cần.

## 10. Băng thông, retry, timeout và hủy

| Tham số | Mặc định | Phạm vi |
|---|---:|---|
| `--limit-rate` | 0 | Byte/giây chung mỗi client; 0 = không throttle |
| `--timeout` | 30 | Timeout mỗi HTTP call |
| `--deadline` | 300 | Hard wall-clock watchdog của CLI (cả cây tiến trình) |
| `--retries` | 2 | 0–10; áp cho GET **và tạo guest account**; content mutation không bao giờ replay |
| `--workers` | 4 | Download workers, 1–32 |

`retryable=true` trong lỗi là thông tin chẩn đoán, **không** giấy phép tự replay
upload/delete/mkdir. Hủy bằng Ctrl+C; SDK dùng `cancel_event` (`threading.Event`)
để hủy cooperative. Sau khi chạm deadline, kiểm tra `data`/journal trước khi chạy
lại mutation — remote có thể đã commit.

## 11. Các lệnh quản lý

Cần owner scope (trừ `servers`); quyền Premium/feature do **server quyết định**.
Dùng `--value` (JSON literal) hoặc `--value-file` (file JSON) — **không dùng đồng
thời cả hai**. Không đặt password nhạy cảm vào argv.

| Lệnh | Ví dụ |
|---|---|
| `account` / `servers` | `gft account --json` |
| `mkdir` | `gft mkdir ROOT_FOLDER_ID --value '"Photos"' --json` |
| `rename` | `gft rename CONTENT_ID --value '"new-name"' --json` |
| `set` | `gft set CONTENT_ID --attribute description --value '"Desc"' --json` |
| `copy` / `move` | `gft copy CONTENT_ID --destination FOLDER_ID --json` |
| `import` | `gft import CONTENT_ID --json` |
| `search` | `gft search FOLDER_ID --query photo --json` |
| `public` | `gft public CONTENT_ID --json` |
| `delete` / `rm` | `gft delete FILE_ID --yes --json` (hỗ trợ danh sách ID phân cách phẩy) |
| `direct-link` | `gft direct-link CONTENT_ID --value '{}' --json` |
| `update-link` / `delete-link` | Cần `--link-id`; `delete-link` yêu cầu `--yes` |
| `restore` | `gft restore CONTENT_ID --json` |
| `empty-recycle` | `gft empty-recycle --yes --json` |

Attribute hỗ trợ: `name`, `public`, `password`, `expiry`, `tags`, `description`,
`modTime` — giá trị/quyền thực tế phụ thuộc API. Thao tác phá hủy (`delete`,
`empty-recycle`, `delete-link`) đều yêu cầu `--yes`.

Lệnh tiện ích: `verify FILE --sha256 HASH`, `schema`, `completion bash|zsh|fish`
(trả script trong response — kiểm tra trước khi dùng). `schema` là schema của
**CLI envelope**, không phải MCP tool schema.

## 12. JSON, exit code, ngôn ngữ và agent

Mặc định auto: Rich trên terminal, JSON khi redirect. Dùng `--json` cho automation;
`--format auto|json|plain|rich`, `--no-color` được hỗ trợ.

```json
{
  "schema_version": "1",
  "ok": true,
  "command": "upload",
  "data": { "planned": true, "operation": "upload", "files": [], "total": 0, "total_bytes": 0, "failed": 0 },
  "error": null,
  "warnings": []
}
```

Schema authoritative: `src/gofile_tool/schema.json` (đóng trong wheel, xem
`gft schema --json`). `info` giữ envelope dịch vụ → metadata ở `data.data`;
download ở `data.files`; batch ở `data.jobs`. Luôn kiểm tra **exit code và `ok`**.

| Exit code | Ý nghĩa |
|---:|---|
| 0 | Thành công |
| 2 | Input/path không hợp lệ, `COLLISION`, `UNSAFE_PATH` |
| 3 | Auth/access, not-found, password, expiry/frozen/Premium |
| 4 | Network, rate limit, deadline, busy |
| 5 | Partial failure, integrity failure |
| 6 | Schema/internal/filesystem/provider/worker |
| 130 | Đã hủy (Ctrl+C) |

### Ngôn ngữ thông báo (i18n) — `--lang vi|en`

Thông báo lỗi và cảnh báo có thể là **tiếng Việt hoặc tiếng Anh**; **mã lỗi**
(`COLLISION`, `PREMIUM_REQUIRED`…), exit code và trường dữ liệu **không đổi**.

```bash
gft dl CONTENT_ID -o ./downloads --lang vi --json
GFT_LANG=vi gft up ./document.pdf --export-token guest.token --json
```

- Thứ tự ưu tiên: `--lang` > `GFT_LANG` > mặc định `en`.
- Python SDK: `from gofile_tool import i18n; i18n.set_language("vi")`.
- `error.message` và `warnings` được dịch; `error.code`, `http_status`,
  `api_status` giữ nguyên.

### Agent

Gọi subprocess với timeout ngoài rồi parse JSON (xem `examples/cli_download.py`).
Không parse bảng terminal, không đặt secret vào prompt/log. **Đây là tích hợp CLI,
không phải MCP** (xem mục 14).

## 13. Python SDK

```python
from gofile_tool import Gofile, GofileError, i18n

i18n.set_language("vi")                      # tùy chọn; mặc định "en"
client = Gofile(timeout=20, deadline=120, limit_rate=1048576)

try:
    metadata = client.info("CONTENT_ID")
    files = client.download("CONTENT_ID", "downloads", workers=4, refresh_links=True)
    if not all(item["ok"] for item in files):
        print("Một số file thất bại — xem kết quả chi tiết, không replay mù")
except GofileError as error:
    print(error.code, error.retryable, error.as_dict()["message"])
```

Upload job có cancellation:

```python
import threading
from gofile_tool import Gofile

cancel = threading.Event()
client = Gofile(deadline=300, cancel_event=cancel)   # GOFILE_TOKEN từ secret manager

result = client.upload_tree(
    source="photos", destination="FOLDER_ID",
    job_dir="transfer-jobs/photos", resume=False,
    include="*.jpg", max_files=500,
)
if result["failed"]:
    print("Job dừng — kiểm tra journal trước khi resume")
```

- Client lấy `GOFILE_TOKEN` nếu có; luồng được phép có thể tạo guest.
- Không chia sẻ một client giữa các caller threads tùy ý.
- Import public từ `gofile_tool`; module nội bộ có thể được tổ chức lại.

## 14. MCP stdio server

**MCP server thật** qua MCP Python SDK 1.30.x — entrypoint **`gft-mcp`**
(Python ≥ 3.10, extra `[mcp]`). Đây là giao thức MCP, không phải "JSON output".

```bash
python -m pip install 'gofile-tool[mcp,browser]'
python -m playwright install chromium
gft-mcp --read-root /ABS/gofile-mcp/read            # mặc định: local-only
gft-mcp --read-root ... --allow-network             # + gofile_info (cần GOFILE_TOKEN)
gft-mcp --read-root ... --allow-network --download-root /ABS/gofile-mcp/downloads
```

| Tool | Điều kiện | Phạm vi |
|---|---|---|
| `gofile_plan_upload` | luôn | Metadata local, không payload/network |
| `gofile_job_status` | luôn | Tóm tắt journal bounded |
| `gofile_info` | `--allow-network` + `GOFILE_TOKEN` | Một trang metadata |
| `gofile_download` | + `--download-root` | ≤1.000 file, ≤64 MiB/file, 2 MiB/s |

- Root/permission là **startup policy của operator**, không nhận từ model.
- Chặn path traversal/symlink, extra arguments, output bounded, lỗi có redaction.
- Không có upload/delete/publish qua MCP; không HTTP/multi-tenant.

Chi tiết: hướng dẫn MCP. Dùng `gft-mcp` (có gạch nối),
không có lệnh `gft mcp`.

## 15. Bảo mật và dữ liệu nhạy cảm

- Chỉ thao tác trên dữ liệu được phép; không bypass entitlement/password/private.
- Giữ token/password ngoài source, argv dễ lộ, log, issue, gói publish.
- Link, filename, remote ID, journal cũng có thể nhạy cảm.
- POSIX: descriptor anchoring/no-follow; fallback Windows yếu hơn trước race.
- MD5 là kiểm tra tương thích provider (không chống collision chủ động); SHA-256
  dùng cho local hash/roundtrip.
- Advisory lock không ngăn process cùng quyền cố tình phá; file `.gft-lock-*`
  còn lại sau job là **cố ý** (tránh race unlink/flock) — không xóa khi có thể
  có process khác đang dùng.
- Chromium sandbox giữ mặc định; `--browser-no-sandbox` là opt-in nguy hiểm,
  chỉ dùng trong container cách ly đã đánh giá.
- Không gắn `ok=true` cho mutation chỉ vì đã gửi request xong mất kết nối.

Đọc SECURITY.md trước khi chạy unattended với dữ liệu quan trọng.

## 16. Cấu trúc dự án

```text
gofile-tool/
├── README.md · README.en.md     # tài liệu chính (VI mặc định, EN phụ)
├── pyproject.toml               # metadata, deps, entrypoints, quality policy
├── src/gofile_tool/
│   ├── api/                     # transport, contents, owner management
│   ├── authentication/          # signing provider, browser worker cách ly
│   ├── filesystem/              # path policy, guarded source/store, locks
│   ├── transfers/               # plan, upload/download, limiter, refresh
│   ├── jobs/                    # upload journal
│   ├── cli/                     # parser, engine, supervisor, extended commands
│   ├── integrations/mcp/        # MCP stdio server (optional)
│   ├── i18n.py                  # catalog thông báo VI/EN
│   ├── client.py · core.py      # public facade · compatibility exports
│   ├── errors.py                # structured errors + exit codes
│   └── schema.json              # JSON Schema của CLI envelope
├── tests/                       # unit · integration · security · platform
├── tools/quality|smoke|workspace# CI checks, live validation (opt-in), budget
├── docs/                        # reference · guides · development · release
└── examples/                    # ví dụ CLI subprocess và Python SDK
```

Quy ước: `snake_case` (module/function), `PascalCase` (class), tên theo trách
nhiệm; script: `run_` (orchestration), `validate_` (smoke), `check_` (guard).
Comment giải thích contract/invariant thay vì mô tả dòng code.

## 17. Test và kiểm chứng

```bash
python -m pip install -e '.[dev,mcp]'
python -m pytest -q                                          # 408 tests, offline
python -m pytest --cov=gofile_tool --cov-branch --cov-report=term-missing
python -m ruff check src tests tools examples
python -m ruff format --check src tests tools examples
```

- **408 tests, coverage 100% statement + branch** (runtime code; `fail_under=100`
  trong quality gate) — suite offline, không cần token/mạng.
- Local HTTP fixtures: crash subprocess, phản hồi hỏng, thay nguồn, lock,
  throttling, refresh identity, i18n, error mapping — đều có regression test.
- Live smoke với fixture thuộc sở hữu test (opt-in): `tools/smoke/validate_live_*.py`.
- Matrix CI: Ubuntu/Windows/macOS × Python 3.9–3.14 — push repo và chạy CI để
  kiểm chứng nền tảng; kết quả test local Linux không thay thế được.

```bash
python tools/quality/run_python_matrix.py
python tools/workspace/check_workspace_budget.py --root . --limit-mib 32
python tools/smoke/validate_live_transfers.py    # cần mạng + opt-in
```

## 18. Build và phát hành PyPI

```bash
python -m pip install build twine
python -m build
python -m twine check dist/*
```

Long description PyPI được **sinh từ README.md** (`tools/quality/build_pypi_description.py`,
CI check tính đồng bộ). Quy trình phát hành (tóm tắt):

1. Version chưa từng upload (PEP 440); CHANGELOG cập nhật đầy đủ.
2. `pytest` + coverage 100% + ruff + `twine check` + clean-install wheel trong venv mới.
3. Artefact không chứa token/journal/cache dữ liệu thử.
4. Upload TestPyPI → verify → PyPI; **không thể upload đè version đã tồn tại** —
   bản fix là version mới (ví dụ `0.2.0` → `0.2.1`), yanked chứ không xóa bản cũ.

Trước khi upload: chạy đủ 5 kiểm tra ở mục 17 và các lệnh trên; sau khi đăng,
yank `0.2.0` và smoke `gft --version` từ bản cài mới.

**Kênh phát hành: stable (`0.2.1`).** Nhãn version không đi kèm kiểm chứng nền tảng —
xem giới hạn ở mục 2 và 3.

## 19. Xử lý lỗi thường gặp

| Hiện tượng | Cách xử lý |
|---|---|
| `gft` không có trong PATH | Kiểm tra environment đã kích hoạt; thử `python -m gofile_tool --help` |
| `COLLISION` với `--export-token` | File token đã tồn tại (create-only): xóa nó, đổi đường dẫn, hoặc thêm `--force` |
| `File or directory not found` | Sai đường dẫn file/thư mục — thông báo nêu rõ đích bị thiếu |
| `WEBSITE_TOKEN_UNAVAILABLE` | Cài `gofile-tool[browser]` + `python -m playwright install chromium`; `gft doctor` báo trạng thái chi tiết |
| `PREMIUM_REQUIRED` / `error-notPremium` | Server yêu cầu gói tài khoản khác cho thao tác/endpoint đó — không phải lỗi cấu hình cục bộ |
| `AUTH_REQUIRED` khi upload thư mục | Cần owner token + `--folder-id` + `--job-dir` |
| `ACCESS_DENIED` | Kiểm tra quyền/tài khoản/nội dung; không retry vô hạn |
| `PASSWORD_REQUIRED` | Đặt password vào biến môi trường, truyền tên biến qua `--password-env` |
| `COLLISION` khi tải | File đích khác nội dung — đổi thư mục output hoặc tự đối soát |
| `BUSY` | Process khác đang giữ lock destination |
| Source changed / plan mismatch | Dừng ghi source, lập plan mới; không ép bỏ kiểm tra toàn vẹn |
| Job có `inflight` | Đối soát remote trước; không xóa journal để replay mù |
| `DEADLINE` | Kiểm tra journal/trạng thái remote trước khi tăng `--deadline` |
| Muốn thông báo tiếng Việt | Thêm `--lang vi` hoặc đặt `GFT_LANG=vi` |
| Không có `gft mcp` | Dùng `gft-mcp` (Python ≥ 3.10 + extra `[mcp]`) |

Khi báo lỗi: version, OS/Python, lệnh đã redact, `error.code`, input tối thiểu.
Không gửi token, password, URL riêng tư hay journal chưa xem xét.

## 20. Tài liệu và giấy phép

- English README · Chỉ mục tài liệu
- CLI reference · Automation contract
- Migration · MCP guide
- Architecture · Testing
- Changelog · Contributing · Security

Giấy phép Apache License 2.0. Thông báo MIT của phần code gốc được giữ
tại LICENSES/MIT-original.txt; xem NOTICE.

Dự án không tự nhận là client chính thức của Gofile và không cam kết vượt giới hạn
của dịch vụ.
