Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ the app.

## Unreleased

### Plugins with a native helper no longer need a new app release

A plugin that ships a native helper program (a "sidecar") used to work only if its
name was hard-coded into the app. Now, the first time such a plugin runs its helper,
DevTool shows a native confirmation dialog with the program's path and SHA-256 and
asks whether to allow it. Your answer is remembered in the OS keychain for that exact
file — a different build of the helper asks again, and uninstalling the plugin forgets
the decision. Helpers bundled with DevTool itself (Redis, RabbitMQ, Container Manager,
Kafka Explorer) run without asking, as before. See
`docs/plugin-sdk/01-architecture.md`.

### ⚠️ Breaking: Redis, RabbitMQ, Container Manager, and Kafka Explorer are now optional plugins

These four tools used to ship built into the app. As of this release they've been
Expand Down
30 changes: 23 additions & 7 deletions docs/plugin-sdk/01-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,29 @@ mật — nó không phải, và biết chính xác nó LÀ gì quan trọng hơ
phải rào chắn runtime. Nó biến "quyền là mô tả" thành "quyền là hàng rào
thật" theo nghĩa: nếu không ai lách qua SDK, thì allowlist trong manifest
đúng là nơi DUY NHẤT quyết định một lời gọi có đi tiếp hay không.
- **Ranh giới thật, có giá trị bảo mật, nằm ở Tier B:** `ALLOWED_SERVICES`
trong `service_host.rs` là một hằng số Rust CỨNG, quyết định lúc BIÊN
DỊCH — không đổi được lúc chạy, không do manifest hay webview quyết định.
Một plugin khai `service: { bin: 'ten-la' }` mà `ten-la` không nằm trong
`ALLOWED_SERVICES` thì lời gọi bị từ chối, bất kể manifest nói gì. Đây là
lý do: manifest do webview đọc — thứ ta đang muốn giới hạn khả năng của
nó — nên nó không thể là nơi cấp quyền chạy tiến trình.
- **Ranh giới thật, có giá trị bảo mật, nằm ở Tier B:** quyền chạy một tiến
trình KHÔNG do manifest hay webview quyết định — manifest do webview đọc,
thứ ta đang muốn giới hạn khả năng của nó, nên nó không thể là nơi cấp
quyền. Có đúng hai nguồn quyền, cả hai nằm ở Rust (`service_host.rs`):
1. `ALLOWED_SERVICES` — hằng số CỨNG, quyết định lúc BIÊN DỊCH, cho các
sidecar DevTool tự đóng gói. Chạy không hỏi.
2. **Sự đồng ý của người dùng** — với mọi tên khác dạng
`devtool-svc-<kebab-case>`, lần đầu chạy app hiện hộp thoại native
(đường dẫn + SHA-256 của file sắp chạy) và hỏi. Hộp thoại do Rust bật,
webview chỉ kích hoạt được câu hỏi chứ không trả lời thay được. Nhờ đó
một plugin mới kèm sidecar không đòi phát hành lại app.

**Quyết định đồng ý lưu ở keychain của OS, không phải file trong
`app_data`:** capability mặc định cho webview ghi tự do vào `app_data`
(`fs:allow-write-file` + `fs:scope-appdata-recursive`), nên mọi thứ ở đó —
kể cả `extensions/index.json` — webview tự sửa được. Mỗi mục gắn với SHA-256
của file: binary bị thay hay cập nhật thì hỏi lại. Máy không có keychain thì
quyết định chỉ sống trong phiên (hỏi thừa, không bao giờ hỏi thiếu). Gỡ
cài đặt thu hồi quyết định.

