You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An Android lease request names an API level and nothing else. Simlock picks the image itself: google_apis for the host ABI if installed, otherwise another installed image for that API level. A requester that needs Google Play, or a plain AOSP image, cannot ask for one.
After this task a lease request can name the Android image tag, for example google_apis_playstore. It is the same word the catalog shows as tag for each installed image. The device is created from an installed image with that tag. A request that names no tag behaves as today.
A request that names a tag never downloads. If no image with that tag is installed for the API level, the request fails, with or without --allow-download. The operator installs other image tags with sdkmanager.
Technical spec
File references are to main at 4f84a6a. Find code by symbol name.
Modules touched
src/core/domain.ts: DeviceSpec gains imageTag?: string. Present only when the request named one. The core carries it unread. sameSpec compares it, so a device with a tag and a device without one never share a pool, and two different tags never do.
src/core/driver.ts:
DeviceRequest gains imageTag?: string.
New UnsupportedRequestOptionError { platform, option }, for a driver that is asked for an option it does not have.
src/core/lease-acquisition-coordinator.ts (#resolveAndDrive): pass imageTag to resolveSpec. A resolved spec whose imageTag differs from the request's is refused, as a wrong mode is today. UnsupportedRequestOptionError rejects the waiter as unresolvable-spec and is mapped to BAD_REQUEST.
src/drivers/android/index.ts:
resolveSpec with imageTag: the candidates are the installed images with that tag. With osVersion, one must exist for that API level; without it, take the newest API level that has one. None: RuntimeMissingError with downloadable false and no component, whose message names the tag. Return the spec with imageTag.
resolveSpec without imageTag: unchanged, and the spec has no imageTag.
#matchingImage takes the tag. With a tag it picks among images of that tag: host ABI first, then any. Without a tag it keeps today's order. Every caller that creates or re-reads a device passes the device's spec.imageTag.
listCatalog's images is already what a tag is checked against; no change.
src/drivers/ios/index.ts: resolveSpec throws UnsupportedRequestOptionError("ios", "imageTag") when the request names one.
src/core/fake-driver.ts, e2e/fake-driver/fake-driver.ts: scriptable image tags per version; resolveSpec honours imageTag the same way.
src/contract/schemas.ts:
The lease request input and leaseRequestRecordSchema.request gain optional imageTag: 1 to 64 characters of A-Z a-z 0-9 _ . -.
deviceSpecSchema gains optional imageTag, so the grant, status and list show it on a device that has one.
src/daemon/error-code.ts: UnsupportedRequestOptionError is BAD_REQUEST.
src/gateway/: the catalog routing stage (A worker is sent only requests its catalog says it can serve #191). A request with imageTag goes only to a worker whose catalog entry for the platform lists an image with that tag, and with that runtime when the request names osVersion. When no worker qualifies, the request fails the way a request for a runtime no worker has fails today. The gateway relays the field unchanged.
src/cli/index.ts: lease --image-tag <tag>.
src/mcp/server.ts: the lease tool gains imageTag.
src/http/app.ts: POST /v1/lease-requests accepts imageTag; the request resource shows it.
src/simlock-client/types.ts, client.ts: imageTag on the lease input and on the device spec.
Docs: docs/CLI.md (--image-tag, that it never downloads, where to read the tags: simlock catalog), docs/HTTP-API.md, docs/CLIENT.md, docs/EVENTS.md and docs/internal/EVENTS.md where a payload lists the spec's fields, docs/internal/ARCHITECTURE.md.
Contract and event changes
lease.request input gains optional imageTag. The device spec in every output gains optional imageTag.
It ships as part of protocol 9. Do not bump the protocol, unless a release tagged after v0.2.0 already carries protocol 9 when this is built; in that case bump to 10 and say so in the PR.
No new event. Events that carry a request or device spec carry imageTag when it is set; both EVENTS.md files say so.
Rules in play
architecture.md rule 1 and 2 (the core compares imageTag and never reads it; only the Android driver knows what a tag is), rule 3 (a driver without the option refuses it itself; the core has no list of platforms that support it), rule 10 (one function picks the image, for resolving and for creating).
safety.md rule 4 (a tagged request never downloads) and rule 10 (the tag is wire input: the schema bounds it before a driver sees it).
ADR 0008 (the catalog's images is what a request can be checked against) and ADR 0009 (the catalog stage).
events.md rule on payload contracts.
documentation.md rule 2.
testing.md rules 1 to 4.
Tests
A request naming an installed tag resolves to a spec with that imageTag, and the device is created from that image.
A request naming a tag that is not installed for the API level fails with RUNTIME_MISSING, with and without allowDownload, and the installer is never called.
A request naming a tag and no osVersion gets the newest API level that has an image with that tag.
A request naming no tag resolves to the same image as before, and its spec has no imageTag.
With two ABIs installed for one tag, the host ABI is picked.
A warm device with another tag is not handed to a request that names a tag.
A warm device with no tag is not handed to a request that names a tag.
A warm device with a tag is not handed to a request that names none.
The grant's device spec carries imageTag for a request that named one, and none otherwise.
An iOS request naming a tag fails with BAD_REQUEST.
A tag with a character outside the allowed set, or over 64 characters, is refused by the schema.
On a gateway, a tagged request goes to the worker whose catalog lists that tag for that API level, and not to one that lists the API level with another tag.
On a gateway, a tagged request no worker can serve fails without being sent to any worker.
The CLI passes --image-tag; the MCP tool and the HTTP route pass imageTag.
Done when
A request naming an installed image tag gets a device created from that image. The grant says which tag it got.
A request naming a tag that is not installed for that API level fails with RUNTIME_MISSING, also with --allow-download.
A request naming no tag gets the same image as on main.
A warm device of another image tag is not handed to a request that names a tag.
Through a gateway, the request goes only to a worker whose catalog lists an image of that tag for that API level.
On a worker, an iOS request that names an image tag is a BAD_REQUEST.
The option is on the CLI, MCP, the HTTP API and the client. docs/CLI.md, docs/HTTP-API.md and docs/CLIENT.md describe it.
SIMLOCK_E2E_SLOW=1, on a machine with two image tags for one API level: a lease with --image-tag boots a device from the named image. Ask the maintainer before running this.
pnpm check is green.
Out of scope
Downloading an image by tag. A component stays a platform and a version (ADR 0010).
Choosing the ABI. The host ABI stays the rule.
A config default for the image tag, and a tag on warm-pool entries.
Scope
An Android lease request names an API level and nothing else. Simlock picks the image itself:
google_apisfor the host ABI if installed, otherwise another installed image for that API level. A requester that needs Google Play, or a plain AOSP image, cannot ask for one.After this task a lease request can name the Android image tag, for example
google_apis_playstore. It is the same word the catalog shows astagfor each installed image. The device is created from an installed image with that tag. A request that names no tag behaves as today.A request that names a tag never downloads. If no image with that tag is installed for the API level, the request fails, with or without
--allow-download. The operator installs other image tags withsdkmanager.Technical spec
File references are to
mainat 4f84a6a. Find code by symbol name.Modules touched
src/core/domain.ts:DeviceSpecgainsimageTag?: string. Present only when the request named one. The core carries it unread.sameSpeccompares it, so a device with a tag and a device without one never share a pool, and two different tags never do.src/core/driver.ts:DeviceRequestgainsimageTag?: string.UnsupportedRequestOptionError { platform, option }, for a driver that is asked for an option it does not have.src/core/lease-acquisition-coordinator.ts(#resolveAndDrive): passimageTagtoresolveSpec. A resolved spec whoseimageTagdiffers from the request's is refused, as a wrongmodeis today.UnsupportedRequestOptionErrorrejects the waiter asunresolvable-specand is mapped toBAD_REQUEST.src/drivers/android/index.ts:resolveSpecwithimageTag: the candidates are the installed images with that tag. WithosVersion, one must exist for that API level; without it, take the newest API level that has one. None:RuntimeMissingErrorwithdownloadablefalse and nocomponent, whose message names the tag. Return the spec withimageTag.resolveSpecwithoutimageTag: unchanged, and the spec has noimageTag.#matchingImagetakes the tag. With a tag it picks among images of that tag: host ABI first, then any. Without a tag it keeps today's order. Every caller that creates or re-reads a device passes the device'sspec.imageTag.listCatalog'simagesis already what a tag is checked against; no change.src/drivers/ios/index.ts:resolveSpecthrowsUnsupportedRequestOptionError("ios", "imageTag")when the request names one.src/core/fake-driver.ts,e2e/fake-driver/fake-driver.ts: scriptable image tags per version;resolveSpechonoursimageTagthe same way.src/contract/schemas.ts:leaseRequestRecordSchema.requestgain optionalimageTag: 1 to 64 characters ofA-Z a-z 0-9 _ . -.deviceSpecSchemagains optionalimageTag, so the grant,statusandlistshow it on a device that has one.src/daemon/error-code.ts:UnsupportedRequestOptionErrorisBAD_REQUEST.src/gateway/: the catalog routing stage (A worker is sent only requests its catalog says it can serve #191). A request withimageTaggoes only to a worker whose catalog entry for the platform lists an image with that tag, and with that runtime when the request namesosVersion. When no worker qualifies, the request fails the way a request for a runtime no worker has fails today. The gateway relays the field unchanged.src/cli/index.ts:lease --image-tag <tag>.src/mcp/server.ts: the lease tool gainsimageTag.src/http/app.ts:POST /v1/lease-requestsacceptsimageTag; the request resource shows it.src/simlock-client/types.ts,client.ts:imageTagon the lease input and on the device spec.docs/CLI.md(--image-tag, that it never downloads, where to read the tags:simlock catalog),docs/HTTP-API.md,docs/CLIENT.md,docs/EVENTS.mdanddocs/internal/EVENTS.mdwhere a payload lists the spec's fields,docs/internal/ARCHITECTURE.md.Contract and event changes
lease.requestinput gains optionalimageTag. The device spec in every output gains optionalimageTag.imageTagwhen it is set; bothEVENTS.mdfiles say so.Rules in play
architecture.mdrule 1 and 2 (the core comparesimageTagand never reads it; only the Android driver knows what a tag is), rule 3 (a driver without the option refuses it itself; the core has no list of platforms that support it), rule 10 (one function picks the image, for resolving and for creating).safety.mdrule 4 (a tagged request never downloads) and rule 10 (the tag is wire input: the schema bounds it before a driver sees it).imagesis what a request can be checked against) and ADR 0009 (the catalog stage).events.mdrule on payload contracts.documentation.mdrule 2.testing.mdrules 1 to 4.Tests
imageTag, and the device is created from that image.RUNTIME_MISSING, with and withoutallowDownload, and the installer is never called.osVersiongets the newest API level that has an image with that tag.imageTag.imageTagfor a request that named one, and none otherwise.BAD_REQUEST.--image-tag; the MCP tool and the HTTP route passimageTag.Done when
RUNTIME_MISSING, also with--allow-download.main.BAD_REQUEST.docs/CLI.md,docs/HTTP-API.mdanddocs/CLIENT.mddescribe it.SIMLOCK_E2E_SLOW=1, on a machine with two image tags for one API level: a lease with--image-tagboots a device from the named image. Ask the maintainer before running this.pnpm checkis green.Out of scope
Depends on
Approval
Written by an agent.