Steven
Steven7 मिनट पढ़ें

आपका Mac ऐप माइक्रोफ़ोन एक्सेस देता है — फिर हर बार खुलने पर उसे भूल जाता है

GeekBye ने माइक्रोफ़ोन की अनुमति माँगी, आपने दे दी, और यह चल गया। अगली बार खोलने पर: गायब। और ऐप System Settings → Microphone में कभी दिखा ही नहीं। गुनहगार एक macOS सुरक्षा फ़ीचर था जो चुपचाप ऐप को एक ऐसे पाथ से चला रहा था जो गायब हो जाता है — यहाँ पूरी जाँच और वह एक-प्रॉम्प्ट वाला फ़िक्स है।

macOS
अनुमतियाँ
इंजीनियरिंग
GeekBye रिलीज़
आपका Mac ऐप माइक्रोफ़ोन एक्सेस देता है — फिर हर बार खुलने पर उसे भूल जाता है

यहाँ एक ऐसा बग है जो आपको अपनी ही आँखों पर शक करा दे। आप GeekBye इंस्टॉल करते हैं, यह माइक्रोफ़ोन एक्सेस माँगता है, आप Allow पर क्लिक करते हैं, और ट्रांसक्रिप्शन चल जाती है। बढ़िया। आप इसे बंद करते हैं, अगली सुबह फिर खोलते हैं — और यह माइक्रोफ़ोन एक्सेस फिर से माँगता है। आप इसे हाथ से ठीक करने के लिए System Settings → Privacy & Security → Microphone में जाकर देखते हैं, और GeekBye उस लिस्ट में है ही नहीं। न डिनाइड। न अलाउड। बस गैरहाज़िर, मानो उसने कभी माँगा ही न हो।

हर अलग-अलग हिस्सा सही दिखता था। प्रॉम्प्ट असली था। अनुमति उस पल में काम करती थी। ऐप सही यूज़ेज स्ट्रिंग्स के साथ ठीक से साइन्ड और नोटराइज़्ड था। फिर भी अनुमति हर बार खुलने पर हवा हो जाती थी। GeekBye v2.0.6 ने इसे ठीक किया — और मूल कारण उन सबसे चालाक चीज़ों में से एक है जो macOS आपकी हिफ़ाज़त के लिए करता है।

वह फ़ीचर जो ऐप को खुद उससे ही छिपा रहा था

गुनहगार है macOS App Translocation, एक Gatekeeper सुरक्षा फ़ीचर। जब आप कोई ऐप डाउनलोड करके सीधे DMG से या अपने ~/Downloads फ़ोल्डर से चलाते हैं — कहीं भी जहाँ वह अभी भी "क्वारंटीन" में है — तो macOS असल में उसे वहाँ से नहीं चलाता जहाँ आप उसे देखते हैं। यह चुपके से उसे एक रैंडमाइज़्ड, रीड-ओनली पाथ पर, /private/var/folders/.../AppTranslocation/… के गहरे अंदर कॉपी कर देता है और उसी कॉपी को चलाता है। यह एक अच्छा बचाव है: यह किसी नुकसानदेह डाउनलोड को अपने बगल की फ़ाइलों से छेड़छाड़ करने से रोकता है।

पर टकराव यहाँ है। macOS का अनुमति सिस्टम (TCC — वह चीज़ जो नज़र रखती है कि आपके माइक, कैमरा, स्क्रीन को कौन इस्तेमाल कर सकता है) एक ऐप को उसके पाथ और कोड आइडेंटिटी से पहचानता है। जब ऐप ट्रांसलोकेट होता है, वह पाथ रैंडम और अस्थायी होता है। तो जब आप माइक्रोफ़ोन एक्सेस देते हैं, macOS ईमानदारी से अनुमति दर्ज कर लेता है — पर एक ऐसे पाथ के ख़िलाफ़ जो अगली बार खुलने पर मौजूद ही नहीं होगा। ऐप फिर खोलिए, macOS उसे एक अलग रैंडम पाथ पर ट्रांसलोकेट करता है, एक ऐसा ऐप देखता है जिसका उसके पास कोई रिकॉर्ड नहीं है, और फिर से पूछता है। और चूँकि वह भूतिया पाथ कभी एक स्थिर जगह नहीं होता, ऐप को System Settings → Microphone में कभी एक स्थायी पंक्ति नहीं मिलती।

ऐप एक भूत को अनुमति दे रहा था।

यही वजह है कि सिर्फ़ कुछ लोग इससे टकराते थे। अगर GeekBye की आपकी कॉपी पहले से /Applications में थी — क्योंकि आपने उसे वहाँ खींचकर रखा, या क्योंकि वह ऑटो-अपडेट के जरिए वहाँ पहुँची — तो कोई क्वारंटीन नहीं, कोई ट्रांसलोकेशन नहीं, एक स्थिर पाथ, और सब कुछ पूरी तरह टिका रहता है। यह बग हमारे लिए और पहली इंस्टॉल के आगे बढ़ चुके हर किसी के लिए अदृश्य था, और यही वह किस्म का बग है जो सबसे लंबा टिकता है।

