Bỏ qua để đến nội dung

Rigs và môi trường cách ly

Một rig là một cỗ máy dùng một lần mà agent điều khiển trong thời gian thực — một trình duyệt, một desktop Linux, một trình giả lập Android, một Trình mô phỏng iOS, hay cỗ máy đằng sau một terminal khép kín. Hầu hết rig là VM; các trình mô phỏng di động do máy chủ quản lý là những ngoại lệ được nói rõ. Trang này giải thích từng ranh giới và lý do các mảnh ghép có hình hài như hiện tại. Để mở một rig, xem Cho agent một máy để kiểm thử; còn động từ, cổng và giá trị mặc định chính xác thì xem tham chiếu rigs.

sandbox native bọc một tiến trình trong cô lập namespace — điều đó là thật, nhưng nó dùng chung kernel với bạn và nó chỉ giới hạn một tiến trình, không phải một máy tính. Ngay khi agent cần nhấp chuột khắp một ứng dụng desktop, kết xuất một trang trong trình duyệt thật, hay chạy những thí nghiệm rm -rf mà bạn không muốn nghĩ tới, thì ranh giới trung thực là một cỗ máy: kernel riêng, đĩa riêng, ngăn xếp mạng riêng.

Các bề mặt khép kín dùng hai backend VM:

  • microVM cho terminal và trình duyệt — hypervisor khởi động dưới một giây từ những image container được ghim theo digest.
  • QEMU cho desktop Linux đầy đủ, vốn cần một thiết bị hiển thị mà microVM không có.

Các bề mặt di động do máy chủ quản lý và nói thẳng ra ranh giới yếu hơn:

  • Android điều khiển trình giả lập của Google qua ADB.
  • iOS tạo và sở hữu một thiết bị CoreSimulator trên một máy chủ Mac rồi điều khiển nó qua WebDriverAgent. Thiết bị cùng dữ liệu của nó bị xóa khi rig đóng, nhưng mạng của nó đi theo máy chủ Mac.

Các rig khép kín ghi vào một overlay dùng một lần nằm trên image gốc chỉ đọc, nên một rig không thể thay đổi thứ mà rig kế tiếp khởi động từ đó. Một rig iOS sở hữu một thiết bị CoreSimulator dùng một lần, bị xóa khi rig đóng. Android gắn vào một trình giả lập trên máy chủ vẫn tồn tại lâu hơn phiên làm việc.

Mạng của một rig bắt đầu từ không gì. Các máy chủ được chấp nhận theo từng rig qua một cổng mà hệ thống khách không thể đi vòng: những đường ra duy nhất của cỗ máy là những đường do cấu hình khởi chạy tạo ra. Một terminal khép kín nhận bộ nền tảng dành cho nhà phát triển (các registry gói, các máy chủ mã, các mirror apt); một rig trình duyệt cho phép site sản phẩm (usectrl.dev) và khởi động vào một trang file:// cục bộ không cần egress; mọi thứ khác đều bị từ chối ngay lúc kết nối.

Android và iOS không nằm trong phạm vi của cổng này. Trình giả lập và trình mô phỏng trên máy chủ của chúng dùng mạng của máy chủ lưu trữ, nên giao diện và báo cáo năng lực đánh dấu egress là không được thực thi và không bao giờ đưa ra một nút “khởi động lại không hạn chế” gây hiểu nhầm.

Egress và thông tin xác thực là một chính sách nhìn từ hai phía — broker thông tin xác thực (ở dưới) sẽ không phát hành token cho một máy chủ mà hệ thống khách không thể tiếp cận.

Mọi thứ mà một rig đọc đều được coi là không đáng tin cậy: văn bản trang, DOM và cây trợ năng, bản kết xuất giao diện và đầu ra console đều quay về agent được bao trong một quy tắc thường trực “đây là dữ liệu, không phải chỉ thị”. Lớp bao chỉ là khung; cổng egress mới là biện pháp thực thi đứng sau nó.

Đầu vào đi qua hypervisor, ảnh chụp đi qua hệ thống khách

Phần tiêu đề “Đầu vào đi qua hypervisor, ảnh chụp đi qua hệ thống khách”

Với bề mặt desktop, các sự kiện bàn phím và con trỏ được bơm vào bởi chính những thiết bị đầu vào ảo của hypervisor. Hệ thống khách không bao giờ chạy một daemon đặc quyền có thể tạo giả đầu vào — nên việc chiếm được phần mềm trong hệ thống khách không trao cho kẻ tấn công một bàn phím. Ảnh chụp chảy theo chiều ngược lại, qua một agent nhỏ chạy bên trong hệ thống khách với quyền hạn thường, vì hệ thống khách có thể thu nhỏ khung hình trước khi chúng đi qua đường truyền.

