Repository navigation
feat(proxy): lease by device spec — --os, --image-tag, --physical honoured or refused by the backend - #3865
feat(proxy): lease by device spec — --os, --image-tag, --physical honoured or refused by the backend#3865V3RON wants to merge 8 commits into
Conversation
…oured or refused by the backend
…id/--serial; keep lease.device at any response level
…ec lease for another --udid/--serial, keep the spec out of the environment
|
Size Report
Startup median (7 runs, lower is better):
|
There was a problem hiding this comment.
🟡 Changes recommended
Explicit blank spec values can silently become unconstrained requests instead of being validated or refused.
2 open issues
What changed in this PR
Adds OS-version and Android-image-tag selection to proxy device leases, addressing #3864.
Changes:
- Exposes device-spec options through CLI, SDK, MCP, and connection defaults.
- Adds backend confirmation, unsupported-spec refusal, and live-lease conflict checks.
- Reports granted device details and adds tests and documentation.
| File | Description |
|---|---|
| website/docs/docs/remote-proxy.md | Documents spec-based leasing. |
| src/mcp/__tests__/command-tools-operator-inputs.test.ts | Checks MCP spec fields. |
| src/daemon-client/daemon-client-rpc.test.ts | Tests allocation wire fields. |
| src/commands/schema/option-schema.ts | Excludes ambient environment defaults. |
| src/commands/schema/command-overrides.ts | Allows spec flags on connect. |
| src/commands/schema/cli-help.ts | Explains proxy spec behavior. |
| src/commands/management/lease-device-spec.ts | Shares command spec fields. |
| src/commands/management/install.ts | Adds install-family spec inputs. |
| src/commands/management/app.ts | Adds open spec inputs. |
| src/commands/command-flags.ts | Projects spec request flags. |
| src/client/lease-client.ts | Reads granted device facts. |
| src/cli/connection/proxy-profile.ts | Stores proxy spec defaults. |
| src/cli/connection/profile-fields.ts | Groups hosted allocation fields. |
| src/cli/commands/router.ts | Accepts granted device metadata. |
| src/cli/commands/router-types.ts | Types granted device metadata. |
| src/cli/commands/proxy-lease-device.ts | Validates and binds spec leases. |
| src/cli/commands/generic.ts | Prints granted device facts. |
| src/cli/commands/connection-runtime.ts | Integrates spec allocation and reporting. |
| src/cli/commands/__tests__/proxy-lease-device-spec.test.ts | Tests proxy spec lifecycle. |
| src/cli/commands/__tests__/generic.test.ts | Tests granted-device output. |
| src/cli.ts | Carries lease facts to output. |
| src/__tests__/agent-device-client-leases.test.ts | Tests SDK allocation fields. |
| src/__tests__/agent-device-client-lease-device-spec.test.ts | Tests daemon and proxy refusals. |
| scripts/integration-progress-model.ts | Identifies spec-test ownership. |
| packages/remote/src/remote-connection-state.ts | Persists lease-bound spec metadata. |
| packages/remote/src/remote-config-schema.ts | Adds spec profile fields. |
| packages/daemon/src/server/request-router.ts | Refuses specs before admission. |
| packages/contracts/src/request-envelope.ts | Adds request spec fields. |
| packages/contracts/src/remote-config-fields.ts | Types profile spec defaults. |
| packages/contracts/src/lease-scope.ts | Defines shared spec handling. |
| packages/contracts/src/facades/client.ts | Exports spec and device types. |
| packages/contracts/src/client-lease.ts | Extends lease contracts. |
| packages/contracts/src/client-app.ts | Extends app-operation options. |
| packages/contracts/src/cli-flags.ts | Types CLI spec flags. |
| packages/contracts/src/__tests__/lease-scope.test.ts | Tests spec and echo readers. |
| packages/command-registry/src/flag-groups.ts | Shares supported spec flags. |
| packages/command-registry/src/flag-definitions-target.ts | Defines public spec flags. |
| docs/adr/0007-remote-device-leases.md | Records spec-leasing decisions. |
Review effort: Balanced
| return stripUndefined({ | ||
| osVersion: nonEmptyString(source.osVersion), | ||
| imageTag: nonEmptyString(source.imageTag), |
| } | ||
| return deviceSpecUnsupportedError( | ||
| keys, | ||
| 'The proxy backend leased a device without confirming the requested device spec, so the lease was released.', |
|
I reviewed 4f94d93. The design is sound, and one open Copilot thread still holds and needs a fix before this is ready: The new tests would fail on the old code, because the flags, keys and guard do not exist there. I did not rerun any tests. The honoured path, where a backend echoes lease.device, is proven only against a test-client fake, since simlock#814 is not available for a live allocate by spec. Not blocking, and fine to take or leave: the release in src/cli/commands/proxy-lease-device.ts:138 uses Smoke failed on |
# Conflicts: # packages/daemon/src/server/request-router.ts
…sical on lease.device
|
The earlier review's main problem is not fixed at df790b7, and the new Not blocking, and you can take or leave these: the CLI checks only that Could one per-key descriptor in The two open inline threads still stand: the blank The Coverage job failed in the I did not run any tests. The MCP/SDK route above comes from reading the code, not from an executed call. The honoured path is proven in the repo only against Before merge, the CLI and the daemon must agree on which spec values name a key, which covers blank strings and now |

Summary
open,install,reinstallanduninstallthroughconnect proxycan now lease by OS version, Android image tag, and physical or virtual class. A backend that cannot honour the spec refuses it rather than ignoring it. 38 files. Closes #3864.agent_device.lease.allocatedata.lease.device--os <version|range>osVersion(opaque string)model,osVersion(exact)--image-tag <tag>imageTagimageTag?--physicalphysical: truephysical(boolean, always present)Rules:
devices.listis not called first.--physical, the backend leases one of its enrolled phones. Onlyphysical: truenames the key;physical: 'yes'or1names no spec.agent-device proxy. The refusal isUNSUPPORTED_OPERATIONwithreason: 'device-spec-unsupported'andkeys, and it happens before admission, so no lease is recorded.lease.device, or with a non-booleanphysical, the CLI releases it and fails with the same reason.--udid/--serial, matches it. Otherwise the command fails withCONNECTION_DEVICE_CONFLICT.connect proxystores the keys as defaults. The keys are visible in MCP and the SDK.open --jsonprintslease.device; the human output showsphysical|virtual.remote-proxy.md,help remote, and an amendment to ADR 0007.--physicalis back, per the maintainer. It was dropped in 1270549 while no phone could reach Simlock's daemon. Simlock's phone path is now merged (Physical devices through agent-device callstackincubator/simlock#870): its front takesphysical(boolean), strips it before forwarding, and echoeslease.device.physical.Validation
At
df790b73a,pnpm check:affected --run --head df790b73aran withexactCommit=true(fail-open, full set): format, lint, typecheck, layering, di-seams, fallow, mcp-metadata, build, package, integration-node and macos-coverage passed.vitest-relatedhad 4989 passed, 1 failed:daemon-client-ensure-drain.test.tstimed out (5 s). The run before, at the previous head, timed out inmacos-recording.test.tsinstead. Both files pass when run alone (7/7). Neither covers a changed file. CI owns device lanes and coverage.Live: the
--physicalshape was proved end to end against Simlock on a Samsung SM-A165F and an iPhone 11 Pro Max (commit 06bb9d1, cherry-picked here).Review: three independent Opus rounds on the
--os/--image-tagversion. All findings except the gaps below are fixed. The round-3 fixes and the--physicalrestore were not reviewed again.Assumption: a spec key that a command leaves out does not constrain a live lease. This follows the existing
--devicerule.Assumption: env vars cannot set the keys; only flags and
connect proxycan.Known gaps:
connectforms other thanproxyaccept the flags but do not store them, as with--device.open --osthen fails withCONNECTION_DEVICE_CONFLICT.