फ़िक्स: ऐप को एक असली घर दो

चूँकि पूरी समस्या एक अस्थिर पाथ है, फ़िक्स यह है कि ऐप को एक स्थिर पाथ पर पहुँचाया जाए। v2.0.6 पहचानता है कि GeekBye कब ट्रांसलोकेटेड चल रहा है (या बस /Applications के बाहर से चल रहा है) और एक-क्लिक वाला "Move to Applications" पेश करता है — macOS के उस रीलोकेशन कॉल का इस्तेमाल करके जो बंडल को /Applications में कॉपी करके वहीं से दोबारा लॉन्च करता है। उस पल के बाद ऐप की एक तयशुदा पहचान होती है: माइक्रोफ़ोन अनुमति टिकती है, स्क्रीन रिकॉर्डिंग टिकती है, और GeekBye आख़िरकार System Settings में वहीं दिखता है जहाँ आप उम्मीद करते हैं।

प्रॉम्प्ट इस बारे में शालीन है। यह Move to Applications, Not Now, और Don't Ask Again पेश करता है — और यह आख़िरी चुनाव याद रखता है, ताकि ऐप कभी उस किसी को तंग न करे जिसके पास इसे कहीं और से चलाने की सोची-समझी वजह है। प्रॉम्प्ट को दिखाया जाए या नहीं — इसका फ़ैसला छोटे, शुद्ध फ़ंक्शनों में अलग किया गया है (क्या यह बिल्ड ट्रांसलोकेटेड है? क्या यह /Applications के बाहर है? क्या यूज़र ने इसे दबा दिया?) ताकि इस लॉजिक की यूनिट-टेस्टिंग बिना किसी असली नोटराइज़्ड बिल्ड को असली क्वारंटीन किए हुए वॉल्यूम पर लॉन्च किए हो सके।

इसी रिलीज़ ने अनुमति के अनुभव को भी सरल किया। GeekBye पहले एक कस्टम, ख़ास इन-ऐप अनुमति विंडो खोलता था — कुछ सौ लाइनों की UI जो उस चीज़ को दोहराने की कोशिश करती थी जो OS पहले से अच्छे से करता है। v2.0.6 ने उसे हटा दिया और नेटिव macOS अनुमति प्रॉम्प्ट पर भरोसा किया, जिसके साथ एक शांत, बिना रुकावट वाला बैनर है जो तभी दिखता है जब कोई ज़रूरी अनुमति सच में गायब हो। कम कोड, और वह व्यवहार जिसे यूज़र पहले से पहचानते हैं क्योंकि बाक़ी हर Mac ऐप इसी तरह काम करता है।

जिस बात पर मुझे सबसे ज़्यादा गर्व है: मानने से पहले हमने इसे साबित किया

ट्रांसलोकेशन का अंदाज़ा लगाकर एक फ़िक्स शिप कर देना आसान होता। इसके बजाय, रिलीज़ ने पहले एक स्टार्टअप डायग्नॉस्टिक शिप किया: लॉन्च पर, GeekBye अब अपना ही एग्ज़िक्यूटेबल पाथ रिपोर्ट करता है और यह कि वह ट्रांसलोकेटेड है या नहीं, /Applications के अंदर है या नहीं, और मौजूदा माइक्रोफ़ोन व स्क्रीन अनुमति की स्थिति। उस टेलीमेट्री ने एक संभावित थ्योरी को एक पुष्ट थ्योरी में बदल दिया — प्रोडक्शन डेटा ने दिखाया कि प्रभावित सेशन असल में /Applications के बाहर ट्रांसलोकेटेड पाथ से ही चल रहे थे, बिलकुल जैसा अनुमान था।

वह क्रम मायने रखता है। "प्रॉम्प्ट आता है पर अनुमति टिकती नहीं" के कई संभावित स्पष्टीकरण हैं — कोई साइनिंग समस्या, कोई गायब यूज़ेज स्ट्रिंग, कोई एंटाइटलमेंट का मसला, कोई TCC डेटाबेस की गड़बड़ी। हमने API-स्तर के कारणों को ख़ारिज किया (रिक्वेस्ट पाथ साफ़-साफ़ सही था), फिर असल दुनिया के डेटा को आइडेंटिटी/पाथ लेयर की ओर इशारा करने दिया, बजाय इसके कि एक उम्मीद भरा फ़िक्स शिप करके यह आस लगाते कि सपोर्ट टिकट रुक जाएँ।

