The ask's id beside the warrant (the hand act's id), as own-retired carries it (A4's request). Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
640 lines
22 KiB
JSON
640 lines
22 KiB
JSON
{
|
|
"format": 1,
|
|
"seat": "mesh-vault",
|
|
"scope": "mesh",
|
|
"grain": "whole",
|
|
"decision": "novox/hq ADR 0161",
|
|
"delivers": "secret",
|
|
"verbs": [
|
|
{
|
|
"name": "get",
|
|
"description": "One secret, sealed to the public key the asker sends (the sealed box of ADR 0206), with its generation; answered only to an asker the vault allows, as the bus proved it. Never the value in the clear, and never to a private key.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"name": {
|
|
"description": "the secret's name",
|
|
"type": "string"
|
|
},
|
|
"public_key": {
|
|
"description": "the asker's X25519 public key as SPKI PEM — never a private key",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"name",
|
|
"public_key"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "secret-ask",
|
|
"description": "Ask the operator for a module's own secret at a desk, from the controller or a caller the vault's manifest names, named as the bus proved it (novox/hq ADR 0563 §8): the ask is recorded in the vault's store and bounded before the prompt opens, and what is typed is sealed to a key the vault made for the call and opens there alone.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"asked_by": {
|
|
"description": "who asked, as the bus named its caller",
|
|
"type": "string"
|
|
},
|
|
"call": {
|
|
"description": "the second step: the call the first step answered",
|
|
"type": "string"
|
|
},
|
|
"desk": {
|
|
"description": "the machine whose prompt asks",
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"description": "the module",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"description": "the secret's name in the module",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the machine the secret is for",
|
|
"type": "string"
|
|
},
|
|
"outcome": {
|
|
"description": "instead of sealed: how the prompt ended",
|
|
"type": "string"
|
|
},
|
|
"sealed": {
|
|
"description": "the second step: the value sealed to the call's key — never the value",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "issued",
|
|
"description": "Take the credential a provider's software issued for a provision, from the controller alone, which asks the provider's tool with a key the vault made for the call; kept as the provision's one credential, or, when the tool answers a value per holder named, each as that holder's own; the same value again writes nothing.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"call": {
|
|
"description": "the second step: the call the first step answered",
|
|
"type": "string"
|
|
},
|
|
"holders": {
|
|
"description": "the provision's holders from that provider, each {node, module}: its tool may answer a value for each, kept as that holder's own and handed to it alone",
|
|
"items": {
|
|
"properties": {
|
|
"module": {
|
|
"description": "the consuming module",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the holder's machine",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"module": {
|
|
"description": "the provider's module",
|
|
"type": "string"
|
|
},
|
|
"provider": {
|
|
"description": "the provider's machine",
|
|
"type": "string"
|
|
},
|
|
"provision": {
|
|
"description": "the provision",
|
|
"type": "string"
|
|
},
|
|
"sealed": {
|
|
"description": "the second step: the value sealed to the call's key — never the value",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "rotate",
|
|
"description": "Make a secret anew. Refused for a value a provider's software issued and for an accepted credential. Never answers the value.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"by": {
|
|
"description": "who asked, when the controller carries the act",
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"description": "the module",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"description": "the secret's name in the module",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the machine, for a module's own secret",
|
|
"type": "string"
|
|
},
|
|
"provider": {
|
|
"description": "the provider's machine",
|
|
"type": "string"
|
|
},
|
|
"provision": {
|
|
"description": "the provision",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "move-in",
|
|
"description": "Take one value of the controller's store in, as it is, from the node-engine of a machine it was sealed to and no other caller: name the row, its origin and generation and get a call and a key made for it, then send the call, the value sealed to that key and a key to read back to. Never replaces a value the vault holds; answers what it kept, read back sealed to that key.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"call": {
|
|
"description": "the second step: the call the first step answered",
|
|
"type": "string"
|
|
},
|
|
"consumer": {
|
|
"description": "the consumer's machine",
|
|
"type": "string"
|
|
},
|
|
"consumer_module": {
|
|
"description": "the consuming module",
|
|
"type": "string"
|
|
},
|
|
"generation": {
|
|
"description": "the controller's generation for the value",
|
|
"type": "string"
|
|
},
|
|
"local": {
|
|
"description": "the credential's local name, when it has one",
|
|
"type": "string"
|
|
},
|
|
"made_at": {
|
|
"description": "when it was made (RFC 3339)",
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"description": "its module",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"description": "its name in the module",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "a module's own secret: its machine",
|
|
"type": "string"
|
|
},
|
|
"origin": {
|
|
"description": "made, accepted or issued, as the controller's store says",
|
|
"type": "string"
|
|
},
|
|
"provider": {
|
|
"description": "a pair credential: the provider's machine",
|
|
"type": "string"
|
|
},
|
|
"provision": {
|
|
"description": "the provision",
|
|
"type": "string"
|
|
},
|
|
"read_back_to": {
|
|
"description": "the second step: a raw X25519 public key the read-back is sealed to",
|
|
"type": "string"
|
|
},
|
|
"sealed": {
|
|
"description": "the second step: the value sealed to the call's key — never the value",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "node-key",
|
|
"description": "State this machine's sealing key to the vault, in its own name, from the node-engine of the machine alone: at its start and whenever the key changes. A first or changed key is recorded and the machine's core secrets are said changed; the same key again changes nothing.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"key": {
|
|
"description": "the machine's sealing key, a raw X25519 public key in base64",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "own",
|
|
"description": "Answer the node-engine of one machine, about its own machine alone (as the bus proved the caller, never an argument), its modules' own secrets and the pair credentials it consumes or provides that it names, each sealed to the key it stated with node-key. A credential the vault does not hold is named missing; never a value in the clear.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"credentials": {
|
|
"description": "the pair credentials the machine's composition reads, each {role: consumer|provider, provision, consumer, consumer_module, provider, local}",
|
|
"items": {
|
|
"type": "object"
|
|
},
|
|
"type": "array"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "issue-account",
|
|
"description": "Mint one bus account the grants part wants, now (novox/hq ADR 0561 §9): only while the controller's lease is handed away, never a node's account or the controller's, never anew for one the vault holds a value or an adopted hash for. Never the value.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"user": {
|
|
"description": "the bus user, e.g. ace.mesh-build-go",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"user"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "sign",
|
|
"description": "Sign with the vault's key or authority (novox/hq ADR 0550 §2): kind node-certificate signs the certificate of a machine's internal name, asked by that machine's node-engine for the serving key its record states, built from bus state alone, or by mesh-enrolment for a node it enrols, for the serving key the node presented at redeem (ADR 0587 §3); kind enrolment signs a redeem answer under its own context, for mesh-enrolment alone. Answers the certificate or the signature and the signer's fingerprint, and says signed; never a key.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"kind": {
|
|
"description": "node-certificate or enrolment",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the machine, for a node certificate: the caller's own, or the node mesh-enrolment enrols",
|
|
"type": "string"
|
|
},
|
|
"reply": {
|
|
"description": "the redeem answer's bytes in base64, for an enrolment",
|
|
"type": "string"
|
|
},
|
|
"serving_key": {
|
|
"description": "from mesh-enrolment: the serving key's public half the enrolling node presented",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"kind"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "enrolment-token",
|
|
"description": "Make a one-time token for a node mesh-enrolment issues on the operator's warrant: its secret kept with its copy sealed to the operator key and its hash written as the bus user enrol.<node>. Answers only what the joining machine must trust (the bus's address, the bus certificate's fingerprint, the vault's public signing key), never the token; with sealed, the token sealed to the operator key, for tokens to relay; with drop, the token and its hash dropped, at the enrolment's end. Asked by mesh-enrolment alone, only from the lease write. The token carries the first tunnel mesh-enrolment built at issue (ADR 0587 §3, insight of 2026-11-02).",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"drop": {
|
|
"description": "\"true\": drop the node's token and its hash",
|
|
"enum": [
|
|
"true",
|
|
"false"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"expires": {
|
|
"description": "when the token expires (RFC 3339), as the enrolment's key says",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the node the token is for",
|
|
"type": "string"
|
|
},
|
|
"sealed": {
|
|
"description": "\"true\": answer the token sealed to the operator key",
|
|
"enum": [
|
|
"true",
|
|
"false"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"tunnel": {
|
|
"additionalProperties": false,
|
|
"description": "the node's first tunnel, built by mesh-enrolment at issue and carried in the token: the hub's public key, the hub's endpoint, the node's tunnel address, its own tunnel key and the network's range",
|
|
"properties": {
|
|
"address": {
|
|
"description": "the joining node's tunnel address",
|
|
"type": "string"
|
|
},
|
|
"hub_endpoint": {
|
|
"description": "the hub's endpoint, host:port",
|
|
"type": "string"
|
|
},
|
|
"hub_key": {
|
|
"description": "the hub's tunnel public key",
|
|
"type": "string"
|
|
},
|
|
"key": {
|
|
"description": "the joining machine's own tunnel public key, as given at issue",
|
|
"type": "string"
|
|
},
|
|
"range": {
|
|
"description": "the private network's range, a prefix",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"address",
|
|
"hub_endpoint",
|
|
"hub_key",
|
|
"key",
|
|
"range"
|
|
],
|
|
"type": "object"
|
|
}
|
|
},
|
|
"required": [
|
|
"node"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "node-account",
|
|
"description": "Mint a joining node's bus account node.<node>, sealed to the sealing key it presented, and write its hash; asked again for the same node and keys, answers the account it already minted; with retire, the account it minted for a revoked enrolment retired. Writes the node's node-logins key naming node.<node>. Asked by mesh-enrolment alone. Never the value in the clear.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"keys_digest": {
|
|
"description": "the digest of every public key the node presented (delivery.KeysDigest)",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the joining node",
|
|
"type": "string"
|
|
},
|
|
"retire": {
|
|
"description": "\"true\": retire the account minted for this node",
|
|
"enum": [
|
|
"true",
|
|
"false"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"sealing_key": {
|
|
"description": "the sealing key's public half the node presented, which the account is sealed to",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"node"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "rotate-node",
|
|
"description": "Begin a node's account rotation to its other login: answered only for a call carrying a hand act recorded through mesh-hand-acts, which the vault reads back by its id. Makes the other login's value sealed to that node, writes it rotating in node-logins and says rotation-begun; says node-account-ready once the bus node's have shows a list holding both logins. One node at a time across the mesh, the bus node last: a call while a rotation runs waits until it is done.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"act": {
|
|
"description": "the id of the hand act recorded for it in mesh-hand-acts",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "the node whose account rotates",
|
|
"type": "string"
|
|
},
|
|
"why": {
|
|
"description": "why, in a sentence",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"why",
|
|
"act"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "node-account-confirm",
|
|
"description": "Confirm a node's switch to its new login: asked by the node-engine dialled as that login, the runtime's proof of the caller being the confirmation. The old login's hash is then removed, and rotation-done said once the bus node's have shows the list without it.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "abandon",
|
|
"description": "Abandon a node's rotation before its old login is retired: the new login and its value dropped, the old one kept; a node that switched switches back first.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"node": {
|
|
"description": "the node whose rotation is abandoned",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"node"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the holder's answer"
|
|
}
|
|
},
|
|
{
|
|
"name": "retire",
|
|
"optional": true,
|
|
"description": "Retire one module's own secret, by node, module and name, on the operator's warrant bound to exactly those three (design 32 *A value no longer read*). Emits own-retired.",
|
|
"callers": "the holder of the seat mesh-config alone",
|
|
"input": {
|
|
"type": "object",
|
|
"properties": {
|
|
"node": {
|
|
"type": "string",
|
|
"description": "the node"
|
|
},
|
|
"module": {
|
|
"type": "string",
|
|
"description": "the module"
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"description": "the own secret's name"
|
|
},
|
|
"warrant": {
|
|
"type": "string",
|
|
"description": "the operator's warrant for this node, module and name: the hand act's id"
|
|
},
|
|
"ask": {
|
|
"type": "string",
|
|
"description": "the id of the operator's ask the warrant answers"
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"module",
|
|
"name",
|
|
"warrant",
|
|
"ask"
|
|
]
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"properties": {
|
|
"retired": {
|
|
"type": "boolean",
|
|
"description": "the secret is gone"
|
|
}
|
|
},
|
|
"required": [
|
|
"retired"
|
|
]
|
|
}
|
|
}
|
|
],
|
|
"description": "The mesh's secrets. accept and move-asks, which no holder served and nothing called, are left out (ADR 0620 §3). The vault's own events stay under its own subjects (ADR 0620 §2).",
|
|
"holder-events": [
|
|
{
|
|
"name": "provisioned",
|
|
"subject": "mesh.mod.<holder>.event.provisioned"
|
|
},
|
|
{
|
|
"name": "rotated",
|
|
"subject": "mesh.mod.<holder>.event.rotated"
|
|
},
|
|
{
|
|
"name": "secret-changed",
|
|
"subject": "mesh.mod.<holder>.event.secret-changed"
|
|
},
|
|
{
|
|
"name": "account-hashed",
|
|
"subject": "mesh.mod.<holder>.event.account-hashed"
|
|
},
|
|
{
|
|
"name": "own-replaced",
|
|
"subject": "mesh.mod.<holder>.event.own-replaced"
|
|
},
|
|
{
|
|
"name": "account-issued",
|
|
"subject": "mesh.mod.<holder>.event.account-issued"
|
|
},
|
|
{
|
|
"name": "signed",
|
|
"subject": "mesh.mod.<holder>.event.signed"
|
|
},
|
|
{
|
|
"name": "rotation-begun",
|
|
"subject": "mesh.mod.<holder>.event.rotation-begun"
|
|
},
|
|
{
|
|
"name": "node-account-ready",
|
|
"subject": "mesh.mod.<holder>.event.node-account-ready"
|
|
},
|
|
{
|
|
"name": "rotation-done",
|
|
"subject": "mesh.mod.<holder>.event.rotation-done"
|
|
},
|
|
{
|
|
"name": "own-retired",
|
|
"subject": "mesh.mod.<holder>.event.own-retired",
|
|
"body": {
|
|
"type": "object",
|
|
"properties": {
|
|
"node": {
|
|
"type": "string",
|
|
"description": "the node"
|
|
},
|
|
"module": {
|
|
"type": "string",
|
|
"description": "the module"
|
|
},
|
|
"name": {
|
|
"type": "string",
|
|
"description": "the secret's name"
|
|
},
|
|
"ask": {
|
|
"type": "string",
|
|
"description": "the ask's id"
|
|
},
|
|
"caller": {
|
|
"type": "string",
|
|
"description": "the caller the vault proved"
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"module",
|
|
"name",
|
|
"caller"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|