Repository navigation
feat(settings): let permission and iOS location settings target an explicit app - #3205
Conversation
Size Report
Startup median (7 runs, lower is better):
|
|
There was a problem hiding this comment.
All reported issues were addressed across 11 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
acaf809 to
5834b3e
Compare
|
I reviewed 5834b3e and found two defects that change which app a settings command targets, plus missing device evidence. The 21 checks pass, and there are no conflicts. First, Second, Third, this is a device-facing change, but I see no live run. Fourth, settings.test.ts:193 never passes Could a smaller design cover this? Send Not blocking: the field description at settings.ts:46 says the app "must not be running" (it should say "need not be running"), commands.md says "permission grant" where it should say "permission change" since deny and reset are also targeted, and The open inline threads still apply: the on/off location states, the clear-app-state test, the commands.md wording and the "must not be running" text. All four still hold, and none can be resolved yet. I did a read-only review and ran no tests. I did not trace the MCP schema surface and assumed it uses the same |
`settings permission` and the iOS-simulator `settings location on|off` privacy change acted only on the app the session had open, so setting a permission before an app's first launch meant opening the app first just to bind it. `simctl privacy` and Android's `pm` need only the bundle id or package, so the requirement was the daemon never being handed one. The named app now rides the request's input payload the way a gesture payload does: `app` is no CLI flag key, and permission's positionals already carry the target and mode. The CLI reaches it through the `--app` option `doctor` already owns, and the client and MCP surfaces through their `app` field, which is now documented. `clear-app-state` keeps carrying its app positionally, unchanged. Where a mutation cannot consume an app at all the request is refused rather than silently dropped: Android's `location on|off` writes the device's `location_mode`, and a macOS permission is a TCC grant to the host process. `settingsAppScope` is that one table, and the refusal carries `setting_app_not_consumed` with `dispatched: no` so a driver branches on the reason and knows no device was touched. No permission is set on a device that never held the app installed differently: the owner resolves the id as it always has, and the Android rule that revoking a granted permission kills the app (#1796) is unchanged.
…the field is documented
5834b3e to
58f310b
Compare
|
Both code defects from the earlier review (5834b3e) are fixed at 58f310b, but the live evidence for the explicit-app path is still missing. Thanks for the quick fixes. The PR body says the device lanes cover this route. They do not: no e2e or replay calls Of the earlier inline threads, the location-state parsing one, the clear-app-state test, the commands.md wording, the clear-app-state input path and the running-app help text are fixed at this commit, so please resolve them. The The code looks good at 58f310b. The Smoke Tests failure looks unrelated: |
`settingsInputApp` dropped `--app` for `location set`, so
`settings location set <lat> <lon> --app X` ignored X without a word — a
dropped argument, not a wrong-app change, and a contradiction this PR's own
rule forbids ("a device-wide change refuses a named app instead of dropping
it"). The daemon's scope table already classifies `location set` as
device-level for every family; the writer just never forwarded the app for
that refusal to land. Forward every `location` state's app so the daemon's
`setting_app_not_consumed` refusal answers it before dispatch, and widen the
client `location set` leg to carry `app` so the writer can.
Co-Authored-By: opencode <noreply@opencode.ai>
|
The code side of this PR is in good shape at 05b1b4c, but the live runs I asked for at 58f310b are still missing, so it is not ready yet. The earlier code findings are fixed, and I have no new code findings. The runs matter because the explicit-app path in settingsWriteAppId only runs in fixture and handler tests. No e2e or replay passes The six cubic-dev-ai threads (location state parsing, clear-app-state test, commands.md wording, location app forwarding, clear-app-state input, field description) are all fixed at this head, so please resolve them. Cubic has not reviewed 05b1b4c yet. The Android smoke check failed at step 30, |
|
Live device evidence for the explicit-app path, run on head 05b1b4c (includes the iOS simulator (iPhone 17 Pro, iOS 26.2)Camera grant to an app the session never opened (Maps, Location with a different session app. Session Location authorization on the simulator lives in locationd's Maps got the grant; Safari, the session app, did not. Note: the iOS success message reads Android emulator (Pixel 9 Pro XL, API 37)Camera grant to an app the session never opened ( Device-wide location with an app named is refused before anything is dispatched: Result
No code changes were needed. I did not exercise the macOS refusal or the earlier handler paths beyond what is above. |
|
Thanks for the live runs at 05b1b4c. They cover every case I asked for: the iOS camera grant lands in TCC.db for an app the session never opened, |
Summary
settings permissionand the iOS-simulatorsettings location on|offprivacy change acted only on the app the session had open, so granting a permission before an app's first launch meant opening the app first just to bind it.simctl privacyand Android'spmneed only the id, so the only real requirement was that the daemon was never handed one.The named app rides the request's
inputpayload the way a gesture payload does:appis no CLI flag key, and permission's positionals already carry target and mode. The CLI reaches it through the--appoptiondoctoralready owns; client and MCP through theirappfield, now described (it was on the undescribed-inputs baseline).clear-app-statestill carries its app positionally.A mutation that cannot consume an app refuses rather than silently dropping it: Android's
location on|offwrites the device'slocation_mode, and a macOS permission is a host TCC grant.settingsAppScopeis that one table, keyed on a target family the daemon derives with the kernel's own predicates so the contracts façade keeps its eager-closure budget; the refusal carriessetting_app_not_consumedwithdispatched: no. No app has to be running; the Android revoke-kills-the-app rule (#1796) is unchanged. 11 files.Validation
Tested at
5834b3e51:pnpm check:affected --runall runnable checks passed (format, lint, typecheck, layering, fallow, build, 531 related test files / 4129 tests, command-docs). New coverage inpackages/contracts/src/settings.test.ts(scope table + refusal),src/commands/capture/settings.test.ts(input carrier,clear-app-stateandlocation setexcluded), andsnapshot-settings-handler.test.ts(iOS permission/location with no session app, explicit app beating the session app, Android permission, and both refusals asserting the owner was never reached).scripts/__tests__/eager-closure-budgets.test.tspins that the contracts façade gains no evaluated module.Residual risk: sharing
--appmeansAGENT_DEVICE_TARGET_APPand user-configtargetAppnow also default the app forsettings, matching doctor's existing precedence; project config is unaffected (projectConfig: false). An.adscript cannot yet round-trip the app — it renders positionals, and a nameless replay hits the owner's existingsession_app_requiredrefusal (#3194) rather than granting to the wrong app. Device lanes (iOS/Android replay) are GitHub-authoritative and cover this route on the head.Closes #3179