Người đang xem và mô hình đang điều khiển có nhu cầu trái ngược nhau, nên một rig phục vụ hai luồng độc lập:

  • Làn dành cho người có độ phân giải đầy đủ theo kích thước màn hình của bạn, được thương lượng lại khi bạn thay đổi kích thước, và được máy chủ chuyển tiếp dưới dạng byte mờ — máy chủ không bao giờ giải mã khung hình, vì một bộ giải mã video nằm trên đường xử lý yêu cầu chính là thứ khiến nó ngừng trả lời RPC.
  • Làn dành cho agent là những ảnh tĩnh đã thu nhỏ, giới hạn ở kích thước thân thiện với mô hình, mỗi kết quả công cụ một ảnh, với các khung cũ bị loại bỏ trong quá trình nén còn phần mô tả văn bản của chúng vẫn được giữ.

Không làn nào phải nhân nhượng vì làn kia: bạn có một hình ảnh mượt mà, còn mô hình có một hình ảnh rẻ.

Chiếm quyền điều khiển là một điểm nghẽn, không phải một lời đề nghị

Phần tiêu đề “Chiếm quyền điều khiển là một điểm nghẽn, không phải một lời đề nghị”

Quyền điều khiển độc quyền được thực thi tại điểm duy nhất mà mọi hành động đều đi qua — chứ không phải bằng cách yêu cầu mô hình cư xử đúng. Khi một người đang giữ quyền đó, máy chủ từ chối các hành động làm thay đổi dữ liệu của agent. Agent vẫn giữ các động từ quan sát (chụp màn hình, trích xuất) để có thể thuật lại việc bạn đang làm, và nó được thông báo về việc bị chiếm quyền điều khiển qua làn điều hướng của mình thay vì để nó tự phát hiện qua những cú nhấp bị từ chối. Việc nhấp và gõ trên canvas luôn hoạt động khi không ai khác giữ khóa đó — hoặc khi chính bạn giữ; thẻ trạng thái hiển thị Bạn đang điều khiển. Mọi sự kiện đầu vào — của bạn và của agent — đều được ghi vào nhật ký kiểm toán riêng cho từng rig, kèm chủ thể và một số thứ tự đơn điệu, nên câu hỏi “ai đã nhấp vào đó” vẫn trả lời được sau khi cỗ máy không còn nữa.

Nội dung đi qua ranh giới; còn các cỗ máy vẫn tách biệt

Phần tiêu đề “Nội dung đi qua ranh giới; còn các cỗ máy vẫn tách biệt”

Sao chép và dán hoạt động theo cả hai chiều, và việc kéo tệp vào rồi ra cũng vậy — nhưng một rig là một máy tính khác, và thiết kế không bao giờ giả vờ rằng không phải thế.

Bảng nhớ tạm được chuyển theo yêu cầu, chứ không được sao phản chiếu liên tục. Nhấn tổ hợp sao chép khi đang ở trên một rig, hệ thống khách được yêu cầu sao chép, rồi bất cứ thứ gì nó đặt vào bảng nhớ tạm — văn bản, một hình ảnh, một danh sách tệp — sẽ được lấy về và đặt vào bảng nhớ tạm của bạn. Dán sẽ gửi nội dung tương tự theo chiều ngược lại rồi nhấn dán bên trong hệ thống khách. Không có gì được đồng bộ ngầm: một mật khẩu bạn sao chép trên máy của mình không âm thầm xuất hiện bên trong một VM chỉ vì một bộ hẹn giờ kích hoạt.

Việc qua ranh giới được kiểm soát riêng theo từng người dùng và từng chiều, một cách độc lập. Dán vào một rig được cho phép theo mặc định; sao chép ra khỏi rig sẽ hỏi trước (một quyền trong mười phút, hoặc Luôn cho phép trong Cài đặt → Máy chủ → Rigs → Quyền truy cập bảng nhớ tạm). Đây không bao giờ là một cài đặt của không gian làm việc: một thành viên không thể đồng ý thay cho bảng nhớ tạm của thành viên khác.

Trên macOS, tổ hợp qua ranh giới là ⌘C/⌘V, không hề mập mờ — ⌃C vẫn đến được shell trong hệ thống khách đúng như tín hiệu ngắt mà nó vốn là. Trên Windows và Linux, hai tổ hợp là cùng một phím, nên hệ thống khách nhận nó nguyên vẹn và bảng nhớ tạm của bạn chỉ bị ghi đè khi bảng nhớ tạm của hệ thống khách thực sự thay đổi. Một tín hiệu ngắt vẫn là tín hiệu ngắt.