तीन बातें जो यह बग सिखाता है

  1. वह अनुमति जो प्रॉम्प्ट तो करती है पर टिकती नहीं, यह एक आइडेंटिटी की समस्या है, API की नहीं। अगर रिक्वेस्ट कोड सही है और अनुमति फिर भी गायब हो जाती है, तो रिक्वेस्ट को दोबारा लिखना बंद करिए। पूछिए कि OS अनुमति को किस पाथ और कोड आइडेंटिटी से बाँध रहा है — और क्या वह पहचान हर बार खुलने पर स्थिर रहती है।
  2. डायग्नॉस्टिक को फ़िक्स के साथ (या उससे पहले) शिप करिए। कुछ ही फ़ील्ड — मैं कहाँ से चल रहा हूँ, मेरी अनुमति की स्थिति क्या है — ने एक पढ़े-लिखे अनुमान को एक सत्यापित मूल कारण में बदला और हमें ठीक-ठीक बताया कि कौन-से यूज़र प्रभावित थे। जिस सीमा पर आपको शक है, उसे पैच करने से पहले उस पर इंस्ट्रुमेंट लगाइए।
  3. जो बग डेवलपरों से छिपते हैं, वे "ग़लत" माहौल में चल रहे होते हैं। हमारा हर डेव मशीन पर /Applications में रहता था, इसलिए बग बनावटी तौर पर हमारे लिए अदृश्य था जबकि पहली बार आने वाले यूज़र पर वार कर रहा था। जब कोई रिपोर्ट दोहराई न जा सके, तो पहला सवाल यह है कि वह कहाँ चलता है, इसमें क्या अलग है, न कि क्या यूज़र से ग़लती हुई है।

GeekBye v2.0.6 ने रीलोकेशन प्रॉम्प्ट और डायग्नॉस्टिक को साथ शिप किया। जिस बड़े रिलायबिलिटी दौर में यह बैठता है, उसके लिए देखिए एक वर्शन 2 में असल में क्या लगता है (v2.0.0) और स्क्रीन रिकॉर्डिंग ग़लत मॉनिटर क्यों कैप्चर करती है (v2.0.10) — एक और बग जो सिर्फ़ एक ख़ास माहौल में सामने आया। पास वाली छोटी-छोटी बातों वाली रिलीज़ के लिए, शांत सॉफ़्टवेयर: फ़्लिकर फ़िक्स और आंसर-मोड चिप (v2.0.3 + v2.0.5)।

संबंधित लेख

सॉफ़्टवेयर को परफेक्शन तक शिप करने की एनाटॉमी: कोड रिव्यू ने वह पकड़ा जो टेस्ट न पकड़ सके
Steven
Steven7 मिनट पढ़ें

सॉफ़्टवेयर को परफेक्शन तक शिप करने की एनाटॉमी: कोड रिव्यू ने वह पकड़ा जो टेस्ट न पकड़ सके

GeekBye v2 सीरीज़ में बार-बार वही एक चीज़ होती रही: एक फिक्स डेवलपर की मशीन पर हर टेस्ट पास कर जाता है, और फिर कोड रिव्यू साबित कर देता है कि यह करीब-करीब सबके लिए फेल हो जाता। यह नौ रिलीज़ के पीछे की वर्कफ़्लो है — रिव्यू गेट, फिक्स-फर्स्ट कैच, और शिप-से-पहले-टेस्ट का अनुशासन जो 'मेरे यहाँ तो चलता है' को 'यह चलता है' में बदल देता है।

इंजीनियरिंग
प्रक्रिया
कोड रिव्यू
एक CSS वेरिएबल, पाँच रिव्यू राउंड, और एक Swift टूलचेन जिसने झूठ बोला
Steven
Steven8 मिनट पढ़ें

एक CSS वेरिएबल, पाँच रिव्यू राउंड, और एक Swift टूलचेन जिसने झूठ बोला

GeekBye v2.0.7 ने पूरे ओवरले को समायोज्य रूप से पारदर्शी बना दिया — जो सुनने में एक-लाइन का CSS बदलाव लगता है और बिलकुल नहीं था। असली कहानी वह है जो कोड रिव्यू ने पकड़ी: दो ऐसी सतहें जिन्होंने फ़ीके होने से इनकार कर दिया, एक रिकॉर्डिंग बार जो उसी opacity पर गलत दिखता था, और एक कंपाइल किया गया बाइनरी जो 672 बाइट इधर-उधर हिलता रहा क्योंकि हमारे अपने डॉक्स ने एक रिव्यूअर को गलत Swift वर्शन बता दिया।

इंजीनियरिंग
डिज़ाइन
बिल्ड
जब फ़ायरवॉल WebSocket को ब्लॉक कर दे, तब लाइव ट्रांसक्रिप्शन का क्या होता है
Steven
Steven6 मिनट पढ़ें

जब फ़ायरवॉल WebSocket को ब्लॉक कर दे, तब लाइव ट्रांसक्रिप्शन का क्या होता है

कॉर्पोरेट नेटवर्क HTTPS को तो जाने देना पसंद करते हैं, पर WebSocket upgrade को चुपचाप मार डालते हैं। इससे रियल-टाइम ट्रांसक्रिप्शन खामोशी से टूट जाती है। GeekBye v2.0.8 अपने आप एक प्योर-HTTPS ट्रांसपोर्ट पर fall back करता है — और इसे बनाते हुए एक ऐसा बग निकला जो पूरे फीचर को बेकार बना देता।

ट्रांसक्रिप्शन
नेटवर्किंग
इंजीनियरिंग