Steven
Steven5 мин четене

Вашето Mac приложение получава достъп до микрофона — после го забравя при всяко стартиране

GeekBye поиска разрешение за микрофона, вие го дадохте и всичко работеше. При следващото стартиране: изчезнало. А приложението изобщо не се появи в Системни настройки → Микрофон. Виновникът беше функция за сигурност на macOS, която тихомълком пускаше приложението от път, който изчезва — ето диагнозата и корекцията с един-единствен подкана.

macOS
Разрешения
Инженеринг
Издания на GeekBye
Вашето Mac приложение получава достъп до микрофона — после го забравя при всяко стартиране

Ето бъг, който те кара да се съмняваш в собствените си очи. Инсталираш GeekBye, той иска достъп до микрофона, натискаш Allow и транскрипцията работи. Чудесно. Затваряш, отваряш го отново на следващата сутрин — и той иска достъп до микрофона пак. Отиваш да провериш Системни настройки → Поверителност и сигурност → Микрофон, за да го оправиш ръчно, а GeekBye дори не е в списъка. Нито отказан. Нито разрешен. Просто липсва, сякаш никога не е искал.

Всяка отделна част изглеждаше правилна. Подканата беше истинска. Разрешението работеше в момента. Приложението беше правилно подписано и нотаризирано с правилните низове за употреба. И въпреки това разрешението се изпаряваше при всяко стартиране. GeekBye v2.0.6 го поправи — а основната причина е едно от най-коварните неща, които macOS прави, за да те защити.

Функцията, която скриваше приложението от самото себе си

Виновникът е macOS App Translocation, функция за сигурност на Gatekeeper. Когато изтеглиш приложение и го пуснеш директно от DMG или от папката ~/Downloads — навсякъде, където все още е „под карантина" — macOS всъщност не го изпълнява оттам, откъдето го виждаш. Той прозрачно го копира на случаен път само за четене, дълбоко под /private/var/folders/.../AppTranslocation/… и изпълнява това копие. Това е добра защита: спира зловредно изтегляне да пипа файлове до себе си.

Но ето сблъсъка. Системата за разрешения на macOS (TCC — тази, която следи кой може да използва микрофона, камерата, екрана ти) идентифицира приложение по неговия път и кодова идентичност. Когато приложението е транслокирано, този път е случаен и временен. Затова, когато дадеш достъп до микрофона, macOS послушно записва разрешението — за път, който няма да съществува при следващото стартиране. Отваряш приложението отново, macOS го транслокира на различен случаен път, вижда приложение, за което няма никакъв запис, и пита пак. И понеже този призрачен път никога не е стабилно място, приложението никога не печели постоянен ред в Системни настройки → Микрофон.

Приложението даваше разрешение на призрак.

Ето защо също така само някои хора го срещаха. Ако твоето копие на GeekBye вече живееше в /Applications — защото си го издърпал там, или защото е стигнало там чрез автоматично обновяване — няма карантина, няма транслокация, стабилен път, и всичко се запазва перфектно. Бъгът беше невидим за нас и за всеки след първата инсталация, точно този вид бъг, който оцелява най-дълго.

Корекцията: дай на приложението истински дом

Тъй като целият проблем е нестабилен път, корекцията е да преместиш приложението на стабилен. v2.0.6 засича кога GeekBye работи транслокирано (или просто работи извън /Applications) и предлага „Move to Applications" с едно кликване — използвайки повикването за преместване на macOS, което копира бъндъла в /Applications и го рестартира оттам. От този момент нататък приложението има фиксирана идентичност: разрешението за микрофон се запазва, записът на екрана се запазва, а GeekBye най-накрая се появява в Системни настройки, където би очаквал.

Подканата е учтива за това. Тя предлага Move to Applications, Not Now и Don't Ask Again — и помни последния избор, така че приложението никога не досажда на някого, който има умишлена причина да го пуска отдругаде. Решението дали изобщо да покаже подканата е изолирано в малки, чисти функции (транслокиран ли е този билд? извън /Applications ли е? потисна ли го потребителят?), така че логиката е тествана единично без нужда да пускаш истински нотаризиран билд на истински том под карантина.

Същото издание опрости и самото изживяване с разрешенията. GeekBye използваше собствен, специално направен вътрешен прозорец за разрешения — няколко стотин реда UI, опитващи се да възпроизведат нещо, което операционната система вече прави добре. v2.0.6 го изтри и се опря на нативната подкана за разрешения на macOS, подкрепена от тих, неблокиращ банер, който се появява само когато необходимо разрешение действително липсва. По-малко код и поведение, което потребителите вече разпознават, защото всяко друго Mac приложение работи по същия начин.

