เราเตอร์คือรีจิสทรี
Hanzo Cloud ไม่มีไฟล์ OpenAPI ที่เช็คอินไว้ ตารางเส้นทางที่กำลังทำงานคือแหล่งที่มา ถูกฉายสามทาง และการทดสอบการสมนัยสองทางทำให้บิลด์ล้มถ้าภาพฉายใดเลื่อน 1,362 การดำเนินการบน 963 เส้นทาง สร้างต่อโปรเซสในเวลาที่มีคำขอ

ในหน้านี้
ไม่มี openapi.yaml ในที่เก็บของ Hanzo Cloud ไม่มีรีจิสทรีที่สองที่ไล่จุดปลาย ไม่มีไฟล์คำอธิบายประกอบ และไม่มีขั้นตัวสร้างใน CI ที่เขียนสเปกลงดิสก์ ถ้าอยากรู้ว่า API คืออะไร ให้ถามโปรเซสที่กำลังรัน มันจะบอกโดยอ่านเราเตอร์ของตัวเอง
บทความนี้ว่าด้วยเหตุที่การจัดแบบนั้นลงเอยเป็นแบบเดียวที่อยู่ได้ และส่วนของมันที่ทำงานไม่ได้ ซึ่งกลายเป็นครึ่งที่มีประโยชน์กว่า
ตารางเดียว สามภาพฉาย
serve.go ประกอบตารางเส้นทางหนึ่งตาราง สามสิ่งจึงอ่านมัน ทั้งหมดอยู่หลัง MountAll เพื่อให้แต่ละสิ่งเห็นตารางที่ครบ:
/zapเล่นซ้ำ ตัวจัดการของ/v1บนการขนส่ง ZAP- คอนโซล เรนเดอร์ พวกมัน
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 บวกเกตภายในอย่าง if kc != nil ของ KMS การนำขึ้นระบบที่ไม่เมานต์ส่วนแอดมินจะไม่เสิร์ฟเส้นทางแอดมิน ดังนั้นสเปกที่ซื่อตรงของการนำขึ้นระบบนั้นจึงไม่โฆษณาพวกมัน
นี่คือเหตุที่เอกสารถูกสร้างต่อโปรเซส ในเวลาที่มีคำขอ แทนที่จะสร้างครั้งเดียวใน 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 ถูกแปลงเท่าที่สายอนุญาต 20 จาก 41 เส้นทางเป็นการดำเนินการที่มีชนิด อีก 21 ยังเป็นตัวจัดการดิบ และแต่ละรายการอยู่ในแผนที่ rawRoutes ใน ops_projection_test.go พร้อมเหตุที่ขยับไม่ได้:
- การเปลี่ยนทางเบราว์เซอร์ 13 รายการ คอลแบ็ก OAuth และทุกขาลิงก์ตอบ
302การดำเนินการที่มีชนิดคืนค่า ไม่ใช่เฮดเดอร์Locationและสถานะในช่วง 300 - เว็บฮุก 6 รายการ HMAC ของ Slack และ GitHub, Ed25519 ของ Discord, JWT ของ Teams Bot Framework, เฮดเดอร์โทเคนลับของ Telegram ทุกตัวยืนยันลายเซ็นบน ไบต์ดิบของคำขอ การดำเนินการที่มีชนิดได้รับ
Inที่ถอดรหัสแล้ว และไม่เคยเห็นไบต์ที่ลายเซ็นถูกคำนวณทับ ดังนั้นการให้ชนิดพวกนี้จะทำลายการยืนยันตัว - ผู้สร้าง
202 Acceptedจำนวน 2cloud.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.