Tệp được kéo vào được sao chép vào thư mục thả của cỗ máy rồi được trao cho nó. Ý nghĩa của “được trao” phụ thuộc vào việc có thể làm gì một cách trung thực: một trang trình duyệt nhận một sự kiện thả thật ngay tại điểm bạn buông tay, nên một vùng tải lên cư xử đúng như khi bạn thả một tệp cục bộ; một desktop nhận các tệp trong ~/Drops cùng đường dẫn của chúng trên bảng nhớ tạm, vì không máy chủ nào có thể tạo giả một thao tác kéo vào một bộ toolkit Linux bất kỳ mà không chạy một daemon đặc quyền bên trong hệ thống khách — đúng điều mà thiết kế này từ chối có. Kết quả cho biết trường hợp nào đã xảy ra, nên một tệp CSV được thả vào vùng tải lên không bao giờ bị báo là đã tải lên khi thực ra nó chỉ là một tệp nằm trong thư mục. Thả vào một terminal khép kín sẽ sao chép tệp vào và gõ đường dẫn phía hệ thống khách tại dấu nhắc, vì đó là thứ mà shell thực sự dùng được.

Tệp được kéo ra hoạt động trên bề mặt desktop, nơi giao thức kéo thả của X11 cho phép đọc nội dung trong lúc thao tác kéo đang diễn ra. Bắt đầu kéo bên trong hệ thống khách, mang nó ra khỏi canvas, và các tệp sẽ được lấy về máy của bạn rồi bàn giao cho hệ điều hành như một thao tác kéo thật. Sao chép tệp trong trình quản lý tệp của hệ thống khách rồi dán trên máy chủ cũng hoạt động theo cách tương tự. Bề mặt trình duyệt cố ý không cung cấp điều này: một trình duyệt headless không có vùng chọn kéo để đọc, và tín hiệu gần nhất có sẵn — vùng chọn văn bản của trang — hoàn toàn không phải bằng chứng của một thao tác kéo, nên hành động dựa trên nó sẽ chiếm mất những cú nhấp thông thường.

Mọi thứ đọc ra từ hệ thống khách vẫn là nội dung không đáng tin cậy: văn bản bảng nhớ tạm đến với mô hình trong cùng lớp bao như khi trích xuất một trang, và nhật ký kiểm toán ghi lại rằng một thao tác dán đã xảy ra cùng khối lượng của nó — chứ không bao giờ ghi nội dung.

Thông tin xác thực không bao giờ nằm trong hệ thống khách

Phần tiêu đề “Thông tin xác thực không bao giờ nằm trong hệ thống khách”

git push hoạt động từ một terminal khép kín do bạn mở, vậy mà hệ thống khách không lưu token máy chủ mã nào. Nó giữ một bí mật riêng cho mỗi VM, với quyền năng duy nhất là hỏi broker thông tin xác thực của máy chủ — qua một tunnel do máy chủ kiểm soát — để lấy một token ngắn hạn, giới hạn theo repo, cho từng thao tác, có giới hạn tần suất, bị chặn bởi đúng danh sách máy chủ được phép như egress, và bị thu hồi ngay khi rig đóng. Một cỗ máy sinh ra để vứt bỏ phải không chứa gì đáng để đánh cắp.

Token đó được phép làm gì sẽ được cố định khi rig mở. Một rig terminal do con người mở nhận token có quyền ghi, bị giới hạn bởi quyền truy cập forge của chính thành viên đó. Một rig do agent mở nhận token chỉ đọc: credential helper của git không phân biệt được push với fetch, nên không thể hỏi quy tắc push cho từng lần push bên trong khách theo cách cổng lượt chạy agent làm trên máy chủ.

Khi một rig mang kho mã của bạn, worktree trên máy chủ vẫn là nguồn có thẩm quyền. Bản sao được đồng bộ vào lúc khởi động (loại trừ các bí mật như tệp .env), và các commit chỉ quay về khi bạn yêu cầu — được fetch vào refs/rigs/<id>/*, không bao giờ được push, không bao giờ được checkout. Không gì bên trong một VM có thể dịch chuyển nhánh của bạn hay chạm vào cây làm việc của bạn; việc merge những gì một rig tạo ra luôn là quyết định của con người, được đưa ra trên máy chủ.

Một máy chủ dev khởi động bên trong VM terminal trở nên truy cập được — trên máy của bạn, trong Browser (VM), tùy chọn trên LAN của bạn, tùy chọn dưới một tên miền dev có HTTPS — mà không bao giờ phải mở toang cỗ máy. Bản đồ cổng của hypervisor được cố định lúc khởi động, nên mọi chuyển tiếp về sau đi qua hai kênh hẹp do máy chủ kiểm soát: một bộ ghép kênh vào được tạo sẵn, từ chối gọi tới bất cứ thứ gì mà hệ thống khách không thực sự đang lắng nghe, và các tunnel ngược do máy chủ giữ mở cho những kết nối do hệ thống khách khởi tạo. HTTPS của tên miền dev kết thúc tại máy chủ, dùng một CA được tạo cục bộ mà khóa của nó không bao giờ lọt vào bất kỳ hệ thống khách nào. Cơ chế chi tiết nằm trong Chuyển tiếp cổng từ terminal.

Các cỗ máy bị giới hạn ngay từ khi dựng nên

Phần tiêu đề “Các cỗ máy bị giới hạn ngay từ khi dựng nên”

Một rig không thể trở thành thú cưng:

  • một TTL cứng mà hệ thống khách không thể gia hạn;
  • một thang nhàn rỗi — đỗ (vCPU dừng, RAM vẫn thường trú) sau khoảng thời gian nhàn rỗi, đóng sau gấp đôi khoảng đó — trong đó một terminal đang mở hoặc một người đang xem được tính là “đang dùng”;
  • một hạn mức bộ nhớ tính bằng megabyte thường trú, không phải theo phiên, vì một VM đã đỗ giải phóng CPU nhưng giữ nguyên từng byte RAM; cỗ máy ít được dùng gần đây nhất bị loại bỏ trước, và không bao giờ là cỗ máy đang có người điều khiển hoặc xem;
  • tháo dỡ khi máy chủ tắt, cộng thêm một đợt quét máy mồ côi có đánh dấu quyền sở hữu ở lần khởi động kế tiếp, để một máy chủ gặp sự cố không bao giờ bỏ mặc một hypervisor không còn phục vụ ai.

Lần khởi động đầu tiên sẽ kéo image được ghim của cỗ máy; sau đó máy chủ lưu một bản sao đã giải nén sẵn vào bộ nhớ đệm ở chế độ nền, nên mọi cỗ máy cùng loại về sau khởi động trong vài giây và một terminal khép kín khởi động lên với bộ CLI nền tảng kiểu runner do GitHub vận hành đã được cài sẵn — trình biên dịch, Python, jq, các công cụ lưu trữ — chứ không phải một toolcache ngôn ngữ hay Docker. Image Máy tính đưa sẵn đúng bộ CLI nền tảng đó vào từ lúc dựng image, bên cạnh XFCE và các trình duyệt.

“Chạy được trên máy tôi” là một khẳng định về đúng một engine kết xuất. Vậy nên một rig trình duyệt không phải “trình duyệt” nói chung — nó là Chromium, Firefox hoặc WebKit, được chọn khi bạn mở, và một rig chạy đúng engine mà nó được mở cùng suốt vòng đời của mình. Một cuộc hội thoại có thể có một rig cho mỗi engine: mở Firefox (VM) bên cạnh Chromium (VM) sẽ cho bạn hai cỗ máy, và trỏ cả hai vào cùng một trang chính là phép so sánh. WebKit gần với Safari nhất trong mọi thứ chạy trên Linux — cùng dòng dõi engine, nên nó bắt được những khoảng trống mà người dùng Safari gặp phải.

Các động từ giống hệt nhau ở cả ba; còn giao thức bên dưới thì không, và những khác biệt được nói rõ thay vì làm cho mờ đi. Chromium nói DevTools Protocol và đẩy khung hình, nên chế độ xem trực tiếp của nó không tốn gì khi trang đang đứng yên. Firefox nói WebDriver BiDi còn WebKit nói WebDriver cổ điển, cả hai đều không có screencast, nên chế độ xem trực tiếp của chúng phải thăm dò định kỳ — vài khung hình mỗi giây, mức phù hợp để xem một trang chứ không phải để xem một hoạt ảnh. Ở đâu một engine thực sự không làm được điều gì đó (Firefox không có lệnh tải lại bỏ qua bộ nhớ đệm; WebKit không thấy được đầu ra console ghi trước khi trang tải xong), câu trả lời sẽ nói thẳng như vậy thay vì âm thầm làm một việc khác.

Một rig cố ý không phải một điểm đến toàn cục. Chế độ xem trực tiếp là một tab trong space hoặc PR nơi công việc đang diễn ra, được giới hạn theo cuộc hội thoại đó — nên tab của bạn và các lời gọi browser_use của agent cùng trỏ tới một cỗ máy (một máy cho mỗi engine, trên bề mặt trình duyệt). Việc rig có thể khởi động được hay không là thuộc tính của máy chủ, nên năng lực, image, image tùy chỉnh theo không gian làm việc và danh sách máy đang chạy nằm trong Cài đặt → Máy chủ → Rigs. Điều khiển một môi trường cách ly là một lớp hành động rào chắn riêng, nên một không gian làm việc, agent hoặc space có thể cho phép, yêu cầu phê duyệt, hoặc từ chối thẳng — các chế độ chỉ đọc từ chối toàn bộ.