2 पॉइंट द्वारा GN⁺ 2026-01-15 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • GitHub API का उपयोग करते समय PR comment link generation feature में ID mismatch की वजह से लिंक काम नहीं करने की समस्या सामने आई
  • जांच में पता चला कि GitHub GraphQL के node ID और REST API के database ID नाम की दो अलग ID systems को साथ-साथ इस्तेमाल करता है
  • node ID को base64 decode करने पर यह पुष्टि हुई कि उसके निचले 32-bit में database ID शामिल है, इसलिए एक सरल bitmask operation से इसे बदला जा सकता है
  • अतिरिक्त विश्लेषण से यह भी सामने आया कि GitHub MessagePack-आधारित नए ID format और string-आधारित legacy format को मिलाकर इस्तेमाल कर रहा है
  • यह संरचना GitHub के आंतरिक object identification system की द्वैधता को दिखाती है, और developers को API integration के समय सावधान रहने की जरूरत है

GitHub की दोहरी ID system की खोज

  • Greptile के AI code review tool feature को विकसित करते समय GitHub PR comment links के काम न करने की समस्या आई
    • saved comment ID को URL में जोड़ा गया, लेकिन click करने पर GitHub page पर नहीं गया
  • GitHub docs देखने पर पता चला कि GraphQL API का node ID और REST API का database ID अलग-अलग systems में मौजूद हैं
    • node ID उदाहरण: PRRC_kwDOL4aMSs6Tkzl8
    • database ID उदाहरण: 2475899260
  • node ID, GitHub भर में objects को globally identify करने के लिए इस्तेमाल होने वाली base64-encoded string है, जबकि database ID integer URL identifier के रूप में उपयोग होती है

node ID और database ID के संबंध का विश्लेषण

  • कई PR comments के node ID और database ID की तुलना करने पर पता चला कि दोनों values एक निश्चित अंतराल के साथ बढ़ती हैं
  • node ID के base64 हिस्से को decode करने पर 96-bit integer बना, और इस value के निचले 32-bit database ID से मेल खाते थे
    • उदाहरण: PRRC_kwDOL4aMSs6Tkzl8 → निचले 32-bit = 2475899260
  • एक सरल bitmask operation से database ID निकाली जा सकती है
    • decoded & ((1 << 32) - 1) जैसे operation से conversion किया जा सकता है

GitHub का legacy ID format

  • पुराने repository (torvalds/linux) के node ID को decode करने पर अलग format की string दिखाई दी
    • उदाहरण: MDEwOlJlcG9zaXRvcnkyMzI1Mjk4010:Repository2325298
  • इस format की संरचना [object type number]:[object name][Database ID] है, यानी यह स्पष्ट string-based identifier है
  • tree object के मामले में 04:Tree2325298:7201bfb9... जैसा रूप मिलता है, जिसमें repository ID और SHA value दोनों शामिल होते हैं
  • GitHub legacy format और नए format दोनों का समानांतर उपयोग कर रहा है, और object type व creation time के अनुसार format बदलता है

नए node ID format की संरचना

  • GitHub की GraphQL migration guide साफ कहती है कि node ID को opaque string की तरह मानना चाहिए, लेकिन इसकी आंतरिक संरचना मौजूद है
  • base64 decode करने के बाद MessagePack से unpack करने पर array रूप में data दिखाई देता है
    • उदाहरण: [0, 47954445, 2475899260]
  • array की संरचना
    • पहला element (0): version identifier होने का अनुमान
    • दूसरा element (47954445): repository का database ID
    • तीसरा element (2475899260): object का database ID
  • object type के अनुसार array की length अलग होती है, और commit में SHA शामिल होता है, जबकि repository में सिर्फ दो elements होते हैं

व्यावहारिक उपयोग और निष्कर्ष

  • नए node ID से database ID निकालने वाले Python code का उदाहरण
    import base64, msgpack
    def node_id_to_database_id(node_id):
        prefix, encoded = node_id.split('_')
        packed = base64.b64decode(encoded)
        array = msgpack.unpackb(packed)
        return array[-1]
    
  • इस तरीके से PR comment का database ID सीधे निकालकर URL link की समस्या हल की जा सकती है
  • GitHub फिलहाल MessagePack-आधारित नए ID system और string-based legacy system दोनों को एक साथ बनाए हुए है
  • यह संरचना GitHub के आंतरिक transition process और compatibility बनाए रखने के प्रयास को दिखाती है, और API इस्तेमाल करने वाले developers को ID format के अंतर पर ध्यान देना चाहिए