Giới hạn cần biết: đồng ý là đồng ý chạy với đầy đủ quyền của người dùng,
không có sandbox; và mã băm được tính ngay trước khi spawn, không giữ file
khoá nên về lý thuyết có cửa sổ thời gian rất ngắn giữa băm và chạy.
- **Vì sao không cần sandbox chống mã độc lúc này:** mọi plugin (kể cả
plugin cài từ URL bên ngoài) hiện do chính người phát hành DevTool viết
và tự host. Đây không phải kho plugin bên thứ ba. Rủi ro thật đang được
Expand Down
6 changes: 4 additions & 2 deletions docs/plugin-sdk/02-manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ export default definePlugin({
});
```

`service.bin` phải khớp một mục trong `bundle.externalBin` của
`tauri.conf.json` VÀ nằm trong `ALLOWED_SERVICES` (hằng số Rust) — xem
Sidecar cài qua URL chỉ cần `service.bin` dạng `devtool-svc-<kebab-case>`;
người dùng được hỏi đồng ý lần đầu chạy. Chỉ sidecar DevTool đóng gói sẵn mới
cần khớp `bundle.externalBin` của `tauri.conf.json` và nằm trong
`ALLOWED_SERVICES` (hằng số Rust) — xem
[04-tier-b-sidecars.md](./04-tier-b-sidecars.md) cho toàn bộ quy trình.
12 changes: 10 additions & 2 deletions docs/plugin-sdk/04-tier-b-sidecars.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,16 @@ cho sidecar của bạn — không đọc/ghi ra ngoài nó, không đoán một

## Đăng ký sidecar vào app

Ba chỗ cần sửa — thiếu một trong ba thì sidecar build được, test được, nhưng
KHÔNG chạy được từ app thật:
**Sidecar chỉ cài qua URL (phần lớn plugin bên ngoài) KHÔNG cần sửa gì trong
app.** Tên bin chỉ cần có dạng `devtool-svc-<kebab-case>`. Lần đầu plugin gọi
nó, app hiện một hộp thoại native với đường dẫn + SHA-256 của file sắp chạy và
hỏi người dùng có cho phép không (xem "Sự đồng ý của người dùng" ở
01-architecture.md). Đồng ý được nhớ trong keychain, gắn với mã băm: cập nhật
binary sang bản khác thì hỏi lại.

Ba chỗ dưới đây chỉ dành cho sidecar do chính DevTool đóng gói sẵn, chạy
không hỏi — thiếu một trong ba thì sidecar build được, test được, nhưng KHÔNG
chạy được từ app thật:

1. **`src-tauri/src/service_host.rs`** — thêm tên bin vào `ALLOWED_SERVICES`
(hằng số Rust, ranh giới tin cậy thật — xem 01-architecture.md).
Expand Down
14 changes: 7 additions & 7 deletions docs/plugin-sdk/05-external-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,13 @@ Xem [04-tier-b-sidecars.md](./04-tier-b-sidecars.md) cho cách viết sidecar.
3. Host mỗi binary ở một URL `https://` (GitHub Release asset là lựa chọn
đơn giản — public, ổn định, không cần hạ tầng riêng).
4. Viết manifest `kind: "service"` liệt kê từng target-triple → `{url, sha256}`.
5. Tên bin trong manifest (`bin`) phải khớp một tên đã có sẵn trong
`ALLOWED_SERVICES` của app đang cài — **cài qua URL KHÔNG tự cấp quyền
chạy cho một tên bin mới**; đây là ranh giới tin cậy cố ý (xem
01-architecture.md). Sidecar bạn tự viết cho DevTool của chính mình thì
bạn cũng là người thêm tên vào `ALLOWED_SERVICES` khi build app — cơ chế
URL chỉ thay đổi CHỖ LẤY BYTES, không thay đổi AI QUYẾT ĐỊNH tên nào
được phép chạy.
5. Tên bin trong manifest (`bin`) phải có dạng `devtool-svc-<kebab-case>`.
**Cài qua URL KHÔNG tự cấp quyền chạy** — manifest do webview đọc nên không
thể là nơi cấp quyền. Nếu tên không nằm trong `ALLOWED_SERVICES` của app
(danh sách các sidecar DevTool tự đóng gói), lần đầu được gọi app hỏi
người dùng qua hộp thoại native (đường dẫn + SHA-256), rồi nhớ quyết định
trong keychain gắn với mã băm. Không cần phát hành lại app cho mỗi plugin
mới; xem 01-architecture.md.

## Nơi lưu và độ ưu tiên lúc chạy

Expand Down
Loading
Loading