mesh
Mesh tohoto procesu: objevování (discovery) — ověřená pozorování dalších běžících instancí Majordomus v jednom registru — a spolupráce (cooperation) — ověřená spojení s důvěryhodnými runtime téhož repozitáře, která replikují relace, tvrzení, předávky a revize jedním žurnálem, jejž každý runtime skládá do stejného stavu. Objevení nic neuděluje; spojení se připouští po jednotlivých peerech a nic, co peer pošle, tu nic nespustí.
Mesh na první pohled
Zda mesh v tomto procesu běží a proč neběží, když neběží; veřejná identita tohoto uzlu; každý discovery provider s jeho stavem a čítači; součty registru; a odmítnuté datagramy podle důvodu. Jediný stav, který ukazuje každý povrch.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh
- Zdroj MCP {"name": "mesh", "uri": "majordomus://mesh"}
Žádné parametry.
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
MeshStatus |
Mesh na první pohled: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Claim rozsahu napříč meshem
Nárokuje cesty repozitáře pro relaci. Výhradní claim, který narazí na živý výhradní claim jiné relace — na tomto runtime nebo na kterémkoli runtime, které tento slyšel — je odmítnut jako `claim_conflict` s claimy, na které narazil; poradní claim se zaznamená a jeho překryvy se nahlásí. Claim žije, dokud je jeho relace otevřená a jeho runtime tepe: claim zhavarovaného držitele sám všude vyprší. Zapisuje jen žurnál tohoto runtime.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_claim
Tělo požadavku — ClaimInput, JSON
příklad exclusive
{"session":"bench","scope":["docs"]}Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/claims" -H "content-type: application/json" -d '{"session":"bench","scope":["docs"]}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Vyhradit rozsah napříč mesh: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Uvolnit claim
Uvolní claim, který drží aktuální běh tohoto runtime, podle jeho klíče. Claim zapsaný jinde je odmítnut jako `not_own`: uvolnit ho smí jen jeho držitel a claim mrtvého držitele místo toho vyprší. Zapisuje jen žurnál tohoto runtime.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- nástroj MCP majordomus_mesh_release
příklad unknown
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/claims/release" -H "content-type: application/json" -d '{"claim":"none/c-0"}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Uvolnění nároku: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Spolupráce na první pohled
Zda tento runtime spolupracuje a proč ne, když nespolupracuje: jeho runtime a proud, identita repozitáře, podle níž se odkazy párují, protokol a funkce odkazu, heartbeat a vypršení, každý propojený peer se stavem odkazu, poslední výměnou, round trip a selháními, každý odmítnutý kandidát s pravidlem, které jej odmítlo, a počitadla handshaků, synchronizací, opětovných připojení, vypršení, replikovaných a odmítnutých událostí.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- Nástroj MCP majordomus_mesh_cooperation
Žádné parametry.
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/cooperation"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
CooperationStatus |
Kooperace v kostce: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Sebekontrola mesh
Každý předpoklad ověřený samotným tímto strojem — deklarace se parsuje, identita se načte a pod allowlistem je na něm, repozitář má identitu meshe, naváže se UDP socket, připojí se multicastová skupina, povolí se broadcast a protokoly discovery a linku podepisují a ověřují od začátku do konce v paměti — a pak vlastní verdikt serveru: ve sdíleném serveru, zda povolená deklarace skutečně aktivovala mesh a, když ne, důvod serveru, který zprávu shodí. Každá neúspěšná kontrola jmenuje svůj dopad a nápravu. Deterministické, druhý uzel není potřeba.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh_doctor
- $ mesh doctor
Žádné parametry.
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/doctor"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
MeshDoctorReport |
Meshová autokontrola: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Žurnál spolupráce
Události žurnálu nad Lamportovým razítkem, v Lamportově pořadí, nejvýše jedna stránka: každá se svým streamem, sekvencí, razítkem, repozitářem, podpisovým klíčem, druhem a tělem. Lamport odpovědi je `after` další stránky.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh_events
Parametry dotazu
| název | typ | povinné | popis | příklady |
| po |
integer (uint64) |
ne |
Pouze události, jejichž Lamportovo razítko je vyšší než toto. |
|
| limit |
integer (uint64) |
ne |
Nejvýše tolik (výchozí 100, nejvýše 1000). |
výchozí: 100 |
| nejnovější |
boolean |
ne |
Nejnovějších `limit` událostí nad `after` místo prvních: o co žádá čtenář, který chce žurnál tak, jak stojí nyní. Stále v pořadí Lamport a `lamport` je pak nejnovější razítko, které žurnál drží, takže navázání za ním čte jen to, co přijde dál. Bez toho se žurnál čte dopředu od `after`, po stránkách. |
|
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/events?limit=100"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
EventList |
Žurnál spolupráce: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Firewall hostitele, jak ho mesh potřebuje
Jaký příchozí provoz deklarace implikuje, že tento stroj musí přijmout — port multicastové skupiny, port broadcastu, je-li povoleným záložním řešením, každý deklarovaný port hubu, jehož adresa je adresou tohoto stroje, a vlastní port serveru, když naslouchá mimo loopback — z privátních sítí, které deklarace jmenuje; jakou frontu firewallu tento host provozuje (ufw, nftables, aplikační firewall macOS); příkazy, které plán tam povolí; co o plánu nyní říká sám firewall (present, missing, inactive nebo bez root nepozorovatelný); a co jádro za posledních pět minut zalogovalo jako zahozené směrem k těmto portům. Selže, když je pozorováno chybějící pravidlo nebo byl zalogován drop. Čte hosta; nic nemění.
- query
- experimentální
- měření výkonu prominuto: external_dependency
- cache vypnuta
- Nástroj MCP majordomus_mesh_firewall
- $ mesh firewall
Parametry dotazu
| název | typ | povinné | popis | příklady |
| port |
celé číslo (uint16) |
ne |
Port, na kterém server tohoto checkoutu naslouchá mimo loopback, když naslouchá: peer ho tam volá protokolem spojení, takže ho je třeba také připustit. Vynecháno, plán drží porty zjišťování a porty hubů, které deklarace tomuto stroji dává. |
|
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/firewall"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
FirewallReport |
Firewall hostitele, jak jej mesh potřebuje: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Publikovat předávku do meshe
Publikovat záznam předávky tohoto checkoutu — nejnovější, nebo pojmenovaný pod .ai/local/state/handovers/ — na každý propojený runtime: jeho úloha, větev, head a čas z front matter, zadaný úkol a milník a jeho tělo v Markdownu, omezené a identifikované digestem těla. Žádná cesta tohoto stroje necestuje a nikdy se nečte žádný soubor mimo adresář předávek.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- nástroj MCP majordomus_mesh_handover_publish
příklad latest
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/handovers" -H "content-type: application/json" -d '{}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Publikovat předávku na mesh: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Převzetí předávky z meshe
Převezme předávku, kterou publikoval jiný runtime: zaznamená převzetí na meshi a zapíše ji do adresáře předávek tohoto checkoutu jako záznam, který `majordomus handover --resolve` najde na téže branchi — jednou, bez ohledu na to, kolikrát se převezme.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_handover_consume
příklad unknown
{"handover":"00000000000000000000000000000000","session":"bench","materialize":false}Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/handovers/consume" -H "content-type: application/json" -d '{"handover":"00000000000000000000000000000000","session":"bench","materialize":false}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
ConsumeAnswer |
Převzetí předávky z meshe: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Identita uzlu tohoto stroje
Identita uzlu uložená pod stavovým adresářem uživatele, jen veřejná polovina: id uzlu, veřejný klíč, zobrazované jméno. Podpisový klíč se neobjevuje v žádné projekci. Nepřítomnost je odpověď, ne chyba — identita se vytvoří, když se mesh poprvé aktivuje.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- Nástroj MCP majordomus_mesh_identity
- $ mesh identity
Žádné parametry.
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/identity"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
MeshIdentityReport |
Identita uzlu tohoto stroje: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Otevřít odkaz (handshake)
Handshake linku, který zasílá jiný runtime: podepsané hello nesoucí jeho kartu runtime, čerstvý nonce a jeho rozsah protokolu. Odmítnuto, typovaně, když je poškozené, příliš velké, špatně podepsané, zastaralé, přehrané, nepodporovaného protokolu, jiného repozitáře, nedůvěryhodné nebo je to tento runtime sám; jinak odpovězeno podepsaným welcome: karta tohoto runtime, id linku, jeho značky a zopakovaný nonce. Mění jen tabulku linků tohoto procesu.
- command
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
Tělo požadavku — podepsané, JSON
příklad malformed
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/link/hello" -H "content-type: application/json" -d '{"body":{},"sig":""}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
LinkReply |
Otevřít spojení (handshake): výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Jedno kolo synchronizace spojení
Replikační kolo, které propojený runtime posílá při každém heartbeatu, podepsané pod jeho id odkazu s rostoucím čítačem: jeho značky a události, které tomuto runtime chybí. Přijme se — ověří od začátku do konce, deduplikuje, aplikuje v pořadí streamu — a odpoví se podepsaně se značkami tohoto runtime a událostmi, které chybí peerovi. Neznámému odkazu nebo restartovanému peerovi se řekne, aby pozdravil znovu.
- command
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
Tělo požadavku — podepsané, JSON
příklad malformed
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/link/sync" -H "content-type: application/json" -d '{"body":{},"sig":""}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
LinkReply |
Jedno kolo synchronizace spojení: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Objevené uzly
Každý runtime, který tento proces pozoroval, jeden záznam na uzel a slot runtime, deduplikovaný napříč všemi zdroji zjišťování, v pořadí podle id uzlu: identita, důvěra, přítomnost, koncové body, schopnosti, repozitáře, původ a verze. V paměti, zaniká s procesem.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh_nodes
Žádné parametry.
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/nodes"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
NodeList |
Objevené uzly: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Jeden runtime
Jeden runtime podle klíče (`<node>-<runtime>`, nebo id uzlu pro jeho první runtime): stroj, na kterém běží, jeho živost, jeho linka odsud, jeho relace a claimy a každé odmítnutí zaznamenané proti němu. Nenalezeno je odpověď s důvodem.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh_peer
Parametry dotazu
| název | typ | povinné | popis | příklady |
| runtime |
string |
ano |
Runtime, `<node>-<runtime>` (samotné id uzlu odpovídá jeho prvnímu runtime). |
unknown: "0000000000000000000000000000000000000000000000000" |
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/peer?runtime=0000000000000000000000000000000000000000000000000"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
PeerDetail |
Jeden runtime: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Kdo spolupracuje, stroj po stroji
Stroj → runtime → relace → claim: každý runtime, s nímž je tento propojen nebo který slyšel přes žurnál, seskupený podle stroje, lokální první; každý runtime s jeho živostí, milisekundami od vzestupu jeho tepu, jeho spojením a jeho nejnovějším živým claimem. Výchozí pohled `summary` vypisuje jen aktivní relace, každou s počtem jejích živých claimů a zkráceným záměrem; `view=full` vypisuje každou relaci s každým claimem. `session` a `runtime` zúží kterýkoli z nich. Vzdálené i lokální runtime sdílejí jeden tvar a digest celého složení uzavírá odpověď: stejné digesty, stejný stav.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- Nástroj MCP majordomus_mesh_peers
Parametry dotazu
| název | typ | povinné | popis | příklady |
| pohled |
MeshView | null |
ne |
`summary` (výchozí) nebo `full`. |
full: "full" |
| tvrzení |
MeshClaimFilter | null |
ne |
`all` (výchozí) nebo `live`: zda se ukončené claimy uchovávají. |
|
| po |
integer (uint64) |
ne |
Pouze relace, claimy a předávky, jejichž poslední Lamportovo razítko je nad touto hodnotou. Review a překryvy nenesou vlastní razítko a ponechají se nebo vyřadí spolu se svými relacemi. |
|
| session |
string |
ne |
Jen to, co patří této relaci: její klíč (`<stream>/<session>`) nebo holé id. |
|
| runtime |
string |
ne |
Jen to, co patří tomuto runtime: `<node>-<runtime>`, nebo id uzlu pro každý runtime daného stroje. |
|
| druh |
MeshKind | null |
ne |
Pouze tato kolekce; ostatní se vrací prázdné. |
|
| limit |
integer (uint) |
ne |
Nejvýše tolik z každé kolekce: nejnovější podle Lamportova razítka tam, kde ho mají, ponechané ve vlastním pořadí skládání. |
|
| open |
boolean |
ne |
Pouze to, co je stále otevřené: aktivní relace, živé claimy, žádosti o review, na které nikdo neodpověděl, a předávky, které nikdo nepřevzal. |
|
| odpovídající |
string |
ne |
Pouze to, co zmiňuje tento text, bez ohledu na velikost písmen: cestu, branch, úkol, pull request, slovo záměru nebo předmětu. |
|
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/peers?view=full"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
PeerTree |
Kdo spolupracuje, stroj po stroji: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Zaregistrovat v mesh tohoto uzlu
Předloží jednu podepsanou obálku; ověří se přesně jako datagram — meze, zastaralost, podpis, politika důvěry — a pokud obstojí, zaznamená se jako pozorování rendezvous. Odpověď nese vlastní obálku tohoto uzlu a kandidáty, které drží jeho registr, každého ověřitelného od začátku do konce podle jeho vlastního podpisu. Registrace nic neuděluje: volající se stává záznamem, nikdy oprávněním. Mění jen paměť tohoto procesu.
- command
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh_register
příklad odmítnuto
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/register" -H "content-type: application/json" -d '{"envelope":{"v":0}}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
RegisterAnswer |
Registrace u mesh tohoto uzlu: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Požádat mesh o review
Požádat o revizi větve, commitu nebo pull requestu, volitelně jednoho pojmenovaného runtimu — který musí být propojen a nést funkci `reviews`, jinak se požadavek odmítne jako `feature_unsupported`. Replikuje se na každý propojený runtime. Zapisuje jen žurnál tohoto runtimu.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_review_request
příklad open
{"session":"bench","subject":"feature/bench","scope":[]}Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/reviews" -H "content-type: application/json" -d '{"session":"bench","subject":"feature/bench","scope":[]}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Požádat mesh o revizi: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Odpovědět na žádost o review
Odpoví na žádost o review z libovolného runtime hodnotou approved, changes_requested nebo commented a poznámkou. Replikuje se na každý propojený runtime. Zapisuje jen žurnál tohoto runtime.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_review_answer
příklad unknown
{"request":"none/r-0","session":"bench","verdict":"commented"}Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/reviews/answer" -H "content-type: application/json" -d '{"request":"none/r-0","session":"bench","verdict":"commented"}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Odpovědět na žádost o revizi: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Stáhnout žádost o posouzení
Ukončit žádost o revizi, kterou tento runtime vznesl — done, void nebo superseded — s volitelnou poznámkou o výsledku, kterou žádost pak nese. Smí to kterákoli relace žádajícího runtimu (znovu připojený žadatel je jiná relace téhož); žádný jiný runtime ne a nikdy se nepočítá jako odpověď. Nezodpovězená žádost se také čte jako vypršelá, dokud její runtime přestal tlouct. Replikuje se na každý propojený runtime. Zapisuje jen žurnál tohoto runtimu.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_review_withdraw
příklad unknown
{"request":"none/r-0","session":"bench","note":"superseded"}Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/reviews/withdraw" -H "content-type: application/json" -d '{"request":"none/r-0","session":"bench","note":"superseded"}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Stáhnout žádost o posouzení: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Otevřít nebo aktualizovat relaci na meshi
Řekne, co relace tohoto runtime je: její klient, worker, záměr, úloha, úkol, milník, branch, head, špinavost a revize kontextu. Replikuje se na každý propojený runtime; pozdější slovo nahrazuje dřívější. Zapisuje jen žurnál tohoto runtime.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_session_open
příklad pojmenovaný
{"session":"bench","intent":"benchmark"}Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/sessions" -H "content-type: application/json" -d '{"session":"bench","intent":"benchmark"}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Otevřít nebo aktualizovat relaci na meshi: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Uzavřít relaci na meshi
Ukončí relaci tohoto runtime; každý claim, který drží, s ní končí, na každém propojeném runtime. Zapisuje jen žurnál tohoto runtime.
- command
- experimentální
- měření výkonu prominuto: transient_state
- cache vypnuta
- Nástroj MCP majordomus_mesh_session_close
příklad pojmenovaný
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/sessions/close" -H "content-type: application/json" -d '{"session":"bench"}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
Zapsáno |
Zavřít relaci na meshi: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Stav, ke kterému konverguje každý propojený runtime
Složený žurnál. Výchozí pohled `summary` je omezený bez ohledu na historii: relace a claimy spočtené podle postavení, každý runtime s jeho živostí, počty a nejnovějším živým claimem, otevřené žádosti o review a předávky, které nikdo nepřevzal, a digest, který dva runtime porovnávají. `view=full` je každá relace, každý claim s postavením (held, released, expired, conflicted s jeho vítězem), poradní překryvy, každá předávka s tím, kdo ji převzal, každá žádost o review s odpověďmi a živost každého streamu na hodinách tohoto runtime. `claims=live`, `after` (Lamportovo razítko), `session` a `runtime` zúží kterýkoli pohled; digest je vždy digestem celého složení.
- query
- experimentální
- vyžaduje se měření výkonu
- cache vypnuta
- nástroj MCP majordomus_mesh_state
Parametry dotazu
| název | typ | povinné | popis | příklady |
| pohled |
MeshView | null |
ne |
`summary` (výchozí) nebo `full`. |
full: "full" |
| tvrzení |
MeshClaimFilter | null |
ne |
`all` (výchozí) nebo `live`: zda se ukončené claimy uchovávají. |
|
| po |
integer (uint64) |
ne |
Pouze relace, claimy a předávky, jejichž poslední Lamportovo razítko je nad touto hodnotou. Review a překryvy nenesou vlastní razítko a ponechají se nebo vyřadí spolu se svými relacemi. |
|
| session |
string |
ne |
Jen to, co patří této relaci: její klíč (`<stream>/<session>`) nebo holé id. |
|
| runtime |
string |
ne |
Jen to, co patří tomuto runtime: `<node>-<runtime>`, nebo id uzlu pro každý runtime daného stroje. |
|
| druh |
MeshKind | null |
ne |
Pouze tato kolekce; ostatní se vrací prázdné. |
|
| limit |
integer (uint) |
ne |
Nejvýše tolik z každé kolekce: nejnovější podle Lamportova razítka tam, kde ho mají, ponechané ve vlastním pořadí skládání. |
|
| open |
boolean |
ne |
Pouze to, co je stále otevřené: aktivní relace, živé claimy, žádosti o review, na které nikdo neodpověděl, a předávky, které nikdo nepřevzal. |
|
| odpovídající |
string |
ne |
Pouze to, co zmiňuje tento text, bez ohledu na velikost písmen: cestu, branch, úkol, pull request, slovo záměru nebo předmětu. |
|
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s "http://127.0.0.1:8741/api/v1/mesh/state?view=full"
Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
MeshStateAnswer |
Stav, na kterém konverguje každý propojený runtime: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Prokázat kooperaci nyní
Spustí živé ověření: spolupráce je aktivní, identita repozitáře se vyřeší, endpointy jsou dosažitelné mimo loopback, heartbeat tluče, žurnál neobsahuje zaseklou mezeru; pak jedno kolo synchronizace s každým peerem, kterého tento runtime volá, s časováním a zjištěním, zda obě strany nyní drží stejné high-water marky. Každá selhavší kontrola pojmenovává dopad a nápravu. Nemění nic kromě replikace žurnálu.
- command
- experimentální
- měření výkonu prominuto: external_dependency
- cache vypnuta
- Nástroj MCP majordomus_mesh_verify
Tělo požadavku — prázdné, JSON
příklad default
Vyzkoušejte
Port je ten, který server zalogoval; 8741 je ten, o který žádá jako první. Hodnoty jsou první příklad operace.
curl -s -X POST "http://127.0.0.1:8741/api/v1/mesh/verify" -H "content-type: application/json" -d '{}'Testováno v apps/majordomus-cli/tests/http_serve.rs, který přehrává routu s těmito hodnotami proti serveru na skutečném socketu.
Odpovědi
| status | tělo | význam |
| 200 |
MeshVerifyReport |
Prokázat spolupráci nyní: výsledek. |
| 400 |
ErrorBody |
invalid_input: Vstup neodpovídá schématu: parametr špatného typu, neznámý parametr nebo hodnota, kterou schopnost odmítne. |
| 404 |
ErrorBody |
not_found: Vstup pojmenovává něco, co repozitář nemá. |
| 422 |
ErrorBody |
refused: Příkaz byl srozumitelný a byl odmítnut z důvodu, který uvádí zpráva. |
| 500 |
ErrorBody |
internal: Schopnost selhala z vlastního důvodu; zpráva ho pojmenovává. |
| výchozí |
ErrorBody |
Jakékoli jiné selhání, které transport hlásí: 405 method_not_allowed pro jinou metodu na této cestě, 400 invalid_input pro tělo, které není objektem JSON. |
Schémata
Komponenty, které používají jen operace tohoto tagu. Každý řádek je pole daného typu, jeho doc komentář je popis; typ vlastněný jinou stránkou na ni odkazuje.
AdmitCommand
object
Jeden příkaz, který připouští pravidlo: štítek pravidla, jeho vektor argumentů přesně tak, jak jej provádí
apply, a totéž v uvozovkách jako jeden řádek, který člověk vloží do kořenového shellu. Obojí jsou projekce jednoho vektoru, takže to, co zpráva ukazuje, je to, co běží.
use std::net::Ipv4Addr;
use majordomus_cli::mesh::firewall::{plan, render, AdmitCommand, Backend};
use majordomus_cli::mesh::MeshConfig;
let config: MeshConfig = serde_json::from_value(serde_json::json!({
"schema": "mesh/v1", "kind": "mesh-declaration", "id": "doc", "enabled": true,
})).unwrap();
let p = plan(Some(&config), &[Ipv4Addr::new(10, 0, 0, 2)], None);
let commands: Vec<AdmitCommand> = render(Backend::Ufw, &p, None);
assert_eq!(commands[0].argv[0], "ufw");
assert_eq!(commands[0].rule, "udp/7741 to 239.255.77.77 from any");
assert_eq!(commands[0].line, "ufw allow in proto udp to 239.255.77.77 port 7741 comment 'majordomus mesh: multicast discovery'");
| vlastnost | typ | povinné | popis |
| pravidlo |
string |
ano |
Pravidlo, které připouští. |
| argv |
array of string |
ano |
Program a jeho argumenty tak, jak byly spuštěny. |
| řádek |
string |
ano |
Totéž, v uvozovkách pro shell. |
Používá FirewallReport
Backend
"ufw" | "nftables" | "application_firewall" | "none"
Firewallová vrstva, kterou tento hostitel provozuje, pokud to exekutor dokáže říct bez oprávnění: určeno
detect z platformy a cesty, a věc, pro kterou jsou
render,
observe a
apply specifické.
use majordomus_cli::mesh::firewall::Backend;
assert_eq!(serde_json::to_value(Backend::ApplicationFirewall).unwrap(), "application_firewall");
assert_eq!(Backend::None.as_str(), "none");
ufwUncomplicated Firewall, front-end pro Debian a Ubuntu: ufw je v cestě.nftablesnftables bez ufw před nimi: nft je na cestě.application_firewallmacOS: aplikační firewall (socketfilterfw), který povoluje spustitelné soubory, ne porty.noneŽádnou firewallovou frontu, kterou tento spustitelný soubor zná; nic se nepozoruje a nic se neaplikuje.
Používá FirewallReport
ClaimInput
object
Vstup mesh.claim.
| vlastnost | typ | povinné | popis |
| session |
string | null |
ne |
Nárokující relace; když je vynechána, vlastní relace volajícího MCP. Otevře se, když je nová. |
| klient |
string | null |
ne |
Klient pro relaci, kterou toto otevře; cli, když je vynechán. |
| scope |
array of string |
ano |
Cesty relativní k repozitáři. |
| intent |
string | null |
ne |
K čemu tvrzení slouží. |
| režim |
ClaimMode | null → ClaimMode |
ne |
exclusive (výchozí) nebo advisory. |
| issue |
string | null |
ne |
Úkol, pro který je tvrzení určeno. |
| úloha |
string | null |
ne |
Úloha pro relaci, kterou toto otevře. |
Používá mesh.claim
ClaimMode
"exclusive" | "advisory"
Zda nárok ostatní vylučuje, nebo jim jen oznamuje. Obojí je užitečné a odpovídají na různé otázky: výhradní nárok je pracovník říkající „needitujte to, dokud tu jsem“, poradní říká „jsem tady“. Výhradní je výchozí, protože nárok převzatý bez zamyšlení nad režimem je nárok, u kterého někdo očekává, že bude respektován.
use majordomus_cli::mesh::journal::ClaimMode;
assert_eq!(ClaimMode::default(), ClaimMode::Exclusive);
assert_eq!(serde_json::to_value(ClaimMode::Advisory).unwrap(), serde_json::json!("advisory"));
exclusiveExkluzivní: druhý exkluzivní claim, který se s tímto rozsahem střetne, je odmítnut, dokud tento žije, na každém runtime, který o něm ví.advisoryPoradní: oznámení, jako nástěnka peerů. Překryvy se hlásí, nikdy neodmítají.
Používá ClaimInput ClaimView MeshClaimBrief
ClaimOverlap
object
Dva živé nároky různých relací, jejichž rozsahy se setkávají, alespoň jeden poradní: hlásí se, nikdy neodmítají.
Překryv je informace, ne verdikt — takhle se dva pracovníci dozvědí, že jsou na stejném místě, aniž by jednoho z nich cokoli zastavilo. Setkávající se cesty jsou uvedeny po dvojicích, ne shrnuty, protože užitečná otázka je, která moje cesta se setkává s kterou jejich.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, StreamLiveness};
use majordomus_cli::mesh::state::{fold, ClaimOverlap};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
for (claim, session, mode) in [
("c1", "s1", ClaimMode::Exclusive),
("c2", "s2", ClaimMode::Advisory),
] {
j.append_own(EventBody::ClaimAcquired { claim: claim.into(), session: session.into(),
scope: vec!["apps".into()], intent: None, mode, issue: None }).unwrap();
}
let state = fold(&j.events(), &|_| StreamLiveness::Own);
let overlap: &ClaimOverlap = &state.overlaps[0];
assert_ne!(overlap.first, overlap.second, "two claims, two sessions");
assert_eq!(overlap.paths, [("apps".to_string(), "apps".to_string())]);
| vlastnost | typ | povinné | popis |
| první |
string |
ano |
Klíč dřívějšího tvrzení. |
| druhý |
string |
ano |
Klíč pozdějšího nároku. |
| cesty |
pole polí čehokoli |
ano |
Cesty, které se potkávají, jako dvojice first ↔ second. |
Používá CooperationState
ClaimState
jedna ze 4 variant
Stav nároku a — kde skončil nebo prohrál — co jej ukončilo. Dvě varianty nesoucí řetězec existují, protože holý verdikt není použitelný: worker, kterému se řekne, že jeho nárok vypršel, potřebuje vědět, zda se jeho relace uzavřela, nebo jeho runtime přestal tepat, a ten, kterému se řekne, že jeho nárok je v konfliktu, potřebuje klíč nároku, který jej porazil, což je tentýž klíč na každém runtime.
use majordomus_cli::mesh::state::ClaimState;
assert!(ClaimState::Held.is_live());
assert!(ClaimState::Conflicted("s/c1".into()).is_live(), "still held, and not the winner");
assert!(!ClaimState::Released.is_live());
// the detail travels with the verdict, so a reader is never left asking who won
let value = serde_json::to_value(ClaimState::Conflicted("s/c1".into())).unwrap();
assert_eq!(value["state"], "conflicted");
assert_eq!(value["detail"], "s/c1");
varianta Živé; u výhradního tvrzení vítěz jeho rozsahu.
varianta Uvolněno jeho držitelem.
variant Skončilo bez uvolnění: relace držitele se uzavřela nebo jeho runtime vypršel.
| state | "expired" | ano | |
| detail | string | ano | |
variant Živé, výlučné a předběhnuté ve svém rozsahu tvrzením, jehož klíč toto jmenuje.
| state | "conflicted" | ano | |
| detail | string | ano | |
Používá ClaimView
ClaimView
object
Jeden claim kdekoli v meshi: kdo co vzal, k čemu a kde to stojí. Lamportovo razítko a sekvence získání se nesou, ne odvozují na požádání, protože jsou tím, čím se rozhoduje o exkluzivitě — každý runtime řadí dva konkurující claimy podle téže trojice, a proto pojmenuje téhož vítěze, bez předávání zpráv a bez „poslední paket vyhrává“.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, StreamLiveness};
use majordomus_cli::mesh::state::{fold, ClaimState, ClaimView};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::ClaimAcquired { claim: "c1".into(), session: "s1".into(),
scope: vec!["apps/majordomus-cli".into()], intent: Some("document the mesh".into()),
mode: ClaimMode::Exclusive, issue: Some("#184".into()) }).unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
let claim: &ClaimView = &state.claims[0];
assert_eq!(claim.scope, ["apps/majordomus-cli"]);
assert_eq!(claim.state, ClaimState::Held);
assert!(claim.acquired_lamport > 0, "the order exclusivity is decided in");
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<claim>. |
| proud |
StreamId → StreamId |
ano |
Zapisovací stream. |
| runtime |
string |
ano |
<node>-<runtime>. |
| session |
string |
ano |
Klíč držící relace. |
| scope |
array of string |
ano |
Nárokované cesty. |
| intent |
string | null |
ne |
K čemu slouží. |
| režim |
ClaimMode → ClaimMode |
ano |
Výhradní, nebo poradní. |
| issue |
string | null |
ne |
Úkol, pro který je. |
| acquired_lamport |
integer (uint64) |
ano |
Lamportovo razítko získání. |
| acquired_seq |
integer (uint64) |
ano |
Pořadí akvizice v rámci jejího proudu: spolu s razítkem a proudem celkové pořadí, v němž se rozhoduje o výlučnosti. |
| state |
ClaimState → ClaimState |
ano |
Jeho postavení. |
Používá CooperationState SessionNode
ConsumeAnswer
object
Odpověď mesh.handover.consume.
| vlastnost | typ | povinné | popis |
| handover |
HandoverView → HandoverView |
ano |
Předávka tak, jak ji drží žurnál. |
| zapsáno |
Written → Written |
ano |
Událost spotřeby. |
| path |
string | null |
ne |
Zapsaný lokální záznam, relativně ke kořeni repozitáře, pokud byl zhmotněn. |
Používá mesh.handover.consume
CooperationCounters
object
Čítače propojení a replikace od startu: co tento runtime udělal, ne co drží. Jsou monotónní a nikdy se nenulují, takže dvě čtení s minutovým odstupem jsou rychlost — což je jediný způsob, jak poznat mesh, který funguje, od meshe, který opakuje, protože oba ukazují stejné peery ve stejných stavech.
Počty jsou všude rozděleny podle směru (handshakes_out proti handshakes_in, refused_in proti refused_out), protože runtime, který odmítá všechny, a ten, kterého odmítají všichni, potřebují opačnou nápravu.
#### use std::collections::BTreeMap;
#### use std::sync::{Arc, Mutex, Weak};
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::*;
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::{LinkReply, LinkTransport, Signed, HELLO_PATH};
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};
#### use majordomus_cli::mesh::trust::TrustPolicy;
#### #[derive(Default)] struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);
#### impl LinkTransport for Net {
#### fn post(&self, e: &str, p: &str, m: &Signed) -> Result<LinkReply, String> {
#### let peer = (self.0.lock().unwrap().get(e).and_then(Weak::upgrade))
#### .ok_or_else(|| format!("{e}: nobody there"))?;
#### Ok(if p == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) }) } }
#### let net = Arc::new(Net::default());
#### let runtime = |endpoint: &str| { let c = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: runtime_id(endpoint),
#### repository: of_root_commits(&["root".into()]), endpoints: vec![endpoint.into()],
#### version: "doc".into(), config: CooperationConfig::default(),
#### trust: TrustConfig { policy: TrustPolicy::Tofu, allow: vec![] }, journal_path: None,
#### registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::clone(&net) as Arc<dyn LinkTransport>, board: None,
#### checkout: CheckoutFacts::default() }).unwrap();
#### net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c)); c };
#### let (a, b) = (runtime("a:1"), runtime("b:1"));
let key = a.dial(&["b:1".into()]).unwrap();
a.sync_with(&key).unwrap();
let dialer: CooperationCounters = a.status().counters;
let answerer = b.status().counters;
assert_eq!((dialer.handshakes_out, dialer.syncs_out), (1, 1));
assert_eq!((answerer.handshakes_in, answerer.syncs_in), (1, 1), "the other side of it");
assert_eq!(answerer.handshakes_out, 0, "B never dialed anybody");
| vlastnost | typ | povinné | popis |
| handshakes_out |
integer (uint64) |
ano |
Handshaky, které tento runtime dokončil jako volající. |
| handshakes_in |
integer (uint64) |
ano |
Handshaky, které tento runtime přijal. |
| dial_failures |
integer (uint64) |
ano |
Číselníky, které nedosáhly žádného koncového bodu. |
| syncs_out |
integer (uint64) |
ano |
Kola synchronizace, která tento runtime dokončil jako volající. |
| syncs_failed |
integer (uint64) |
ano |
Kola synchronizace, která selhala v transportu. |
| syncs_in |
integer (uint64) |
ano |
Kola synchronizace, na která tento runtime odpověděl. |
| events_sent |
integer (uint64) |
ano |
Události odeslané v požadavcích synchronizace. |
| events_served |
integer (uint64) |
ano |
Události obsloužené v odpovědích synchronizace. |
| opětovná připojení |
integer (uint64) |
ano |
Znovu naváže handshake po vypršení nebo přerušeném spojení. |
| restarty |
integer (uint64) |
ano |
Pozorované restarty peerů. |
| peers_expired |
integer (uint64) |
ano |
Odkazy vypršely. |
| claims_refused |
integer (uint64) |
ano |
Nároky odmítnuté kvůli konfliktu. |
| vlákna |
integer (uint64) |
ano |
Vlákna kooperace, která právě žijí. |
| refused_in |
mapa celých čísel (uint64) |
ano |
Hello a synchronizace, které tento runtime odmítl, podle kódu. |
| refused_out |
mapa celých čísel (uint64) |
ano |
Odmítnutí, která tento runtime obdržel nebo uplatnil na welcome, podle kódu. |
Používá CooperationStatus
CooperationState
object
Celý sloučený stav, každá kolekce v pořadí klíčů, a jeho otisk: dva runtimy, které souhlasí, vypíšou stejný otisk.
Smyslem je otisk. Konvergence je jinak tvrzení, které z jednoho stroje nikdo neověří; s otiskem dva operátoři porovnají jediný krátký řetězec a vědí, zda jejich runtime vidí tentýž svět. opaque_events je druhá polovina téže poctivosti: události druhů, které tento spustitelný soubor neinterpretuje, se počítají a přeposílají místo zahazování, takže provoz novějšího peera je vidět a tiše nechybí.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, SessionInfo, StreamLiveness};
use majordomus_cli::mesh::state::{fold, CooperationState};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionOpened { info: SessionInfo::named("s1", "cli") }).unwrap();
let events = j.events();
let state: CooperationState = fold(&events, &|_| StreamLiveness::Own);
assert_eq!(state.digest.len(), 32);
// the same events in another order, and twice over, are the same state
let mut shuffled = events.clone();
shuffled.reverse();
shuffled.extend(events);
assert_eq!(fold(&shuffled, &|_| StreamLiveness::Own).digest, state.digest);
| vlastnost | typ | povinné | popis |
| relace |
pole SessionView → SessionView |
ano |
Každá relace. |
| tvrzení |
pole ClaimView → ClaimView |
ano |
Každé tvrzení. |
| překryvy |
pole ClaimOverlap → ClaimOverlap |
ano |
Poradní překryvy mezi živými nároky. |
| předávky |
pole HandoverView → HandoverView |
ano |
Každá předávka. |
| recenze |
pole ReviewView → ReviewView |
ano |
Každá žádost o revizi. |
| opaque_events |
integer (uint) |
ano |
Události druhů, které tento spustitelný soubor neinterpretuje. |
| otisk |
string |
ano |
32 hex znaků SHA-256 kanonického JSON všeho výše. |
Používá MeshStateAnswer
CooperationStatus
object
Celý runtime spolupráce tak, jak ho hlásí každý povrch: příkazová řádka, HTTP povrch i MCP vykreslují tuto jedinou hodnotu, takže člověk a agent, kteří se ptají na totéž téhož runtime, nikdy nedostanou různé odpovědi.
Jediným čtením odpovídá na tři otázky, které mesh vyvolává — spolupracuje tento runtime vůbec, čím mluví a s kým je propojen — a zůstává použitelný i tehdy, když je odpověď záporná: neaktivní runtime stále hlásí svůj rozsah protokolu a důvod, místo absence, kterou by volající musel složitě vykládat.
#### use std::sync::Arc;
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::{CheckoutFacts, Cooperation, CooperationSetup};
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::HttpTransport;
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::of_root_commits;
#### let cooperation = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: "0000000000000001".into(),
#### repository: of_root_commits(&["root".into()]), endpoints: vec!["127.0.0.1:9".into()],
#### version: "doc".into(), config: CooperationConfig::default(), trust: TrustConfig::default(),
#### journal_path: None, registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::new(HttpTransport), board: None, checkout: CheckoutFacts::default(),
#### }).unwrap();
use majordomus_cli::mesh::cooperation::CooperationStatus;
let running: CooperationStatus = cooperation.status();
assert_eq!(running.runtime.as_deref(), Some(cooperation.runtime_key()));
assert!(running.peers.is_empty(), "nothing is dialed until something dials");
// and where there is no runtime at all, the same shape says why
let none = CooperationStatus::inactive("the mesh declaration is disabled");
assert_eq!(none.protocol, running.protocol, "still answerable about what it speaks");
| vlastnost | typ | povinné | popis |
| aktivní |
boolean |
ano |
Zda kooperace běží v tomto procesu. |
| důvod |
string | null |
ne |
Proč ne, když ne. |
| runtime |
string | null |
ne |
Tento runtime, <node>-<runtime>. |
| proud |
StreamId | null → StreamId |
ne |
Aktuální proud tohoto runtimu. |
| repozitář |
MeshRepositoryIdentity | null → MeshRepositoryIdentity |
ne |
Identita repozitáře, podle které se odkazy shodují. |
| protocol |
pole any |
ano |
Rozsah verzí protokolu odkazu, kterým se mluví. |
| funkce |
array of string |
ano |
Funkce spojení, které nesla. |
| heartbeat_seconds |
integer (uint64) |
ano |
Sekundy mezi heartbeaty. |
| expiry_seconds |
integer (uint64) |
ano |
Sekundy ticha před vypršením. |
| endpointy |
array of string |
ano |
Kde tento runtime odpovídá. |
| seedy |
array of string |
ano |
Deklarovaná semínka. |
| peers |
pole PeerView → PeerView |
ano |
Každý propojený peer podle klíče runtime. |
| odmítnuto |
pole RefusedView → RefusedView |
ano |
Odmítnutí kandidáti podle endpointu. |
| čítače |
CooperationCounters → CooperationCounters |
ano |
Counters. |
| žurnál |
JournalTallies → JournalTallies |
ano |
Součty žurnálu. |
| started_at |
string | null |
ne |
Kdy spolupráce začala, RFC 3339. |
Používá mesh.cooperation
DoctorCheck
object
Verdikt jedné kontroly.
| vlastnost | typ | povinné | popis |
| check |
string |
ano |
Co bylo zkontrolováno. |
| ok |
boolean |
ano |
Zda platí. |
| detail |
string |
ano |
Důkaz: cesta, adresa, chyba. |
| dopad |
string | null |
ne |
Co selhání nebo omezení znamená pro mesh. |
| náprava |
string | null |
ne |
Co s tím dělat. |
Používá MeshDoctorReport
Trvanlivost
"synced" | "memory" | "not_durable" | "unknown"
Zda událost, kterou tento runtime zapsal, dosáhla disku tohoto stroje: co potvrzuje připojení a jediná věc, kterou o tom smí volající říct.
use majordomus_cli::mesh::journal::Durability;
assert_eq!(serde_json::to_value(Durability::NotDurable).unwrap(), "not_durable");
assert_eq!(Durability::default(), Durability::Unknown, "an answer that did not say");
assert!(Durability::Synced.is_on_disk() && !Durability::NotDurable.is_on_disk());
syncedPřipsáno do souboru žurnálu a synchronizováno (fsync jeho dat), než se připsání vrátilo.memoryŽurnál nemá soubor: žije v paměti a u svých peerů, podle konfigurace.not_durableZápis do souboru žurnálu selhal. Událost je držena v paměti a replikována peerům a tomuto stroji zanikne při restartu běhu, pokud ji nedrží některý peer. Není potvrzena jako trvalá.unknownNehlášeno: odpověď od spustitelného souboru, který je starší než toto pole.
Používá Written
Prázdné
object
Žádný vstup.
Používá mesh.verify
Obálka
object
Obálka na drátě: inzerát plus jeho podpis.
| vlastnost | typ | povinné | popis |
| v |
integer (uint32) |
ano |
Verze protokolu. |
| pk |
string |
ano |
Veřejný klíč Ed25519, hex. Id uzlu se z něj odvozuje, nikdy nenese: pole, které by se mohlo s klíčem rozcházet, je pole, které někdo zfalšuje. |
| inst |
InstanceId → InstanceId |
ano |
Tento běh uzlu. |
| název |
string |
ne |
Lidský název uzlu. Pouze prezentace. |
| seq |
integer (uint64) |
ano |
Monotónní na instanci: přehraný datagram nese čítač, který čtenář už viděl, a zahazuje se. |
| ts |
integer (uint64) |
ano |
Sekundy od epochy Unixu v době podpisu. |
| ep |
array of string |
ne |
Kde tento uzel odpovídá na HTTP, jako autority host:port, nejvýše MAX_ENDPOINTS. Poradní: endpoint je místo, kde zkusit, identita je klíč. |
| stropy |
array of string |
ne |
Transporty, které uzel obsluhuje: http, mcp, ws. Očištěné povědomí o schopnostech, nikdy ne autorizace. |
| repozitáře |
array of string |
ne |
Repozitáře, které tento uzel obsluhuje, jako id repozitářů meshe (32 hex, viz super::repository): odvozená z kořenových commitů repozitáře nebo jeho deklarované identity, nikdy z cesty, takže jeden repozitář naklonovaný na dvou strojích je rozpoznán jako jeden. Digest nic neprozrazuje; čtenář, který obsluhuje stejný repozitář, ho pozná, kdokoli jiný se dozví jen „nějaký repo“. |
| ver |
string |
ne |
Verze executable, informativní. |
| rt |
string |
ne |
Slot runtimu (16 hex): který server tohoto uzlu — jeden na checkout. Ve verzi 1 prázdný. Při prázdnosti vynechán z podepsaných bajtů, takže podpis verze 1 se ověří beze změny. |
| sig |
string |
ano |
Ed25519 přes Advertisement::signing_bytes, hex. |
Používá RegisterAnswer
EventList
object
Odpověď mesh.events.
| vlastnost | typ | povinné | popis |
| aktivní |
boolean |
ano |
Zda spolupráce funguje. |
| počet |
integer (uint) |
ano |
Kolik událostí tato odpověď nese. |
| lamport |
integer (uint64) |
ano |
after další stránky: razítko poslední události, kterou tato stránka nese, nebo after, které bylo požadováno, když žádnou nenese. Stránka nikdy nekončí uprostřed řady shodných razítek, takže navázání po ní nic nevynechá (I2140). |
| events |
pole typu MeshEvent → MeshEvent |
ano |
Události v Lamportově pořadí. |
Používá mesh.events
FirewallObservation
object
Vlastní slovo firewallu, posouzené proti plánu: stav, důkazy za ním a štítky pravidel, která nebyla přijata, když je stav
missing.
use majordomus_cli::mesh::firewall::{judge_ufw, plan, FirewallObservation, FirewallObservationState};
let o: FirewallObservation = judge_ufw("Status: inactive\n", &plan(None, &[], None));
assert_eq!(o.state, FirewallObservationState::Inactive);
assert!(o.missing.is_empty() && o.detail.contains("inactive"));
| vlastnost | typ | povinné | popis |
| state |
FirewallObservationState → FirewallObservationState |
ano |
Verdikt. |
| detail |
string |
ano |
Důkaz: stavový řádek, nalezená pravidla, nebo odmítnutí. |
| chybí |
array of string |
ne |
Nepřijatá pravidla, podle štítku, když je state missing. |
Používá FirewallReport
FirewallObservationState
"no_backend" | "inactive" | "present" | "missing" | "unobservable"
Co firewall hostitele říká o plánu, jedním slovem. Samo o sobě je selháním jen
missing;
unobservable je absence, kterou může log jádra ještě změnit v selhání.
use majordomus_cli::mesh::firewall::FirewallObservationState;
assert_eq!(serde_json::to_value(FirewallObservationState::Unobservable).unwrap(), "unobservable");
no_backendNení backend, který by se dal zeptat.inactiveFirewall je vypnut: nic nefiltruje, nic není potřeba.presentKaždé pravidlo plánu je přijato.missingAlespoň jedno pravidlo plánu není přijato.unobservableFirewall se z tohoto procesu nešlo zeptat — vyžaduje root.
Používá FirewallObservation
FirewallPlan
object
Co deklarace implikuje, že tento hostitel musí připouštět: pravidla, sítě, ze kterých je připouštějí, porty hubů, pro které je tento stroj uveden, a adresy, které plán viděl. Odpověď
plan; prázdné
rules je „nic není potřeba“, což je odpověď pro žádnou deklaraci i pro vypnutou.
use majordomus_cli::mesh::firewall::{plan, FirewallPlan};
let nothing: FirewallPlan = plan(None, &[], None);
assert!(nothing.rules.is_empty() && nothing.hub_ports.is_empty() && nothing.networks.is_empty());
| vlastnost | typ | povinné | popis |
| local_addresses |
array of string |
ano |
Adresy tohoto stroje, jak je plán viděl. |
| sítě |
array of string |
ano |
Privátní sítě, z nichž peery pocházejí: obklopující rozsahy každé adresy, kterou deklarace jmenuje, nebo adres tohoto stroje, když žádnou nejmenuje. |
| hub_ports |
pole celých čísel (uint16) |
ano |
Porty deklarovaných hubů, jimiž tento stroj je. |
| rules |
pole FirewallRule → FirewallRule |
ano |
Přijetí, v pevném pořadí. |
Používá FirewallReport
FirewallReport
object
Celý report: plán, backend, příkazy, slovo firewallu a jádra, s jednou větou verdiktu a jedním
ok. To, co odpovídá
mesh.firewall a co čte kontrola
firewall doctoru.
use majordomus_cli::mesh::firewall::{report, FirewallReport, BLOCK_WINDOW_SECONDS};
let r: FirewallReport = report(None, &[], None);
assert!(r.ok && r.commands.is_empty());
assert_eq!(r.window_seconds, BLOCK_WINDOW_SECONDS);
assert_eq!(r.platform, std::env::consts::OS);
| vlastnost | typ | povinné | popis |
| ok |
boolean |
ano |
Zda hostitel mesh připouští, pokud to lze pozorovat: nic nechybí a nic není zaznamenáno jako zahozené. |
| platforma |
string |
ano |
Platforma (linux, macos, …). |
| backend |
Backend → Backend |
ano |
Nalezená čelní vrstva firewallu. |
| spustitelný soubor |
string | null |
ne |
Spustitelný soubor, jako který server běží, což je to, co firewall macOS připouští. |
| plan |
FirewallPlan → FirewallPlan |
ano |
Co z deklarace vyplývá, že musí tento hostitel připustit. |
| commands |
pole AdmitCommand → AdmitCommand |
ano |
Příkazy, které ho na tomto backendu připouštějí; to, co spouští apply. |
| pozorování |
FirewallObservation → FirewallObservation |
ano |
Vlastní slovo firewallu o plánu. |
| window_seconds |
integer (uint64) |
ano |
Okno, které blocked_recently pokrývá, v sekundách. |
| blocked_recently |
object | null |
ne |
Zahození, která kernel zaznamenal směrem k portům plánu v rámci okna, po portech; chybí, když se log nepodařilo přečíst. |
| verdikt |
string |
ano |
Věta, kterou člověk čte. |
Používá mesh.firewall
FirewallRule
object
Jedno příchozí povolení, které mesh na tomto hostiteli potřebuje: protokol a port, skupina, na kterou je adresováno, jde-li o multicast, sítě, z nichž smí přijít, a věta, která říká proč. Pravidlo se vždy odvozuje, nikdy nepíše ručně;
FirewallRule::label je to, jak je pojmenovává verdikt.
use majordomus_cli::mesh::firewall::{FirewallRule, Protocol, Role};
let rule = FirewallRule {
role: Role::Hub,
protocol: Protocol::Tcp,
port: 8791,
destination: None,
sources: vec!["192.168.7.0/24".into()],
reason: "this machine is a declared rendezvous hub".into(),
};
assert_eq!(rule.label(), "tcp/8791 from 192.168.7.0/24");
| vlastnost | typ | povinné | popis |
| role |
Role → Role |
ano |
Why. |
| protocol |
Protocol → Protocol |
ano |
Transportní protokol. |
| port |
celé číslo (uint16) |
ano |
Cílový port. |
| cíl |
string | null |
ne |
Cílová adresa, pokud jde o multicastovou skupinu; None pro adresu tohoto hostitele. |
| zdroje |
array of string |
ano |
Sítě, z nichž může provoz přicházet, jako CIDR; prázdné připouští libovolný zdroj, což platí jen pro multicastovou skupinu, jejíž TTL ji drží v segmentu. |
| důvod |
string |
ano |
Věta, kterou člověk čte vedle pravidla. |
Používá FirewallPlan
HandoverBody
object
Předávka tak, jak ji nese mesh: fakta záznamu a jeho tělo, omezené.
Putuje psaný text plus těch několik faktů, které příjemci umožní ho zařadit — úloha, úkol, větev, commit. Není mezi nimi žádná cesta z disku autora, protože checkout, který to čte, je jinde, a cesta z jiného stroje je nanejvýš šum. Identitou je digest těla, takže předávka publikovaná dvakrát opakováním nebo dvěma runtimy je všude jedna předávka.
use majordomus_cli::mesh::journal::HandoverBody;
let body = "# Objective\nship the mesh\n".to_string();
let handover = HandoverBody {
id: HandoverBody::digest_of(&body),
task: Some("t-1".into()),
issue: Some("#184".into()),
milestone: None,
branch: Some("feature/mesh-cooperation".into()),
head: None,
created_at: None,
name: None,
body,
};
assert_eq!(handover.id, HandoverBody::digest_of(&handover.body));
let wire = serde_json::to_value(&handover).unwrap();
assert!(wire.get("milestone").is_none(), "what it does not say is omitted");
| vlastnost | typ | povinné | popis |
| id |
string |
ano |
Otisk obsahu (32 hex): táž předávka publikovaná dvakrát je jedna předávka. |
| úloha |
string | null |
ne |
Úloha, kterou předávka uzavírá nebo v níž pokračuje. |
| issue |
string | null |
ne |
Úkol, k němuž patří. |
| milestone |
string | null |
ne |
Milník, do něhož patří. |
| větev |
string | null |
ne |
Branch, na které byl zapsán. |
| head |
string | null |
ne |
Commit, při kterém byl záznam zapsán. |
| created_at |
string | null |
ne |
Kdy bylo napsáno, RFC 3339, podle hodin jeho autora. |
| název |
string | null |
ne |
Název souboru záznamu v místě původu, informativní. |
| tělo |
string |
ano |
Tělo Markdownu (# Objective, # Current State, # Next Action, ...). |
Používá HandoverView
HandoverConsumeInput
object
Vstup mesh.handover.consume.
| vlastnost | typ | povinné | popis |
| handover |
string |
ano |
Id předávky (její digest obsahu). |
| session |
string | null |
ne |
Přebírající relace; když je vynechána, vlastní relace volajícího MCP. |
| materialize |
boolean | null |
ne |
Zda ji zapsat jako lokální záznam předávky, který majordomus handover --resolve najde (výchozí true). |
Používá mesh.handover.consume
HandoverPublishInput
object
Vstup mesh.handover.publish.
| vlastnost | typ | povinné | popis |
| path |
string | null |
ne |
Záznam, relativně ke kořeni repozitáře a uvnitř .ai/local/state/handovers/; při vynechání nejnovější záznam. Nic mimo tento adresář tento příkaz nikdy nečte. |
| issue |
string | null |
ne |
Úkol, ke kterému předávka patří. |
| milestone |
string | null |
ne |
Milník, do něhož patří. |
Používá mesh.handover.publish
HandoverView
object
Předávka kdekoli v meshi se všemi, kdo ji převzali. Id je otisk těla, takže táž předávka publikovaná dvakrát — opakovaným pokusem nebo dvěma runtime, které ji obě viděly — je tady jedna předávka; a
consumed_by je to, co brání tomu, aby dva workery mlčky převzaly totéž pokračování, protože seznam se skládá z událostí, které má každý runtime.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, HandoverBody, Journal, StreamLiveness};
use majordomus_cli::mesh::state::{fold, HandoverView};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
let body = "# Objective\nship\n".to_string();
let handover = HandoverBody { id: HandoverBody::digest_of(&body), task: None, issue: None,
milestone: None, branch: Some("feature/x".into()), head: None, created_at: None,
name: None, body };
let id = handover.id.clone();
j.append_own(EventBody::HandoverPublished { handover }).unwrap();
j.append_own(EventBody::HandoverConsumed { handover: id.clone(), session: "s1".into() })
.unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
let view: &HandoverView = &state.handovers[0];
assert_eq!(view.id, id, "identified by what it says, not by who said it");
assert_eq!(view.consumed_by.len(), 1, "somebody has picked this one up");
| vlastnost | typ | povinné | popis |
| id |
string |
ano |
Digest obsahu. |
| proud |
StreamId → StreamId |
ano |
Stream, který jej poprvé publikoval. |
| runtime |
string |
ano |
<node>-<runtime> vydavatele. |
| published_lamport |
integer (uint64) |
ano |
Lamportovo razítko první publikace. |
| handover |
HandoverBody → HandoverBody |
ano |
Fakta a tělo záznamu. |
| consumed_by |
array of string |
ano |
Každá relace, která to spotřebovala, podle klíče, v pořadí Lamporta. |
Používá ConsumeAnswer CooperationState
InstanceId
string
Jeden běh uzlu: 16 hex znaků entropie OS, nových při každém startu procesu. Restart zachová id uzlu a mění toto, podle čehož čtenář rozliší „vrátil se tentýž uzel“ od „tentýž proces tu stále je“.
Používá Envelope NodeRecord PublicIdentity
JournalTallies
object
Čítače žurnálu od startu: kolik drží, kolik zapsal, přijal, vstřebal, odmítl, zadržel a zhutnil. Právě ony umožňují diagnostikovat problém replikace z jediného počítače — runtime, jehož
received nikdy neroste, není propojen, ten, jehož
rejected roste, dostává něco, co nepřijme, a ten, jehož
pending zůstává vysoké, mu chybí událost před tím, co má.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, JournalTallies};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
let before: JournalTallies = j.tallies();
assert_eq!((before.written, before.events), (0, 0));
j.append_own(EventBody::SessionClosed { session: "s1".into() }).unwrap();
let after = j.tallies();
assert_eq!((after.written, after.events, after.streams), (1, 1, 1));
assert!(after.lamport > before.lamport);
| vlastnost | typ | povinné | popis |
| streamy |
integer (uint) |
ano |
Sledované proudy. |
| events |
integer (uint) |
ano |
Uchované události. |
| zapsáno |
integer (uint64) |
ano |
Události zapsané tímto runtime od startu. |
| přijato |
integer (uint64) |
ano |
Přijaté a uložené události. |
| duplicity |
integer (uint64) |
ano |
Absorbovaná duplicitní doručení. |
| zamítnuto |
integer (uint64) |
ano |
Odmítnuté události. |
| čeká |
integer (uint) |
ano |
Události, které se právě teď drží kvůli mezeře. |
| zhutněno |
integer (uint64) |
ano |
Události zahozené kompakcí od startu. |
| neprůhledné |
integer (uint) |
ano |
Události druhu, který tento spustitelný soubor neinterpretuje, držené a předávané dál. |
| lamport |
integer (uint64) |
ano |
Nejvyšší viděné Lamportovo razítko. |
| write_failures |
integer (uint64) |
ne |
Připojuje do souboru žurnálu, který od startu selhal: události byly drženy v paměti a replikovány a nejsou na disku tohoto stroje. Nenulová hodnota způsobí selhání mesh doctor. |
| nečitelné |
integer (uint64) |
ne |
Řádky souboru žurnálu, které poslední znovunačtení nemohlo přečíst: utržené, poškozené nebo zapsané něčím, co není tento žurnál. Počítají se, nikdy se tiše nezahazují. |
| unread_bytes |
integer (uint64) |
ne |
Bajty souboru žurnálu, které poslední opětovné načtení nechalo nepřečtené, protože leží za MAX_RELOAD_BYTES: jsou na disku a kompakce je zachovává, ale nejsou v paměti. Nenulová hodnota způsobí selhání mesh doctor. |
Používá CooperationStatus
LinkRefusal
object
Odmítnutí: kód, důvod slovy a rozsah protokolu odmítajícího, aby šlo nesoulad verzí diagnostikovat z obou konců.
Nést rozsah protokolu odmítajícího v každém odmítnutí, ne jen v tom o protokolech, je to, co činí problém verzí viditelným ze strany, která má log: volající vidí, co odpovídající mluví, aniž by kdokoli musel číst druhý stroj.
use majordomus_cli::mesh::link::{LinkRefusal, RefusalCode, LINK_PROTOCOL_MAX};
let refusal = LinkRefusal::new(RefusalCode::Untrusted, "the key is not in the allowlist");
assert_eq!(refusal.code, RefusalCode::Untrusted);
assert_eq!(refusal.proto_max, LINK_PROTOCOL_MAX);
assert_eq!(refusal.to_string(), "untrusted: the key is not in the allowlist");
| vlastnost | typ | povinné | popis |
| kód |
RefusalCode → RefusalCode |
ano |
Pravidlo, které odmítlo. |
| detail |
string |
ano |
Proč, slovy. |
| proto_min |
integer (uint32) |
ano |
Nejstarší protokol odmítajícího. |
| proto_max |
integer (uint32) |
ano |
Nejnovější protokol odmítajícího. |
Používá LinkReply RefusedView
LinkReply
object
Co hello nebo sync odpovídá po drátě: podepsanou zprávu nebo odmítnutí. Obojí jsou úspěšné odpovědi — transport je nese stejně a ani jedno není chyba — protože odmítnutí je rozhodnutí, které tento protokol chce mít zaznamenané a viditelné, a odpověď, která by dorazila jako selhání HTTP, by se nedala odlišit od peera, který je mimo provoz.
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::link::{sign, Domain, LinkReply, RefusalCode};
let node = NodeIdentity::ephemeral().unwrap();
let accepted = LinkReply::accepted(sign(&node, Domain::Welcome, serde_json::json!({})));
assert!(accepted.signed.is_some() && accepted.refusal.is_none());
let refused = LinkReply::refused(RefusalCode::SelfLink, "this runtime dialled itself");
assert!(refused.signed.is_none());
assert_eq!(refused.refusal.unwrap().code, RefusalCode::SelfLink);
| vlastnost | typ | povinné | popis |
| podepsáno |
Signed | null → Signed |
ne |
Podepsaná odpověď welcome nebo sync, pokud byla přijata. |
| odmítnutí |
LinkRefusal | null → LinkRefusal |
ne |
Odmítnutí, když ne. |
Používá mesh.link.hello mesh.link.sync
LinkState
"connecting" | "connected" | "degraded" | "unreachable" | "expired"
Postavení linky z pohledu tohoto runtimu. Je to tvrzení o spojení a nikdy o peerovi: runtime dosažitelný jen přes třetí stranu je zde
Expired, zatímco jeho proudy všude pulzují, což je důvod, proč claimy následují proudy, ne tohle.
Varianty jsou řazeny podle toho, jak hluboko článek spadl, takže nejhorší článek v tabulce je maximum a čtenář je nikdy nemusí řadit ručně.
use majordomus_cli::mesh::cooperation::LinkState;
let table = [LinkState::Connected, LinkState::Unreachable, LinkState::Degraded];
assert_eq!(table.iter().max(), Some(&LinkState::Unreachable), "the worst link shows");
assert_eq!(serde_json::to_value(LinkState::Connected).unwrap(), "connected");
connectingProbíhá handshake, nebo se dosud nikdy nevyměňovalo.connectedVýměna do dvou heartbeatů.degradedKola selhávají; poslední výměna je mladší než polovina expirace.unreachablePoslední výměna je starší než polovina doby platnosti; spojení brzy vyprší.expiredŽádná výměna v rámci expirace: spojení se zahodí a znovu se vytočí.
Používá PeerVerdict PeerView
MachineNode
object
Jeden stroj ve stromu peerů.
| vlastnost | typ | povinné | popis |
| uzel |
string |
ano |
Id uzlu. |
| název |
string |
ano |
Jeho zobrazovaný název, když jej uvedla karta nebo tento uzel. |
| lokální |
boolean |
ano |
Zda je to tento stroj. |
| runtime |
pole RuntimeNode → RuntimeNode |
ano |
Jeho runtime. |
Používá PeerTree
MeshClaimBrief
object
Jeden živý nárok, stručně: čí je, k čemu slouží a kolik cest drží, s jeho záměrem oříznutým na
SUMMARY_TEXT znaků — dost na to, aby bylo jasné, koho se zeptat.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, SessionInfo, StreamLiveness};
use majordomus_cli::mesh::state::fold;
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionOpened { info: SessionInfo::named("s1", "claude-code") })
.unwrap();
for (claim, path) in [("c1", "apps/a"), ("c2", "apps/b")] {
j.append_own(EventBody::ClaimAcquired { claim: claim.into(), session: "s1".into(),
scope: vec![path.into()], intent: Some("work".into()), mode: ClaimMode::Exclusive,
issue: Some("#1".into()) }).unwrap();
}
j.append_own(EventBody::ClaimReleased { claim: "c1".into() }).unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
use majordomus_cli::mesh::page::{summarize, ClaimBrief};
let summary = summarize(&state, &[]);
let newest: &ClaimBrief = summary.runtimes[0].newest_claim.as_ref().unwrap();
assert_eq!((newest.issue.as_deref(), newest.paths), (Some("#1"), 1));
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<claim>. |
| session |
string |
ano |
Klíč držící relace. |
| issue |
string | null |
ne |
Úkol, pro který je. |
| intent |
string | null |
ne |
K čemu slouží, zkráceno na SUMMARY_TEXT znaků. |
| cesty |
integer (uint) |
ano |
Kolik cest si nárokuje. |
| režim |
ClaimMode → ClaimMode |
ano |
Výhradní, nebo poradní. |
| acquired_lamport |
integer (uint64) |
ano |
Lamportovo razítko získání. |
Používá MeshRuntimeSummary RuntimeNode
MeshClaimCounts
object
Claimy podle postavení: držené, konfliktní, uvolněné a vypršelé. Držené a konfliktní jsou živé; zbylé dva jsou historie, počítané, ne vypisované.
use majordomus_cli::mesh::page::ClaimCounts;
let counts = ClaimCounts { held: 2, released: 5, ..ClaimCounts::default() };
assert_eq!(serde_json::to_value(&counts).unwrap()["released"], 5);
| vlastnost | typ | povinné | popis |
| držené |
integer (uint) |
ano |
Živý a u výlučného claimu vítěz svého rozsahu. |
| v konfliktu |
integer (uint) |
ano |
Živé, výlučné a předběhnuté ve svém rozsahu. |
| vydáno |
integer (uint) |
ano |
Uvolněno držitelem. |
| vypršelo |
integer (uint) |
ano |
Skončilo bez releasu. |
Používá MeshRuntimeSummary MeshSummary
MeshClaimFilter
"all" | "live"
Které claimy úplná odpověď ponechá: všechny včetně ukončených, nebo jen ty stále živé — otázka, kterou executor klade, než převezme lease.
use majordomus_cli::mesh::page::ClaimFilter;
assert_eq!(ClaimFilter::default(), ClaimFilter::All);
assert_eq!(serde_json::from_str::<ClaimFilter>(r#""live""#).unwrap(), ClaimFilter::Live);
allKaždý claim, včetně ukončených.liveJen tvrzení, která jsou stále živá: držená, nebo sporná a stále držená.
Používá mesh.peers mesh.state
MeshDoctorReport
object
Celá autokontrola.
| vlastnost | typ | povinné | popis |
| ok |
boolean |
ano |
Zda platí každá kontrola. |
| kontroly |
pole DoctorCheck → DoctorCheck |
ano |
Kontroly v pořadí, v jakém proběhly. |
Používá mesh.doctor
MeshEvent
object
Jedna událost tak, jak ji nese drát a úložiště. Tělo se drží jako JSON, aby událost neznámého druhu přežila uložení i přenos bajt po bajtu;
MeshEvent::body ho interpretuje.
Každé pole nad podpisem je jím kryto, což činí relay neškodným: runtime, který událost přeposílá, nemůže změnit její proud, pořadí, repozitář ani tělo, aniž by si toho další čtenář všiml, a tak za nic neručí. Nástěnné hodiny jsou jediné pole, kterým se nic nerozhoduje — aktuálnost se měří beaty a monotónními hodinami, nikdy porovnáním představ dvou strojů o čase.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, MeshEvent};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionClosed { session: "s1".into() }).unwrap();
let event: &MeshEvent = &j.events()[0];
assert_eq!(event.seq, 1, "dense from 1 within its stream");
assert_eq!(event.kind(), "session_closed");
assert_eq!(event.id(), format!("{}/1", event.stream));
// a relayed byte changed anywhere under the signature is a different event
let mut tampered = event.clone();
tampered.repo = "another-repository".into();
assert_ne!(tampered.signing_bytes(), event.signing_bytes());
| vlastnost | typ | povinné | popis |
| v |
integer (uint32) |
ano |
Verze formátu události. |
| proud |
StreamId → StreamId |
ano |
Stream, který to zapsal. |
| seq |
integer (uint64) |
ano |
Souvisle číslováno od 1 v rámci proudu. |
| lamport |
integer (uint64) |
ano |
Lamportovo razítko: nad každým razítkem, které jeho zapisovatel viděl. |
| v |
integer (uint64) |
ano |
Nástěnné hodiny zapisovatele, sekundy od epochy Unixu. Jen informativní: nic se nerozhoduje porovnáním s hodinami jiného stroje. |
| repo |
string |
ano |
ID repozitáře meshe, k němuž událost patří. |
| pk |
string |
ano |
Veřejný klíč Ed25519 zapisovatele, hex; jeho digest je uzlem proudu. |
| tělo |
libovolný |
ano |
Tělo, označené kind. |
| sig |
string |
ano |
Ed25519 nad kanonickými bajty všeho výše, hex. |
Používá EventList
MeshHandoverBrief
object
Předávka, kterou nikdo nepřevzal, stručně: id, které
mesh.handover.consume přebírá, kdo ji publikoval a na co navazuje. Její tělo zůstává v plném pohledu.
use majordomus_cli::mesh::page::HandoverBrief;
let brief = HandoverBrief { id: "ab12".into(), runtime: "n-r".into(),
branch: Some("feature/x".into()), issue: None, published_lamport: 7 };
assert_eq!(serde_json::to_value(&brief).unwrap()["branch"], "feature/x");
| vlastnost | typ | povinné | popis |
| id |
string |
ano |
Digest obsahu: to, co bere mesh.handover.consume. |
| runtime |
string |
ano |
<node>-<runtime> vydavatele. |
| větev |
string | null |
ne |
Větev, kterou pokračuje. |
| issue |
string | null |
ne |
Úkol, který pokračuje. |
| published_lamport |
integer (uint64) |
ano |
Lamportovo razítko první publikace. |
Používá MeshSummary
MeshIdentityReport
object
Odpověď mesh.identity: identita uzlu tohoto stroje, pouze veřejná polovina.
| vlastnost | typ | povinné | popis |
| path |
string | null |
ne |
Kde soubor identity žije (nebo by žil). |
| přítomno |
boolean |
ano |
Zda soubor existuje. |
| identity |
PublicIdentity | null → PublicIdentity |
ne |
Veřejná identita, když soubor existuje a načte se. Podpisový klíč tu není, není v žádné projekci a není v žádném logu. |
| chyba |
string | null |
ne |
Proč se identita nenačetla, když se nenačetla. |
Používá mesh.identity
MeshKind
"sessions" | "claims" | "overlaps" | "handovers" | "reviews"
Jedna kolekce složeného stavu, jak ji pojmenovává
kind: čtenář, který chce jen revize, nedostane claimy.
use majordomus_cli::mesh::page::Kind;
assert_eq!(serde_json::from_str::<Kind>(r#""reviews""#).unwrap(), Kind::Reviews);
assert!(serde_json::from_str::<Kind>(r#""everything""#).is_err());
sessionsRelace.claimsTvrzení.overlapsPoradní se překrývá.handoversPředávky.reviewsŽádosti o review.
Používá mesh.peers mesh.state
MeshProviderState
"running" | "failed" | "stopped"
Zdraví poskytovatele, tak jak ho hlásí každý povrch.
runningVlákna běží, socket navázán (kde jej poskytovatel má).failedPoskytovatel se nemohl spustit nebo zemřel; ProviderStatus::detail říká proč. Selhání jednoho poskytovatele nikdy nezastaví jiného — izolace selhání je smlouva.stoppedZastaveno správcem.
Používá ProviderStatus
MeshRepositoryBasis
"declared" | "root_commits"
Z čeho byla odvozena identita repozitáře, což čtenář potřebuje, aby ji mohl posoudit: identita převzatá z kořenových commitů je fakt o historii, kterou sdílejí dva klony, zatímco deklarovaná je rozhodnutí, které někdo učinil, a jen druhou lze změnit úpravou souboru.
use majordomus_cli::mesh::repository::{declared, of_root_commits, MeshRepositoryBasis};
assert_eq!(declared("majordomus").unwrap().basis, MeshRepositoryBasis::Declared);
assert_eq!(
of_root_commits(&["a".repeat(40)]).basis,
MeshRepositoryBasis::RootCommits,
);
declaredcooperation.repository v deklaraci meshe.root_commitsKořenové commity repozitáře.
Používá MeshRepositoryIdentity
MeshRepositoryIdentity
object
Identita repozitáře v meshi, kterou nese každé oznámení, link a událost, spolu s popisem, odkud pochází.
detail existuje proto, aby člověk, kterému se řekne, že dva checkouty nejsou týž repozitář, viděl, z čeho byl každý odvozen, místo porovnávání dvou neprůhledných digestů.
use majordomus_cli::mesh::repository::MeshRepositoryIdentity;
use majordomus_cli::mesh::repository::of_root_commits;
let identity: MeshRepositoryIdentity = of_root_commits(&["a".repeat(40)]);
assert_eq!(identity.id.len(), 32, "32 hex characters, on every machine");
assert_eq!(identity.detail, "aaaaaaaaaaaa", "the evidence, short enough to read");
| vlastnost | typ | povinné | popis |
| id |
string |
ano |
32 hex: co nesou inzeráty, spoje a události. |
| základ |
MeshRepositoryBasis → MeshRepositoryBasis |
ano |
Z čeho bylo odvozeno. |
| detail |
string |
ano |
Důkaz čitelný člověkem: deklarovaná hodnota, nebo kořenové commity. |
Používá CooperationStatus
MeshReviewBrief
object
Otevřená žádost o review, stručně: její klíč, co se má posoudit a koho se ptá. V souhrnu jsou uvedeny jen žádosti, na které nikdo neodpověděl.
use majordomus_cli::mesh::page::ReviewBrief;
let brief = ReviewBrief { key: "s/r1".into(), subject: "feature/x".into(), issue: None,
reviewer: None };
assert!(serde_json::to_value(&brief).unwrap().get("issue").is_none(), "absent, not null");
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<review>. |
| předmět |
string |
ano |
Co se má posoudit, oříznuto na SUMMARY_TEXT znaků. |
| issue |
string | null |
ne |
Úkol. |
| reviewer |
string | null |
ne |
Runtime, na který se ptalo, pokud nějaký byl. |
Používá MeshSummary
MeshRuntimeSummary
object
Jeden runtime, spočtený: jeho živost a tep, jeho relace a claimy podle postavení a jeho nejnovější živý claim. Souhrn je vypisuje, živé runtimy první.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, SessionInfo, StreamLiveness};
use majordomus_cli::mesh::state::fold;
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionOpened { info: SessionInfo::named("s1", "claude-code") })
.unwrap();
for (claim, path) in [("c1", "apps/a"), ("c2", "apps/b")] {
j.append_own(EventBody::ClaimAcquired { claim: claim.into(), session: "s1".into(),
scope: vec![path.into()], intent: Some("work".into()), mode: ClaimMode::Exclusive,
issue: Some("#1".into()) }).unwrap();
}
j.append_own(EventBody::ClaimReleased { claim: "c1".into() }).unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
use majordomus_cli::mesh::page::{summarize, RuntimeSummary};
let summary = summarize(&state, &[]);
let runtime: &RuntimeSummary = &summary.runtimes[0];
assert_eq!((runtime.sessions.active, runtime.claims.held, runtime.claims.released), (1, 1, 1));
| vlastnost | typ | povinné | popis |
| runtime |
string |
ano |
<node>-<runtime>. |
| živost |
StreamLiveness → StreamLiveness |
ano |
Vlastní, živý nebo vypršelý. |
| last_beat_ms |
integer | null |
ne |
Milisekundy od posledního vzrůstu jeho tepu, podle hodin tohoto runtime. |
| relace |
MeshSessionCounts → MeshSessionCounts |
ano |
Jeho relace podle postavení. |
| tvrzení |
MeshClaimCounts → MeshClaimCounts |
ano |
Jeho tvrzení podle postavení. |
| newest_claim |
MeshClaimBrief | null → MeshClaimBrief |
ne |
Jeho nejnovější živý claim. |
Používá MeshSummary
MeshSessionCounts
object
Relace podle stavu: kolik je aktivních, uzavřených a vypršelých. Počet zůstává stejně velký, kolik relací mesh viděl, a proto souhrn nese počty.
use majordomus_cli::mesh::page::SessionCounts;
let none = SessionCounts::default();
assert_eq!(serde_json::to_value(&none).unwrap(),
serde_json::json!({ "active": 0, "closed": 0, "expired": 0 }));
| vlastnost | typ | povinné | popis |
| aktivní |
integer (uint) |
ano |
Otevřená, na runtime, který bije. |
| uzavřeno |
integer (uint) |
ano |
Uzavřeny vlastním runtimem. |
| vypršelo |
integer (uint) |
ano |
Nikdy neuzavřeno, na runtime, který přestal tepat. |
Používá MeshRuntimeSummary MeshSummary
MeshSource
"udp_multicast" | "udp_broadcast" | "rendezvous" | "synthetic"
Odkud pozorování pochází. Záznam jich shromažďuje víc; provenance je odpovědí na „proč vidím tento uzel“.
udp_multicastMulticastový datagram.udp_broadcastBroadcastový datagram.rendezvousOdpověď nebo registrace rendezvous.syntheticSyntetický poskytovatel (testy, self-check).
Používá Sighting
MeshStateAnswer
object
Odpověď mesh.state.
| vlastnost | typ | povinné | popis |
| aktivní |
boolean |
ano |
Zda spolupráce funguje. |
| pohled |
MeshView → MeshView |
ano |
Co odpověď nese: summary nebo full. |
| důvod |
string | null |
ne |
Proč ne. |
| summary |
MeshSummary | null → MeshSummary |
ne |
Souhrn v pohledu souhrnu: počty, nejnovější živý claim každého runtime, otevřené recenze a nepřevzaté předávky. |
| state |
CooperationState | null → CooperationState |
ne |
Složený stav zúžený filtry, v plném pohledu; jeho digest je digest celého složení. |
| streamy |
pole StreamView → StreamView |
ano |
Živost každého streamu. |
Používá mesh.state
MeshStatus
object
Celý mesh tak, jak ho hlásí každý povrch.
| vlastnost | typ | povinné | popis |
| aktivní |
boolean |
ano |
Zda v tomto procesu běží mesh. |
| důvod |
string | null |
ne |
Proč ne, když není: žádná deklarace, zakázáno, žádná identita, zastaveno. |
| identity |
PublicIdentity | null → PublicIdentity |
ne |
Tento uzel, když má mesh identitu. |
| trust_policy |
string | null |
ne |
Platná politika důvěry. |
| providers |
pole ProviderStatus → ProviderStatus |
ano |
Každý provider, v kanonickém pořadí (podle id). |
| součty |
Tallies → Tallies |
ano |
Součty registru. |
| odmítnutí |
Refusals → Refusals |
ano |
Odmítnuté datagramy podle důvodu. |
| started_at |
string | null |
ne |
Kdy mesh začal, RFC 3339. |
Používá mesh.status
MeshSummary
object
Mesh v odpovědi, kterou pracovník čte celou: počty, každý runtime, otevřené recenze a nepřevzaté předávky, každý seznam omezený
SUMMARY_LIST se zbytkem započítaným.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{ClaimMode, EventBody, Journal, SessionInfo, StreamLiveness};
use majordomus_cli::mesh::state::fold;
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionOpened { info: SessionInfo::named("s1", "claude-code") })
.unwrap();
for (claim, path) in [("c1", "apps/a"), ("c2", "apps/b")] {
j.append_own(EventBody::ClaimAcquired { claim: claim.into(), session: "s1".into(),
scope: vec![path.into()], intent: Some("work".into()), mode: ClaimMode::Exclusive,
issue: Some("#1".into()) }).unwrap();
}
j.append_own(EventBody::ClaimReleased { claim: "c1".into() }).unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
use majordomus_cli::mesh::page::{summarize, Summary};
let summary: Summary = summarize(&state, &[]);
assert_eq!((summary.claims.held, summary.claims.released), (1, 1));
assert_eq!(summary.digest, state.digest);
| vlastnost | typ | povinné | popis |
| otisk |
string |
ano |
Otisk celého složení: stejné otisky, stejný stav. |
| relace |
MeshSessionCounts → MeshSessionCounts |
ano |
Každá relace podle stavu. |
| tvrzení |
MeshClaimCounts → MeshClaimCounts |
ano |
Každé tvrzení podle postavení. |
| překryvy |
integer (uint) |
ano |
Poradní překryvy mezi živými nároky. |
| runtime |
pole MeshRuntimeSummary → MeshRuntimeSummary |
ano |
Každý runtime započítán, živé první; nejvýše SUMMARY_LIST. |
| runtimes_not_listed |
integer (uint) |
ano |
Runtime za seznamem, spočítané. |
| open_reviews |
pole MeshReviewBrief → MeshReviewBrief |
ano |
Žádosti o review, na které nikdo neodpověděl; nejvýše SUMMARY_LIST. |
| open_reviews_not_listed |
integer (uint) |
ano |
Otevřená review za hranicí seznamu, spočítaná. |
| untaken_handovers |
pole MeshHandoverBrief → MeshHandoverBrief |
ano |
Předávky, které nikdo nepřevzal; nejvýše SUMMARY_LIST. |
| untaken_handovers_not_listed |
integer (uint) |
ano |
Nepřevzaté předávky za seznamem, spočítané. |
Používá MeshStateAnswer
MeshVerifyCheck
object
Jedna ověřovací kontrola: co se kontrolovalo, zda to platí, důkazy a — když je něco špatně nebo omezeno — dopad a co s tím dělat.
Dopad a nápravu nese verdikt s sebou, místo aby je nechával na tom, kdo ho vykresluje, takže selhávající kontrola je použitelná, kdekoli se čte — v terminálu, v odpovědi JSON nebo u agenta, který mesh nikdy neviděl. Kontrola, která platí, nenese ani jedno, protože není co dělat.
#### use std::sync::Arc;
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::{CheckoutFacts, Cooperation, CooperationSetup};
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::HttpTransport;
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::of_root_commits;
#### let cooperation = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: "0000000000000001".into(),
#### repository: of_root_commits(&["root".into()]), endpoints: vec!["127.0.0.1:9".into()],
#### version: "doc".into(), config: CooperationConfig::default(), trust: TrustConfig::default(),
#### journal_path: None, registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::new(HttpTransport), board: None, checkout: CheckoutFacts::default(),
#### }).unwrap();
use majordomus_cli::mesh::cooperation::MeshVerifyCheck;
let report = cooperation.verify();
let first: &MeshVerifyCheck = &report.checks[0];
assert_eq!(first.check, "cooperation");
assert!(first.detail.contains(cooperation.runtime_key()), "the evidence, not a verdict");
assert!(first.remediation.is_none(), "a check that holds asks for nothing");
| vlastnost | typ | povinné | popis |
| check |
string |
ano |
Co bylo zkontrolováno. |
| ok |
boolean |
ano |
Zda platí. |
| detail |
string |
ano |
Důkazy. |
| dopad |
string | null |
ne |
Co selhání nebo omezení znamená pro spolupráci. |
| náprava |
string | null |
ne |
Co dělat. |
Používá MeshVerifyReport
MeshVerifyReport
object
Co
mesh verify zjistil: místní kontroly, kolo každého peera a následný digest stavu. Digest je to, co činí report hodným spuštění na dvou strojích — dva runtimy, které vypíší stejný digest, mají stejné relace, claims, předávky a recenze, a dva, které ne, mají co sladit, ať říkají jejich odkazy cokoli.
ok je konjunkce všeho pod ním, takže volající může jednat podle jednoho pole a člověk může číst zbytek, aby zjistil, která jeho část nebyla pravdivá.
#### use std::sync::Arc;
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::{CheckoutFacts, Cooperation, CooperationSetup};
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::HttpTransport;
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::of_root_commits;
#### let cooperation = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: "0000000000000001".into(),
#### repository: of_root_commits(&["root".into()]), endpoints: vec!["127.0.0.1:9".into()],
#### version: "doc".into(), config: CooperationConfig::default(), trust: TrustConfig::default(),
#### journal_path: None, registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::new(HttpTransport), board: None, checkout: CheckoutFacts::default(),
#### }).unwrap();
use majordomus_cli::mesh::cooperation::MeshVerifyReport;
let report: MeshVerifyReport = cooperation.verify();
assert_eq!(report.runtime.as_deref(), Some(cooperation.runtime_key()));
assert_eq!(report.digest, Some(cooperation.state().digest), "what a peer is compared to");
assert_eq!(report.ok, report.checks.iter().all(|c| c.ok), "one field for every check");
| vlastnost | typ | povinné | popis |
| ok |
boolean |
ano |
Zda platí každá kontrola a uspělo každé kolo. |
| runtime |
string | null |
ne |
Tento runtime. |
| kontroly |
pole MeshVerifyCheck → MeshVerifyCheck |
ano |
Kontroly v pořadí, v jakém proběhly. |
| peers |
pole PeerVerdict → PeerVerdict |
ano |
Verdikt každého propojeného peera. |
| otisk |
string | null |
ne |
Digest stavu po kolech. |
Používá mesh.verify
MeshView
"summary" | "full"
Kolik nese odpověď o meshi. Souhrn je výchozí, protože je to odpověď, kterou pracovník přečte celou bez ohledu na historii meshe; plný fold je o jedno slovo dál, když čtenář potřebuje každý záznam.
use majordomus_cli::mesh::page::View;
assert_eq!(View::default(), View::Summary);
assert_eq!(serde_json::to_value(View::Full).unwrap(), "full");
summaryPočty, nejnovější živý nárok každého runtime, otevřené revize a nepřevzaté předávky: omezené, ať je historie jakákoli.fullVšechno, zúžené jen filtry.
Používá mesh.peers mesh.state MeshStateAnswer PeerTree
NodeId
string
Stabilní identita uzlu: 32 hex znaků SHA-256 jeho veřejného klíče Ed25519. Odvozená, nikdy volená: dva uzly s jedním id drží jeden klíč.
Používají NodeRecord PublicIdentity
NodeList
object
Odpověď mesh.nodes: každý uzel, který tento proces pozoroval.
| vlastnost | typ | povinné | popis |
| počet |
integer (uint) |
ano |
Kolik uzlů registr obsahuje. |
| nodes |
pole NodeRecord → NodeRecord |
ano |
Uzly v pořadí podle id uzlu — jediné kanonické pořadí, které ukazuje každý povrch. |
Používá mesh.nodes
NodeRecord
object
Jeden objevený uzel: kanonický záznam, který promítá každý povrch.
| vlastnost | typ | povinné | popis |
| node_id |
NodeId → NodeId |
ano |
Id uzlu: digest klíče níže. |
| runtime |
string |
ne |
Runtime slot: který server uzlu (jeden na checkout), 16 hex; prázdné u inzerátu verze 1. Záznam je jeden runtime: dva worktrees jednoho stroje jsou dva záznamy pod jedním id uzlu a jedním klíčem. |
| public_key |
string |
ano |
Veřejný klíč Ed25519, který prokázal inzeráty tohoto záznamu. |
| display_name |
string |
ano |
Vlastní zobrazovaný název uzlu. Jen prezentace. |
| instance_id |
InstanceId → InstanceId |
ano |
Aktuální běh uzlu. |
| důvěra |
TrustState → TrustState |
ano |
Co politika rozhodla. |
| přítomnost |
Presence → Presence |
ano |
Zda uzel nyní odpovídá. |
| endpointy |
array of string |
ano |
Inzerované autority host:port. |
| capabilities |
array of string |
ano |
Inzerované transporty (http, mcp, ws). |
| repozitáře |
array of string |
ano |
Inzerované otisky repozitářů. |
| protocol_version |
integer (uint32) |
ano |
Inzerovaná verze protokolu. |
| verze |
string |
ano |
Inzerovaná verze executable. |
| zdroje |
pole Sighting → Sighting |
ano |
Každý zdroj, jímž byl tento uzel viděn, s nejnovějším zahlédnutím pro každý zdroj. |
| first_seen |
string |
ano |
Poprvé spatřeno, RFC 3339. |
| last_seen |
string |
ano |
Naposledy viděno, RFC 3339. |
| restarty |
integer (uint64) |
ano |
Kolik instancí toto id uzlu ukázalo (restart je zvýší). |
Používá NodeList
PeerDetail
object
Odpověď mesh.peer.
| vlastnost | typ | povinné | popis |
| nalezeno |
boolean |
ano |
Zda je runtime zde znám. |
| důvod |
string | null |
ne |
Proč ne, když ne. |
| machine |
string | null |
ne |
Stroj, na kterém běží. |
| runtime |
RuntimeNode | null → RuntimeNode |
ne |
Runtime, jeho spojení a jeho relace. |
| odmítnuto |
pole RefusedView → RefusedView |
ano |
Odmítnutí zaznamenaná proti němu. |
Používá mesh.peer
PeerTree
object
Odpověď mesh.peers: stroj → runtime → relace → nárok, každá úroveň z jednoho žurnálu a jedné tabulky spojení.
| vlastnost | typ | povinné | popis |
| aktivní |
boolean |
ano |
Zda spolupráce funguje. |
| pohled |
MeshView → MeshView |
ano |
Co odpověď nese: summary nebo full. |
| důvod |
string | null |
ne |
Proč ne. |
| runtime |
string | null |
ne |
Tento runtime. |
| repozitář |
string | null |
ne |
Id repozitáře v mesh. |
| stroje |
pole MachineNode → MachineNode |
ano |
Stroje, místní jako první. |
| odmítnuto |
pole RefusedView → RefusedView |
ano |
Odmítnutí kandidáti, s pravidlem. |
| otisk |
string | null |
ne |
Digest stavu spolupráce: shodné digesty, shodný stav. |
Používá mesh.peers
PeerVerdict
object
Co řekl jeden kolo synchronizace, spuštěné teď a ne vzpomenuté, o jednom peeru. Ověření nehlásí stav spojení a nekončí tím: vymění si data s peerem a řekne, zda výměna fungovala a zda obě strany skončily se stejnými značkami, což je rozdíl mezi peerem, který odpovídá, a peerem, který souhlasí.
round_trip a converged jsou volitelné, protože peer, kterého tento runtime nevolá, se neptá — chybějící odpověď není selhání a hlásit tam false by způsobilo, že spojení jen pro příchozí vypadá pokaždé rozbité.
#### use std::collections::BTreeMap;
#### use std::sync::{Arc, Mutex, Weak};
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::*;
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::{LinkReply, LinkTransport, Signed, HELLO_PATH};
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};
#### use majordomus_cli::mesh::trust::TrustPolicy;
#### #[derive(Default)] struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);
#### impl LinkTransport for Net {
#### fn post(&self, e: &str, p: &str, m: &Signed) -> Result<LinkReply, String> {
#### let peer = (self.0.lock().unwrap().get(e).and_then(Weak::upgrade))
#### .ok_or_else(|| format!("{e}: nobody there"))?;
#### Ok(if p == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) }) } }
#### let net = Arc::new(Net::default());
#### let runtime = |endpoint: &str| { let c = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: runtime_id(endpoint),
#### repository: of_root_commits(&["root".into()]), endpoints: vec![endpoint.into()],
#### version: "doc".into(), config: CooperationConfig::default(),
#### trust: TrustConfig { policy: TrustPolicy::Tofu, allow: vec![] }, journal_path: None,
#### registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::clone(&net) as Arc<dyn LinkTransport>, board: None,
#### checkout: CheckoutFacts::default() }).unwrap();
#### net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c)); c };
#### let (a, b) = (runtime("a:1"), runtime("b:1"));
a.dial(&["b:1".into()]).unwrap();
let dialer: &PeerVerdict = &a.verify().peers[0];
assert_eq!(dialer.round_trip, Some(true), "asked, and answered");
let answerer = &b.verify().peers[0];
assert!(!answerer.dialed, "B does not dial A, so B asks nothing of it");
assert_eq!(answerer.round_trip, None, "and reports no verdict it did not earn");
| vlastnost | typ | povinné | popis |
| runtime |
string |
ano |
Runtime klíč peera. |
| state |
LinkState → LinkState |
ano |
Postavení spojení po kole. |
| vytočeno |
boolean |
ano |
Zda tento runtime peera vytáčí (a tedy s ním nyní provedl kolo). |
| round_trip |
boolean | null |
ne |
Zda kolo uspělo; None, když peer volá tento runtime místo toho. |
| rtt_ms |
integer | null |
ne |
Cesta tam a zpět, milisekundy. |
| sbíhá |
boolean | null |
ne |
Zda obě strany po kole drží stejnou horní hranici každého streamu. |
| detail |
string |
ano |
Co se stalo. |
Používá MeshVerifyReport
PeerView
object
Jeden peer tak, jak ho ukazuje každý povrch: kdo to je, jak ho tento runtime oslovuje a čím si spojení prošlo. Čítače se nesou na peera, nejen v součtech, protože otázka, kterou si člověk u kolísajícího meshe klade, je, který peer kolísá, a
restarts odpovídá na jinou než
reconnects — peer, jehož proces stále umírá, proti spojení, které stále padá pod procesem, který nikdy nespadl.
#### use std::collections::BTreeMap;
#### use std::sync::{Arc, Mutex, Weak};
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::*;
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::{LinkReply, LinkTransport, Signed, HELLO_PATH};
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};
#### use majordomus_cli::mesh::trust::TrustPolicy;
#### #[derive(Default)] struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);
#### impl LinkTransport for Net {
#### fn post(&self, e: &str, p: &str, m: &Signed) -> Result<LinkReply, String> {
#### let peer = (self.0.lock().unwrap().get(e).and_then(Weak::upgrade))
#### .ok_or_else(|| format!("{e}: nobody there"))?;
#### Ok(if p == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) }) } }
#### let net = Arc::new(Net::default());
#### let runtime = |endpoint: &str| { let c = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: runtime_id(endpoint),
#### repository: of_root_commits(&["root".into()]), endpoints: vec![endpoint.into()],
#### version: "doc".into(), config: CooperationConfig::default(),
#### trust: TrustConfig { policy: TrustPolicy::Tofu, allow: vec![] }, journal_path: None,
#### registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::clone(&net) as Arc<dyn LinkTransport>, board: None,
#### checkout: CheckoutFacts::default() }).unwrap();
#### net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c)); c };
#### let (a, b) = (runtime("a:1"), runtime("b:1"));
a.dial(&["b:1".into()]).unwrap();
let peer: &PeerView = &a.peers()[0];
assert_eq!(peer.runtime, b.runtime_key(), "the durable identity, not the endpoint");
assert!(peer.outbound, "this runtime dials it");
assert_eq!(peer.handshakes, 1);
assert_eq!(peer.restarts, 0, "the peer's process has not died under the link");
| vlastnost | typ | povinné | popis |
| runtime |
string |
ano |
<node>-<runtime>: trvalá identita peera. |
| uzel |
string |
ano |
Uzel (digest klíče stroje). |
| instance |
string |
ano |
Aktuální instance. |
| název |
string |
ano |
Zobrazované jméno uzlu. |
| verze |
string |
ano |
Verze spustitelného souboru. |
| lokální |
boolean |
ano |
Zda peer běží na tomto stroji (stejný klíč uzlu). |
| důvěra |
TrustState → TrustState |
ano |
Verdikt důvěry, pod nímž byl link přijat. |
| protocol |
integer (uint32) |
ano |
Vyjednaný protokol linku. |
| funkce |
array of string |
ano |
Funkce spojení, které peer nese. |
| endpointy |
array of string |
ano |
Kde peer odpovídá. |
| state |
LinkState → LinkState |
ano |
Postavení odkazu. |
| odchozí |
boolean |
ano |
Zda tento runtime peera vytáčí. |
| příchozí |
boolean |
ano |
Zda peer volá tento runtime. |
| endpoint |
string | null |
ne |
Endpoint, který tento runtime vytáčí, když vytáčí. |
| last_exchange_ms |
integer | null |
ne |
Milisekundy od poslední úspěšné výměny v kterémkoli směru. |
| rtt_ms |
integer | null |
ne |
Poslední round trip, milisekundy. |
| selhání |
integer (uint32) |
ano |
Po sobě jdoucí selhaná kola. |
| last_error |
string | null |
ne |
Poslední selhání slovy. |
| handshaky |
integer (uint64) |
ano |
Dokončená handshaky s tímto peerem. |
| opětovná připojení |
integer (uint64) |
ano |
Handshaky po vypršení nebo přerušeném spojení. |
| restarty |
integer (uint64) |
ano |
Nové instance viděného peera (jeho proces se restartoval). |
| linked_at |
string |
ano |
Kdy bylo aktuální spojení navázáno, RFC 3339. |
Používá CooperationStatus RuntimeNode
Presence
"present" | "absent"
Zda uzel nyní odpovídá, podle svých vlastních oznámení.
presentInzerát dorazil do PRESENCE_TTL.absentNic v rámci TTL; uzel může být pryč nebo nedostupný. Zůstává vypsán, dokud neuplyne RETENTION, poté zcela vyprší.
Používá NodeRecord
Protokol
"udp" | "tcp"
Transportní protokol pravidla: objevování jsou datagramy, registrace a linkový protokol jsou spojení. Serializováno jako slovo, které bere front firewallu.
use majordomus_cli::mesh::firewall::Protocol;
assert_eq!(serde_json::to_value(Protocol::Udp).unwrap(), "udp");
assert_eq!(serde_json::to_value(Protocol::Tcp).unwrap(), "tcp");
udpDatagramy: zjišťování.tcpSpojení: registrace hubu a protokol linku.
Používá FirewallRule
ProviderStatus
object
Stav jednoho poskytovatele: stav, proč a jeho čítače.
| vlastnost | typ | povinné | popis |
| id |
string |
ano |
Id providera: udp_multicast, udp_broadcast, rendezvous, synthetic. |
| state |
MeshProviderState → MeshProviderState |
ano |
Stav. |
| detail |
string | null |
ne |
Proč, když Failed; co sleduje, když Running. |
| odesláno |
integer (uint64) |
ano |
Odeslaná oznámení. |
| přijato |
integer (uint64) |
ano |
Datagramy zaslechnuté a předané manažeru. |
Používá MeshStatus
PublicIdentity
object
Co smí o tomto uzlu vědět každý: id, veřejný klíč, zobrazované jméno a instance tohoto běhu. Vše, co inzerát nese; nic, co podepisuje.
| vlastnost | typ | povinné | popis |
| node_id |
NodeId → NodeId |
ano |
Id uzlu: digest veřejného klíče. |
| public_key |
string |
ano |
Veřejný klíč Ed25519, 64 hexadecimálních znaků. Kdo drží odpovídající tajný klíč, je tento uzel; jiný důkaz neexistuje. |
| display_name |
string |
ano |
Lidský název uzlu ze souboru identity; výchozí je prvních osm znaků id uzlu. Jen prezentace — nikdy se nepoužívá pro důvěru. |
| instance_id |
InstanceId → InstanceId |
ano |
Tento běh uzlu. |
Používá MeshIdentityReport MeshStatus
RefusalCode
"malformed" | "oversized" | "protocol_unsupported" | "signature" | "stale" | "replay" | "repository_mismatch" | "untrusted" | "self_link" | "not_active" | "unknown_link" | "capacity" | "feature_unsupported" | "misaddressed"
Proč byla zpráva spojení odmítnuta. Každé odmítnutí je typované, spočítané a zobrazené: mesh, který peera odmítne, říká, které pravidlo to udělalo, místo aby zahodil socket.
Kódy jsou diagnóza, kterou člověk potřebuje, když se dva runtimy nepropojí, a jsou záměrně různé tam, kde se nápravy liší: Untrusted je klíč k přidání, RepositoryMismatch jsou dva různé repozitáře, SelfLink je konfigurace, která volá vlastní endpoint, a UnknownLink není vůbec selhání, ale pokyn pozdravit znovu.
use majordomus_cli::mesh::link::RefusalCode;
// the wire word is the code's identity across surfaces, and it is stable
assert_eq!(RefusalCode::RepositoryMismatch.as_str(), "repository_mismatch");
assert_eq!(
serde_json::to_value(RefusalCode::Untrusted).unwrap(),
serde_json::json!("untrusted"),
);
assert_ne!(RefusalCode::Untrusted, RefusalCode::RepositoryMismatch);
malformedNe tvar zprávy.oversizedPřes MAX_LINK_MESSAGE.protocol_unsupportedRozsahy protokolu se nepotkávají.signaturePodpis se neověřuje.staleČasové razítko je mimo okno skew.replayNonce nebo čítač, který už byl viděn.repository_mismatchPeer slouží jinému repozitáři: pravidlo izolace.untrustedKlíči peera politika tohoto runtime nedůvěřuje: objevení není důvěra.self_linkPeer je právě tento runtime.not_activeSpolupráce tohoto runtime není aktivní.unknown_linkId spoje je zde neznámé: odpovídající se restartoval nebo spoj vypršel; pozdravte znovu.capacityHranice tohoto runtime je plná.feature_unsupportedPeerovi chybí funkce, kterou operace potřebuje.misaddressedHello adresované jinému runtime: zachyceno na cestě tam a přehráno zde.
Používá LinkRefusal
Odmítnutí
object
Odmítnuté datagramy podle důvodu. Diagnóza nepřátelské nebo špatně nakonfigurované sítě: mesh, který slyší nesmysly, to říká s čísly, místo aby byl tiše prázdný.
| vlastnost | typ | povinné | popis |
| příliš velké |
integer (uint64) |
ano |
Delší než hranice datagramu. |
| poškozeno |
integer (uint64) |
ano |
Není to obálka. |
| verze |
integer (uint64) |
ano |
Verze protokolu, kterou tento spustitelný soubor nečte. |
| meze |
integer (uint64) |
ano |
Pole mimo meze. |
| zastaralé |
integer (uint64) |
ano |
Mimo okno posunu hodin. |
| podpis |
integer (uint64) |
ano |
Podpis, který se neověří. |
| self_heard |
integer (uint64) |
ano |
Datagramy tohoto uzlu samotného, slyšené zpět a přeskočené. |
| přetečení |
integer (uint64) |
ne |
Pozorování zahozená, protože fronta k registru byla plná: záplava, počítaná, nikoli držená (I2133). |
Používá MeshStatus
RefusedView
object
Kandidát, který byl odmítnut, s pravidlem, které jej odmítlo. Odmítnutí se uchovává a zobrazuje, ne logovat a zahodit, protože nejčastějším selháním meshe je spojení, které se nikdy nevytvoří: osoba, která deklarovala seed a nevidí žádného peera, potřebuje rozhodnutí, které o něm padlo — špatný repozitář, klíč, který nikdo nepovolil, příliš velká odchylka hodin — a směr říká, která strana je učinila.
#### use std::collections::BTreeMap;
#### use std::sync::{Arc, Mutex, Weak};
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::*;
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::{LinkReply, LinkTransport, RefusalCode, Signed, HELLO_PATH};
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::{of_root_commits, runtime_id};
#### use majordomus_cli::mesh::trust::TrustPolicy;
#### #[derive(Default)] struct Net(Mutex<BTreeMap<String, Weak<Cooperation>>>);
#### impl LinkTransport for Net {
#### fn post(&self, e: &str, p: &str, m: &Signed) -> Result<LinkReply, String> {
#### let peer = (self.0.lock().unwrap().get(e).and_then(Weak::upgrade))
#### .ok_or_else(|| format!("{e}: nobody there"))?;
#### Ok(if p == HELLO_PATH { peer.accept_hello(m) } else { peer.accept_sync(m) }) } }
#### let net = Arc::new(Net::default());
#### let runtime = |endpoint: &str, policy: TrustPolicy| {
#### let c = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: runtime_id(endpoint),
#### repository: of_root_commits(&["root".into()]), endpoints: vec![endpoint.into()],
#### version: "doc".into(), config: CooperationConfig::default(),
#### trust: TrustConfig { policy, allow: vec![] }, journal_path: None,
#### registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::clone(&net) as Arc<dyn LinkTransport>, board: None,
#### checkout: CheckoutFacts::default() }).unwrap();
#### net.0.lock().unwrap().insert(endpoint.into(), Arc::downgrade(&c)); c };
#### let a = runtime("a:1", TrustPolicy::Tofu);
#### let strict = runtime("s:1", TrustPolicy::DenyUnknown);
a.dial(&["s:1".into()]).expect_err("reachable, and not trusted");
let refused: &RefusedView = &strict.status().refused[0];
assert_eq!(refused.refusal.code, RefusalCode::Untrusted);
assert_eq!(refused.direction, "inbound", "this runtime refused the hello");
assert_eq!(refused.runtime.as_deref(), Some(a.runtime_key()));
| vlastnost | typ | povinné | popis |
| endpoint |
string |
ano |
Volaný endpoint, nebo inbound:<runtime> pro odmítnuté hello. |
| směr |
string |
ano |
outbound (tento runtime odmítl uvítání peera nebo peer odmítl tento hello) nebo inbound (tento runtime odmítl hello peera). |
| runtime |
string | null |
ne |
Klíč runtimu peera, když ho uvedla jeho karta. |
| odmítnutí |
LinkRefusal → LinkRefusal |
ano |
Odmítnutí. |
| v |
string |
ano |
Kdy, RFC 3339. |
Používá CooperationStatus PeerDetail PeerTree
RegisterAnswer
object
Co odpovídá registrace: zda byla obálka přijata a kandidáty, které rendezvous drží. Definováno zde vedle klienta; schopnost to znovu exportuje.
| vlastnost | typ | povinné | popis |
| přijato |
boolean |
ano |
Zda byla předložená obálka přijata do lokálního registru. |
| odmítnutí |
string | null |
ne |
Proč ne, když nebylo. |
| candidates |
pole Envelope → Envelope |
ano |
Podepsané obálky uzlů, které tento rendezvous právě drží, včetně uzlu odpovídajícího. Každá se ověřuje vlastním podpisem; rendezvous za nic neručí. |
Používá mesh.register
RegisterInput
object
Vstup mesh.register: jedna podepsaná obálka přesně tak, jak ji nese drát.
| vlastnost | typ | povinné | popis |
| obálka |
libovolný |
ano |
Obálka. Zde ověřená přesně jako datagram — meze, zastaralost, podpis — dřív, než se cokoli zaznamená. |
Používá mesh.register
ReleaseInput
object
Vstup mesh.release.
| vlastnost | typ | povinné | popis |
| claim |
string |
ano |
Klíč tvrzení, <stream>/<claim>, tak, jak na něj odpovědělo mesh.claim. |
Používá mesh.release
ReviewAnswer
object
Jedna odpověď na žádost o review: kdo odpověděl, jak rozhodl a proč. Verdikt je jedno ze tří deklarovaných slov, takže žadatel podle něj může jednat, aniž by četl poznámku; poznámka je místo pro zdůvodnění a je volitelná, protože „schváleno“ ji často nepotřebuje.
use majordomus_cli::mesh::state::ReviewAnswer;
let answer = ReviewAnswer {
session: "a1b2c3d4-r1-0f/s2".into(),
verdict: "changes_requested".into(),
note: Some("the fold is not deterministic".into()),
};
assert_eq!(answer.verdict, "changes_requested");
// the note is omitted rather than carried empty when there is nothing to say
let bare = ReviewAnswer { note: None, ..answer };
let value = serde_json::to_value(&bare).unwrap();
assert!(value.get("note").is_none());
| vlastnost | typ | povinné | popis |
| session |
string |
ano |
Klíč odpovídající relace. |
| verdikt |
string |
ano |
Verdikt. |
| poznámka |
string | null |
ne |
Poznámka. |
Používá ReviewView
ReviewAnswerInput
object
Vstup mesh.review.answer.
| vlastnost | typ | povinné | popis |
| request |
string |
ano |
Klíč požadavku, <stream>/<review>. |
| session |
string | null |
ne |
Odpovídající relace; když je vynechána, vlastní relace volajícího MCP. |
| verdikt |
string |
ano |
approved, changes_requested nebo commented. |
| poznámka |
string | null |
ne |
Poznámka. |
Používá mesh.review.answer
ReviewRequestInput
object
Vstup mesh.review.request.
| vlastnost | typ | povinné | popis |
| session |
string | null |
ne |
Žádající relace; při vynechání relace volajícího MCP. |
| předmět |
string |
ano |
Co zkontrolovat: větev, commit, pull request. |
| scope |
array of string |
ne |
Cesty, které pokrývá. |
| issue |
string | null |
ne |
Úkol. |
| reviewer |
string | null |
ne |
Dotazovaný runtime (<node>-<runtime>); když je vynechán, kdokoli. |
| tělo |
string | null |
ne |
Co reviewer potřebuje navíc kromě předmětu: důkazy, příkazy, otázku. Až 8 KiB, více řádků. |
Používá mesh.review.request
ReviewState
"open" | "answered" | "withdrawn" | "expired"
Stav žádosti o posouzení: zda na ni už někdo odpověděl. Záměrně tu není
Approved ani
Rejected — na žádost může odpovědět několik runtime a verdikty jsou vlastní odpovědi, takže jejich sloučení do jednoho stavu by zahodilo neshodu, kvůli které stojí za to ptát se druhého posuzovatele.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, StreamLiveness};
use majordomus_cli::mesh::state::{fold, ReviewState};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::ReviewRequested { review: "r1".into(), session: "s1".into(),
subject: "feature/x".into(), scope: vec![], issue: None, reviewer: None, body: None }).unwrap();
let asked = fold(&j.events(), &|_| StreamLiveness::Own);
assert_eq!(asked.reviews[0].state, ReviewState::Open);
let request = asked.reviews[0].key.clone();
j.append_own(EventBody::ReviewAnswered { request, session: "s2".into(),
verdict: "approved".into(), note: None }).unwrap();
assert_eq!(fold(&j.events(), &|_| StreamLiveness::Own).reviews[0].state, ReviewState::Answered);
openNikdo neodpověděl.answeredAlespoň jedna odpověď.withdrawnRuntime, který se ptal, žádost ukončil: hotovo, zrušeno nebo překonáno. Cokoli bylo odpovězeno dříve, zůstává u něj.expiredNikdo neodpověděl a runtime, který se ptal, přestal tepat. Čtení živosti, stejně jako vypršení nároku, rozhodnuté ze žurnálu a tepů streamů, aby žádný runtime nepotřeboval hodiny jiného — runtime, který znovu tepe, se čte opět jako otevřený.
Používá ReviewView
ReviewView
object
Jedna žádost o review kdekoli v meshi se všemi odpověďmi, které vyvolala. Žádost bez
reviewer je nabídka celému meshi, nikoli nikomu, proto jsou odpovědi seznam: přidat ji může kterýkoli propojený runtime s funkcí
reviews a jsou uloženy v Lamportově pořadí, aby je každý runtime četl ve stejné posloupnosti.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, StreamLiveness};
use majordomus_cli::mesh::state::{fold, ReviewView};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::ReviewRequested { review: "r1".into(), session: "s1".into(),
subject: "feature/mesh-cooperation".into(), scope: vec!["src/mesh".into()],
issue: Some("#184".into()), reviewer: None, body: None }).unwrap();
let request = fold(&j.events(), &|_| StreamLiveness::Own).reviews[0].key.clone();
j.append_own(EventBody::ReviewAnswered { request, session: "s2".into(),
verdict: "approved".into(), note: Some("reads well".into()) }).unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
let review: &ReviewView = &state.reviews[0];
assert_eq!(review.subject, "feature/mesh-cooperation");
assert_eq!(review.reviewer, None, "offered to the mesh, not addressed");
assert_eq!(review.answers[0].verdict, "approved");
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<review>. |
| session |
string |
ano |
Klíč žádající relace. |
| předmět |
string |
ano |
Co se má zrecenzovat. |
| scope |
array of string |
ano |
Cesty, které pokrývá. |
| issue |
string | null |
ne |
Úkol. |
| reviewer |
string | null |
ne |
Runtime, na který se ptalo, pokud nějaký byl. |
| tělo |
string | null |
ne |
Co recenzent potřebuje nad rámec předmětu, když to žadatel napsal. |
| state |
ReviewState → ReviewState |
ano |
Jeho postavení. |
| odpovědi |
pole ReviewAnswer → ReviewAnswer |
ano |
Odpovědi v Lamportově pořadí. |
| výsledek |
string | null |
ne |
Vlastní výsledek nebo důvod žadatele, zapsaný, když žádost stáhl. Nikdy odpověď: review je verdikt jiné relace. |
Používá CooperationState
ReviewWithdrawInput
object
Vstup mesh.review.withdraw.
| vlastnost | typ | povinné | popis |
| request |
string |
ano |
Klíč požadavku, <stream>/<review>. |
| session |
string | null |
ne |
Relace, která stahuje, ze tázajícího se runtime; pokud chybí, vlastní relace volajícího MCP. |
| poznámka |
string | null |
ne |
Výsledek nebo důvod žadatele, nejvýše 8 KiB: co z toho vzešlo, nebo proč je neplatné. |
Používá mesh.review.withdraw
Role
"multicast" | "broadcast" | "hub" | "link"
Proč pravidlo existuje: která část deklarace jej implikovala. Role je to, co člověk čte vedle pravidla a co jmenuje verdikt, a serializuje se v snake case.
use majordomus_cli::mesh::firewall::Role;
assert_eq!(serde_json::to_value(Role::Hub).unwrap(), "hub");
let back: Role = serde_json::from_value(serde_json::json!("multicast")).unwrap();
assert_eq!(back, Role::Multicast);
multicastDeklarovaná multicastová skupina: každý runtime segmentu se do ní inzeruje.broadcastDeklarovaný broadcastový port, když je broadcast povolenou záložní možností.hubTento stroj je deklarovaný rendezvous hub: flotila se registruje zde.linkServer tohoto stroje oslovují peerové protokolem linku.
Používá FirewallRule
RuntimeNode
object
Jeden runtime ve stromě peerů.
| vlastnost | typ | povinné | popis |
| runtime |
string |
ano |
<node>-<runtime>. |
| this_runtime |
boolean |
ano |
Zda je to runtime, který odpovídá. |
| živost |
StreamLiveness → StreamLiveness |
ano |
Zda jeho stream tepe: own, live, nebo expired. |
| last_beat_ms |
integer | null |
ne |
Milisekundy od posledního vzrůstu jeho tepu, podle hodin tohoto runtime. |
| odkaz |
PeerView | null → PeerView |
ne |
Linka tohoto runtimu k němu, pokud existuje. |
| newest_claim |
MeshClaimBrief | null → MeshClaimBrief |
ne |
Jeho nejnovější živý claim, řečeno stručně. |
| relace |
pole SessionNode → SessionNode |
ano |
Jeho relace; v souhrnném pohledu jen aktivní. |
Používá MachineNode PeerDetail
SessionCloseInput
object
Vstup mesh.session.close.
| vlastnost | typ | povinné | popis |
| session |
string | null |
ne |
Relace; pokud chybí, vlastní relace volajícího MCP. |
Používá mesh.session.close
SessionInfo
object
Co relace o sobě sděluje meshi. Každé pole je veřejný fakt o rozpracované práci; žádné není cestou na disku autora, tajemstvím ani přihlašovacím údajem.
Téměř vše zde je volitelné a to je návrh: relace říká, co ví, a pole, které vynechá, se vynechá, ne nese prázdné, takže čtenář odliší „žádná úloha“ od „úloha, která se nejmenuje nijak“. Opětovné otevření téhož id relace tento záznam nahradí, a tak relace, která svou větev zjistí později, informuje mesh.
use majordomus_cli::mesh::journal::SessionInfo;
let mut info = SessionInfo::named("s1", "claude-code");
assert_eq!(info.task, None);
assert!(serde_json::to_value(&info).unwrap().get("task").is_none(), "unsaid, not empty");
info.branch = Some("feature/mesh-cooperation".into());
assert_eq!(serde_json::to_value(&info).unwrap()["branch"], "feature/mesh-cooperation");
| vlastnost | typ | povinné | popis |
| session |
string |
ano |
Id relace v rámci jejího proudu. |
| klient |
string |
ano |
Klient: claude-code, codex, cli, ... |
| worker |
string | null |
ne |
Vlastní jméno workera pro sebe, pokud nějaké uvedl. |
| intent |
string | null |
ne |
Co relace říká, že dělá. |
| úloha |
string | null |
ne |
Id úlohy (t-...), pod níž relace pracuje. |
| issue |
string | null |
ne |
Úkol (I0001, #184), ke kterému práce patří. |
| milestone |
string | null |
ne |
Milník, ke kterému práce patří. |
| checkout |
string | null |
ne |
Id checkoutu (digest, nikdy cesta). |
| větev |
string | null |
ne |
Checkoutnutá větev. |
| head |
string | null |
ne |
Commit, který je vyčerpán. |
| špinavé |
boolean | null |
ne |
Zda měl pracovní strom v okamžiku výroku nepotvrzené změny. |
| kontext |
string | null |
ne |
Revize kontextu, ze které relace vychází (digest, který jmenuje kompilátor kontextu). |
Používá SessionNode SessionView
SessionInput
object
Vstup mesh.session.open: co relace říká sama o sobě.
| vlastnost | typ | povinné | popis |
| session |
string | null |
ne |
Id relace v tomto runtimu; při vynechání relace volajícího MCP. |
| klient |
string | null |
ne |
Klient (claude-code, codex, cli); cli, když chybí. |
| worker |
string | null |
ne |
Jméno, kterým se worker označuje sám. |
| intent |
string | null |
ne |
Co dělá. |
| úloha |
string | null |
ne |
Id úlohy. |
| issue |
string | null |
ne |
Úkol. |
| milestone |
string | null |
ne |
Milník. |
| větev |
string | null |
ne |
Větev. |
| head |
string | null |
ne |
Hlava. |
| špinavé |
boolean | null |
ne |
Zda je pracovní strom špinavý. |
| kontext |
string | null |
ne |
Revize kontextu, ze které vychází. |
Používá mesh.session.open
SessionNode
object
Jedna relace ve stromu peerů.
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<session>. |
| info |
SessionInfo → SessionInfo |
ano |
Co relace naposledy řekla sama o sobě. |
| state |
SessionState → SessionState |
ano |
Jeho postavení. |
| tvrzení |
pole ClaimView → ClaimView |
ano |
Claimy, které drží nebo držel; v souhrnném pohledu prázdné, kde se místo toho počítají. |
| claims_held |
integer (uint) |
ano |
Kolik z jeho tvrzení je živých. |
| recenze |
array of string |
ano |
Žádosti o review, které otevřela, podle klíče. |
Používá RuntimeNode
SessionState
"active" | "closed" | "expired"
Postavení relace, jak ho čte každý runtime meshe. Důležitý je rozdíl mezi
Closed a
Expired: první je relace, která řekla, že skončila, druhá taková, jejíž runtime přestal tepat a už nemůže říct nic. Obě ukončují nároky relace, ale jen druhá je stroj, od kterého by nikdo neměl čekat odpověď.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, SessionInfo, StreamLiveness};
use majordomus_cli::mesh::state::{fold, SessionState};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionOpened { info: SessionInfo::named("s1", "cli") }).unwrap();
assert_eq!(fold(&j.events(), &|_| StreamLiveness::Own).sessions[0].state, SessionState::Active);
// the same events, read on a runtime that no longer hears the writer
let gone = fold(&j.events(), &|_| StreamLiveness::Expired);
assert_eq!(gone.sessions[0].state, SessionState::Expired);
activeOtevřeno a jeho runtime žije.closedUzavřeno vlastním runtime.expiredNikdy neuzavřena, ale její runtime přestal tepat: pryč, pokud je to komukoli známo.
Používá SessionNode SessionView
SessionView
object
Jedna relace kdekoli v meshi, jak ji vidí fold: co o sobě relace řekla, odkud píše a zda se stále počítá. Klíčem je
<stream>/<session>, nikoli vlastní id relace, protože dva runtimy mohou obě relace nazvat
s1 a mesh je musí udržet odděleně.
use std::sync::Arc;
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::journal::{EventBody, Journal, SessionInfo, StreamLiveness};
use majordomus_cli::mesh::state::{fold, SessionView};
let j = Journal::open(Arc::new(NodeIdentity::ephemeral().unwrap()), "0000000000000001",
"repo".into(), None).unwrap();
j.append_own(EventBody::SessionOpened { info: SessionInfo::named("s1", "claude-code") })
.unwrap();
let state = fold(&j.events(), &|_| StreamLiveness::Own);
let view: &SessionView = &state.sessions[0];
assert!(view.key.ends_with("/s1"), "qualified by the stream that wrote it: {}", view.key);
assert_eq!(view.info.client, "claude-code");
assert_eq!(view.runtime, view.stream.runtime_key());
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<session>: jedinečné napříč meshem. |
| proud |
StreamId → StreamId |
ano |
Zapisovací stream. |
| runtime |
string |
ano |
<node>-<runtime>. |
| uzel |
string |
ano |
Uzel (stroj). |
| info |
SessionInfo → SessionInfo |
ano |
Co relace naposledy řekla sama o sobě. |
| state |
SessionState → SessionState |
ano |
Jeho postavení. |
| updated_lamport |
integer (uint64) |
ano |
Lamportovo razítko jeho posledního slova. |
Používá CooperationState
Spatření
object
Jedna položka provenance: zdroj a odkud pozorování fyzicky pochází.
| vlastnost | typ | povinné | popis |
| zdroj |
MeshSource → MeshSource |
ano |
Druh poskytovatele, který to viděl. |
| path |
string |
ano |
Síťová cesta jako text: adresa odesílatele, rozhraní, URL rendezvous. |
| v |
string |
ano |
Kdy, RFC 3339. |
Používá NodeRecord
Podepsáno
object
Podepsaná zpráva: tělo JSON a podpis Ed25519 nad jeho kanonickými bajty pod doménou zprávy. Tělo zůstává JSON, aby pole, která přidá novější peer, přežila zdejší ověření beze změny.
Uchování těla jako JSON, a ne jako bajtů, které byly podepsány, činí protokol rozšiřitelným: pole, které přidal novější peer, projde ověřením nedotčené, protože podpis se kontroluje nad kanonickou podobou všeho, co tam je, a ne nad tvarem, který tato verze zná.
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::link::{sign, verify_signed, Domain, Signed};
let node = NodeIdentity::ephemeral().unwrap();
let signed: Signed = sign(&node, Domain::SyncRequest, serde_json::json!({ "b": 2, "a": 1 }));
assert_eq!(signed.sig.len(), 128, "hex Ed25519");
// key order is not content, so a round trip through JSON still verifies
let wire = serde_json::to_string(&signed).unwrap();
let back: Signed = serde_json::from_str(&wire).unwrap();
assert!(verify_signed(&node.public.public_key, Domain::SyncRequest, &back));
| vlastnost | typ | povinné | popis |
| tělo |
libovolný |
ano |
Zpráva. |
| sig |
string |
ano |
Hex Ed25519 přes doménu a kanonický JSON body. |
Používá mesh.link.hello mesh.link.sync LinkReply
StreamId
string
Jeden proud: běh jednoho runtimu jednoho uzlu.
<node 32 hex>-<runtime 16 hex>-<instance 16 hex>. Uzel je klíč stroje, runtime je server jednoho checkoutu na tom stroji, instance je jeden běh procesu tohoto serveru — takže dva worktrees na jednom stroji jsou dva proudy a restart je nový proud téhož runtimu.
Číslování událostí uvnitř streamu místo globálně činí replikaci levnou a jednoznačnou: mezera v jednom streamu je viditelná bez koordinace s kýmkoli a (stream, seq) identifikuje událost na každém stroji, který ji drží.
use majordomus_cli::mesh::journal::StreamId;
let id = StreamId::new(&"a".repeat(32), &"b".repeat(16), &"c".repeat(16)).unwrap();
assert_eq!(id.node(), "a".repeat(32));
assert_eq!(id.runtime(), "b".repeat(16));
// a restart is a new stream, and the same runtime
let after = StreamId::new(&"a".repeat(32), &"b".repeat(16), &"d".repeat(16)).unwrap();
assert_ne!(after, id);
assert_eq!(after.runtime_key(), id.runtime_key());
Používá ClaimView CooperationStatus HandoverView MeshEvent SessionView StreamView
StreamLiveness
"own" | "live" | "expired"
Zda proud právě mluví, podle hodin tohoto runtime. Je to verdikt o proudu, ne o spojení: runtime dosažitelný jen přes relay žije a runtime, který spadl, přestane tepat pro všechny najednou.
Own se drží stranou od
Live, protože vlastní proud runtime nepotřebuje důkaz — je to ta věc, která tepe.
use majordomus_cli::mesh::journal::StreamLiveness;
assert!(StreamLiveness::Own.is_alive() && StreamLiveness::Live.is_alive());
assert!(!StreamLiveness::Expired.is_alive());
assert_eq!(
serde_json::to_value(StreamLiveness::Expired).unwrap(),
serde_json::json!("expired"),
);
ownAktuální vlastní proud tohoto běhu.liveJeho tep stoupl v rámci vypršení.expiredJeho tep nevzrostl v rámci expirace, nebo nebyl nikdy slyšet.
Používá MeshRuntimeSummary RuntimeNode StreamView
StreamView
object
Živost jednoho proudu.
| vlastnost | typ | povinné | popis |
| proud |
StreamId → StreamId |
ano |
Proud. |
| živost |
StreamLiveness → StreamLiveness |
ano |
Vlastní, živý nebo vypršelý. |
| last_beat_ms |
integer | null |
ne |
Milisekundy od okamžiku, kdy se jeho tep zvedl. |
Používá MeshStateAnswer
Součty
object
Součty registru pro stav a zdraví.
| vlastnost | typ | povinné | popis |
| nodes |
integer (uint) |
ano |
Držené záznamy. |
| důvěryhodné |
integer (uint) |
ano |
Z nich důvěryhodných. |
| přítomno |
integer (uint) |
ano |
Z toho přítomných. |
| přijato |
integer (uint64) |
ano |
Pozorování přijatá od startu. |
| přehráno |
integer (uint64) |
ano |
Přehrané datagramy zahozené od startu. |
| vypršelo |
integer (uint64) |
ano |
Záznamy, jejichž platnost od startu vypršela. |
| vytlačeno |
integer (uint64) |
ano |
Záznamy vytlačené od startu kvůli místu. |
Používá MeshStatus
TrustState
jedna ze 3 variant
O čem politika rozhodla u jednoho uzlu.
variant Platný, zaznamenaný, ničemu nedůvěryhodný. Klidový stav neznámého uzlu.
variant Politika tomuto klíči důvěřuje; detail říká, které pravidlo (allowlist, tofu).
| state | "trusted" | ano | |
| detail | string | ano | |
varianta Politika tento uzel odmítla; detail říká proč (například změna klíče TOFU). Odmítnutý uzel zůstává vypsán — operátor ladící mesh potřebuje vidět, co bylo odmítnuto, a ne se divit mlčení.
| state | "rejected" | ano | |
| detail | string | ano | |
Používá NodeRecord PeerView
Zapsáno
object
Co operace zapsala, jako její odpověď volajícímu. Každá operace mesh je událost připojená do žurnálu tohoto runtime a volající dostane tři fakta, která si sám nezjistí: klíč vytvořené věci platný v celém mesh, událost, která to oznamuje, a Lamportovo razítko, které ji řadí vůči událostem všech ostatních.
Klíč je to, čím se adresuje pozdější operace — claim se uvolňuje klíčem, který vrátilo jeho získání, nikdy lokálním jménem, které dostal — a razítko je to, s čím porovnává volající, který čeká, až peer dožene stav.
#### use std::sync::Arc;
#### use majordomus_cli::mesh::config::{CooperationConfig, TrustConfig};
#### use majordomus_cli::mesh::cooperation::{CheckoutFacts, Cooperation, CooperationSetup};
#### use majordomus_cli::mesh::identity::NodeIdentity;
#### use majordomus_cli::mesh::link::HttpTransport;
#### use majordomus_cli::mesh::registry::MeshRegistry;
#### use majordomus_cli::mesh::repository::of_root_commits;
#### let cooperation = Cooperation::new(CooperationSetup {
#### identity: Arc::new(NodeIdentity::ephemeral().unwrap()), runtime: "0000000000000001".into(),
#### repository: of_root_commits(&["root".into()]), endpoints: vec!["127.0.0.1:9".into()],
#### version: "doc".into(), config: CooperationConfig::default(), trust: TrustConfig::default(),
#### journal_path: None, registry: Arc::new(MeshRegistry::new()),
#### transport: Arc::new(HttpTransport), board: None, checkout: CheckoutFacts::default(),
#### }).unwrap();
use majordomus_cli::mesh::cooperation::Written;
use majordomus_cli::mesh::journal::{ClaimMode, Durability, SessionInfo};
let session = SessionInfo::named("s1", "cli");
let written: Written = cooperation
.claim(&session, vec!["docs".into()], None, ClaimMode::Advisory, None)
.unwrap();
assert!(written.lamport > 0, "placed against every other runtime's events");
assert_eq!(written.durability, Durability::Memory, "this journal has no file");
// and the key it returned is how the claim is addressed from here on
cooperation.release(&written.key).unwrap();
| vlastnost | typ | povinné | popis |
| klíč |
string |
ano |
<stream>/<local id> toho, co bylo vytvořeno nebo změněno. |
| událost |
string |
ano |
<stream>/<seq> události, která to oznamuje. |
| lamport |
integer (uint64) |
ano |
Lamportovo razítko události. |
| odolnost |
Durability → Durability |
ne |
Zda událost dorazila na disk tohoto stroje: synced, memory (žurnál bez souboru, konfigurací), nebo not_durable — držená a replikovaná peerům, na disku zde není a není potvrzena jako trvalá. unknown od spustitelného souboru, který ji předchází. |
Používá mesh.claim mesh.release mesh.handover.publish mesh.review.request mesh.review.answer mesh.review.withdraw mesh.session.open mesh.session.close ConsumeAnswer