1 टिप्पणियां

 
GN⁺ 2026-01-15
Hacker News टिप्पणियाँ
  • नवीनतम GitHub global node ID को 'X-Github-Next-Global-ID' हेडर के ज़रिए जबरन इस्तेमाल कराया जा सकता है
    ID, ऑब्जेक्ट के type prefix और base64-encoded msgpack payload से मिलकर बनता है
    उदाहरण के लिए मेरा user ID "U_kgDOAAhEkg" [0, 541842] में decode होता है, जो REST API के databaseId से मेल खाता है
    लेकिन ऐसी internal implementation पर निर्भर न करें; GraphQL API के databaseId फ़ील्ड को सीधे query करना बेहतर है
    संबंधित दस्तावेज़: GraphQL global node ID migration guide, मेरी GitHub user जानकारी, CyberChef decoding उदाहरण, GitHub ETag implementation

  • इस तरह decode करना नाज़ुक लगता है
    GraphQL का global node ID मूल रूप से opaque होना चाहिए
    GitHub के कई types (PullRequest आदि) databaseId फ़ील्ड देते हैं, इसलिए वही इस्तेमाल करना सही है
    ज़्यादातर GraphQL APIs type name और DB ID को base64 में encode करती हैं, लेकिन यह नियम हमेशा बना रहेगा इसकी गारंटी नहीं है
    संदर्भ: PullRequest object docs, GraphQL global ID spec

    • GitHub के GraphQL types में permalink, url जैसे फ़ील्ड और UniformResourceLocatable interface मौजूद हैं, इसलिए URL को खुद बनाने की ज़रूरत नहीं है
    • ऐसी internal structure के समय के साथ टूटने की संभावना बहुत अधिक है
      इसी वजह से API permalink देता है। ID या link pattern कभी भी बदल सकते हैं
    • अगर identifier में metadata रखना है, तो users को internal structure पर निर्भर होने से रोकने के लिए उसे encrypt करना बेहतर है
      pagination token में भी यह तरीका अक्सर इस्तेमाल होता है
  • 010:Repository2325298 जैसी ID की संरचना साफ़ दिखती है
    010 type enum है, Repository नाम है, और 2325298 DB ID है
    यानी यह length prefix जैसा रूप है। Repository 10 अक्षरों का है, Tree 4 का

    • इससे BitTorrent protocol याद आता है
    • यह लगभग URN जैसा दिखता है
  • Opus 4.5 को यह GitHub ID decoding trick पता है, और यह अपने-आप decoding code लिख देता है

  • लेखक ने जो पाया है वह तकनीकी रूप से सही है, लेकिन documented नहीं है और supported भी नहीं है
    GitHub पहले भी node ID की internal structure को चुपचाप बदल चुका है
    अगर वे MessagePack array में field जोड़ दें, encoding बदल दें, encrypt कर दें, या UUID-आधारित format पर चले जाएँ,
    तो ऐसी internal structure पर निर्भर सिस्टम तुरंत टूट जाएगा

  • मैं जिन GitHub identifiers को स्पष्ट रूप से store करता हूँ, वे ज़्यादातर immutable URL keys (issue/PR नंबर या commit hash) होते हैं
    comment ID को JSON blob के अंदर वैसे ही रख देता हूँ
    हर चीज़ को normalize करने की ज़रूरत नहीं होती। JSON काफ़ी तेज़ है
    जब तक आप comment स्तर पर cross-query नहीं कर रहे, performance समस्या बनने की संभावना बहुत कम है

    • लेकिन issue/PR URL immutable नहीं होता
      अगर repository का नाम बदल जाए या उसे किसी दूसरी organization में move कर दिया जाए, तो URL बदल सकता है
  • पुराने v3 API में ID नहीं थी, इसलिए अगर कोई username या repository name बदल देता था, तो यह ट्रैक करना मुश्किल हो जाता था कि वह कौन है
    इसलिए मैंने team-स्तरीय ownership management system खुद बनाया
    Terraform provider अच्छा नहीं था, इसलिए offboarding के समय “जो एकमात्र admin था वही चला गया” जैसी समस्याएँ बार-बार आती थीं
    हर repository किसी team की ownership में होती है, और access permission भी सिर्फ़ team स्तर पर दी जाती है

    • “user को access देना” की बजाय “team को permission दो, और user उस team का member है” वाला सोचने का तरीका कहीं अधिक असरदार है
      ऐसा team-based access control सिर्फ़ GitHub ही नहीं, दूसरे systems में भी उपयोगी है
  • यह Hyrum’s Law का क्लासिक मामला है — जैसे ही लोग undocumented behavior पर निर्भर होने लगते हैं, वह अंततः टूटता ही है

  • database design में आमतौर पर बाहर की दुनिया को opaque natural key दी जाती है, और अंदर incrementing integer ID इस्तेमाल होती है

    • इसके दो कारण होते हैं
      1. बाहर से object count उजागर न हो
      2. सिर्फ़ ID बढ़ाकर सभी objects को enumerate न किया जा सके
        लेकिन composite ID इस्तेमाल करने पर यह समस्या कुछ कम हो जाती है
        उदाहरण के लिए अगर repository ID के भीतर object ID शामिल हो, तो ID बढ़ाने पर भी उसी repository के objects ही explore किए जा सकेंगे
        इसमें entropy या timestamp मिला दिया जाए तो दुरुपयोग लगभग असंभव हो जाता है
    • लेकिन natural key बदल सकती है
      इसलिए अर्थहीन surrogate key को expose करना ज़्यादा सुरक्षित है
      उदाहरण के लिए YouTube अंदरूनी तौर पर index number इस्तेमाल करे, फिर भी बाहर की दुनिया को अर्थहीन code-आधारित ID देता है
  • अब समझ आता है कि पिछले कुछ वर्षों में GitHub team ने Rails में sharded/multi-database support को इतना क्यों बढ़ाया है