Частта, с която най-много се гордея: доказахме го, преди да го повярваме

Щеше да е лесно да предположим транслокация и да пуснем корекция. Вместо това изданието пусна първо диагностика при стартиране: при стартиране GeekBye сега докладва собствения си път на изпълнимия файл и дали е транслокиран, дали е вътре в /Applications, и текущия статус на разрешенията за микрофон и екран. Тази телеметрия превърна една правдоподобна теория в потвърдена — продукционните данни показаха, че засегнатите сесии всъщност работят от транслокирани пътища извън /Applications, точно както беше предсказано.

Този ред има значение. „Подканата се появява, но разрешението не се запазва" има няколко възможни обяснения — проблем с подписа, липсващ низ за употреба, проблем с entitlement, странност в базата данни на TCC. Изключихме причините на ниво API (пътят на заявката беше доказуемо правилен), после оставихме реалните данни да сочат към слоя на идентичността/пътя, вместо да пуснем обнадеждаваща корекция и да се надяваме, че тикетите за поддръжка спират.

Три неща, на които учи този бъг

  1. Разрешение, което подканя, но не се запазва, е проблем на идентичността, не на API-то. Ако кодът на заявката е правилен, а разрешението пак изчезва, спри да пренаписваш заявката. Питай към кой път и кодова идентичност операционната система обвързва разрешението — и дали тази идентичност е стабилна между стартиранията.
  2. Пусни диагностиката с (или преди) корекцията. Няколко полета — откъде работя, какъв е статусът на разрешенията ми — превърнаха едно образовано предположение в проверена основна причина и ни казаха точно кои потребители са засегнати. Инструментирай границата, която подозираш, преди да я закърпиш.
  3. Бъговете, които се крият от разработчиците, са тези, работещи в „грешната" среда. Нашият живееше в /Applications на всяка машина за разработка, така че бъгът беше структурно невидим за нас, докато удряше потребителите при първа инсталация. Когато доклад не се възпроизвежда, първият въпрос е какво е различно за мястото, където работи, не греши ли потребителят.

GeekBye v2.0.6 пусна подканата за преместване и диагностиката заедно. За по-широката дъга на надеждността, в която това се вписва, виж какво всъщност изисква версия 2 (v2.0.0) и защо записът на екрана хваща грешния монитор (v2.0.10) — друг бъг, който изплува само в специфична среда. За изданието с дребни детайли до него, спокоен софтуер: корекцията на трептенето и чипът за режим-на-отговор (v2.0.3 + v2.0.5).

Свързани статии

Да различиш обаждане от отворено приложение
Steven
Steven8 мин четене

Да различиш обаждане от отворено приложение

GeekBye може да забележи, че си се присъединил към видео среща, и да ти предложи да я запише. Разпознаването се оказва лесната половина — Swift binary, който чете заглавия на прозорци на всеки десет секунди. Трудната половина е прецизността: да не се задейства, когато Zoom е просто отворен, да не пита за среща, която вече записваш, и да не заглушава микрофона в обаждането, в което всъщност си. Три издания, всяко от които е предпазител, който трябваше да се научи да не побеждава сам себе си.

Инженерство
macOS
Desktop
Анатомията на изпращането на софтуер до съвършенство: как прегледът на кода улови това, което тестовете не можаха
Steven
Steven6 мин четене

Анатомията на изпращането на софтуер до съвършенство: как прегледът на кода улови това, което тестовете не можаха

В цялата поредица за GeekBye v2 се случва едно и също нещо: дадена поправка минава всеки тест на машината на разработчика, а после прегледът на кода доказва, че тя би се провалила за почти всеки друг. Това е работният процес зад девет издания — портата на прегледа, ранните улавяния при поправките и дисциплината „тествай преди да изпратиш“, която превръща „при мен работи“ в „работи“.

Инженеринг
Процес
Преглед на кода
Как да предавате отчет на живо без трептене
Steven
Steven5 мин четене

Как да предавате отчет на живо без трептене

Когато срещата ви приключи, обобщението на GeekBye вече се попълва на живо, вместо да ви кара да гледате въртящ се индикатор. За да изглежда стриймингът в интерфейса спокоен, а не накъсан, се наложи да решим трептенето два пъти — веднъж за структурираните полета, веднъж за markdown — и втората поправка беше рендер, който вече притежавахме.

Инженеринг
Фронтенд
Стрийминг