Skip to content

Android settings permission response: one permissions list for changed ids, not permission: "a,b" #2701

Description

@thymikee

Purpose

Android reports which permission ids a call actually changed under two different field names, and one of them is comma-joined text inside a field typed singular. A consumer that wants the changed ids has to know which target shape produced the response and then split a string.

One Android target legitimately expands to several ids: location is ACCESS_FINE_LOCATION + ACCESS_COARSE_LOCATION, photos resolves to a media candidate at runtime. So "what I asked for" and "what changed" are different facts, and only all currently reports the second one as a list.

Current shape

packages/platform-android/src/settings-permission.ts:

Path Response
named target revoke (~L145) { permission: revoked.join(','), priorGrantState, warnings? }
declared pm target revoke (~L527) { permission: [...values].join(','), priorGrantState, warnings? }
target all (~L191) { permission: 'all', applied, warnings? }
not-requested error details (~L506) { appPackage, permission: values.join(',') }

Input side, packages/contracts/src/client-settings.ts (~L59) declares the request as permission: PermissionTarget — a single target — while SettingOptions.permissionTarget (packages/contracts/src/settings.ts ~L50, src/daemon/handlers/snapshot-settings.ts ~L30) is a bare string. The wire carries one target; only the platform knows the expansion.

Required behavior

One field for "ids this call changed", named the same on every path:

// named target, multi-id expansion
{ permission: 'location', permissions: ['android.permission.ACCESS_FINE_LOCATION', 'android.permission.ACCESS_COARSE_LOCATION'], priorGrantState: 'granted' }

// target all
{ permission: 'all', permissions: [...], warnings?: [...] }
  1. permissions: string[] carries the ids actually mutated, in the order applied. permission keeps meaning the requested target.
  2. applied folds into permissions; do not keep it as a long-lived alias.
  3. Error details use permissions: values instead of a joined string.
  4. Mirror the shape in the public client types and the versioned help, and update website/docs/docs/commands.md — it currently documents priorGrantState (L738) without stating the id-list field.
  5. Add a CHANGELOG entry under Changed.

Before preserving any compatibility alias, run git tag --contains on the introducing commits in a clone with full history (AGENTS.md: unreleased API has no external compatibility obligation). cf1f91da49 introduced the joined permission for revoke; this could not be settled from a shallow clone, so decide it there rather than defaulting to an alias.

Observable completion

  • No .join(',') in a response or error-detail field in settings-permission.ts.
  • pnpm vitest run packages/platform-android/src/__tests__/settings-permission.test.ts src/commands/capture/settings.test.ts green, with a new test asserting a location deny reports both location ids in permissions.
  • The Android provider scenario for permissions asserts the list shape end to end, not a split of permission.
  • pnpm check:quick, pnpm check:command-docs, pnpm format clean.

Dependencies

No blocker. Split out of #2363 so a maestro/iOS change did not also rewrite the Android response contract. Related to #2700 but independent: that issue owns skip-vs-abort classification, this one owns the response shape.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions