Remote lease backend that confines a proxy client to one macOS app
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- macos, typescript
- Lĩnh vực
- backend-api-design, desktop
Hướng nghiên cứu
Start with packages/kernel/src/contracts.ts, then read ADR 0007, ADR 0029 and ADR 0031, and compare the existing harmonyos-instance backend. The acceptance criteria define done: a proxy client can use only the leased app, every out-of-scope action is refused with a typed error (including through batch), and tests mutation-check the rules.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem
A remote agent cannot be handed one macOS app on a proxy host. Through agent-device proxy plus connect proxy, devices --platform macos lists the host Mac, but open is refused: LEASE_BACKEND_BY_PLATFORM in packages/kernel/src/contracts.ts has entries only for ios, android and harmonyos, and its comment says the macOS desktop host maps to no backend on purpose. Observed on 0.21.12 (and reported on 0.21.20), and the same mapping is on main (2f933e5). #2989 (platform axis) does not change this.
The refusal is correct for a whole desktop: a macOS device is the host Mac, and a lease on it would give the client desktop, frontmost-app and menubar surfaces, any other app's windows, install and launch of arbitrary apps, and full-screen capture. Nothing in the current lease model can say "this client may drive this one app and nothing else".
Use case: a host Mac runs an app under test for a developer on another Mac, and the developer's coding agent should snapshot, click, type and screenshot that app through the host's proxy, without being able to touch the host's other apps or windows. This is what Stim (appandflow/stim#2477) needs to let agents drive an app it runs on another Mac.
What exists and why it is not enough
- Leases (ADR 0007) rent one device by
backend+provider+deviceKey. For macOS the device is the whole host. - Daemon policy (#3064, ADR 0029) confines a daemon to allowed devices and commands. It is per daemon, not per lease, and its device scope is the host Mac, so it cannot name a bundle id. A policy alone cannot express "this client, this app".
- macOS native app backend (ADR 0031,
AGENT_DEVICE_MACOS_APP_BACKEND=native) drives one session app through accessibility actions without Automation Mode and captures that app's front window. It is the right engine for this, but the session app is chosen by the client'sopen, and nothing restricts which app. - Human-control holds (#2078) already use a host-only loopback admin route that supplies an exact lease device scope with the local daemon token. That is the pattern for a host administrator pinning a scope.
retainOnClose(#3208) already gives a caller-owned lease lifecycle.- #3216 / #3217 (explicit macOS surface lost from recorded actions) are related: a scoped lease needs the explicit surface visible in admission and the journal, so the two should agree on how an explicit
--surfaceis carried.
Proposal
Add one lease backend, macos-app, whose device key is exactly one app: a bundle id, optionally with a pid (<bundleId> or <bundleId>@<pid>). It follows the shape of the harmonyos-instance backend (#2266: about 300 added lines across 17 files, most of them tests and wire-compat ledger entries).
Admission rules for a macos-app lease
All refusals use the existing typed error with a do-not-retry hint, and apply inside the daemon so batch and replay steps are covered the way #3064 covers them.
openaccepts only the leased bundle id (and, if the key has a pid, only that process). Any other app is refused.openwith an explicit--surfaceother thanappis refused.desktop,frontmost-appandmenubarsurfaces are refused for the lease's lifetime, including on commands that carry a surface afteropen.install,install-from-sourceand launching any app other than the leased one are refused.- Screenshots are limited to the leased app's window. Whole-screen capture and screen recording are refused (ADR 0031 item 6 already makes the app-surface screenshot a single window; this makes it an enforced guarantee).
- Commands that act outside the app are refused: system alerts, clipboard, settings, and anything else not on an allow list the backend declares. An allow list fails closed for commands added later, as in ADR 0029.
- If the leased process exits, or a pid-pinned key no longer matches the running process, the lease is no longer usable and requests fail with a typed error. A bundle-only key follows the next process of that bundle.
snapshotand refs only ever describe the leased app's windows.
Who allocates it
A tenant cannot allocate a macos-app lease for an arbitrary bundle, or the scope would be self-chosen. A host administrator allocates it over the existing loopback-only, daemon-token route used by human-control holds, and the proxy does not forward it:
PUT /admin/leases/<leaseId>
{ "tenantId": "...", "runId": "...", "clientId": "...",
"leaseBackend": "macos-app", "leaseProvider": "proxy",
"deviceKey": "com.example.app@12345", "ttlMs": 300000, "retainOnClose": true }
DELETE /admin/leases/<leaseId>
The client then connects with the usual --remote-config fields it already accepts (daemonBaseUrl, daemonAuthToken, leaseId, leaseBackend: "macos-app", platform: "macos") and runs open <bundleId> --platform macos. Tenant-side lease_allocate for macos-app is refused. Heartbeat and release behave as for other leases, and an admin DELETE revokes access at once. Like other proxy leases (ADR 0007), it does not survive a daemon restart; the host administrator re-allocates it, and the client sees the typed inactive-lease error until then.
If a loopback admin route for leases is too large a surface, an acceptable smaller variant is to let the host start the daemon with a policy entry that declares which macos-app keys tenants may allocate ("leases": { "macos-app": { "allow": [{ "bundleId": "..." }] } }), reusing the ADR 0029 file and fail-closed loading. A host that runs one app per client would start one policy per allowed bundle, and the admin route would not be needed.
What a host integrator needs to detect support
A way to learn that the daemon supports the backend before it hands a client access, for example leaseBackends in /health (or the daemon-policy digest work #3064 mentions as a follow-up). Without it, the integrator can only compare versions.
Alternatives considered
- One daemon per app, confined by daemon policy. Works today for commands, but policy cannot name a bundle id, so the daemon still reaches the whole desktop. Adding
apps.allowto the policy would work and is a smaller change, at the cost of one daemon, state directory and port per hosted app. Acceptable fallback; a lease backend lets one daemon serve many apps. - Leasing the whole host Mac. Rejected: gives the client the desktop.
- A client-side restriction. Rejected: the client is the untrusted party.
Non-goals
Other platforms, tenant self-service allocation, driving more than one app per lease, XCTest-backend specifics beyond refusing what leaks outside the app, and changes to ADR 0031's default backend.
Acceptance
- A proxy client holding a
macos-applease canopen,snapshot,click,fill,screenshotandclosethe leased app, and every rule above is refused with a typed error, including throughbatch. - A second app running on the host is invisible to
snapshotand unreachable byopenand by coordinates. - A tenant cannot allocate or widen the lease; releasing it from the admin route stops the client at its next request.
- Tests mutation-check each rule, as #3064 did.
- Ngôn ngữ chính
- TypeScript
- Star
- 4.8k
- Fork
- 315
- Merge trung bình
- 11 giờ 37 phút
- Pull request đã merge (30 ngày)
- 556
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của callstack/agent-device
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
callstack/agent-device#1869 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
iOS: type/fill still reads its pre-focus element after the focus tap, ending the runner sessionĐang mởbug needs-triage
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
callstack/agent-device#3238 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
fix(apple-runner): fence prep spawns after teardown or last-waiter cancellationCó thể đã có người làm @thymikee đã nhận hôm nay. Đang mởneeds-triage
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 42/100
callstack/agent-device#3220 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Explicit macOS surface is lost from recorded actions and replay scriptsCó thể đã có người làm @janicduplessis đã nhận 1 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
callstack/agent-device#3216 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
macOS native app backend: follow-ups (guarantees, evidence, persistent helper, session backend)Đang mởenhancement needs-triage
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 15/100
callstack/agent-device#3213 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của callstack/agent-device
Issue tương tự
-
fix: txId branch of the contract-state streams drops every state after the named transactionĐang mởbot:ai-assisted status:untriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
midnightntwrk/midnight-js#1424 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
mksglu/context-mode#1268 ·
Maintainer thường phản hồi trong vòng 5 ngày
-
Edit:Đang mởcheck:failed streams:edit
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 60/100
iptv-org/iptv#54352 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Table] reserveSelectedRowOnPaginate=false 时表头全选包含其他页数据Có thể đã có người làm @dvd233 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Tencent/tdesign-react#4416 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
area:widget bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
interledger/publisher-tools#894 ·
Maintainer thường phản hồi trong vòng 1 ngày