Skip to content

refactor(mobile): set permissions on the app by name, without an open first - #1025

Merged
okwasniewski merged 4 commits into
tester-army:mainfrom
thymikee:refactor/mobile-permissions-explicit-app
Oct 12, 2026
Merged

okwasniewski merged 4 commits into
tester-army:mainfrom
thymikee:refactor/mobile-permissions-explicit-app

Conversation

@thymikee

@thymikee thymikee commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

What and why

  • agent-device's settings permission acted only on the app its session was on. To set a permission before the first launch, the engine opened the app first just to put the session on it. That took:

    • a sessionApp field on the surface and on every slot binding;
    • a sessions.list at worker start, to check that the warm-up's session survived;
    • a foreground open before setPermission and before the permissions a launch presets;
    • a retry that matched the refusal text requires an active app in session.
  • agent-device 0.21.21 takes an explicit app (callstack/agent-device#3179, filed from this integration), and 0.21.25 resolves a display name there and refuses an app that isn't installed (callstack/agent-device#3386). This PR bumps agent-device to 0.21.25 for that: on 0.21.22 a target pinned by display name (bundleId: 'Settings', as in the quickstart) would get its permission written for a client literally named Settings. simctl privacy and pm need only the id, not a running app. All of the above is gone:

    client.settings.update({ setting: 'permission', permission, state, ...this.selection(), ...(app === undefined ? {} : { app }) })
  • The permission call carries the worker's device selection. Before, the open in front of it bound the session to the device; without that open, a worker with no session (after closeApp, or on a slot whose earlier worker retired) would send the change to the daemon's default device.

  • device.setPermission() acts on the pinned app, as its docs say, not on whichever app the session last opened.

  • The warm-up in prepare still opens the pinned app, so a test that starts without app.open() finds it on screen. Its other reason, that a timed-out open resets the daemon every slot shares, is gone since agent-device 0.21.21 (callstack/agent-device#3177), and the comments say so.

flowchart LR
  subgraph main
    A1[open app, foreground] --> B1[settings permission] --> C1[open --relaunch]
  end
  subgraph this branch
    B2[settings permission --app] --> C2[open --relaunch]
  end
Loading

Verified

Ran it locally: yes

  • iOS 27.1 simulator (iPhone 17 Pro), a scratch project on the built packages, target com.apple.Maps. The test runs device.closeApp(), device.setPermission('photos', 'grant'), app.open(), device.closeApp(), device.setPermission('photos', 'deny'). Commands agent-device received for the session, from its events.ndjson:
main this branch
boot, session_list, close, open, settings, open, close, open, settings boot, close, settings, open, close, settings
  • The simulator's TCC.db has kTCCServicePhotos | com.apple.Maps | 0 from the branch's final deny.
  • On 0.21.25, the same simulator with the target pinned by display name (app: { bundleId: 'Maps' }): device.setPermission('photos', 'grant') before the first app.open() wrote kTCCServicePhotos | com.apple.Maps | 2.
  • Not run locally: Android, and the mobile benchmark. This PR's mobile jobs run both.

Checklist

  • Changeset added (pnpm changeset) for any change to a published package, or the change is testbed, docs, or CI only.
  • Breaking change: title carries !, the changeset body names what breaks and what replaces it, and the deprecation warning landed a window earlier (stability policy in CONTRIBUTING.md).
  • Docs updated in the same PR: the docs/**/*.mdx page for the behavior, and skills/e2e/ if the skill describes it.
  • Contract change: emitted .d.ts reviewed, tests/types/sdk-types.ts updated; wire change edits the schema and both fixtures.
  • Engine contract change (e2e/engine): changesets for e2e, @e2e-dev/web, and @e2e-dev/mobile.

DeviceLease loses the optional sessionApp it inherited from SlotBinding. It was never documented, and the lease-to-binding path already dropped it.

🤖 Generated with Claude Code

thymikee and others added 2 commits October 10, 2026 18:10
… first

agent-device 0.21.21 takes an explicit app on settings permission
(callstack/agent-device#3179), so a permission needs no open to put the
session on the app. Drops the session-app bookkeeping, the sessions list
at worker start, the refusal-text retry, and the binding's sessionApp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0.21.25 resolves a display name on settings permission --app
(callstack/agent-device#3386), which the explicit-app permission change
needs for a target pinned by display name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@thymikee
thymikee marked this pull request as ready for review October 12, 2026 06:51

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 13 files

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread .changeset/mobile-permissions-explicit-app.md Outdated
thymikee and others added 2 commits October 12, 2026 08:55

@okwasniewski okwasniewski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

@okwasniewski
okwasniewski merged commit 880ae70 into tester-army:main Oct 12, 2026
23 checks passed
@thymikee
thymikee deleted the refactor/mobile-permissions-explicit-app branch October 12, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants