Zdůvodnění
Cesta je název a název zapsaný na dvou místech je název, který bude znamenat dvě věci. Tento repozitář za to už jednou zaplatil: Swagger UI bylo připojeno na /docs, protože zatím nic neobsluhovalo dokumentaci, a ve chvíli, kdy dokumentace přišla, byla zřejmá cesta zabrána. Nikdo nerozhodl, že prohlížeč API má vlastnit slovo „docs“; stalo se to proto, že mount byl konstanta v routeru a význam slova žil jen v hlavách lidí, kteří ten router četli.
project.interfaces-are-projections@1 už vyžaduje, aby se schopnost definovala jednou a z ní se odvozovalo každé rozhraní, a routy, které spustitelný soubor obsluhuje sám, se tím řídí. Co toto pravidlo nezasahuje, je druhá polovina webového povrchu — generované adresáře, publikovaný web, zprávy, které producent zapisuje — což nejsou schopnosti a každé z nich zvlášť znal router, publikační skript, model kontrol i dokumentace. Povrch přidaný tak, jak se přidávaly dřívější, stál registraci v každém z nich a registrace, na kterou člověk zapomene, není ta routerová, protože rozbitá routa se pozná za minutu. Je to ta dokumentační, a referenční přehled rout, který lže, se pozná, až když mu někdo uvěřil.
Topologie se proto rozlišuje, nevypisuje. Každý konzument čte totéž rozlišení, takže se plocha nemůže objevit v jedné projekci a chybět v jiné, a plocha odstraněná u svého producenta zmizí ze všech společně, místo aby zanechala položku navigace ukazující na cestu, která už neodpovídá.
Požadované chování
Povrch se deklaruje jednou, u svého producenta: routa, na kterou spustitelný soubor odpovídá, se deklaruje v capability!, který její modul už nese, generovaný adresář se deklaruje vedle svého výstupu a web aplikace se čte z vlastní konfigurace generátoru webu. Neexistuje žádný centrální manifest povrchů a rozřešený manifest zapsaný pro diagnostiku je jednorázový — nic jej nesmí číst jako pravdu, kterou nelze přepočítat.
Každá webová projekce se odvozuje z tohoto jednoho rozlišení. Router rozesílá tak, že se rozlišené topologie ptá, který povrch vlastní cestu požadavku, a nikdy tak, že by jmenoval povrch ve větvi match. Úvodní stránka na / se vykresluje z topologie, seskupená podle kategorie, kterou povrch deklaruje, a zúžená na povrchy označené pro člověka; odkaz na ní je mount, který byl rozlišen, nikdy cesta napsaná do šablony. Strojově čitelný index, publikovaný strom, generovaná reference cest na webu a cíle měření výkonu jsou projekce téže hodnoty. Ručně udržovaná tabulka cest — v Rustu, v šabloně, v Markdownu, v JSON, YAML nebo TOML — je vada bez ohledu na to, zda se právě shoduje.
Vlastnictví tras se validuje, nenechává se na pořadí vkládání. Plocha vlastní svůj mount a vše pod ním; dvě plochy si nesmějí nárokovat jednu cestu ve stejném světě; vnořený nárok je chyba, pokud ho vnější plocha nedeklaruje. Validace odmítá při konstrukci, dříve než proces obslouží požadavek, místo aby se projevila jako špatná odpověď uživateli. Registr popisuje spustitelný soubor, který běží: plocha, jejíž runtime schopnost tento build či toto volání nemá, chybí v topologii, a tedy na stránce a v indexu, místo aby byla inzerována a nefungovala.
Dva jmenné prostory nejvyšší úrovně jsou vyhrazeny a nelze je přeřadit. /docs je vlastní dokumentace tohoto repozitáře a nic jiného — nesmí být nikdy znovu přidělen Swagger UI ani jinému subsystému, kterému to slovo jen připadá pohodlné. /swagger je Swagger UI. /openapi.json se odvozuje z registru schopností a je to dokument, který Swagger UI čte. Přidání, odebrání nebo přejmenování povrchu je změna jeho deklarace a ničeho jiného; změna, která navíc vyžaduje úpravu stránky, tabulky nebo manifestu, znamená, že projekce, kterou upravuje, není odvozená, a je nutné ji takovou udělat.
Chování při selhání
majordomus web validate hlásí zjištění pro duplicitní mount v rámci jednoho světa, vnořené tvrzení, které vnější povrch nedeklaroval, neznámou kategorii nebo viditelnost a nativní povrch bez handleru; skončí s 10, je-li jakékoli zjištění chyba. Konstrukce routeru odmítá tytéž podmínky, místo aby nastartovala, a jmenuje povrchy, které kolidují.
Dvě rezervovaná jména se drží o krok dřív, protože validátor, který by běžel jen když se někdo rozhodne ho spustit, by byl slabší ochranou: přesunutí Swagger UI na /docs, zatímco ho dokumentace stále drží, je kolize připojení, kterou odmítne validátor i router, a přesunutí tam po odstranění dokumentace selže the_reserved_mounts_belong_to_the_surfaces_that_own_them v http/surfaces.rs a případ 89_web_surface, které ověřují připojení proti producentům, kteří je musí vlastnit. Jména vynucují testy, které nelze přeskočit, ne běhový nález. majordomus generate --check selže, když commitnutá projekce topologie pod docs/generated/ není tím, co registr nyní rozřešuje, a scripts/generate-site-data --check selže, když se odvozená kopie webu od ní rozešla — takže povrch přidaný bez regenerace je červené sestavení, ne zastaralá stránka.
Ověření
bash test/run.sh 89_web_surface, který zvenku spustitelného souboru dokazuje, že /swagger poskytuje Swagger UI, že /docs poskytuje dokumentaci, a ne prohlížeč, že sestavený mount dokumentace nepohltí své sousedy, že žádný path traversal z něj neunikne, že odkazy úvodní stránky a strojově čitelný index popisují tutéž množinu a že ani jedno vykreslení / nevytiskne, kde na hostiteli checkout leží.
majordomus web validate, spouštěný scripts/rust-check, drží invarianty topologie; vlastní sady crate pokrývají model a router, včetně řazení, které činí vlastnictví deterministickým, a odmítnutí při konstrukci. majordomus generate --check drží docs/generated/web.json aktuální a scripts/generate-site-data --check drží aktuální kopii na webu, takže povrch přidaný bez regenerace shodí build, a nestárne tiše na stránce.
Kontrola site-basepath v .ai/repo/ci/gates.yaml spouští scripts/site-basepath-check, která odmítne odkaz absolutní vůči originu ve zdroji dokumentace — jedinou věc, kvůli níž by publikovaný web a mount /docs potřebovaly různé zdroje.
/api/v1/web/surfaces odpovídá programu stejným vyřešením. Přes obsluhovaný socket odpovídá, co ten proces servíruje; z příkazového řádku odpovídá, co servíruje repozitář. Obojí čte jednu hodnotu vyřešenou jednou na proces a za žádným z nich není druhé objevování.