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

Open
#2,701 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
72/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
android, git, typescript

Research direction

Start with packages/platform-android/src/settings-permission.ts and the public contracts in packages/contracts/src/client-settings.ts, packages/contracts/src/settings.ts, and src/daemon/handlers/snapshot-settings.ts. Run the specified Vitest command and inspect the Android provider scenario, then check git tag --contains for the introducing commits before deciding compatibility. Done means every response and error detail exposes changed ids as permissions, with types, docs, changelog, tests, and the listed checks updated and passing.

Written by the indexing model from the issue text.

Description

ready-for-agent refactor

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.

Dominant language
TypeScript
Stars
4.7k
Forks
304
Avg merge
11h 46m
Merged PRs (30d)
471

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from callstack/agent-device

All issues in callstack/agent-device

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.