997 lines
26 KiB
JSON
997 lines
26 KiB
JSON
{
|
|
"format": 1,
|
|
"seat": "mesh-module-assigner",
|
|
"scope": "mesh",
|
|
"grain": "whole",
|
|
"domain": "Placement",
|
|
"decision": "novox/hq ADR 0567, ADR 0634, ADR 0635",
|
|
"description": "The seat that places modules on nodes (ADR 0567): the state of placement and the proposals that change it. Renamed from mesh-placement (ADR 0634 §9).",
|
|
"verbs": [
|
|
{
|
|
"name": "placement",
|
|
"description": "Read placement: one node's key, the nodes one module is placed on, or every key, each with its revision, and how full the state is against its cap. With history, one node's or one module's changes in order: a revision the state keeps whole, an older one as the proposal's changes from its placement-changed event.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"history": {
|
|
"description": "\"true\": the changes in order, from the stream and the state's revisions",
|
|
"enum": [
|
|
"true",
|
|
"false"
|
|
],
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"description": "one module: the nodes it is placed on",
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"description": "one node",
|
|
"type": "string"
|
|
},
|
|
"seats": {
|
|
"description": "\"true\": who holds each seat, and on which node (the state seat-holders); with node, that node's",
|
|
"enum": [
|
|
"true",
|
|
"false"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "placement as read: nodes, keys with their revisions, history, seat holders, the state's fill"
|
|
}
|
|
},
|
|
{
|
|
"name": "proposals",
|
|
"description": "Every open proposal of placement: its changes, the revision of each key it was laid over, its candidates, every node's answer, the differences computed and answered, its verdict and its ask. Narrowed to one by id.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "one proposal's id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the open proposals"
|
|
}
|
|
},
|
|
{
|
|
"name": "propose",
|
|
"description": "Propose a change of placement, with why: laid over the current keys and refused at once, naming every finding, when the result cannot be placed (two modules on one host port, a provider not placed, a seat held once held twice, two nodes with one address, two hubs, a module the indexer does not hold, a node with no record). Otherwise the nodes it touches compose it in shadow and answer, and on a passing verdict the operator is asked to approve it. Who proposes is the caller, as the runtime proves it. An add-node from mesh-enrolment, whose warrant names its node and address, is written with no ask of its own: its Approve is the enrolment's (ADR 0587 §7).",
|
|
"optional": true,
|
|
"input": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"changes": {
|
|
"description": "the changes, each an object with `op`: place (node, module, ports, bindings), take-off (node, module), pin (node, provision, provider {node, module}), unpin (node, provision), hold (node, module, claim, scope, kind, site), unhold (node, module, claim), decide (node, field, value: a decided field of the node, its address among them), config (node, module, mesh-wide, layer, mesh-wide-values, values), add-node (node, decided, keys: a joining node, mesh-enrolment's alone, the proposal's one change, with the enrolment's warrant, its tunnel key alone at the operator's yes; ADR 0587 §7), remove-node (node: a joining node never confirmed, taken off when its enrolment ends; mesh-enrolment's alone, on the same warrant)",
|
|
"items": {
|
|
"required": [
|
|
"op",
|
|
"node"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"minItems": 1,
|
|
"type": "array"
|
|
},
|
|
"warrant": {
|
|
"description": "for an add-node alone: the enrolment's warrant {node, address, ask, warrant}, naming the change's node and address",
|
|
"required": [
|
|
"node",
|
|
"address",
|
|
"ask",
|
|
"warrant"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"why": {
|
|
"description": "why, shown to the operator with the proposal",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"why",
|
|
"changes"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the proposal's id and its verdict, or every finding refused at once"
|
|
}
|
|
},
|
|
{
|
|
"name": "withdraw",
|
|
"description": "Withdraw an open proposal: its key and its candidates are deleted and placement-withdrawn carries it whole. With why.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "the proposal's id",
|
|
"type": "string"
|
|
},
|
|
"why": {
|
|
"description": "why, kept in the event",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"why"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "the proposal withdrawn"
|
|
}
|
|
},
|
|
{
|
|
"name": "again",
|
|
"description": "Judge an open proposal now with the answers that stand, and raise its ask again when its verdict passes and the operator's channel does not hold the ask. Nothing more: the recovery of a proposal whose judgement or ask was lost.",
|
|
"optional": true,
|
|
"input": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "the proposal's id",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"answer": {
|
|
"type": "object",
|
|
"description": "what was judged or asked again"
|
|
}
|
|
}
|
|
],
|
|
"events": [
|
|
{
|
|
"name": "placement-proposed",
|
|
"body": {
|
|
"$ref": "#/defs/PlacementEvent"
|
|
}
|
|
},
|
|
{
|
|
"name": "placement-withdrawn",
|
|
"body": {
|
|
"$ref": "#/defs/PlacementEvent"
|
|
}
|
|
},
|
|
{
|
|
"name": "placement-judged",
|
|
"body": {
|
|
"$ref": "#/defs/PlacementEvent"
|
|
}
|
|
},
|
|
{
|
|
"name": "placement-changed",
|
|
"body": {
|
|
"$ref": "#/defs/PlacementEvent"
|
|
}
|
|
}
|
|
],
|
|
"family": {
|
|
"name": "mesh-module-assigner.events",
|
|
"max-age-days": 7
|
|
},
|
|
"states": [
|
|
{
|
|
"name": "placement",
|
|
"template": "state",
|
|
"key-forms": [
|
|
{
|
|
"key": "<node>.node",
|
|
"value": {
|
|
"type": "object",
|
|
"description": "a node's key: what a person decided of it, its pins and holdings, and the modules placed on it; the commit of a write",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
},
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"decided": {
|
|
"$ref": "#/defs/NodeDecided"
|
|
},
|
|
"modules": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"module": {
|
|
"type": "string"
|
|
},
|
|
"digest": {
|
|
"type": "string",
|
|
"description": "the digest of the module key's value it stands for"
|
|
}
|
|
},
|
|
"required": [
|
|
"module",
|
|
"digest"
|
|
]
|
|
},
|
|
"description": "the modules placed, in the order the composition reads them"
|
|
},
|
|
"pins": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"$ref": "#/defs/Provider"
|
|
}
|
|
},
|
|
"holds": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/defs/Holding"
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"decided",
|
|
"modules"
|
|
]
|
|
},
|
|
"description": "a node's key"
|
|
},
|
|
{
|
|
"key": "<node>.<module>",
|
|
"value": {
|
|
"type": "object",
|
|
"description": "a module's key: the module as placed",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
},
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"placed": {
|
|
"$ref": "#/defs/PlacedModule"
|
|
},
|
|
"previous": {
|
|
"$ref": "#/defs/PlacedModule",
|
|
"description": "the value it replaces while a write is under way"
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"placed"
|
|
]
|
|
},
|
|
"description": "one module on a node; no module is named node"
|
|
}
|
|
],
|
|
"history": 64,
|
|
"description": "placements, one key per node and one per module placed on it, written only on the operator's Approve of a proposal by compare-and-set at the revision it was laid over"
|
|
},
|
|
{
|
|
"name": "proposals",
|
|
"template": "state",
|
|
"key-forms": [
|
|
{
|
|
"key": "<proposal>",
|
|
"value": {
|
|
"$ref": "#/defs/Proposal"
|
|
},
|
|
"description": "an open proposal, by its id"
|
|
}
|
|
],
|
|
"history": 5,
|
|
"description": "open proposals; a key leaves when the proposal is applied, withdrawn, declined or expired"
|
|
},
|
|
{
|
|
"name": "candidates",
|
|
"template": "state",
|
|
"key-forms": [
|
|
{
|
|
"key": "<proposal>.<node>",
|
|
"value": {
|
|
"type": "object",
|
|
"description": "one node's candidate in one proposal",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
},
|
|
"proposal": {
|
|
"type": "string"
|
|
},
|
|
"reached": {
|
|
"type": "boolean",
|
|
"description": "the proposal changes this node's composition through another's key"
|
|
},
|
|
"placement": {
|
|
"$ref": "#/defs/Placement",
|
|
"description": "the node's placement with the proposal laid over it; absent when the proposal takes its key away"
|
|
}
|
|
},
|
|
"required": [
|
|
"proposal"
|
|
]
|
|
},
|
|
"description": "a node's candidate"
|
|
}
|
|
],
|
|
"history": 5,
|
|
"description": "the candidates a proposal needs answers on; a node watches its own"
|
|
},
|
|
{
|
|
"name": "pulses",
|
|
"template": "state",
|
|
"key-forms": [
|
|
{
|
|
"key": "answer.<proposal>.<node>",
|
|
"value": {
|
|
"type": "object",
|
|
"description": "the bound on one node's answer",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"description": "the bound on a node's answer"
|
|
},
|
|
{
|
|
"key": "ask.<proposal>",
|
|
"value": {
|
|
"type": "object",
|
|
"description": "the bound on a raised ask",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"description": "the bound on a proposal's raised ask"
|
|
}
|
|
],
|
|
"description": "bounds, each a key that lives for the bound; the server's delete marker when one ends is the event that fails a silent node or an unanswered ask"
|
|
},
|
|
{
|
|
"name": "seat-holders",
|
|
"template": "state",
|
|
"key-forms": [
|
|
{
|
|
"key": "<seat>",
|
|
"value": {
|
|
"$ref": "#/defs/SeatHolders"
|
|
},
|
|
"description": "a seat held once for the mesh"
|
|
},
|
|
{
|
|
"key": "<seat>.<node>",
|
|
"value": {
|
|
"$ref": "#/defs/SeatHolders"
|
|
},
|
|
"description": "a node seat on one node"
|
|
}
|
|
],
|
|
"description": "who holds which seat on which node, composed from every node's placement"
|
|
}
|
|
],
|
|
"defs": {
|
|
"Provider": {
|
|
"type": "object",
|
|
"description": "the module on a node that answers a requirement or holds a seat",
|
|
"properties": {
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"module"
|
|
]
|
|
},
|
|
"PlacedModule": {
|
|
"type": "object",
|
|
"description": "one module placed on a node",
|
|
"properties": {
|
|
"module": {
|
|
"type": "string"
|
|
},
|
|
"ports": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "integer"
|
|
},
|
|
"description": "the host port each declared port is published on, by the port the software listens on"
|
|
},
|
|
"bindings": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"$ref": "#/defs/Provider"
|
|
},
|
|
"description": "by provision, the provider each requirement that keeps data is bound to"
|
|
},
|
|
"mesh-wide": {
|
|
"type": "object",
|
|
"description": "the whole mesh's settings layer of the module's placement"
|
|
},
|
|
"has-mesh-wide": {
|
|
"type": "boolean"
|
|
},
|
|
"layer": {
|
|
"type": "object",
|
|
"description": "this node's settings layer of the module's placement"
|
|
},
|
|
"has-layer": {
|
|
"type": "boolean"
|
|
},
|
|
"mesh-wide-values": {
|
|
"type": "object",
|
|
"description": "config values a person set in the whole mesh's layer, for a module in the settings form"
|
|
},
|
|
"values": {
|
|
"type": "object",
|
|
"description": "config values a person set in this node's layer, for a module in the settings form"
|
|
}
|
|
},
|
|
"required": [
|
|
"module"
|
|
]
|
|
},
|
|
"Holding": {
|
|
"type": "object",
|
|
"description": "one seat a module placed on the node holds",
|
|
"properties": {
|
|
"claim": {
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"type": "string"
|
|
},
|
|
"site": {
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"claim",
|
|
"module"
|
|
]
|
|
},
|
|
"NodeDecided": {
|
|
"type": "object",
|
|
"description": "what a person decides of a node; no secret and no key material",
|
|
"properties": {
|
|
"endpoint": {
|
|
"type": "string"
|
|
},
|
|
"site": {
|
|
"type": "string"
|
|
},
|
|
"hub": {
|
|
"type": "boolean"
|
|
},
|
|
"address": {
|
|
"type": "string"
|
|
},
|
|
"public-domain": {
|
|
"type": "string"
|
|
},
|
|
"account": {
|
|
"type": "string"
|
|
},
|
|
"account-home": {
|
|
"type": "string"
|
|
},
|
|
"agent-account": {
|
|
"type": "string"
|
|
},
|
|
"agent-account-home": {
|
|
"type": "string"
|
|
},
|
|
"adopted": {
|
|
"type": "boolean"
|
|
},
|
|
"taken": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"tunnel": {
|
|
"$ref": "#/defs/FoundTunnel",
|
|
"description": "the tunnel found on the node when it was adopted"
|
|
},
|
|
"peer-names": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"description": "on the hub, the name a person gave a peer of that tunnel, by its public key"
|
|
}
|
|
}
|
|
},
|
|
"FoundTunnel": {
|
|
"type": "object",
|
|
"description": "a tunnel found on the machine when it was adopted: everything but its private key",
|
|
"properties": {
|
|
"interface": {
|
|
"type": "string"
|
|
},
|
|
"unit": {
|
|
"type": "string"
|
|
},
|
|
"config": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"type": "integer"
|
|
},
|
|
"mtu": {
|
|
"type": "integer"
|
|
},
|
|
"address": {
|
|
"type": "string"
|
|
},
|
|
"range": {
|
|
"type": "string"
|
|
},
|
|
"public-key": {
|
|
"type": "string"
|
|
},
|
|
"peers": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/defs/FoundTunnelPeer"
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"interface"
|
|
]
|
|
},
|
|
"FoundTunnelPeer": {
|
|
"type": "object",
|
|
"description": "one peer of a found tunnel",
|
|
"properties": {
|
|
"public-key": {
|
|
"type": "string"
|
|
},
|
|
"address": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"public-key"
|
|
]
|
|
},
|
|
"Placement": {
|
|
"type": "object",
|
|
"description": "one node's placement assembled",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
},
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"revision": {
|
|
"type": "string"
|
|
},
|
|
"decided": {
|
|
"$ref": "#/defs/NodeDecided"
|
|
},
|
|
"modules": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/defs/PlacedModule"
|
|
}
|
|
},
|
|
"pins": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"$ref": "#/defs/Provider"
|
|
},
|
|
"description": "by provision, the provider chosen for the node"
|
|
},
|
|
"holds": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/defs/Holding"
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"decided",
|
|
"modules"
|
|
]
|
|
},
|
|
"ProposalChange": {
|
|
"type": "object",
|
|
"description": "one change of a proposal",
|
|
"properties": {
|
|
"op": {
|
|
"type": "string",
|
|
"description": "place, take-off, pin, unpin, hold, unhold, decide, config, seed, add-node or remove-node"
|
|
},
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"module": {
|
|
"type": "string"
|
|
},
|
|
"ports": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"bindings": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"$ref": "#/defs/Provider"
|
|
}
|
|
},
|
|
"provision": {
|
|
"type": "string"
|
|
},
|
|
"provider": {
|
|
"$ref": "#/defs/Provider"
|
|
},
|
|
"claim": {
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"type": "string"
|
|
},
|
|
"kind": {
|
|
"type": "string"
|
|
},
|
|
"site": {
|
|
"type": "string"
|
|
},
|
|
"field": {
|
|
"type": "string"
|
|
},
|
|
"value": {
|
|
"description": "a decided field's value"
|
|
},
|
|
"mesh-wide": {
|
|
"type": "object"
|
|
},
|
|
"layer": {
|
|
"type": "object"
|
|
},
|
|
"mesh-wide-values": {
|
|
"type": "object"
|
|
},
|
|
"values": {
|
|
"type": "object"
|
|
},
|
|
"whole": {
|
|
"$ref": "#/defs/Placement",
|
|
"description": "the node's whole placement, for a seed"
|
|
},
|
|
"decided": {
|
|
"$ref": "#/defs/NodeDecided"
|
|
},
|
|
"keys": {
|
|
"type": "object",
|
|
"properties": {
|
|
"identity": {
|
|
"type": "string"
|
|
},
|
|
"overlay": {
|
|
"type": "string"
|
|
},
|
|
"sealing": {
|
|
"type": "string"
|
|
},
|
|
"serving": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"identity",
|
|
"sealing"
|
|
],
|
|
"description": "the public halves of a joining node's keys"
|
|
}
|
|
},
|
|
"required": [
|
|
"op",
|
|
"node"
|
|
]
|
|
},
|
|
"Warrant": {
|
|
"type": "object",
|
|
"description": "the enrolment's warrant an add-node carries",
|
|
"properties": {
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"address": {
|
|
"type": "string"
|
|
},
|
|
"ask": {
|
|
"type": "string"
|
|
},
|
|
"warrant": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"node",
|
|
"address",
|
|
"ask",
|
|
"warrant"
|
|
]
|
|
},
|
|
"Verdict": {
|
|
"type": "object",
|
|
"description": "the holder's judgement of a proposal's answers",
|
|
"properties": {
|
|
"state": {
|
|
"type": "string",
|
|
"description": "waits, pass or fail"
|
|
},
|
|
"at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"fails": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"silent": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"until": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"intended": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"unintended": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"carried": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"answers": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "object"
|
|
},
|
|
"description": "every node's answer to its candidate, by node"
|
|
},
|
|
"notes": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"state",
|
|
"at"
|
|
]
|
|
},
|
|
"Proposal": {
|
|
"type": "object",
|
|
"description": "an open proposal",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
},
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"by": {
|
|
"type": "string"
|
|
},
|
|
"why": {
|
|
"type": "string"
|
|
},
|
|
"at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"written": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"changes": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/defs/ProposalChange"
|
|
}
|
|
},
|
|
"seed": {
|
|
"type": "boolean"
|
|
},
|
|
"export-digest": {
|
|
"type": "string"
|
|
},
|
|
"base": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "integer"
|
|
},
|
|
"description": "by node whose key it changes, the revision of the key it was laid over (0: none)"
|
|
},
|
|
"must": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"hand-back": {
|
|
"type": "boolean"
|
|
},
|
|
"state": {
|
|
"type": "string",
|
|
"description": "answering, failed or asked"
|
|
},
|
|
"verdict": {
|
|
"$ref": "#/defs/Verdict"
|
|
},
|
|
"ask": {
|
|
"type": "string"
|
|
},
|
|
"words": {
|
|
"type": "string"
|
|
},
|
|
"again": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"warrant": {
|
|
"$ref": "#/defs/Warrant"
|
|
},
|
|
"withdrawn": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"by",
|
|
"why",
|
|
"at",
|
|
"changes",
|
|
"base",
|
|
"state"
|
|
]
|
|
},
|
|
"PlacementEvent": {
|
|
"type": "object",
|
|
"description": "what each placement event carries",
|
|
"properties": {
|
|
"proposal": {
|
|
"$ref": "#/defs/Proposal"
|
|
},
|
|
"nodes": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
},
|
|
"description": "for placement-changed, by node the revisions before and after and the modules added, removed or changed"
|
|
},
|
|
"warrant": {
|
|
"type": "object",
|
|
"description": "who approved it, through which channel, when",
|
|
"properties": {
|
|
"warrant": {
|
|
"type": "string"
|
|
},
|
|
"words": {
|
|
"type": "string"
|
|
},
|
|
"at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
"required": [
|
|
"warrant",
|
|
"words",
|
|
"at"
|
|
]
|
|
},
|
|
"ended": {
|
|
"type": "string",
|
|
"description": "for placement-withdrawn, why it ended"
|
|
}
|
|
},
|
|
"required": [
|
|
"proposal"
|
|
]
|
|
},
|
|
"SeatHolders": {
|
|
"type": "object",
|
|
"description": "one key of seat-holders",
|
|
"properties": {
|
|
"v": {
|
|
"type": "integer"
|
|
},
|
|
"seat": {
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"type": "string"
|
|
},
|
|
"outside": {
|
|
"type": "boolean",
|
|
"description": "the claim names no seat of the seat list"
|
|
},
|
|
"holders": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object",
|
|
"properties": {
|
|
"module": {
|
|
"type": "string"
|
|
},
|
|
"node": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"module",
|
|
"node"
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"required": [
|
|
"seat",
|
|
"scope",
|
|
"holders"
|
|
]
|
|
}
|
|
}
|
|
}
|