राउटर ही रजिस्ट्री है
Hanzo Cloud में कोई चेक-इन OpenAPI फ़ाइल नहीं है। जीवित मार्ग तालिका ही स्रोत है, तीन तरह से प्रक्षेपित, और यदि कोई प्रक्षेपण बहक जाए तो एकैकी आच्छादन परीक्षण बिल्ड को गिरा देता है। 963 पथों पर 1,362 संक्रियाएँ, अनुरोध के समय प्रत्येक प्रक्रिया के लिए उत्पन्न।

इस पृष्ठ पर
Hanzo Cloud भंडार में कोई openapi.yaml नहीं है। अंतबिंदुओं की दूसरी रजिस्ट्री नहीं, कोई टिप्पणी फ़ाइल नहीं, और CI में कोई जनरेटर चरण नहीं जो विनिर्देश को डिस्क पर लिखे। API क्या है यह जानना हो तो एक चलती प्रक्रिया से पूछो, वह अपना राउटर पढ़कर बताती है।
यह लेख इस बारे में है कि वही व्यवस्था अंत में टिकी क्यों रही, और उसके उन हिस्सों के बारे में जो काम नहीं करते, जो अधिक उपयोगी आधा निकलते हैं।
एक तालिका, तीन प्रक्षेपण
serve.go एक मार्ग तालिका बनाता है। फिर तीन चीज़ें उसे पढ़ती हैं, सब MountAll के बाद, ताकि प्रत्येक पूरी तालिका देखे:
/zapZAP परिवहन पर/v1हैंडलरों को फिर से चलाता है।- कंसोल उन्हें रेंडर करता है।
GET /v1/openapi.jsonउन्हें वर्णित करता है।
तीनों में से कोई किसी चीज़ की प्रति नहीं रखता। यही पूरा डिज़ाइन प्रतिबंध है, और बाकी सब इसी से निकलता है। जो प्रक्षेपण अंतबिंदुओं की अपनी सूची रखे वह सत्य का दूसरा स्रोत होगा, और सत्य का दूसरा स्रोत बहकता है, कभी-कभी नहीं, हमेशा, उस ताल के अनुसार जितनी बार कोई भूल जाता है।
वर्णन वाला प्रक्षेपण वही है जिसके बारे में लोग पूछते हैं, अतः: openapi.Live(app) app.Fiber().GetRoutes(true) को बुलाता है, और openapi/ में हर अन्य फलन लौटकर आने वाले []Route का शुद्ध फलन है। दस्तावेज़ राउटर से नहीं बनता। दस्तावेज़ ही राउटर है, दूसरे आकार में।
जीवित राउटर पढ़ना ही एकमात्र पूर्ण स्रोत क्यों है
स्पष्ट विकल्प स्रोत को स्कैन करना है। वह काम नहीं करता, और कारण ठीक कहने लायक है, क्योंकि यही कारण है कि बहुत से API औज़ार चुपचाप कम रिपोर्ट करते हैं।
POST /v1/kms/auth/login इस तरह पंजीकृत है:
Group("/v1/kms/auth").Post("/login")
कोई grep वह पथ नहीं ढूँढता। स्ट्रिंग /v1/kms/auth/login कोडबेस में मौजूद नहीं है। वह केवल जोड़े गए राउटर में, रनटाइम पर, तब होती है जब फ्रेमवर्क समूह उपसर्ग और पत्ती को जोड़ चुका होता है।
फिर बात और बिगड़ती है, उस ढंग से जो वास्तव में सही है। मार्गों का समूह परिनियोजन विन्यास का फलन है, cfg.Enabled, साथ ही KMS जैसे आंतरिक द्वार if kc != nil। जो परिनियोजन प्रशासन नहीं चढ़ाता वह प्रशासन मार्ग नहीं देता। इसलिए उस परिनियोजन का ईमानदार विनिर्देश उन्हें विज्ञापित नहीं करता।
इसीलिए दस्तावेज़ प्रत्येक प्रक्रिया के लिए, अनुरोध के समय बनता है, CI में एक बार बनने के बजाय। CI में बना विनिर्देश एक काल्पनिक अधिकतम परिनियोजन बताता है, जो शायद वही न हो जिससे आप बात कर रहे हैं। जीवित राउटर से पढ़ा विनिर्देश उस प्रक्रिया को बताता है जिसने आपको उत्तर दिया।
वह परीक्षण जो इसे सच बनाता है
ऐसी वास्तुकला जिसमें विनिर्देश बहक न सके एक दावा है, और दावों को द्वार चाहिए। हमारा एकैकी आच्छादन है, cmd/cloud/openapi_test.go में:
func TestSpecDoesNotDriftFromLiveRouter(t *testing.T) {
यह apps.Wire() में हर उपतंत्र चढ़ाता है, दस्तावेज़ बनाता है, और मानचित्रण दोनों ओर जाँचता है: हर जीवित मार्ग एक संक्रिया के रूप में आता है, और हर संक्रिया के पीछे एक जीवित मार्ग है। किसी भी दिशा में उपसमुच्चय नहीं।
आज चलाएँ:
bijection holds over 1362 operations / 963 paths / 138 products
यह भंडार का एकमात्र परीक्षण है जिसकी विफलता का अर्थ है कि प्रकाशित दस्तावेज़ झूठ बोल रहा है। बाकी जो टूटता है वह उत्पाद को गलत करता है; यह अनुबंध को गलत करता है, जो बदतर है, क्योंकि समाकलक पहले ही उसके विरुद्ध बन चुके हैं।
गिनती का हिलना समस्या नहीं है, वह हर बार हिलती है जब कोई उपतंत्र जुड़ता है। जो संख्या मायने रखती है वह दोनों पक्षों का अंतर है, और वह संख्या 0 है वरना बिल्ड गिरता है।
उत्पाद अक्ष यांत्रिक है
/v1/ के बाद पहला पथ खंड ही उत्पाद है। openapi.Product उसे पढ़ता है और प्रत्येक संक्रिया को उससे टैग करता है, जिससे CLI hanzo <product> <resource> <verb> बना सकता है, बिना किसी के यह निर्णय किए कि आदेश कहाँ रहना चाहिए।
यह जान-बूझकर उपतंत्र का नाम नहीं है। clients/billing /v1/finance/* भी देता है, और URL वही है जो कॉलर देखता है, इसलिए URL जीतता है। अक्ष का नाम आंतरिक पैकेज पर रखने से CLI एक संपादित कलाकृति बन जाता, जिसमें राय हों और जिसे कोई रखे, प्रक्षेपण के बजाय।
राउटर आपको क्या नहीं बता सकता
यह सीमा है, और हम इसके चारों ओर काम करने का इरादा नहीं रखते।
विधि, पथ, पथ प्राचल और उत्पाद राउटर से निकाले जा सकते हैं। अनुरोध और प्रतिक्रिया स्कीमा, क्वेरी और हेडर प्राचल, स्थिति कोड, और प्रमाणीकरण नहीं। राउटर एक func(*zip.Ctx) error रखता है। अनुरोध प्रकार हैंडलर के शरीर के अंदर एक स्थानीय चर है:
var req secretPutRequest
json.Unmarshal(ctx.Body(), &req)
Go किसी फलन मान से उसके शरीर में परावर्तित नहीं कर सकता। यहाँ कोई चतुर सुधार नहीं है, और जनरेटर में कोशिश का अर्थ अनुमान लगाना होगा, जिससे विनिर्देश में आत्मविश्वासी, गलत प्रविष्टियाँ आ जाती हैं।
स्कीमा तक एकमात्र रास्ता एक टाइप की हुई संक्रिया है:
zip.Get[In, Out](...)
In और Out पंजीकरण पर हैं, इसलिए स्कीमा किसी का मन पढ़े बिना उपलब्ध है। और क्योंकि वे पंजीकरण पर हैं, वही प्रविष्टि एक MCP औज़ार भी देती है। zip/openapi.go और zip/mcp.go एक रजिस्ट्री के दो पाठक हैं। यह चौथा प्रक्षेपण है, और यह चौथे तंत्र के बिना आया।
प्रवास रचना से क्रमिक है: GetRoutes(), app.ops का अधिसमुच्चय है, इसलिए हैंडलर को टाइप की हुई संक्रिया में बदलना स्कीमा जोड़ता है, उसके ऊपर कुछ बदले बिना।
वे मार्ग जिन्हें टाइप नहीं किया जा सकता, और क्यों
clients/integrations तार जितना अनुमति देता है उतना बदला गया है: 41 में से 20 मार्ग टाइप की हुई संक्रियाएँ हैं। शेष 21 कच्चे हैंडलर रहते हैं, और प्रत्येक ops_projection_test.go की rawRoutes तालिका में उस कारण के साथ है जिससे वह नहीं हिल सकता:
- 13 ब्राउज़र पुनर्निर्देश। OAuth कॉलबैक और हर लिंक टांग
302से उत्तर देते हैं। टाइप की हुई संक्रिया एक मान लौटाती है,Locationहेडर और 300 श्रेणी की स्थिति नहीं। - 6 वेबहुक। Slack और GitHub का HMAC, Discord का Ed25519, Teams Bot Framework का JWT, Telegram का गुप्त-टोकन हेडर। हर एक कच्चे अनुरोध बाइट पर हस्ताक्षर का प्रमाणीकरण करता है। टाइप की हुई संक्रिया डिकोड किया
Inपाती है और वे बाइट कभी नहीं देखती जिन पर हस्ताक्षर गिना गया, इसलिए इन्हें टाइप करना उनकी प्रमाणीकरण तोड़ देगा। - 2
202 Acceptedनिर्माता।cloud.Createdहमें 201 की सीवन देता है। 202 की सीवन नहीं है। दो मार्गों को एक चाहिए, इसलिए दो मार्ग प्रतीक्षा करते हैं।
हम समझते हैं कि वह सूची पूरे तंत्र की सबसे मूल्यवान कलाकृति है। यह ठीक वहीं की गिनी, परीक्षण से जड़ी सूची है जहाँ अमूर्तता रुकती है, हर प्रविष्टि पर एक कारण जिसे समीक्षक से बहस हो सकती है। यह उस विफलता को रोकती है जिसमें एक मार्ग चुपचाप कच्चे हैंडलर पर लौट जाए और दस्तावेज़, MCP औज़ार समूह, और CLI से एक साथ गायब हो जाए, अदृश्य रूप से, क्योंकि कुछ भी यह दावा नहीं कर रहा था कि वह वहाँ था।
वास्तुकला वे भाग नहीं है जो सामान्य होते हैं। वह वे भाग हैं जो सामान्य होते हैं, साथ ही उन भागों का ईमानदार, लागू लेखा जो नहीं होते।
इससे क्या मिलता है
Hanzo Cloud के विरुद्ध जुड़ने वाला कॉलर एक दस्तावेज़ पढ़ता है जिसे उन्हीं अनुरोधों का उत्तर देने वाली प्रक्रिया ने बनाया, उसी परिनियोजन में जिससे वे सच में बात कर रहे हैं, कुछ मिलीसेकंड पहले। MCP पर बुलाने वाला एजेंट उसी हैंडलर तक पहुँचता है, उसी किरायेदारी जाँच के साथ, जैसे REST कॉलर। एक अनाम /mcp कॉल को वही 403 मिलता है जो REST देता है, क्योंकि यह वही कोड पथ है और एक परीक्षण उसे जकड़ता है।
इसमें से किसी के लिए यह ज़रूरी नहीं था कि कोई कुछ फिर से उत्पन्न करना याद रखे।
सामान्य रूप: यदि दो कलाकृतियों को सहमत होना है, तो एक को दूसरे से उत्पन्न करके आशा न करो। एक को दूसरे का दृश्य बनाओ, और वह परीक्षण लिखो जो तब गिरे जब वे न हों।
और पढ़ें

Cloud-Native Commerce: Why Architecture Matters
How we built Crowdstart as a cloud-native platform from day one, and why this matters for commerce.

एजेंटिक एलएलएम के युग में हेडलेस कॉमर्स की तैयारी
खरीदार एजेंट बन रहे हैं। बिना मनुष्य के किसी एलएलएम के लिए पठनीय, हस्ताक्षर-योग्य और भुगतान-योग्य होने में क्या लगता है, और Hanzo आज उसके लिए क्या देता है।

Introducing Enso — one API, routed to the best frontier intelligence
Enso is Hanzo's learned router: no single frontier model leads every benchmark, so Enso routes each request to the model most likely to win it — and learns from your feedback as it goes. Microsecond routing on a CPU, a transparent per-request meter, and a 1% fee that pays for itself. Here is how it works, the measured results, and the cost-transparency angle a monolith cannot offer.