Skip to content

fix(ios): drive simulator biometrics through notifyutil - #2981

Merged
thymikee merged 3 commits into
callstack:mainfrom
okwasniewski:oskar/ios-biometrics-notifyutil
Sep 26, 2026
Merged

thymikee merged 3 commits into
callstack:mainfrom
okwasniewski:oskar/ios-biometrics-notifyutil

Conversation

@okwasniewski

@okwasniewski okwasniewski commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

settings faceid|touchid <match|nonmatch|enroll|unenroll> ran xcrun simctl biometric ... in several argument orders. No shipped Xcode has that subcommand (Xcode 26.6: Unrecognized subcommand: biometric), so every call failed as UNSUPPORTED_OPERATION and the error-text sniff that classified it hid the cause.

The setting now posts the same notifications the Simulator.app Features menu posts, through simctl spawn <udid> notifyutil:

  • match / nonmatch: -p com.apple.BiometricKit_Sim.<pearl|fingerTouch>.<match|nomatch>
  • enroll / unenroll: -s com.apple.BiometricKit.enrollmentChanged <1|0> -p com.apple.BiometricKit.enrollmentChanged

One command per action, no argument-order retries, no message sniffing; a failed post is COMMAND_FAILED with the attempted argv in details.attempts. Docs note the route.

agent-device settings faceid enroll
agent-device settings faceid match

Touched: app-settings.ts, its unit test, the managed-runtime provider scenario, commands.md (4 files).

Validation

Tested commit 7134de457 (rebased on 34f2eb1; review follow-up: iPhone/iPad leaf refusal and enrollment read-back).

  • pnpm check:affected --run: passed.
  • Live, iPhone 17 Pro / iOS 26.2 simulator, Xcode 26.6, CLI at this head: settings faceid enroll then xcrun simctl spawn <udid> notifyutil -g com.apple.BiometricKit.enrollmentChanged reads 1; unenroll reads 0; faceid match, touchid nonmatch return Updated setting; faceid toggle is refused as INVALID_ARGS before anything is spawned.
  • Not checked: a Face ID prompt inside an app accepting the posted match; the notifications are the ones Detox and Appium post for the same purpose.

Review in cubic

Copilot AI lite review requested due to automatic review settings September 25, 2026 15:36

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Copy link
Copy Markdown

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 4 files

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

Fix all with cubic | Re-trigger cubic

Comment thread packages/platform-apple/src/core/app-settings.ts Outdated
Comment thread website/docs/docs/commands.md Outdated
@okwasniewski

Copy link
Copy Markdown
Contributor Author

CI note: the Smoke Tests failure on this head is the fixture E2E step timing out at wait for Agent Device Tester after No fixture app bundle at .tmp/fixture-app, before any settings command ran. This change touches only the biometric simctl argv. I have no rerun rights here; a maintainer rerun should clear it.

No shipped Xcode has a simctl biometric subcommand, so every faceid and
touchid setting failed as unsupported. Post the BiometricKit_Sim match and
nomatch notifications and flip enrollmentChanged through simctl spawn
notifyutil, the route Simulator.app's Features menu uses.
…ollment back

Apple TV and Vision Pro simulators pass the kind-only simulator gate but never
observe BiometricKit_Sim, so a post there exited 0 and reported an update that
changed nothing. Enroll and unenroll now read the enrollmentChanged state back
and fail when it did not flip.
@okwasniewski
okwasniewski force-pushed the oskar/ios-biometrics-notifyutil branch from 84e0e7f to 635a3e3 Compare September 25, 2026 16:12
Copilot AI review requested due to automatic review settings September 25, 2026 16:12

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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

Copy link
Copy Markdown

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 4 files (changes from recent commits).

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

Fix all with cubic | Re-trigger cubic

Comment thread packages/contracts/src/settings.ts Outdated
@thymikee

Copy link
Copy Markdown
Member

The code is ready as of 635a3e3. Smoke Tests failing in the "Restore and build iOS XCTest runner" step is unrelated: it fails on the toolchain probe xcrun --sdk iphonesimulator --show-sdk-version hitting a spawnSync ETIMEDOUT after TEST BUILD SUCCEEDED, before any agent-device settings command runs, and this diff only touches the settings faceid/touchid simctl argv, a contracts constant, tests, and docs. I did not rerun the live iOS 26.2 simulator results the PR body reports and take them as stated; I also could not confirm on a current runtime that BiometricKit_Sim consumes the pearl/fingerTouch match and nomatch posts (the cited evidence is prior art from Detox and Appium, not an in-app LocalAuthentication prompt), and I could not confirm that notifyutil runs both the -s and -p actions of one invocation in order, since the -g read-back only proves the state was set, not that the post fired. Not blocking: notifyutil -p <name> at https://github.com/callstack/agent-device/blob/635a3e3/packages/platform-apple/src/core/app-settings.ts#L420 exits 0 for any name so it doesn't prove BiometricKit_Sim consumed the post (only enroll/unenroll have a read-back; an optional live run where a LocalAuthentication prompt resolves on match and fails on nonmatch would close this, though the repo fixtures have no such prompt), and APPLE_BIOMETRIC_LEAF_REFUSAL at https://github.com/callstack/agent-device/blob/635a3e3/packages/contracts/src/settings.ts#L243 could stay local to platform-apple rather than living in contracts until a daemon or capability reader needs it, unlike APPLE_TEXT_SIZE_LEAF_REFUSAL which the daemon's snapshot-settings.ts already reads — both can be taken or left. A maintainer rerun of Smoke Tests is the next step to clear the xcrun toolchain-probe timeout.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Sep 25, 2026
Copilot AI review requested due to automatic review settings September 25, 2026 16:40

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@thymikee

Copy link
Copy Markdown
Member

Reviewed at 7134de4. The only change since 635a3e3 is a one-line rewording of APPLE_BIOMETRIC_LEAF_REFUSAL.hint in packages/contracts/src/settings.ts. No test or fixture asserts the old text, and the new hint uses the real settings faceid <state> / settings touchid <state> syntax. The code verdict stays clean.

The failing Smoke Tests job times out in simctl openurl while it opens the snapshot-depth fixture. This PR does not touch the open or deep-link route, so this looks unrelated. I did not reproduce it.

Not blocking: requireBiometricLeaf (app-settings.ts#L460) repeats requireTextSizeLeaf (settings-text-size.ts#L31-L40) except for the refusal constant. Could they share one helper that takes the refusal?

@thymikee
thymikee merged commit 13a7b5d into callstack:main Sep 26, 2026
15 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants