Repository navigation
Touch ID: явно відкривати вікно перед підписом - #68
Merged
Merged
Conversation
The approval helper relied on an implicit prompt from the Security framework when it signed with an unevaluated LAContext. From the MCP approval chain that prompt never appeared, so the helper blocked until Node killed it after 120 seconds with an empty stderr. setup and approve now call evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics) with the unchanged prompt text, wait at most 90 seconds, then sign with the evaluated context made non-interactive. A whole-operation deadline of 110 seconds keeps every failure below the 120-second approval TTL, with exit status 1 and a message on stderr. No password or software fallback, reuse stays 0, and the key ACL is unchanged. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
0design
marked this pull request as ready for review
October 28, 2026 18:31
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Причина
Підтвердження кейса через MCP зависало: вікна Touch ID не було, helper через 120 с убивав тайм-аут Node, у помилці лишалося
Command failed: …/touchid-approve approveбез stderr.approve()(іsetup()) підписували ключем Secure Enclave з неоціненимLAContext:context(reason:)лише перевірявcanEvaluatePolicyі ніколи не викликавevaluatePolicy. Вікно мав показати сам Security framework під час підпису. Реєстрація з терміналу так спрацювала, а з ланцюжка MCP-підтвердження вікно не з'явилось, і виклик підпису блокувався без меж. Окрема проба з явнимevaluatePolicy(.deviceOwnerAuthenticationWithBiometrics)показала вікно й повернула OK і в терміналі, і черезnode execFileз тим самим оточенням.Точну причину, чому неявне вікно не з'являється саме в ланцюжку MCP, не встановлено. Виправлення не залежить від неї: вікно відкривається явно, а будь-яка відмова має межу в часі.
Що змінено в
tools/touchid-approve/main.swiftauthenticate(_:reason:):evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason:)з тим самим текстом вікна (Decision / SHA-256 / Run / Gate; дляsetup— «Set up the Touch ID approval key»). Чекає на семафорі не довше 90 с. Тайм-аут →invalidate()закриває вікно → вихід 1 зі stderr.interactionNotAllowed = true, і підпис іде вже оціненим контекстом. Якщо оцінка чомусь не покриває ACL ключа, підпис одразу падає й не чекає на невидиме неявне вікно.approve(): спершу перевіряє, що ключ зареєстровано, потім показує вікно, потім завантажує ключ і підписує.setup(): вікно перед створенням або завантаженням ключа й підписом.APPROVAL_TTL_MSі за тайм-аут Node.localizedFallbackTitle = "",touchIDAuthenticationAllowableReuseDuration = 0, ACL[.biometryCurrentSet, .privateKeyUsage], текст у вікні, формат ключа й файлів.Чому
evaluatePolicy, а неevaluateAccessControl. СамеevaluatePolicyз біометричною політикою показало вікно в цьому ланцюжку.evaluateAccessControlтут ще не перевіряли. До того ж уapproveдовелося б заново будуватиSecAccessControl, бо його не зберігають разом із ключем, і будь-яке розходження з ACL ключа повернуло б підпис до неявного вікна. Біометрична політика не допускає пароля й задовольняє вимогу.biometryCurrentSet. Зміну набору відбитків і далі відхиляє Secure Enclave.Тести (без вікна Touch ID і без справжнього ключа)
test/touchid-explicit-prompt.test.mjs:approve()іsetup()явна оцінка стоїть перед завантаженням, створенням ключа й підписом; політика лише біометрична; є очікування з тайм-аутом,invalidate, неінтерактивний контекст після оцінки; виконується співвідношення 90 < 110 < TTL; не змінились fallback, reuse, ACL і текст вікна;main.swiftз main перевірка падає;execFileзі скриптом, що завершується з кодом 1, повертає stderr helper у помилціTouchIdAnchor.confirm.touchid-compile) проходить. Повний набір тестів падає в тих самих 48 тестах «CLAUDECODE is set», що й на main; набір назв збігається.Закріплення каталогу
Артефакт Core змінився (
main.swiftі README helper входять у пакет). Закріплення оновлене тим самим шляхом, що й у попередніх злиттях:npm pack --ignore-scripts→registry/catalog.source.json→scripts/build-registry.mjs(export +--check).Межі
~/.q-core.🤖 Generated with Claude Code