mesh.link.hello
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.
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í
- modul mesh
- #mesh
- #cooperation
- #link
Zpřístupnění
Kde je tato jedna definice dosažitelná. Absence je explicitní: povrch, který není uveden, ji nenese.
| povrch | jako |
|---|---|
| MCP | — |
| HTTP | POST /api/v1/mesh/link/hello operationId mesh.link.hello |
| příkazová řádka | — |
Schémata
Kanonický vstup a výstup z typů Rustu; schéma nástroje MCP a parametry a odpovědi OpenAPI se odvozují z nich.
vstup · Podepsáno
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 | object | ano | Zpráva. |
| sig | string | ano | Hex Ed25519 přes doménu a kanonický JSON body. |
JSON Schema
{
"description": "A signed message: a JSON body and the Ed25519 signature over its canonical bytes under\nthe message's domain. The body stays JSON so that fields a newer peer adds survive\nverification here unchanged.\n\nKeeping the body as JSON rather than as the bytes that were signed is what makes the\nprotocol extensible: a field a newer peer added is carried through verification\nuntouched, because the signature is checked over the canonical form of whatever is\nthere rather than over a shape this version knows.\n\n```\nuse majordomus_cli::mesh::identity::NodeIdentity;\nuse majordomus_cli::mesh::link::{sign, verify_signed, Domain, Signed};\n\nlet node = NodeIdentity::ephemeral().unwrap();\nlet signed: Signed = sign(&node, Domain::SyncRequest, serde_json::json!({ \"b\": 2, \"a\": 1 }));\nassert_eq!(signed.sig.len(), 128, \"hex Ed25519\");\n\n// key order is not content, so a round trip through JSON still verifies\nlet wire = serde_json::to_string(&signed).unwrap();\nlet back: Signed = serde_json::from_str(&wire).unwrap();\nassert!(verify_signed(&node.public.public_key, Domain::SyncRequest, &back));\n```",
"properties": {
"body": {
"description": "The message."
},
"sig": {
"description": "Hex Ed25519 over the domain and the canonical JSON of `body`.",
"type": "string"
}
},
"required": [
"body",
"sig"
],
"title": "Signed",
"type": "object"
}výstup · LinkReply
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 |
|---|---|---|---|
| odmítnutí | jedno ze 2 | ne | Odmítnutí, když ne. |
| podepsáno | jedno ze 2 | ne | Podepsaná odpověď welcome nebo sync, pokud byla přijata. |
JSON Schema
{
"$defs": {
"LinkRefusal": {
"description": "A refusal: the code, the reason in words, and the protocol range of the refuser so a\nversion mismatch is diagnosable from either end.\n\nCarrying the refuser's protocol range in every refusal, not only in the one about\nprotocols, is what makes a version problem visible from the side that has the log: the\ndialer sees what the answerer speaks without anyone having to read the other machine.\n\n```\nuse majordomus_cli::mesh::link::{LinkRefusal, RefusalCode, LINK_PROTOCOL_MAX};\n\nlet refusal = LinkRefusal::new(RefusalCode::Untrusted, \"the key is not in the allowlist\");\nassert_eq!(refusal.code, RefusalCode::Untrusted);\nassert_eq!(refusal.proto_max, LINK_PROTOCOL_MAX);\nassert_eq!(refusal.to_string(), \"untrusted: the key is not in the allowlist\");\n```",
"properties": {
"code": {
"$ref": "#/$defs/RefusalCode",
"description": "The rule that refused."
},
"detail": {
"description": "Why, in words.",
"type": "string"
},
"proto_max": {
"description": "The refuser's newest protocol.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"proto_min": {
"description": "The refuser's oldest protocol.",
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"code",
"detail",
"proto_min",
"proto_max"
],
"type": "object"
},
"RefusalCode": {
"description": "Why a link message was turned down. Every refusal is typed, counted and shown: a mesh\nthat refuses a peer says which rule did, instead of dropping a socket.\n\nThe codes are the diagnosis a person needs when two runtimes will not link, and they\nare deliberately distinct where the remedies differ: `Untrusted` is a key to add,\n`RepositoryMismatch` is two different repositories, `SelfLink` is a configuration that\ndials its own endpoint, and `UnknownLink` is not a failure at all but an instruction to\nsay hello again.\n\n```\nuse majordomus_cli::mesh::link::RefusalCode;\n\n// the wire word is the code's identity across surfaces, and it is stable\nassert_eq!(RefusalCode::RepositoryMismatch.as_str(), \"repository_mismatch\");\nassert_eq!(\n serde_json::to_value(RefusalCode::Untrusted).unwrap(),\n serde_json::json!(\"untrusted\"),\n);\nassert_ne!(RefusalCode::Untrusted, RefusalCode::RepositoryMismatch);\n```",
"oneOf": [
{
"const": "malformed",
"description": "Not the shape of the message.",
"type": "string"
},
{
"const": "oversized",
"description": "Over `MAX_LINK_MESSAGE`.",
"type": "string"
},
{
"const": "protocol_unsupported",
"description": "The protocol ranges do not meet.",
"type": "string"
},
{
"const": "signature",
"description": "The signature does not verify.",
"type": "string"
},
{
"const": "stale",
"description": "The timestamp is outside the skew window.",
"type": "string"
},
{
"const": "replay",
"description": "A nonce or a counter already seen.",
"type": "string"
},
{
"const": "repository_mismatch",
"description": "The peer serves another repository: the isolation rule.",
"type": "string"
},
{
"const": "untrusted",
"description": "The peer's key is not trusted by this runtime's policy: discovery is not trust.",
"type": "string"
},
{
"const": "self_link",
"description": "The peer is this very runtime.",
"type": "string"
},
{
"const": "not_active",
"description": "This runtime's cooperation is not active.",
"type": "string"
},
{
"const": "unknown_link",
"description": "The link id is unknown here: the answerer restarted or expired the link; say hello.",
"type": "string"
},
{
"const": "capacity",
"description": "A bound of this runtime is full.",
"type": "string"
},
{
"const": "feature_unsupported",
"description": "The peer lacks a feature the operation needs.",
"type": "string"
},
{
"const": "misaddressed",
"description": "A hello addressed to another runtime: captured on its way there and replayed here.",
"type": "string"
}
]
},
"Signed": {
"description": "A signed message: a JSON body and the Ed25519 signature over its canonical bytes under\nthe message's domain. The body stays JSON so that fields a newer peer adds survive\nverification here unchanged.\n\nKeeping the body as JSON rather than as the bytes that were signed is what makes the\nprotocol extensible: a field a newer peer added is carried through verification\nuntouched, because the signature is checked over the canonical form of whatever is\nthere rather than over a shape this version knows.\n\n```\nuse majordomus_cli::mesh::identity::NodeIdentity;\nuse majordomus_cli::mesh::link::{sign, verify_signed, Domain, Signed};\n\nlet node = NodeIdentity::ephemeral().unwrap();\nlet signed: Signed = sign(&node, Domain::SyncRequest, serde_json::json!({ \"b\": 2, \"a\": 1 }));\nassert_eq!(signed.sig.len(), 128, \"hex Ed25519\");\n\n// key order is not content, so a round trip through JSON still verifies\nlet wire = serde_json::to_string(&signed).unwrap();\nlet back: Signed = serde_json::from_str(&wire).unwrap();\nassert!(verify_signed(&node.public.public_key, Domain::SyncRequest, &back));\n```",
"properties": {
"body": {
"description": "The message."
},
"sig": {
"description": "Hex Ed25519 over the domain and the canonical JSON of `body`.",
"type": "string"
}
},
"required": [
"body",
"sig"
],
"type": "object"
}
},
"description": "What a hello or a sync answers over the wire: a signed message or a refusal. Both are\nsuccessful replies — the transport carries them the same way and neither is an error —\nbecause a refusal is a decision this protocol wants recorded and shown, and an answer\nthat arrived as an HTTP failure would be indistinguishable from a peer that is down.\n\n```\nuse majordomus_cli::mesh::identity::NodeIdentity;\nuse majordomus_cli::mesh::link::{sign, Domain, LinkReply, RefusalCode};\n\nlet node = NodeIdentity::ephemeral().unwrap();\nlet accepted = LinkReply::accepted(sign(&node, Domain::Welcome, serde_json::json!({})));\nassert!(accepted.signed.is_some() && accepted.refusal.is_none());\n\nlet refused = LinkReply::refused(RefusalCode::SelfLink, \"this runtime dialled itself\");\nassert!(refused.signed.is_none());\nassert_eq!(refused.refusal.unwrap().code, RefusalCode::SelfLink);\n```",
"properties": {
"refusal": {
"anyOf": [
{
"$ref": "#/$defs/LinkRefusal"
},
{
"type": "null"
}
],
"description": "The refusal, when not."
},
"signed": {
"anyOf": [
{
"$ref": "#/$defs/Signed"
},
{
"type": "null"
}
],
"description": "The signed welcome or sync answer, when accepted."
}
},
"title": "LinkReply",
"type": "object"
}Politiky
- benchmark
- povinné — cíl na každém transportu, který expozice deklaruje; případy jsou ty ze vstupního typu
- cache
- vypnuto — každé volání spustí handler
Cíle benchmarku
Odvozeno z registru pro tento repozitář: jeden požadavek na transport a případy, které poskytuje typ vstupu. Celá matice je na stránce měření výkonu.