स्कोप
कुंजी को क्या करने की अनुमति है।
शब्दावली
एक बंद समुच्चय, resource:action। इतना छोटा कि किसी व्यक्ति को चेकबॉक्स सूची में दिखाया जा सके, और इतना स्थिर कि संग्रहित ग्रांट का अर्थ एक साल बाद भी वही रहे। यही शब्दावली वर्कस्पेस की भूमिका लिखने में इस्तेमाल होती है और यही MCP टूल्स को गेट करती है, इसलिए केवल-पढ़ने वाला क्लाइंट भेजने वाला टूल देख तक नहीं सकता। एक वर्णमाला, तीन सतहें।
| स्कोप | क्या देता है |
|---|---|
| emails:send | ईमेल भेजना |
| emails:read | भेजे गए संदेश और उनकी डिलीवरी स्थिति पढ़ना |
| drafts:read | ड्राफ़्ट पढ़ना |
| drafts:write | ड्राफ़्ट बनाना और संपादित करना |
| threads:read | थ्रेड और संदेश पढ़ना |
| threads:write | थ्रेड पर लेबल लगाना, उन्हें पढ़ा हुआ करना और आर्काइव करना |
| labels:read | लेबल पढ़ना |
| labels:write | लेबल बनाना और संपादित करना |
| contacts:read | संपर्क पढ़ना |
| contacts:write | संपर्क जोड़ना, संपादित करना और हटाना |
| audiences:read | ऑडियंस और उनमें कौन है, यह पढ़ना |
| audiences:write | ऑडियंस बनाना और संपादित करना, और बदलना कि उनमें कौन है |
| calendar:read | कैलेंडर इवेंट और आमंत्रण पढ़ना |
| calendar:write | कैलेंडर इवेंट बनाना, बदलना और उनका जवाब देना |
| templates:read | ईमेल टेम्पलेट पढ़ना और उनका प्रीव्यू देखना |
| templates:write | ईमेल टेम्पलेट बनाना, संपादित करना और उनसे भेजना |
| domains:read | डोमेन और उनकी DNS स्थिति पढ़ना |
| domains:write | डोमेन सत्यापित और कॉन्फ़िगर करना |
| webhooks:read | webhook एंडपॉइंट और डिलीवरी पढ़ना |
| webhooks:write | webhooks बनाना, संपादित करना और जाँचना |
| rules:read | मेल नियम पढ़ना और उन्हें जाँचना |
| rules:write | मेल नियम बनाना, संपादित करना और पुनःक्रमित करना |
| connections:read | कौन-से मेलबॉक्स जुड़े हैं, यह पढ़ना |
| members:read | देखना कि वर्कस्पेस में कौन है और वे क्या रखते हैं |
| members:write | लोगों को जोड़ना और हटाना, और बदलना कि वे किन तक पहुँच सकते हैं |
| roles:read | यह वर्कस्पेस जो भूमिकाएँ परिभाषित करता है उन्हें पढ़ना |
| roles:write | भूमिकाएँ बनाना, संपादित करना और हटाना |
| settings:read | मेलबॉक्स सेटिंग्स पढ़ना, हस्ताक्षर सहित |
| settings:write | मेलबॉक्स सेटिंग्स और हस्ताक्षर बदलना |
| keys:write | बिना किसी के कंसोल खोले अपना ही सीक्रेट बदलना |
बिना सोची-समझी स्कोप सूची के बनी कुंजी को emails:send मिलता है और कुछ नहीं। किसी क्रेडेंशियल के लिए सुरक्षित डिफ़ॉल्ट वही सबसे संकरी चीज़ है जो उसे उपयोगी बनाती है।
कुंजी उसके पीछे की भूमिका से सीमित होती है
कुंजी किसी भूमिका के विरुद्ध जारी की जा सकती है, और भूमिका दूसरा ग्रांट नहीं, एक सीमा है। कुंजी असल में क्या कर सकती है, यह उसके अपने स्कोप और उस भूमिका की अनुमतियों का प्रतिच्छेदन है (key.scopes ∩ role.permissions), जो हर अनुरोध पर, किसी भी एंडपॉइंट तक पहुँचने से पहले, सीमा पर एक बार निकाला जाता है। आगे किसी को यह पता ही नहीं कि भूमिकाएँ हैं: जो स्कोप भूमिका नहीं रखती वह बस उस सूची में नहीं होता जिसे स्कोप-जाँचें पढ़ती हैं।
इसलिए दोनों सूचियाँ साथ पढ़ी जाती हैं और अकेले कोई नहीं जीतती। emails:send रखने वाली कुंजी ऐसी भूमिका के नीचे नहीं भेज सकती जो वह नहीं रखती; और emails:send रखने वाली भूमिका उस कुंजी को कुछ नहीं देती जिसने वह कभी माँगा ही नहीं। स्कोप पर टिक लगाना अधिकार माँगना है, और भूमिका तय करती है कि माँगे हुए में से कितना आपको मिलेगा।
जिस कुंजी की कोई भूमिका नहीं, उसकी कोई सीमा नहीं, और इसलिए वह उतनी ही चौड़ी है जितना वह वर्कस्पेस जिसके विरुद्ध वह जारी हुई। भूमिकाओं से पहले बनी हर कुंजी यही लिए है, और मालिक को भी वही मिलता है अगर वह फ़ील्ड छोड़ दे — इसलिए null भूमिका कुंजी की सबसे संकरी नहीं, सबसे चौड़ी अवस्था है। यही वजह है कि भूमिका हटाते समय आपसे पूछा जाता है कि उसकी कुंजियाँ कहाँ जाएँ: उन्हें अनाथ छोड़ना चुपचाप उन सबको पदोन्नत कर देता।
प्रतिच्छेदन जारी करते समय कुंजी पर छाप नहीं दिया जाता, हर अनुरोध पर हल होता है। इससे भूमिका संकरी करना एक जीवंत निरस्तीकरण बन जाता है, जो कुंजी घुमाए बिना कॉल करने वाले के अगले कॉल पर लागू होता है, और चौड़ी करना भी ठीक उसी तरह जीवंत है — और यही आधा हिस्सा याद रखने लायक है।
GET /ping और GET /keys/self एक खास विफलता के लिए grantedScopes और roleId के साथ scopes भी बताते हैं। scopes प्रभावी सूची है और केवल वही किसी चीज़ को अधिकृत करती है; grantedScopes वह है जिसके साथ कुंजी जारी हुई थी। जो दूसरी में है और पहली में नहीं, वह भूमिका ने ले लिया — और यही अंतर “मेरी कुंजी पर emails:send है और मुझे insufficient_scope मिल रहा है” का पूरा जवाब है। समाधान दूसरी कुंजी नहीं, भूमिका में बदलाव है।
curl "$OE/ping" -H "$AUTH" { "ok": true, "keyId": "4c1b257a66287fd113bd89d0", "mode": "live", "scopes": ["emails:read", "threads:read"], "roleId": "role_c40a95f21cc65d31c2a89e07", "grantedScopes": ["emails:send", "emails:read", "threads:read"], "workspaceId": "10417196-e324-4283-af98-66ec62167c47"}पाँच अनुमतियाँ किसी कुंजी तक कभी पहुँच ही नहीं सकतीं: api-keys:read, api-keys:write, billing:read, billing:write और workspace:manage। वे अनुमतियाँ हैं पर स्कोप नहीं, इसलिए कोई भी भूमिका चाहे कितनी उदार हो, उन्हें टोकन पर नहीं डाल सकती: दूसरी कुंजी बनाना, यह बदलना कि दूसरी कुंजी क्या कर सकती है, या प्लान बदलना — ये केवल साइन-इन किया व्यक्ति ही करता है। कुंजी अपने साथ जो एक चीज़ कर सकती है वह है अपना सीक्रेट बदलना, keys:write स्कोप के पीछे। GET /roles/permissions उन पाँच को scope: false से चिह्नित करता है, और इसी से एक ही कंपोनेंट भूमिका-मैट्रिक्स और कुंजी-निर्माण की चेकबॉक्स सूची दोनों रेंडर कर पाता है।
roles:write असल में पूरी शब्दावली के बराबर है, और इसके उलट दिखाना और ख़तरनाक दस्तावेज़ीकरण होता। उसे रखने वाली कुंजी उसी भूमिका को PATCH कर सकती है जो उसे सीमित करती है और खुद को बाकी सब दे सकती है, और चूँकि सीमा हर अनुरोध पर हल होती है, चौड़ी सीमा अगले ही कॉल पर लागू हो जाती है। यह भरने लायक छेद नहीं है, क्योंकि जो भूमिका-संपादक भूमिकाएँ संपादित न कर सके वह भूमिका-संपादक है ही नहीं। यह इस बात का कारण है कि roles:write उस कुंजी पर न डालें जिसे कभी बस सदस्य-सूची पढ़नी थी।
भेजने का स्कोप
स्कोप से अलग, कुंजी को इस बात में भी सीमित किया जा सकता है कि वह किसके रूप में भेज सकती है। वह दो सूचियाँ रखती है। domainAllowlist में पूरे डोमेन होते हैं, और डोमेन रखने वाली कुंजी उस पर मौजूद किसी भी पते के रूप में भेज सकती है, उन पतों के रूप में भी जो कुंजी के बाद बने। addressAllowlist में अकेले पते होते हैं। दोनों खाली छोड़ दें और कुंजी उतनी ही चौड़ी है जितना वर्कस्पेस, उससे ज़्यादा कभी नहीं। GET /keys/self दोनों सूचियाँ दिखाता है और GET /addresses बताता है कि दी गई कुंजी असल में क्या इस्तेमाल कर सकती है — और यही अस्पष्ट from_address_forbidden का जवाब है।
वही समुच्चय यह भी सीमित करता है कि कुंजी क्या पढ़ती है। भेजी गई मेल, ट्रैकिंग और कैलेंडर केवल उन्हीं पतों के लिए जवाब देते हैं जिनके रूप में कुंजी भेज सकती है, इसलिए एक डोमेन तक सीमित कुंजी न किसी दूसरे की ओर से भेजती है और न पढ़ती है। पूरा डोमेन कुंजी को उस डोमेन का ट्रैकिंग होस्ट सेट करने भी देता है, जो अकेले पतों तक सीमित कुंजी नहीं कर सकती।
तो तीन सीमाएँ हुईं, और वे एक-दूसरे को रद्द करने के बजाय जुड़ती हैं: कुंजी पर मौजूद स्कोप, उसके ऊपर की भूमिका की अनुमतियाँ, और वे डोमेन तथा पते जिन्हें वह From header में डाल सकती है। भेजने के लिए तीनों चाहिए, और अस्वीकरण केवल उसी का नाम लेता है जो पहले मिला।