docs/adr/0012-isolated-workspace.mdXem bản gốc Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.
0012. Không gian làm việc biệt lập - một SandboxExecutor + phần phụ trợ mỏng, sắp xếp các công cụ thông qua đường nối, sao chép tại gốc
Trạng thái: Đã chấp nhận
Ngày: 2026-07-03
Đã sửa đổi: 2026-07-04 — đã thêm §10: một SANDBOX_GIT_TOKEN, hai cơ chế tiêm — modal
tiêm trực tiếp nó vào sandbox env; docker cung cấp nó cho Proxy thông tin xác thực (tự động tương tác
khi token được đặt) để nhân viên không bị tín dụng. Một núm xoay cho phép mô hình đẩy một nhánh/mở PR
từ bên trong hộp cát; sự phân chia docker-vs-modal chỉ là cách token được đưa vào, không phải cái nào
token hoặc nơi nó được định cấu hình.
Đã sửa đổi: 2026-07-13 — §10 được thay thế bởi ADR-0016: không có
cơ chế tiêm hai dài hơn. Proxy thông tin xác thực bị xóa và docker chấp nhận phương thức trực tiếp
tiêm, vậy SANDBOX_GIT_TOKEN đạt đến môi trường Công nhân như GITHUB_TOKEN trong cả hai phần phụ trợ — và một
quá trình đóng hộp cát có thể đọc được nó. §§1–9 (toàn bộ thiết kế Không gian làm việc biệt lập, bao gồm cả bàn tay)
không thay đổi. Văn bản §10 bên dưới không được chỉnh sửa để ghi lại những gì đã được quyết định vào ngày 2026-07-04.
Thay thế một phần, ADR-0011: §2 (Docker
hình dạng vỏ cố định), §3 (hình dạng trống rỗng / không có cây cục bộ theo phương thức) và hai hình dạng trên mỗi chế độ
bash mô tả. Nó giữ lại ADR-0011 §1 ( CommandExecutor đường may + SANDBOX_MODE
bảo vệ khởi động), §5 (an toàn phát lại cho bash hộp cát), §6 (Proxy xác thực docker headless) và
§7 (thang cô lập-phụ trợ).
Bối cảnh
ADR-0011 đã được vận chuyển SANDBOX_MODE=docker|modal dưới dạng phần chia phụ gia: các công cụ tệp máy chủ được giữ lại
hoạt động trên cây repo thực trong khi chỉ bash chạy trong một .decode/sandbox/ gãi. hai
phần phụ trợ phân kỳ rõ ràng — Docker đã tạo ra một vỏ liên tục xuyên qua điểm đánh dấu+$? giao thức với một
hết thời gian chờ giết và khởi động lại; Modal đã chạy fresh-exec trong một bản ghi từ xa trống không có cây cục bộ - mỗi cái
cần của riêng mình bash mô tả. Điều này hoạt động nhưng không bị cô lập (các công cụ tệp của agent vẫn
chạm vào repo thực) cũng như không đồng nhất (hai hình dạng, hai mô tả, hai bộ vỏ cạnh).
Mục tiêu bây giờ là Không gian làm việc biệt lập theo kiểu codex/opencode: ở chế độ hộp cát, agent hoạt động trên một
git clone của repository do người dùng cung cấp tại /workspace, với toàn bộ phạm vi công cụ (tệp + shell)
được chứa ở đó, trong khi các hiện vật khai thác của chính bộ decode vẫn được giữ nguyên. none chế độ phải giữ nguyên byte.
Hai lực thiết kế đã được con người giải quyết trong quá trình chải lông:
- Công cụ tệp trung thực. Thiết kế đầu tiên giữ các công cụ tệp trên máy chủ
.decode/sandbox/gương được giữ lại được hội tụ với điều khiển từ xa bằng đồng bộ hóa mtime-delta. Điều này đã bị từ chối: một mtime delta không thể tuyên truyền điều khiển từ xarm, vậyread/globcuối cùng sẽ nói dối về Không gian làm việc. Thay vào đó, tập tin các công cụ hoạt động trực tiếp trên hệ thống tệp hộp cát thông qua đường nối phụ trợ — harness piExecutionEnvmẫu "hoán đổi tập hợp" (hoán đổi phần phụ trợ I/O của công cụ tệp trên mỗi môi trường thực thi). - Vận chuyển tối thiểu. Với hoạt động tệp trực tiếp, không có đồng bộ hóa cho mỗi cuộc gọi; các byte duy nhất vượt qua là MỘT lần tải lên bootstrap khi tạo và (Chỉ phương thức) MỘT lần quét xuất cuối phiên.
Các sự kiện được xác nhận trong khi xác định phạm vi (chuỗi công cụ đã cài đặt): modal 1.5.1 vạch trần Sandbox.filesystem
(SandboxFilesystem) với read_bytes / write_bytes / copy_from_local (máy chủ→điều khiển từ xa) /
copy_to_local (từ xa→máy chủ) / list_files / make_directory / remove / stat - được xác minh qua
modal.sandbox_fs; ContainerProcess.stdin là một thứ có thể ghi được StreamWriter (tar-over-exec cũng là
khả thi cho bootstrap). Docker CLI, cấu trúc liên kết Proxy thông tin xác thực và tính an toàn khi phát lại
{"cache": False} config không thay đổi so với ADR-0011. ADR này được chuẩn bị thành các nhiệm vụ 078–085
(tính năng isolated-workspace).
Quyết định
-
Thay thế, không thêm. Trong chế độ hộp cát, Không gian làm việc bị cô lập là hoạt động — phần tách M8 (công cụ lưu trữ tệp trên repo thực +
bashtrong một vết xước) sẽ ngừng hoạt động ở trạng thái hướng tới người dùng.nonevẫn giống hệt byte (máy chủLocalExecutor; công cụ tập tin đường dẫn trực tiếp;deps.cwd== khởi chạy cwd). -
Một
SandboxExecutor+ hai phần phụ trợ mỏng. Hai người thực thi hợp nhất thành MỘTSandboxExecutor(tạo → thực thibash -lc <cmd>mỗi cuộc gọi → hủy; fresh-exec trong cả hai) trên mộtSandboxBackendGiao thức mang exec + file ops + vòng đời. Docker's Persist-Shell + marker/$?giao thức + máy shell-reset/kill-and-restart bị xóa; thời gian chờ của docker bây giờ sẽ giết chết một cáidocker execvà container vẫn tồn tại (phản ánh quy tắc exec-dies-sandbox-survives của Modal). Tính bền vững của hệ thống tập tin vẫn ở cả hai (một vùng chứa/một hộp cát mỗi phiên). -
Không gian làm việc = sao chép tại thư mục gốc.
/workspace(hộp cát) ≡ máy chủ.decode/sandbox/(settings.sandbox_workspace_dir) ≡ agit clonecủa repo người dùng cung cấp thông qua--repo <url-or-local-path>/SANDBOX_REPO(bản sao phía máy chủ tại HEAD đã cam kết của nguồn, sử dụng tín dụng git xung quanh;--localđể có bản sao cục bộ nhanh). Không có repo → Không gian làm việc trống.--repovớiSANDBOX_MODE=none→ một dòng stderr thân thiện, lối ra khác không. Kết quả được trả về thông qua việc xây dựng Trở lại tay (§8), không đẩy thủ công.Sửa đổi (2026-07). Việc hạ cấp thành trống trên một bản sao không thành công vẫn là chính sách của REPL và chỉ REPL's: nó giả sử một người đọc cảnh báo và phản ứng. Cuộc chạy headless không có chuyện đó con người, do đó, sự thất bại của quá trình nhân bản hiện là gây tử vong (
runtime/flow.py::_prepare_headless_tool_scope). Điều gì đã buộc điều này: một URL trình duyệt (…/tree/main) đã qua dưới dạng--repođể ba agent được trả lương chạy tới hoàn thành bên trong Không gian làm việc trống và Người giao lại sau đó đã từ chối gửi bất kỳ không gian làm việc nào trong số đó ("không phải là git repo có nguồn gốc"). Sự xuống cấp trong im lặng chỉ là một mặc định hợp lý khi có ai đó đang xem; nếu không, nó sẽ chuyển lỗi đánh máy trong một giây thành N lần chạy lãng phí. -
Công cụ tệp hoạt động trên hệ thống tệp hộp cát thông qua đường nối ("hoán đổi bộ").
SandboxBackendGiao thức phát triểnread_bytes/write_bytes/make_directory/list_dir/stat/remove; logic phía máy chủ được chia sẻ (ngăn chặn, tìm kiếm/thay thế của chỉnh sửa, cắt ngắn, kết xuất) vẫn ở trên đường nối và chỉ vận chuyển byte là cho mỗi phần phụ trợ. Docker hoạt động của tệp là pathlib đơn giản trên Workspace được gắn liên kết (mount làm cho thư mục máy chủ be hộp cát fs - zero hệ thống ống nước từ xa, luôn trung thực). **Các hoạt động của tệp Modal làSandboxFilesystemAPI (trực tiếp chống lại điều khiển từ xa - không có gương).glob/grepchạy dưới dạng lệnh từ xa (find/grep) thông quaexeccho cả hai phần phụ trợ (không bao giờ tải xuống cây để tìm kiếm), với tính chẵn lẻ đầu ra cho máy chủ triển khai. Ngăn chặn được phân lớp: phía trên đường nối, toán học về đường dẫn bất khả tri phụ trợ (_resolve_logical, một nếp gấp gốc logic - không phải máy chủPath.resolve, vì đường dẫn Modal không phải là máy chủ đường dẫn) từ chối../ lối thoát tuyệt đối cho cả hai chương trình phụ trợ; và bởi vì docker mount được chia sẻ với máy chủ, phần phụ trợ docker ngoài ra giải quyết các liên kết tượng trưng về mặt vật lý bên dưới đường nối và tăng lênWorkspaceEscape(mộtOSErrorlớp tệp hiển thị dưới dạng từ chối), do đó, một liên kết tượng trưng được đặt trong Không gian làm việc bởibashkhông thể theo dõi quá trình gắn kết vào máy chủ - chỉ riêng chuỗi toán học không thể nhìn thấy một liên kết tượng trưng. Modal không cần lớp như vậy (tệp chỉ hoạt động từ xa trên hộp cát dùng một lần - không có fs máy chủ để trốn vào).nonechế độ giữ các công cụ đường dẫn trực tiếp ngày nay, giống hệt byte. -
Việc vận chuyển là tối thiểu (đồng bộ hóa mtime đã ngừng hoạt động). Docker: liên kết gắn kết là phương tiện vận chuyển duy nhất (luôn hoạt động - không khởi động, không xuất). Modal: MỘT tải lên bootstrap của repo nhân bản + kỹ năng gieo mầm tại sandbox tạo (
copy_from_local/ tar-over-exec) và ONE cuối phiên càn quét xuất khẩu/workspace→ chủ nhà.decode/sandbox/(copy_to_local) nên không gian làm việc cuối cùng là Host-visible để chuyển giao git. Giữa phiên/shipcó thể kích hoạt tính năng xuất độc lập ( hộp cát vẫn tồn tại). Không có điểm đánh dấu, không có vùng đồng bằng cho mỗi cuộc gọi, không có máy móc giới hạn kích thước. -
Trang chủ khai thác so với phạm vi công cụ. Cwd ra mắt là Trang chủ khai thác —
.decode/sessions,.decode/MEMORY.md, nhật ký,.decode/skills, và.decode/settings.jsontập tin quyền luôn neo ở đó. Chỉ phạm vi công cụ của agent (deps.cwd) di chuyển vào Không gian làm việc.AgentDepsphát triểnharness_home; danh mục kỹ năng/người điều phối và bộ nhớ được đọcharness_home, trong khi công cụ tìm kiếm/tập tin +bashđọcdeps.cwd.extract_on_exit, việc tạo nhật ký phiên và tải/lưu giữ tệp quyền được xâu chuỗi vớiharness_homemột cách rõ ràng. TRONGnonechế độ hai đều bình đẳng. -
Quy tắc đặt công cụ: chỉ tính toán tùy ý vượt qua ranh giới. Khai thác có cấu trúc các hoạt động vẫn ở phía máy chủ, với hiệu ứng của chúng nằm trong Không gian làm việc nếu có liên quan:
(Các) công cụ Vị trí Phạm vi read/write/editlogic máy chủ, vận chuyển byte qua đường nối phụ trợ Không gian làm việc ( deps.cwd)glob/greplogic máy chủ; việc tìm kiếm thực hiện trong hộp cát ( exectìm/grep)Không gian làm việc bashbên trong hộp cát Không gian làm việc enter_plan_mode/exit_plan_mode/sleep/todo_write/skill/ask_userchủ nhà tiêm trạng thái / bối cảnh khai thác thuần túy; Nhiệm vụ + tạo phẩm phiên/bộ nhớ tại Harness Home web_fetchchủ, vẫn bị kiểm soát ngay cả ở chế độ hộp cát đến mạng chủ lsp+ Công cụ làm giàu chẩn đoán sau chỉnh sửamáy chủ ( ty), chỉ vào đường dẫn Workspacenone+docker: các tập tin Workspace trực tiếp;modal: nỗ lực tốt nhất-vô hiệu hóa + ghi chú thân thiện (ADR-0007-nhất quán)agent/agent phụ (M10, tương lai) vòng lặp máy chủ; các công cụ của nó kế thừa các đường nối phiên (đường nối trình thực thi cấp mô-đun + tương tự deps.cwd) - nóbashđưa vào phiên hộp cát CÙNG, các công cụ tệp của nó trong cùng một Không gian làm việcKhông gian làm việc miễn phí (không có máy móc mới) Nhà máy MCP (M15, tương lai) quyết định vị trí trên mỗi máy chủ (công việc trong tương lai) — -
Trở lại Git — khai thác vận chuyển Không gian làm việc dưới dạng Nhánh phiên, phía máy chủ. Kết quả của phiên hộp cát được đảm bảo tồn tại: khai thác (a) thu thập git Workspace cục bộ tiểu bang tại
.decode/sandbox(docker: mount trực tiếp; modal: bị người thực thi quét xuốngexport()đầu tiên —/shipkích hoạt xuất khẩu giữa phiên); (b) đảm bảo chúng vào một cơ chế xác địnhdecode/<session-id-short>Chi nhánh phiên — mô hình không được tin cậy để cam kết, do đó nhánh được trỏ vào trạng thái cuối cùng và bất kỳ cây công việc bẩn nào đều được tự động cam kết (của chính mô hình các nhánh/cam kết được giữ nguyên, không bao giờ viết lại); và (c) gửi chúng vớigit Push Origin decode/<session-id>using the user's ambient host credentials —--repo <URL>hạ cánh nhánh trên điều khiển từ xa,--repo <local path>trong repository nguồn cục bộ, không có thông tin xác thực. ** Mỗi lệnh git chạy phía máy chủ đối với Không gian làm việc cục bộ — không có thông tin xác thực nào được đưa vào hộp cát**, giống hệt bất biến bí mật không bao giờ có trong hộp cát mà Proxy thông tin xác thực (§9) duy trì. Nó bị bỏ qua vì Không gian làm việc no-repo / non-git / không thay đổi-vs-clone-HEAD. Độ bền theo lớp: Phiên cục bộ Nhánh luôn tồn tại ngay cả khi việc đẩy không thành công (một dòng thân thiện đặt tên cho nó và.decode/sandbox/vị trí). Được kích hoạt cả hai tự động (Lối ra REPL — nỗ lực tối đa/không gây tử vong cùng với việc phân tích bộ nhớ/LSP/bộ thực thi; headlessdecode run --repohoàn thành) và một cách rõ ràng (chỉ nhàn rỗi/shipLệnh TUI, dành riêng như/compact//clear, in ấn nhánh + kết quả đẩy; một dòng thân thiện "không có không gian làm việc hộp cát" trongnonechế độ).Bản sửa đổi (2026-07, lần chạy từ xa đầu tiên). "Phía máy chủ" nghĩa là quy trình sở hữu Không gian làm việc, cái trên ngăn xếp từ xa không phải là máy đã gõ
decode run. Một bản sao chạy headless, hoạt động và quét lại Không gian làm việc của nó bên trong vùng chứa luồng Kitaru; vận chuyển từ do đó việc gửi cli đã đẩy chiếc máy tính xách tay đó không liên quan.decode/sandboxtrong khi cuộc chạy là thực tế công việc đã chết với container. Hai bản sửa lỗi, cả hai đều tồn tại trong mã:- Tay quay headless chạy trong dòng (
runtime/flow.py::_ship_headless_workspace), trongfinally, sau người thực thi gặt hái - gặt là thứ quét qua hộp cát phương thức hệ thống tập tin vào Không gian làm việc đang được chuyển đi. Ngăn xếp cục bộ không bị ảnh hưởng (luồng chạy đang trong quá trình, cùng một cwd). REPL //shipcác đường dẫn không thay đổi. - Quá trình đẩy không có thông tin xác thực xung quanh trong vùng chứa luồng, do đó, nó xác thực bằng
SANDBOX_GIT_TOKENkhi một cài đặt được thiết lập — trong quy trình khai thác, thông qua cùng một thông tin xác thực người trợ giúp mà Công nhân nhận được. Không thay đổi: không có thông tin xác thực nào được đưa vào hộp cát (ADR-0016 §4). Và dòng không bao giờ mất kết quả không còn hứa hẹn chi nhánh địa phương là "an toàn": trong một lần chạy từ xa nhánh tồn tại chính xác như thời gian tồn tại của container.
- Tay quay headless chạy trong dòng (
-
Giữ lại từ ADR-0011, không thay đổi.
CommandExecutorđường may +SANDBOX_MODEkhởi động bảo vệ (§1); sự an toàn khi chơi lại{"cache": False}điểm kiểm tra bash khisandbox_mode != "none"(§5); Proxy thông tin xác thực của docker không có giao diện — hiện được kết nối với docker bộ điều hợp phụ trợ,install_executorđường may còn nguyên vẹn (§6); và bảng bậc thang phụ trợ cách ly (§7). REPL tương tác không có kitaru vànoneđường dẫn không nhập mô-đun hộp cát. -
Thông tin đăng nhập của công cụ Sandbox — một
SANDBOX_GIT_TOKEN, được chèn khác nhau cho mỗi chương trình phụ trợ. Ngoài ra sự hỗ trợ từ phía máy chủ (§8), một mô hình có thể muốn thực hiện cuộc gọi được xác thực của riêng mình từ bên trong Không gian làm việc —git pushchi nhánh của nó,gh pr create— để kết quả đi từ xa → từ xa mà không có xuất/gửi "đồng bộ" phía máy chủ. Cài đặt đơn,SANDBOX_GIT_TOKEN, cung cấp điều đó thông tin xác thực cho cả hai chương trình phụ trợ; chỉ có cơ chế tiêm là khác, bởi vì chỉ docker mới có thể đồng định vị một proxy:- docker → Proxy thông tin xác thực (không có tín dụng). Sidecar mitmproxy headless được giữ lại (§9 / §6)
đưa thông tin xác thực sau khi yêu cầu rời khỏi nhân viên, trên mạng docker mỗi lần chạy —
công nhân giữ token no. Khi nào
SANDBOX_GIT_TOKENđược đặt không trống proxy tự động tương tác (không tách biệtSANDBOX_CREDENTIAL_PROXY_ENABLEDcờ cần thiết) vàgithub_token_rulesxây dựng hai quy tắc tiêu đề phía máy chủ từ một token đó - Bearer forapi.github.com, Cơ bảnx-access-token:<PAT>chogithub.comgit Transport (git-over-HTTPS của GitHub không chấp nhận Bearer). git là được cài đặt vào trình chạy có dây proxy khi tạo (apt của nó thoát ra thông qua chuyển tiếp của proxy với máy nhân bản Debian, CA đã được tin cậy) để quy tắc Cơ bản có một máy khách - một mô hìnhgit pushtừ bên trong hộp cát xác thực từ đầu đến cuối trong khi nhân viên không có token. (Cổng đang mở giá trị đã giải quyết, phản ánh phương thứcif token:: rõ ràngSANDBOX_GIT_TOKEN=quyết định không giá trị và để proxy xuống — nó không bao giờ tham gia và đưa vào các tiêu đề rác trống.)SANDBOX_CREDENTIAL_PROXY_ENABLEDcờ +DEFAULT_PROXY_RULES(Bí mật Kitaru) vẫn là tướng quân đường dẫn cho các máy chủ khác. Đây là con đường cứng rắn; nó tốn một thùng chứa mitmproxy và CA-trust bước. - modal → tiêm trực tiếp (
SANDBOX_GIT_TOKEN). Modal không có mạng cùng vị trí để chạy proxy bật, do đó, token tương tự được đưa vào hộp cát:SANDBOX_GIT_TOKENcưỡi mộtmodal.Secretvào sandbox env nhưGITHUB_TOKENvà một git người trợ giúp thông tin xác thực đã nướng sẽ đọc$GITHUB_TOKENtại thời điểm đẩy (vì vậy token sẽ sử dụng Bí mật, không bao giờ là lớp hình ảnh được lưu trong bộ nhớ đệm).GITHUB_TOKENphục vụ cả haigit pushvàghcùng một lúc - không có base64, không sắp xếp quy tắc, không có token giả. Đơn giản hơn nhưng token có có thể đọc được bên trong hộp cát. nguồn được thống nhất (một cài đặt); cơ chế sự bất đối xứng được chọn có mục đích: docker chia sẻ hạt nhân máy chủ, do đó việc giữ bí mật cho nhân viên (tiêm sau khi xuất ra) sẽ kiếm được sự phức tạp; modal là một hộp từ xa, phù du, do đó, token có phạm vi bên trong nó có một vụ nổ giới hạn bán kính và mua sự đơn giản thực sự — được giảm nhẹ bằng cách yêu cầu PAT chi tiết, có phạm vi repo (Nội dung
- Yêu cầu kéo), không phải là token cổ điển rộng rãi.
SANDBOX_GIT_TOKENtrống — bỏ đặt (mặc định) hoặc an rõ ràngSANDBOX_GIT_TOKEN=— không tiêm gì vào cả hai chương trình phụ trợ và tắt proxy docker trừ khi cờ chọn tham gia, do đó, bất biến nghiêm ngặt "không có bí mật trong hộp cát" được giữ cho đến khi người vận hành chọn tham gia; sự hỗ trợ từ phía máy chủ (§8) vẫn là cách không cần thông tin xác thực để gửi kết quả.
Sửa đổi (2026-07-13 —
ghtàu ở cả hai hộp cát; docker cần token mồi nhử). §10 được đặt têngh pr createnhư một trường hợp thúc đẩy nhưng chỉ từng cài đặt git. Một cuộc chạy thực sự đã chứng minh khoảng cách: mô hình đẩy nhánh của nó rồi chếtgh: command not found— lực đẩy đã hạ cánh rồi, nên lần lượt đã hoàn thành một nửa, đó là hình dạng thất bại tồi tệ nhất có thể xảy ra.ghhiện đã được cài đặt cùng với git trong cả hai phần phụ trợ (nó không có trong mọt sách Debian, vì vậy cả hai đều lấy repository apt của GitHub): docker cài đặt nó mỗi phiên trong_git_setup_command(); modal sẽ biến nó thành một lớp hình ảnh được lưu trong bộ nhớ cache.Đường dẫn docker cần một điều mà ADR này không lường trước được — và §10 ở trên đã gợi ý về điều đó khi nó ghi nhận phương thức cần "không có token giả".
ghtừ chối đưa ra bất kỳ yêu cầu nào khi nó không tìm thấy token nào trong env của nó: nó bị lỗi cục bộ vớigh auth login, không bao giờ gửi yêu cầu HTTP proxy tồn tại để xác thực. Do đó, một công nhân không có thẻ không thể lái xegh, dù thế nào đi chăng nữa sửa các Quy tắc proxy. Vì vậy, người được ủy quyền đưa cho công nhân một mồi nhửGH_TOKEN(proxy._GH_PLACEHOLDER_TOKEN):ghtiến hành, gửiAuthorization: token <decoy>, và phần bổ sung ghi đè tiêu đề đó bằng thông tin xác thực thực sau khi yêu cầu đã rời khỏi nhân viên (mitmproxy'sheaders[name] = valuethay thế thay vì nối thêm). Tính bất biến không bị ảnh hưởng - mồi nhử là một chuỗi trơ không xác thực gì cả và thông tin xác thực thực sự vẫn chỉ tồn tại trong vùng chứa proxy. Chi phí có thể quan sát được:docker exec <worker> env | grep -i tokenbây giờ in mồi nhử thay vì không có gì, vì vậy "công nhân không giữ token" được xác minh bằng cách kiểm tra xem nó chứa gì không phải là bí mật, đúng hơn là nó chẳng có gì cả.phương thức không cần mồi nhử:
ghđọc thực tếGITHUB_TOKENcáimodal.Secretđã tiêm rồi.Sửa đổi (2026-07-13 —
DEFAULT_PROXY_RULEStênSettingscác lĩnh vực, không phải bí mật của Kitaru). Trong đó §10 nóiSANDBOX_CREDENTIAL_PROXY_ENABLEDcờ +DEFAULT_PROXY_RULES(Bí mật của Kitaru) vẫn là đường dẫn chung cho các vật chủ khác, một nửa bí mật Kitaru được thay thế (ADR-0015 §6): mẫu tiêu đề của quy tắc đặt tên choSettingstrường ({{ acme_api_token }}) và giải quyết từ cấu hình ngậm nước — ở điều khiển từ xaDECODE_ENVgiá trị đến thông qua Nhóm môi trường. Cờ, danh sách quy tắc và vai trò đường dẫn chung không thay đổi; chỉ có đường nối độ phân giải được di chuyển.SANDBOX_GIT_TOKEN/github_token_rules()(cái này chủ đề của phần) không bị ảnh hưởng — chúng xây dựng các giá trị tiêu đề theo nghĩa đen, vì base64 cơ bản biến đổi là một phép tính mà không mẫu nào có thể diễn đạt được. - docker → Proxy thông tin xác thực (không có tín dụng). Sidecar mitmproxy headless được giữ lại (§9 / §6)
đưa thông tin xác thực sau khi yêu cầu rời khỏi nhân viên, trên mạng docker mỗi lần chạy —
công nhân giữ token no. Khi nào
Sơ đồ
flowchart TB
subgraph home["HARNESS HOME = launch cwd (always anchors artifacts)"]
art[".decode/sessions · .decode/MEMORY.md · logs<br/>.decode/skills · .decode/settings.json"]
end
subgraph none["SANDBOX_MODE=none (DEFAULT — byte-identical)"]
nfiles["read/write/edit/glob/grep — direct pathlib"]
nbash["bash — LocalExecutor (host subprocess)"]
end
subgraph sandbox["SANDBOX_MODE=docker|modal — ISOLATED WORKSPACE"]
tools["file/search tools + bash<br/>deps.cwd = WORKSPACE (logical root)<br/>shared logic host-side: containment · edit · truncate · render"]
exec{{"SandboxExecutor (one) — create · exec bash -lc · export · destroy<br/>SandboxBackend Protocol: exec + file ops"}}
tools --> exec
docker["DockerBackend<br/>exec = docker exec (fresh) · file ops = pathlib on the MOUNT<br/>-v .decode/sandbox:/workspace (live, always truthful)"]
modal["ModalBackend<br/>exec = sb.exec (fresh) · file ops = SandboxFilesystem (direct)<br/>glob/grep = remote find/grep · 1 bootstrap upload + 1 export sweep"]
exec --> docker
exec --> modal
ws["WORKSPACE = /workspace ≡ .decode/sandbox<br/>= git clone of --repo (or empty)"]
docker -->|bind mount| ws
modal -->|copy_from_local / copy_to_local| ws
end
subgraph proxy["CREDENTIAL PROXY (retained, headless+docker) — worker holds NO secret"]
mitm["mitmproxy addon container — injects header after the request leaves the worker"]
end
docker -. proxy path .-> mitm
subgraph gtok["SANDBOX_GIT_TOKEN (opt-in, §10) — ONE token, injected per-backend"]
tok["docker: sources the proxy (auto-engages) → Bearer/Basic header after egress, worker token-free<br/>modal: modal.Secret → GITHUB_TOKEN env + git credential helper (readable in-sandbox by design)"]
end
tok -. docker: feeds .-> mitm
modal -. modal: direct inject .-> tok
git(["Hand-back: decode/<session-id> branch<br/>secured + pushed host-side — no cred in the sandbox"])
ws --> git
classDef homec fill:#4527a0,stroke:#311b92,color:#ffffff;
classDef nonec fill:#1565c0,stroke:#0d47a1,color:#ffffff;
classDef toolc fill:#00838f,stroke:#005662,color:#ffffff;
classDef seamc fill:#37474f,stroke:#102027,color:#ffffff;
classDef exec fill:#2e7d32,stroke:#1b5e20,color:#ffffff;
classDef wsc fill:#ef6c00,stroke:#e65100,color:#ffffff;
classDef sec fill:#c62828,stroke:#8e0000,color:#ffffff;
classDef ext fill:#6a1b9a,stroke:#38006b,color:#ffffff;
class art homec;
class nfiles,nbash nonec;
class tools toolc;
class exec seamc;
class docker,modal exec;
class ws wsc;
class mitm sec;
class tok mcredc;
class git ext;
classDef mcredc fill:#ad1457,stroke:#880e4f,color:#ffffff;
hậu quả
- Một đường may, một hình dạng, một mô tả. Hai người thực thi + hai
bashmô tả thu gọn thành mộtSandboxExecutor+ một đoạn sandbox thống nhất; quy tắc thực thi mới giống hệt nhau trên các chương trình phụ trợ. Các trường hợp cạnh shell cố định (đồng bộ hóa điểm đánh dấu, đặt lại shell, chia nhỏ không có vòng lặp) đều bị xóa mã. - Công cụ tệp không bao giờ nói dối. Hoạt động của tệp trực tiếp (docker mount / modal
SandboxFilesystem) có nghĩa làread/globluôn phản ánh Không gian làm việc thực sự - bao gồm cả việc xóa - mà mirror+mtime-sync bị từ chối không thể đảm bảo. Giá là một chuyến khứ hồi từ xa cho mỗi hoạt động trên Modal (có thể chấp nhận được; lớp công cụ là tuần tự). - Vận chuyển tối thiểu. Chỉ tải lên bootstrap (cả hai) và xuất cuối phiên (Modal) vượt qua dây; docker cưỡi thú cưỡi của nó miễn phí.
- Sự cô lập là thực tế và thống nhất — toàn bộ phạm vi công cụ của agent là Không gian làm việc; harness
hiện vật riêng ở tại Harness Home; git là sự hỗ trợ thông qua cơ chế đẩy phía máy chủ nhỏ
(cam kết → chi nhánh →
git push), với thông tin xác thực vẫn nằm trong quá trình lưu trữ — không bao giờ nằm trong Worker, bất biến giống như Proxy thông tin xác thực. - Kết quả tồn tại theo từng lớp — việc chuyển giao luôn để lại dấu vết cục bộ
decode/<id>chi nhánh (công việc bẩn thỉu được giữ lại, cam kết mô hình được giữ nguyên) và đẩy nó đến--reponguồn khi tín dụng cho phép; một cú đẩy thất bại là một dòng đặt tên chi nhánh thân thiện, không bao giờ bị mất phiên. Tự động thoát + rõ ràng/ship. - Các subagent M10 kế thừa điều này miễn phí — chúng chạy trên vòng lặp máy chủ nhưng các công cụ của chúng nhận
đường nối thực thi cấp mô-đun +
deps.cwd, vì vậy họbashvà nộp hồ sơ cho các hoạt động trong cùng một phiên Không gian làm việc không có hệ thống dây điện bổ sung. - Giữ lại các đảm bảo — trình bảo vệ khởi động, an toàn phát lại, Proxy thông tin xác thực (công nhân giữ
không có bí mật), thang cách ly, REPL không có kitaru và byte giống hệt
nonecon đường. - Một token, hai tư thế (§10). Một đơn
SANDBOX_GIT_TOKENcung cấp thông tin xác thực trong hộp cát cho một công cụ đã được xác thực gọi từ bên trong sandbox trên cả hai chương trình phụ trợ — docker cung cấp nó cho Proxy thông tin xác thực (tự động tham gia, nhân viên không có token), phương thức giao dịch độ cứng để đơn giản bằng cách tiêm nó vào sandbox env. Nguồn thống nhất; chỉ có cơ chế khác nhau. Mặc định (trống) không tiêm gì và dựa vào sự hỗ trợ của phía chủ nhà nên "không có bí mật trong hộp cát" vẫn giữ ở mọi nơi cho đến khi nhà điều hành chọn tham gia. Chi phí trung thực: token modal đã chọn tham gia có thể được đọc bởi một agent được đưa vào nhanh chóng, chỉ bị giới hạn bởi phạm vi của PAT — lý do khiến đường dẫn docker vẫn dựa trên proxy. - Trần trung thực (
ponytail:):- LSP phương thức là nỗ lực tốt nhất —
tychạy phía máy chủ và không thể truy cập fs từ xa. Nâng cấp đường dẫn: chạytybên trong hộp cát trên stdio đường ống (hoãn lại). - Mất phương thức trong chuyến bay khi hồi sinh — hộp cát hết hạn tối đa được tạo lại + khởi động lại
từ máy chủ
.decode/sandboxtrạng thái; các thay đổi trong hộp cát kể từ lần xuất cuối cùng có thể bị mất (tệp ghi chú nói như vậy) - vẫn tốt hơn so với thiết lập lại toàn bộ cũ. - Địa phương
--repochỉ nhân bản HEAD — bụi cây làm việc không được cam kết của nguồn cục bộ không được sao chép.
- LSP phương thức là nỗ lực tốt nhất —
Công việc tương lai
- Tự động cho phép các công cụ hộp cát — cổng vẫn giữ nguyên byte giống với
nonechế độ tính năng này (con người- giải quyết); việc xử lý "trong hộp cát" là phê duyệt tự động bị trì hoãn (được thực hiện từ ADR-0011). - Khóa lối ra cứng — hợp tác
http_proxy/CA vẫn giữ nguyên mức trần; nội bộ từ chối mặc định mạng là đường dẫn nâng cấp (được mang từ ADR-0011). - Đầu ra thống nhất cho lưu lượng truy cập web của agent — định tuyến
web_fetch(và công cụ gửi đi phía máy chủ khác cuộc gọi) thông qua hộp cát / Proxy thông tin xác thực cho một câu chuyện đầu ra — được xem xét, hoãn lại. tybên trong hộp cát — bản nâng cấp LSP Modal (và docker chặt chẽ hơn) qua đường ống stdio.- Vị trí MCP trên mỗi máy chủ (M15) — các máy chủ MCP hướng tới không gian làm việc bên trong ranh giới, bên ngoài-SaaS phía máy chủ; quyết định khi nào nhà máy MCP hạ cánh.
- git-aware /Manifest Transport — nếu tar bootstrap/export cần mở rộng quy mô, a vận chuyển địa chỉ nội dung hoặc git-diff thay thế bản sao toàn bộ cây.
- Tạo PR tự động (
gh pr create) — xoay nút đẩydecode/<id>Phiên Chi nhánh thành một kéo yêu cầu - được chuyển sang M14 (bước đánh giá PR trên đám mây).