Regenerate the domain contracts; hand-acts and conditions clients; operator-channel client moves; the seat-set package ends (ADR 0634, ADR 0635; issue 1966)
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -3,6 +3,13 @@
|
||||
// Package meshconfig is the contract of the seat "mesh-config", defined whole (seats/mesh-config/seat.json): The mesh's config values: read and set one, and the renames still open. mesh-config's own events stay under its own subjects (ADR 0620 §2).
|
||||
package meshconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-config"
|
||||
|
||||
@@ -38,6 +45,53 @@ func HolderSubjectRetiring(holder string) string { return "mesh.stream." + holde
|
||||
// HolderSubjectRetired is where the holder publishes retired, kept in config.events.
|
||||
func HolderSubjectRetired(holder string) string { return "mesh.stream." + holder + ".event.retired" }
|
||||
|
||||
const (
|
||||
StateResolved = "resolved"
|
||||
)
|
||||
|
||||
// ResolvedByNodeModuleKeyKey is the key of one value of the state resolved under the form "<node>.<module>.<key>".
|
||||
func ResolvedByNodeModuleKeyKey(node, module, key string) string {
|
||||
return node + "." + module + "." + key
|
||||
}
|
||||
|
||||
// ParseResolvedByNodeModuleKeyKey reads the parts of a key of the form "<node>.<module>.<key>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseResolvedByNodeModuleKeyKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v4 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, true
|
||||
}
|
||||
|
||||
// DecodeResolvedByNodeModuleKeyValue reads one value of the state resolved under the form "<node>.<module>.<key>", refusing a field ResolvedByNodeModuleKeyValue does not know and any text after the value.
|
||||
func DecodeResolvedByNodeModuleKeyValue(raw []byte) (ResolvedByNodeModuleKeyValue, error) {
|
||||
var v ResolvedByNodeModuleKeyValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ConfigInput is what config takes.
|
||||
type ConfigInput struct {
|
||||
// list (when not given), set, clear or history
|
||||
@@ -129,3 +183,17 @@ type RetiredHolderEvent struct {
|
||||
// the node
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ResolvedByNodeModuleKeyValue is one value of the state resolved under the key <node>.<module>.<key>.
|
||||
type ResolvedByNodeModuleKeyValue struct {
|
||||
Key string `json:"key"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
// the predefined key the value falls back to
|
||||
Predefined string `json:"predefined,omitempty"`
|
||||
// an unset value is the operator's own to set
|
||||
Required bool `json:"required,omitempty"`
|
||||
Source string `json:"source"`
|
||||
Trusted bool `json:"trusted,omitempty"`
|
||||
Value any `json:"value,omitempty"`
|
||||
}
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
// Package nodeengine is the contract of the seat "node-engine", defined whole (seats/node-engine/seat.json): The node seat every node's engine holds (novox/hq ADR 0563, ADR 0618 §3, §4): its hand acts on the operator's warrant, its read-only judgements, its compositions and what it reads of a manifest. Each verb is answered on this node's subject, mesh.seat.node-engine.tool.<verb>.<node>, and each event is published on mesh.seat.node-engine.event.<event>.<node>, the node's name its last token.
|
||||
package nodeengine
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "node-engine"
|
||||
|
||||
@@ -57,6 +64,222 @@ func SubjectManifestReadsChanged(caller string) string {
|
||||
return "mesh.seat.node-engine.event.manifest-reads-changed." + caller
|
||||
}
|
||||
|
||||
const (
|
||||
StateHave = "have"
|
||||
StateComposed = "composed"
|
||||
StateData = "data"
|
||||
StatePackages = "packages"
|
||||
StateHealth = "health"
|
||||
)
|
||||
|
||||
// HaveByNodeModuleKey is the key of one value of the state have under the form "<node>.<module>".
|
||||
func HaveByNodeModuleKey(node, module string) string { return node + "." + module }
|
||||
|
||||
// ParseHaveByNodeModuleKey reads the parts of a key of the form "<node>.<module>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseHaveByNodeModuleKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeHaveByNodeModuleValue reads one value of the state have under the form "<node>.<module>", refusing a field HaveByNodeModuleValue does not know and any text after the value.
|
||||
func DecodeHaveByNodeModuleValue(raw []byte) (HaveByNodeModuleValue, error) {
|
||||
var v HaveByNodeModuleValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// HaveByNodeNodeKey is the key of one value of the state have under the form "<node>.node".
|
||||
func HaveByNodeNodeKey(node string) string { return node + ".node" }
|
||||
|
||||
// ParseHaveByNodeNodeKey reads the parts of a key of the form "<node>.node", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseHaveByNodeNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".node")
|
||||
if !found0 || v0 == "" {
|
||||
return "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeHaveByNodeNodeValue reads one value of the state have under the form "<node>.node", refusing a field HaveByNodeNodeValue does not know and any text after the value.
|
||||
func DecodeHaveByNodeNodeValue(raw []byte) (HaveByNodeNodeValue, error) {
|
||||
var v HaveByNodeNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ComposedByNodeModuleFingerprintKey is the key of one value of the state composed under the form "<node>.<module>.<fingerprint>".
|
||||
func ComposedByNodeModuleFingerprintKey(node, module, fingerprint string) string {
|
||||
return node + "." + module + "." + fingerprint
|
||||
}
|
||||
|
||||
// ParseComposedByNodeModuleFingerprintKey reads the parts of a key of the form "<node>.<module>.<fingerprint>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseComposedByNodeModuleFingerprintKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v4 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, true
|
||||
}
|
||||
|
||||
// DecodeComposedByNodeModuleFingerprintValue reads one value of the state composed under the form "<node>.<module>.<fingerprint>", refusing a field ComposedByNodeModuleFingerprintValue does not know and any text after the value.
|
||||
func DecodeComposedByNodeModuleFingerprintValue(raw []byte) (ComposedByNodeModuleFingerprintValue, error) {
|
||||
var v ComposedByNodeModuleFingerprintValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// DataByNodeModuleKey is the key of one value of the state data under the form "<node>.<module>".
|
||||
func DataByNodeModuleKey(node, module string) string { return node + "." + module }
|
||||
|
||||
// ParseDataByNodeModuleKey reads the parts of a key of the form "<node>.<module>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseDataByNodeModuleKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeDataByNodeModuleValue reads one value of the state data under the form "<node>.<module>", refusing a field DataByNodeModuleValue does not know and any text after the value.
|
||||
func DecodeDataByNodeModuleValue(raw []byte) (DataByNodeModuleValue, error) {
|
||||
var v DataByNodeModuleValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PackagesByNodeKey is the key of one value of the state packages under the form "<node>".
|
||||
func PackagesByNodeKey(node string) string { return node }
|
||||
|
||||
// ParsePackagesByNodeKey reads the parts of a key of the form "<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePackagesByNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodePackagesByNodeValue reads one value of the state packages under the form "<node>", refusing a field PackagesByNodeValue does not know and any text after the value.
|
||||
func DecodePackagesByNodeValue(raw []byte) (PackagesByNodeValue, error) {
|
||||
var v PackagesByNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// HealthByNodeKey is the key of one value of the state health under the form "<node>".
|
||||
func HealthByNodeKey(node string) string { return node }
|
||||
|
||||
// ParseHealthByNodeKey reads the parts of a key of the form "<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseHealthByNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeHealthByNodeValue reads one value of the state health under the form "<node>", refusing a field HealthByNodeValue does not know and any text after the value.
|
||||
func DecodeHealthByNodeValue(raw []byte) (HealthByNodeValue, error) {
|
||||
var v HealthByNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Act is one act asked through the seat, as acts reads it (ADR 0563 §9).
|
||||
type Act struct {
|
||||
// the act: hand-over, access-act, judge-directories or setuid-search
|
||||
@@ -561,3 +784,104 @@ type RefusedEvent = ActSaid
|
||||
|
||||
// ManifestReadsChangedEvent is the body of the event manifest-reads-changed.
|
||||
type ManifestReadsChangedEvent = ManifestReadsChanged
|
||||
|
||||
// HaveByNodeModuleValue is one value of the state have under the key <node>.<module>.
|
||||
type HaveByNodeModuleValue struct {
|
||||
Build string `json:"build,omitempty"`
|
||||
BuildAlone bool `json:"build-alone,omitempty"`
|
||||
// the composition's digest
|
||||
Composed string `json:"composed,omitempty"`
|
||||
Detail string `json:"detail,omitempty"`
|
||||
// the fingerprint held
|
||||
Fp string `json:"fp,omitempty"`
|
||||
// the accounts handed
|
||||
Handed map[string]any `json:"handed,omitempty"`
|
||||
// how it is
|
||||
Health string `json:"health"`
|
||||
Judgement string `json:"judgement,omitempty"`
|
||||
Kept []string `json:"kept,omitempty"`
|
||||
// how far it has come
|
||||
Phase string `json:"phase"`
|
||||
// a pull the engine waits for
|
||||
PullWait map[string]any `json:"pull-wait,omitempty"`
|
||||
Sealed []string `json:"sealed,omitempty"`
|
||||
SealedAt map[string]any `json:"sealed-at,omitempty"`
|
||||
// the user list written
|
||||
UserList map[string]any `json:"user-list,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
// what it waits for
|
||||
Waits string `json:"waits,omitempty"`
|
||||
}
|
||||
|
||||
// HaveByNodeNodeValue is one value of the state have under the key <node>.node.
|
||||
type HaveByNodeNodeValue struct {
|
||||
Busy map[string]any `json:"busy,omitempty"`
|
||||
Candidates map[string]map[string]any `json:"candidates,omitempty"`
|
||||
Composed string `json:"composed,omitempty"`
|
||||
// own, or the controller's
|
||||
Composes string `json:"composes,omitempty"`
|
||||
ComposesWhy string `json:"composes-why,omitempty"`
|
||||
Filters map[string]any `json:"filters,omitempty"`
|
||||
Profile map[string]any `json:"profile,omitempty"`
|
||||
// the node's record: its tunnel and certificate
|
||||
Record map[string]any `json:"record,omitempty"`
|
||||
Sealed []string `json:"sealed,omitempty"`
|
||||
SealedAt map[string]any `json:"sealed-at,omitempty"`
|
||||
Strays map[string]any `json:"strays,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
Windows map[string]any `json:"windows,omitempty"`
|
||||
}
|
||||
|
||||
// ComposedByNodeModuleFingerprintValue is one value of the state composed under the key <node>.<module>.<fingerprint>.
|
||||
type ComposedByNodeModuleFingerprintValue struct {
|
||||
Data bool `json:"Data,omitempty"`
|
||||
FP string `json:"FP"`
|
||||
Filled []string `json:"Filled,omitempty"`
|
||||
Module string `json:"Module"`
|
||||
Node string `json:"Node"`
|
||||
// the node's own adoption, identities, groups, libraries and provisioner account
|
||||
Own map[string]any `json:"Own,omitempty"`
|
||||
// the module's plan
|
||||
Plan map[string]any `json:"Plan,omitempty"`
|
||||
// why the composition was refused
|
||||
Refused string `json:"Refused,omitempty"`
|
||||
Resources []map[string]any `json:"Resources,omitempty"`
|
||||
V int64 `json:"V,omitempty"`
|
||||
}
|
||||
|
||||
// DataByNodeModuleValue is one value of the state data under the key <node>.<module>.
|
||||
type DataByNodeModuleValue struct {
|
||||
Digest string `json:"digest"`
|
||||
Items []map[string]any `json:"items"`
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// PackagesByNodeValuePackagesItem is a type of the contract.
|
||||
type PackagesByNodeValuePackagesItem struct {
|
||||
Absent bool `json:"absent,omitempty"`
|
||||
Modules []string `json:"modules,omitempty"`
|
||||
Package string `json:"package,omitempty"`
|
||||
}
|
||||
|
||||
// PackagesByNodeValue is one value of the state packages under the key <node>.
|
||||
type PackagesByNodeValue struct {
|
||||
Node string `json:"node"`
|
||||
Packages []PackagesByNodeValuePackagesItem `json:"packages"`
|
||||
}
|
||||
|
||||
// HealthByNodeValue is one value of the state health under the key <node>.
|
||||
type HealthByNodeValue struct {
|
||||
At string `json:"at"`
|
||||
Contract int64 `json:"contract,omitempty"`
|
||||
Fallback map[string]any `json:"fallback,omitempty"`
|
||||
Found []map[string]any `json:"found,omitempty"`
|
||||
Network map[string]any `json:"network,omitempty"`
|
||||
Node string `json:"node"`
|
||||
Peers []map[string]any `json:"peers,omitempty"`
|
||||
Relogin []map[string]any `json:"relogin,omitempty"`
|
||||
Root []map[string]any `json:"root,omitempty"`
|
||||
Units map[string]any `json:"units,omitempty"`
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
module git.novox.be/novox/mesh-contracts/go/seats/operatorchannel
|
||||
|
||||
go 1.26.0
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,172 @@
|
||||
// Package meshconditionsclient is the logic every observer, healer and reader of conditions shares over the seat
|
||||
// mesh-conditions (novox/hq ADR 0564, ADR 0634 §4): how a finding's key is made and checked, the scopes and the bounds,
|
||||
// the order a person reads conditions in, and the answers a notification offers. The layouts are the seat's contract's.
|
||||
package meshconditionsclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
)
|
||||
|
||||
// The two severities, how soon the operator is needed.
|
||||
const (
|
||||
Urgent = "urgent"
|
||||
Warning = "warning"
|
||||
)
|
||||
|
||||
// The scopes a condition's key starts with: what kind of thing is wrong.
|
||||
const (
|
||||
ScopeMachine = "machine"
|
||||
ScopePlan = "plan"
|
||||
ScopeCall = "call"
|
||||
ScopeBuild = "build"
|
||||
ScopeMerge = "merge"
|
||||
ScopeProvider = "provider"
|
||||
ScopeSeat = "seat"
|
||||
ScopeBus = "bus"
|
||||
ScopeCore = "core"
|
||||
ScopeProbe = "probe"
|
||||
ScopeMesh = "mesh"
|
||||
// ScopeDelivery is a delivery by its id (novox/hq ADR 0239); ScopeModule a module on a machine, `<module>.<machine>`.
|
||||
ScopeDelivery = "delivery"
|
||||
ScopeModule = "module"
|
||||
)
|
||||
|
||||
// Scopes is every scope, in the order a person reads them.
|
||||
var Scopes = []string{ScopeMachine, ScopePlan, ScopeCall, ScopeBuild, ScopeMerge, ScopeProvider,
|
||||
ScopeSeat, ScopeBus, ScopeCore, ScopeProbe, ScopeMesh, ScopeDelivery, ScopeModule}
|
||||
|
||||
// Who resolves a condition.
|
||||
const (
|
||||
ResolverSelf = "self"
|
||||
ResolverOperator = "operator"
|
||||
ResolverAgent = "agent"
|
||||
)
|
||||
|
||||
// ResolverHealer is the resolver of a condition a registered healer works on.
|
||||
func ResolverHealer(name string) string { return "healer:" + name }
|
||||
|
||||
// The bounds a condition keeps.
|
||||
const (
|
||||
KeptEvidence = 10
|
||||
KeptTried = 10
|
||||
KeptGaps = 8
|
||||
MaxSilence = 7 * 24 * time.Hour
|
||||
ReopenWithin = 10 * time.Minute
|
||||
)
|
||||
|
||||
// CauseOperatorAnswer is the cause of an act the operator chose.
|
||||
const CauseOperatorAnswer = "operator-answer"
|
||||
|
||||
// The changes a condition event says.
|
||||
const (
|
||||
ChangeRaised = "raised"
|
||||
ChangeReopened = "reopened"
|
||||
ChangeSeverity = "severity"
|
||||
ChangeResolver = "resolver"
|
||||
ChangeSilenced = "silenced"
|
||||
ChangeUnsilenced = "silence-ended"
|
||||
ChangeCleared = "cleared"
|
||||
ChangeWords = "words"
|
||||
)
|
||||
|
||||
var unsafeKey = regexp.MustCompile(`[^A-Za-z0-9_=/-]`)
|
||||
|
||||
// Key is a condition's key: its scope, the parts of its id and a token, each made safe for a bus key.
|
||||
func Key(scope, id, token string) string {
|
||||
var parts []string
|
||||
for _, p := range append(append([]string{scope}, strings.Split(id, ".")...), token) {
|
||||
p = unsafeKey.ReplaceAllString(strings.TrimSpace(p), "_")
|
||||
if p == "" {
|
||||
p = "_"
|
||||
}
|
||||
parts = append(parts, p)
|
||||
}
|
||||
return strings.Join(parts, ".")
|
||||
}
|
||||
|
||||
// EventFor is the seat's event that says a change.
|
||||
func EventFor(change string) string {
|
||||
switch change {
|
||||
case ChangeRaised, ChangeReopened:
|
||||
return seat.EventConditionRaised
|
||||
case ChangeCleared:
|
||||
return seat.EventConditionCleared
|
||||
}
|
||||
return seat.EventConditionChanged
|
||||
}
|
||||
|
||||
// ShowKeeper is the call that shows one condition whole.
|
||||
func ShowKeeper(key string) string { return seat.Seat + "." + seat.VerbConditions + " key=" + key }
|
||||
|
||||
// SilenceAction is the answer a notification offers to stop a condition's messages for a week.
|
||||
func SilenceAction(key string) seat.Action {
|
||||
return seat.Action{Label: "Silence for a week", Verb: seat.Seat + "." + seat.VerbSilence, Level: seat.ActionLevelAcknowledge,
|
||||
Arguments: map[string]string{"key": key, "for": "7d", "why": "", "cause": CauseOperatorAnswer}}
|
||||
}
|
||||
|
||||
// CheckFinding refuses a finding the keeper could not make a condition of, naming why.
|
||||
func CheckFinding(f seat.FindingsByKeyValue) error {
|
||||
known := false
|
||||
for _, s := range Scopes {
|
||||
known = known || s == f.Subject.Scope
|
||||
}
|
||||
token := f.Ref
|
||||
if token == "" {
|
||||
token = f.Kind
|
||||
}
|
||||
switch {
|
||||
case !known:
|
||||
return fmt.Errorf("health: a finding's scope is one of %s, not %q", strings.Join(Scopes, ", "), f.Subject.Scope)
|
||||
case strings.TrimSpace(f.Subject.ID) == "":
|
||||
return fmt.Errorf("health: a %s finding names what it is about", f.Subject.Scope)
|
||||
case strings.TrimSpace(f.Kind) == "":
|
||||
return fmt.Errorf("health: the finding %s has no kind", f.Key)
|
||||
case f.Key != Key(f.Subject.Scope, f.Subject.ID, token):
|
||||
return fmt.Errorf("health: the finding's key %q is not %q, its scope, id and kind", f.Key, Key(f.Subject.Scope, f.Subject.ID, token))
|
||||
case f.Severity != Urgent && f.Severity != Warning:
|
||||
return fmt.Errorf("health: the finding %s is urgent or a warning, not %q", f.Key, f.Severity)
|
||||
case strings.TrimSpace(f.Summary) == "":
|
||||
return fmt.Errorf("health: the finding %s says nothing", f.Key)
|
||||
case strings.TrimSpace(f.Source) == "":
|
||||
return fmt.Errorf("health: the finding %s does not say what saw it", f.Key)
|
||||
case strings.TrimSpace(f.Observer) == "":
|
||||
return fmt.Errorf("health: the finding %s does not name its observer", f.Key)
|
||||
case len(f.Evidence) > KeptEvidence:
|
||||
return fmt.Errorf("health: the finding %s keeps %d observations, at most %d", f.Key, len(f.Evidence), KeptEvidence)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Order sorts conditions as a person reads them: urgent first, then oldest raised, then by key.
|
||||
func Order(list []seat.ConditionsByKeyValue) {
|
||||
raised := func(c seat.ConditionsByKeyValue) time.Time { t, _ := time.Parse(time.RFC3339Nano, c.Raised); return t }
|
||||
sort.SliceStable(list, func(i, j int) bool {
|
||||
if list[i].Severity != list[j].Severity {
|
||||
return list[i].Severity == Urgent
|
||||
}
|
||||
if ri, rj := raised(list[i]), raised(list[j]); !ri.Equal(rj) {
|
||||
return ri.Before(rj)
|
||||
}
|
||||
return list[i].Key < list[j].Key
|
||||
})
|
||||
}
|
||||
|
||||
// SilencedAt says whether the condition's messages are silenced at now.
|
||||
func SilencedAt(c seat.ConditionsByKeyValue, now time.Time) bool {
|
||||
if c.Silenced == nil {
|
||||
return false
|
||||
}
|
||||
until, err := time.Parse(time.RFC3339Nano, c.Silenced.Until)
|
||||
return err == nil && now.Before(until)
|
||||
}
|
||||
|
||||
// Escalated says the condition waits on the operator after healers tried.
|
||||
func Escalated(c seat.ConditionsByKeyValue) bool {
|
||||
return c.Resolver == ResolverOperator && len(c.Tried) > 0
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package meshconditionsclient
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
|
||||
)
|
||||
|
||||
// ADR 0564 clause 3: the key rule, the checks of a finding, the order and the silence a person reads conditions by.
|
||||
func TestAFindingsKeyAndTheOrderOfConditions(t *testing.T) {
|
||||
if k := Key("machine", "g14.local", "silent"); k != "machine.g14.local.silent" {
|
||||
t.Errorf("key %s", k)
|
||||
}
|
||||
if k := Key("call", "a b", ""); k != "call.a_b._" {
|
||||
t.Errorf("an unsafe part and an empty token: %s", k)
|
||||
}
|
||||
good := seat.FindingsByKeyValue{Key: "machine.g14.silent", Kind: "silent", Severity: Warning, Summary: "x", Source: "S1",
|
||||
Observer: "mesh-delivery-watchman", Subject: seat.Subject{Scope: ScopeMachine, ID: "g14"}}
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
change func(*seat.FindingsByKeyValue)
|
||||
refuse string
|
||||
}{
|
||||
{"a good finding", func(*seat.FindingsByKeyValue) {}, ""},
|
||||
{"an unknown scope", func(f *seat.FindingsByKeyValue) { f.Subject.Scope = "moon" }, "scope is one of"},
|
||||
{"a key that is not its subject's", func(f *seat.FindingsByKeyValue) { f.Key = "machine.g14.other" }, "is not"},
|
||||
{"a reference as the key's last part", func(f *seat.FindingsByKeyValue) { f.Ref = "gone"; f.Key = "machine.g14.gone" }, ""},
|
||||
{"no summary", func(f *seat.FindingsByKeyValue) { f.Summary = " " }, "says nothing"},
|
||||
{"no observer", func(f *seat.FindingsByKeyValue) { f.Observer = "" }, "observer"},
|
||||
{"a severity of neither kind", func(f *seat.FindingsByKeyValue) { f.Severity = "info" }, "urgent or a warning"},
|
||||
{"too much evidence", func(f *seat.FindingsByKeyValue) { f.Evidence = make([]seat.Evidence, KeptEvidence+1) }, "keeps 11"},
|
||||
} {
|
||||
f := good
|
||||
c.change(&f)
|
||||
err := CheckFinding(f)
|
||||
if (c.refuse == "") != (err == nil) || (err != nil && !strings.Contains(err.Error(), c.refuse)) {
|
||||
t.Errorf("%s: %v", c.name, err)
|
||||
}
|
||||
}
|
||||
list := []seat.ConditionsByKeyValue{
|
||||
{Key: "b", Severity: Warning, Raised: "2026-11-01T10:00:00Z"},
|
||||
{Key: "c", Severity: Urgent, Raised: "2026-11-02T10:00:00Z"},
|
||||
{Key: "a", Severity: Urgent, Raised: "2026-11-01T10:00:00.5Z", Silenced: &seat.ConditionsByKeyValueSilenced{Until: "2026-11-03T00:00:00Z"}},
|
||||
}
|
||||
Order(list)
|
||||
if got := list[0].Key + list[1].Key + list[2].Key; got != "acb" {
|
||||
t.Errorf("order %s, want urgent oldest first", got)
|
||||
}
|
||||
now := time.Date(2026, 11, 2, 0, 0, 0, 0, time.UTC)
|
||||
if !SilencedAt(list[0], now) || SilencedAt(list[0], now.Add(48*time.Hour)) || SilencedAt(list[1], now) {
|
||||
t.Error("silence is until its end")
|
||||
}
|
||||
if EventFor(ChangeReopened) != seat.EventConditionRaised || EventFor(ChangeSilenced) != seat.EventConditionChanged ||
|
||||
EventFor(ChangeCleared) != seat.EventConditionCleared {
|
||||
t.Error("a change is said as its event")
|
||||
}
|
||||
if a := SilenceAction("k"); a.Verb != "mesh-conditions.silence" || ShowKeeper("k") != "mesh-conditions.conditions key=k" {
|
||||
t.Errorf("the seat's addresses: %+v", a)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshconditionsclient
|
||||
|
||||
go 1.26.0
|
||||
|
||||
require git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions v0.0.0
|
||||
@@ -0,0 +1,88 @@
|
||||
// Package meshhandactsclient is the logic every module that records an act by hand shares over the seat mesh-hand-acts
|
||||
// (novox/hq ADR 0565 clauses 10 and 11, ADR 0634 §4): the recorder, which asks the seat alone, and what makes an act a
|
||||
// repair. The act's layout is the seat's contract's.
|
||||
package meshhandactsclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts"
|
||||
)
|
||||
|
||||
// The verbs an act is recorded under in the log, and the causes and kinds that are no repair.
|
||||
const (
|
||||
VerbRecord = "hand-act record"
|
||||
VerbDrill = "hand-act drill"
|
||||
VerbWarrant = "warrant"
|
||||
// CauseDrill is a drill's cause, never counted as a repair; CauseOperatorAnswer an act the operator chose.
|
||||
CauseDrill = "drill"
|
||||
CauseOperatorAnswer = "operator-answer"
|
||||
// KindRecordedBuilds is a push that only moved recorded builds: no repair (ADR 0242).
|
||||
KindRecordedBuilds = "recorded-builds"
|
||||
)
|
||||
|
||||
// Repair says the act counts toward a cause repeated: not a drill, not an operator's answer, not recorded builds.
|
||||
func Repair(a seat.Act) bool {
|
||||
return a.Cause != CauseDrill && a.Verb != VerbDrill && a.Cause != CauseOperatorAnswer && a.Kind != KindRecordedBuilds
|
||||
}
|
||||
|
||||
// Request is one act a recorder records: what, why, its cause, the condition it addresses, and its verb in the log (a
|
||||
// repair when empty).
|
||||
type Request struct {
|
||||
What string `json:"what"`
|
||||
Why string `json:"why"`
|
||||
Cause string `json:"cause,omitempty"`
|
||||
Condition string `json:"condition,omitempty"`
|
||||
Verb string `json:"verb,omitempty"`
|
||||
}
|
||||
|
||||
// Taken is which log took an act, and what its holder answered.
|
||||
type Taken struct {
|
||||
Log string `json:"log"`
|
||||
Answer json.RawMessage `json:"answer,omitempty"`
|
||||
}
|
||||
|
||||
// Recorder records acts for a module through the seat mesh-hand-acts alone. An act the seat does not take is an error
|
||||
// that says nothing was recorded, never a quiet success.
|
||||
type Recorder struct {
|
||||
// Ask calls a seat verb by its address (`seat:<seat>.<verb>`): the runtime's ask.
|
||||
Ask func(key string, body any) (json.RawMessage, error)
|
||||
}
|
||||
|
||||
// NoResponder says err is the bus finding nobody to answer: the seat has no holder now.
|
||||
func NoResponder(err error) bool {
|
||||
return err != nil && strings.Contains(err.Error(), "no responders")
|
||||
}
|
||||
|
||||
// Record records one act.
|
||||
func (r Recorder) Record(q Request) (Taken, error) {
|
||||
if strings.TrimSpace(q.What) == "" || strings.TrimSpace(q.Why) == "" {
|
||||
return Taken{}, errors.New("a hand act says what was done and why: nothing was recorded")
|
||||
}
|
||||
body := map[string]any{"what": q.What, "why": q.Why}
|
||||
for k, v := range map[string]string{"cause": q.Cause, "condition": q.Condition, "verb": q.Verb} {
|
||||
if v != "" {
|
||||
body[k] = v
|
||||
}
|
||||
}
|
||||
return r.record(seat.VerbHandAct, body)
|
||||
}
|
||||
|
||||
// RecordWarrant records what the asking module did on the operator's warrant for its ask.
|
||||
func (r Recorder) RecordWarrant(asker, ask string) (Taken, error) {
|
||||
return r.record(seat.VerbWarranted, map[string]any{"asker": asker, "ask": ask})
|
||||
}
|
||||
|
||||
func (r Recorder) record(verb string, body any) (Taken, error) {
|
||||
answer, err := r.Ask("seat:"+seat.Seat+"."+verb, body)
|
||||
if err == nil {
|
||||
return Taken{Log: seat.Seat, Answer: answer}, nil
|
||||
}
|
||||
if NoResponder(err) {
|
||||
return Taken{}, fmt.Errorf("%s has no holder that answers: nothing was recorded (%w)", seat.Seat, err)
|
||||
}
|
||||
return Taken{}, fmt.Errorf("%s.%s refused, nothing was recorded: %w", seat.Seat, verb, err)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package meshhandactsclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts"
|
||||
)
|
||||
|
||||
// ADR 0565 clauses 10 and 11 (issue 1953 L5-S2, S4, L5b): an act reads the controller's entries unchanged, and a
|
||||
// recorder records through the seat alone, the controller's verbs being gone, and says loudly when nothing was recorded.
|
||||
func TestAnActIsRecordedInTheLogThatAnswers(t *testing.T) {
|
||||
// The shape of mesh-controller internal/link HandAct, as its bucket keeps an entry (handacts.go at 0fbb5ef3).
|
||||
raw := `{"id":"act-1","at":"2026-10-28T09:00:00Z","by":"person.jochen","verb":"hand-act record","why":"a stuck consumer",` +
|
||||
`"cause":"consumer-lost","condition":"bus.EVENTS.x.consumer-lost","via":"telegram","ask":"a-1","proofs":["P1"],` +
|
||||
`"requested-by":"bus.EVENTS.x.consumer-lost","outcome":"done"}`
|
||||
var a seat.Act
|
||||
if err := json.Unmarshal([]byte(raw), &a); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
again, _ := json.Marshal(a)
|
||||
var want, got map[string]any
|
||||
_ = json.Unmarshal([]byte(raw), &want)
|
||||
_ = json.Unmarshal(again, &got)
|
||||
if !reflect.DeepEqual(want, got) || !Repair(a) || Repair(seat.Act{Cause: CauseDrill}) || Repair(seat.Act{Verb: VerbDrill}) {
|
||||
t.Errorf("the controller's entry reads back as %s", again)
|
||||
}
|
||||
noResponders := errors.New("nats: no responders available for request")
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
seat error
|
||||
ctrl error
|
||||
log string
|
||||
refused string
|
||||
asked string
|
||||
warrants bool
|
||||
}{
|
||||
{name: "the seat answers", log: seat.Seat, asked: "seat:mesh-hand-acts.hand-act"},
|
||||
{name: "no holder: nothing recorded, the controller never asked", seat: noResponders, refused: "nothing was recorded",
|
||||
asked: "seat:mesh-hand-acts.hand-act"},
|
||||
{name: "the seat refuses", seat: errors.New("why is required"), refused: "refused, nothing was recorded",
|
||||
asked: "seat:mesh-hand-acts.hand-act"},
|
||||
{name: "a warrant without a holder", seat: noResponders, warrants: true, refused: "nothing was recorded",
|
||||
asked: "seat:mesh-hand-acts.warranted"},
|
||||
{name: "a warrant recorded", warrants: true, log: seat.Seat, asked: "seat:mesh-hand-acts.warranted"},
|
||||
} {
|
||||
var asked []string
|
||||
r := Recorder{Ask: func(key string, body any) (json.RawMessage, error) {
|
||||
asked = append(asked, key)
|
||||
if strings.HasPrefix(key, "seat:mesh-hand-acts.") {
|
||||
return json.RawMessage(`{}`), c.seat
|
||||
}
|
||||
return json.RawMessage(`{}`), c.ctrl
|
||||
}}
|
||||
var taken Taken
|
||||
var err error
|
||||
if c.warrants {
|
||||
taken, err = r.RecordWarrant("mesh-config", "ask-1")
|
||||
} else {
|
||||
taken, err = r.Record(Request{What: "silenced", Why: "known", Cause: "silent", Verb: "conditions silence"})
|
||||
}
|
||||
if (c.refused != "") != (err != nil) || (err != nil && !strings.Contains(err.Error(), c.refused)) || taken.Log != c.log ||
|
||||
strings.Join(asked, ",") != c.asked {
|
||||
t.Errorf("%s: took %q, %v, asked %v", c.name, taken.Log, err, asked)
|
||||
}
|
||||
}
|
||||
if _, err := (Recorder{}).Record(Request{What: "x"}); err == nil {
|
||||
t.Error("an act with no why was recorded")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient
|
||||
|
||||
go 1.26.0
|
||||
|
||||
require git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts v0.0.0
|
||||
@@ -0,0 +1,384 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshconditions is the contract of the seat "mesh-conditions", defined whole (seats/mesh-conditions/seat.json): What is wrong with the mesh now (ADR 0564): the open conditions raised from the observers' findings and cleared when a finding goes.
|
||||
package meshconditions
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-conditions"
|
||||
|
||||
const (
|
||||
VerbConditions = "conditions"
|
||||
VerbSilence = "silence"
|
||||
VerbResync = "resync"
|
||||
)
|
||||
|
||||
const (
|
||||
EventConditionRaised = "condition-raised"
|
||||
EventConditionChanged = "condition-changed"
|
||||
EventConditionCleared = "condition-cleared"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbConditions, VerbSilence, VerbResync}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventConditionRaised, EventConditionChanged, EventConditionCleared}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-conditions.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// SubjectConditionRaised is where condition-raised is published.
|
||||
const SubjectConditionRaised = "mesh.seat.mesh-conditions.event.condition-raised"
|
||||
|
||||
// SubjectConditionChanged is where condition-changed is published.
|
||||
const SubjectConditionChanged = "mesh.seat.mesh-conditions.event.condition-changed"
|
||||
|
||||
// SubjectConditionCleared is where condition-cleared is published.
|
||||
const SubjectConditionCleared = "mesh.seat.mesh-conditions.event.condition-cleared"
|
||||
|
||||
const (
|
||||
StateConditions = "conditions"
|
||||
StateFindings = "findings"
|
||||
)
|
||||
|
||||
// ConditionsByKeyKey is the key of one value of the state conditions under the form "<key>".
|
||||
func ConditionsByKeyKey(key string) string { return key }
|
||||
|
||||
// ParseConditionsByKeyKey reads the parts of a key of the form "<key>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseConditionsByKeyKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeConditionsByKeyValue reads one value of the state conditions under the form "<key>", refusing a field ConditionsByKeyValue does not know and any text after the value.
|
||||
func DecodeConditionsByKeyValue(raw []byte) (ConditionsByKeyValue, error) {
|
||||
var v ConditionsByKeyValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// FindingsByKeyKey is the key of one value of the state findings under the form "<key>".
|
||||
func FindingsByKeyKey(key string) string { return key }
|
||||
|
||||
// ParseFindingsByKeyKey reads the parts of a key of the form "<key>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseFindingsByKeyKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeFindingsByKeyValue reads one value of the state findings under the form "<key>", refusing a field FindingsByKeyValue does not know and any text after the value.
|
||||
func DecodeFindingsByKeyValue(raw []byte) (FindingsByKeyValue, error) {
|
||||
var v FindingsByKeyValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Action is one answer the operator may give from a notification.
|
||||
type Action struct {
|
||||
Arguments map[string]string `json:"arguments,omitempty"`
|
||||
Label string `json:"label"`
|
||||
Level string `json:"level,omitempty"`
|
||||
Machine string `json:"machine,omitempty"`
|
||||
// the seat verb the operator channel calls
|
||||
Verb string `json:"verb"`
|
||||
}
|
||||
|
||||
// The values of Action's level.
|
||||
const (
|
||||
ActionLevelAcknowledge = "acknowledge"
|
||||
ActionLevelApprove = "approve"
|
||||
)
|
||||
|
||||
// ConditionEventGapsItem is a type of the contract.
|
||||
type ConditionEventGapsItem struct {
|
||||
Cleared string `json:"cleared,omitempty"`
|
||||
Reopened string `json:"reopened,omitempty"`
|
||||
}
|
||||
|
||||
// ConditionEventSilenced is a type of the contract.
|
||||
type ConditionEventSilenced struct {
|
||||
By string `json:"by,omitempty"`
|
||||
Since string `json:"since,omitempty"`
|
||||
Until string `json:"until,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// ConditionEventTriedItem is a type of the contract.
|
||||
type ConditionEventTriedItem struct {
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Outcome string `json:"outcome,omitempty"`
|
||||
What string `json:"what,omitempty"`
|
||||
}
|
||||
|
||||
// ConditionEvent is a condition and what changed.
|
||||
type ConditionEvent struct {
|
||||
Actions []Action `json:"actions,omitempty"`
|
||||
At string `json:"at"`
|
||||
Change string `json:"change"`
|
||||
Cleared string `json:"cleared,omitempty"`
|
||||
Count int64 `json:"count,omitempty"`
|
||||
Epoch int64 `json:"epoch,omitempty"`
|
||||
Event string `json:"event"`
|
||||
// newest first, at most 10
|
||||
Evidence []Evidence `json:"evidence,omitempty"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
First string `json:"first,omitempty"`
|
||||
Gaps []ConditionEventGapsItem `json:"gaps,omitempty"`
|
||||
Headline string `json:"headline,omitempty"`
|
||||
// scope.id.token
|
||||
Key string `json:"key"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
LastObserved string `json:"last-observed,omitempty"`
|
||||
LooksUnread string `json:"looks-unread,omitempty"`
|
||||
Needs string `json:"needs,omitempty"`
|
||||
Observations int64 `json:"observations,omitempty"`
|
||||
Raised string `json:"raised,omitempty"`
|
||||
Resolved string `json:"resolved,omitempty"`
|
||||
// self, operator, agent or healer:<name>
|
||||
Resolver string `json:"resolver,omitempty"`
|
||||
Severity string `json:"severity,omitempty"`
|
||||
// the tool call that shows it
|
||||
Show string `json:"show,omitempty"`
|
||||
Silenced *ConditionEventSilenced `json:"silenced,omitempty"`
|
||||
// the row, probe or event that saw it
|
||||
Source string `json:"source,omitempty"`
|
||||
Subject *Subject `json:"subject,omitempty"`
|
||||
// one line
|
||||
Summary string `json:"summary,omitempty"`
|
||||
Tried []ConditionEventTriedItem `json:"tried,omitempty"`
|
||||
Was string `json:"was,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// The values of ConditionEvent's change.
|
||||
const (
|
||||
ConditionEventChangeRaised = "raised"
|
||||
ConditionEventChangeReopened = "reopened"
|
||||
ConditionEventChangeSeverity = "severity"
|
||||
ConditionEventChangeResolver = "resolver"
|
||||
ConditionEventChangeSilenced = "silenced"
|
||||
ConditionEventChangeSilenceEnded = "silence-ended"
|
||||
ConditionEventChangeCleared = "cleared"
|
||||
ConditionEventChangeWords = "words"
|
||||
)
|
||||
|
||||
// The values of ConditionEvent's severity.
|
||||
const (
|
||||
ConditionEventSeverityUrgent = "urgent"
|
||||
ConditionEventSeverityWarning = "warning"
|
||||
)
|
||||
|
||||
// Evidence is one observation, as it was said.
|
||||
type Evidence struct {
|
||||
At string `json:"at"`
|
||||
Said string `json:"said"`
|
||||
}
|
||||
|
||||
// Subject is what the condition is about.
|
||||
type Subject struct {
|
||||
// the other machines it concerns
|
||||
Also []string `json:"also,omitempty"`
|
||||
// its id within the scope
|
||||
ID string `json:"id"`
|
||||
// the machine it concerns, when there is one
|
||||
Machine string `json:"machine,omitempty"`
|
||||
// machine, plan, call, build, merge, provider, seat, bus, core, probe, mesh, delivery or module
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
// ConditionsInput is what conditions takes.
|
||||
type ConditionsInput struct {
|
||||
// with history: how many days back (default 7, at most 90)
|
||||
Days string `json:"days,omitempty"`
|
||||
// "true": every raising, change, silence and clearing lately, oldest first
|
||||
History string `json:"history,omitempty"`
|
||||
// a condition's key: that one whole; with history, only its transitions
|
||||
Key string `json:"key,omitempty"`
|
||||
// only those about this machine
|
||||
Machine string `json:"machine,omitempty"`
|
||||
// only this scope: machine, plan, call, build, merge, provider, seat, bus, core, probe, mesh, delivery or module
|
||||
Scope string `json:"scope,omitempty"`
|
||||
// only urgent, or only warning
|
||||
Severity string `json:"severity,omitempty"`
|
||||
}
|
||||
|
||||
// The values of ConditionsInput's history.
|
||||
const (
|
||||
ConditionsInputHistoryTrue = "true"
|
||||
ConditionsInputHistoryFalse = "false"
|
||||
)
|
||||
|
||||
// ConditionsAnswer is what conditions answers.
|
||||
type ConditionsAnswer = map[string]any
|
||||
|
||||
// SilenceInput is what silence takes.
|
||||
type SilenceInput struct {
|
||||
// the cause in a word (the condition's kind when absent)
|
||||
Cause string `json:"cause,omitempty"`
|
||||
// how long: 30m, 4h, 2d; at most 7d
|
||||
For string `json:"for"`
|
||||
// the condition's key
|
||||
Key string `json:"key"`
|
||||
// why, required and recorded
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// SilenceAnswer is what silence answers.
|
||||
type SilenceAnswer = map[string]any
|
||||
|
||||
// ResyncInput is what resync takes.
|
||||
type ResyncInput struct {
|
||||
}
|
||||
|
||||
// ResyncAnswer is what resync answers.
|
||||
type ResyncAnswer = map[string]any
|
||||
|
||||
// ConditionRaisedEvent is the body of the event condition-raised.
|
||||
type ConditionRaisedEvent = ConditionEvent
|
||||
|
||||
// ConditionChangedEvent is the body of the event condition-changed.
|
||||
type ConditionChangedEvent = ConditionEvent
|
||||
|
||||
// ConditionClearedEvent is the body of the event condition-cleared.
|
||||
type ConditionClearedEvent = ConditionEvent
|
||||
|
||||
// ConditionsByKeyValueGapsItem is a type of the contract.
|
||||
type ConditionsByKeyValueGapsItem struct {
|
||||
Cleared string `json:"cleared,omitempty"`
|
||||
Reopened string `json:"reopened,omitempty"`
|
||||
}
|
||||
|
||||
// ConditionsByKeyValueSilenced is a type of the contract.
|
||||
type ConditionsByKeyValueSilenced struct {
|
||||
By string `json:"by,omitempty"`
|
||||
Since string `json:"since,omitempty"`
|
||||
Until string `json:"until,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// ConditionsByKeyValueTriedItem is a type of the contract.
|
||||
type ConditionsByKeyValueTriedItem struct {
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Outcome string `json:"outcome,omitempty"`
|
||||
What string `json:"what,omitempty"`
|
||||
}
|
||||
|
||||
// ConditionsByKeyValue is one value of the state conditions under the key <key>.
|
||||
type ConditionsByKeyValue struct {
|
||||
Actions []Action `json:"actions,omitempty"`
|
||||
Count int64 `json:"count,omitempty"`
|
||||
Epoch int64 `json:"epoch,omitempty"`
|
||||
// newest first, at most 10
|
||||
Evidence []Evidence `json:"evidence,omitempty"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
First string `json:"first,omitempty"`
|
||||
Gaps []ConditionsByKeyValueGapsItem `json:"gaps,omitempty"`
|
||||
Headline string `json:"headline,omitempty"`
|
||||
// scope.id.token
|
||||
Key string `json:"key"`
|
||||
Kind string `json:"kind"`
|
||||
LastObserved string `json:"last-observed"`
|
||||
LooksUnread string `json:"looks-unread,omitempty"`
|
||||
Needs string `json:"needs,omitempty"`
|
||||
Observations int64 `json:"observations,omitempty"`
|
||||
Raised string `json:"raised"`
|
||||
Resolved string `json:"resolved,omitempty"`
|
||||
// self, operator, agent or healer:<name>
|
||||
Resolver string `json:"resolver,omitempty"`
|
||||
Severity string `json:"severity"`
|
||||
Silenced *ConditionsByKeyValueSilenced `json:"silenced,omitempty"`
|
||||
// the row, probe or event that saw it
|
||||
Source string `json:"source,omitempty"`
|
||||
Subject Subject `json:"subject"`
|
||||
// one line
|
||||
Summary string `json:"summary,omitempty"`
|
||||
Tried []ConditionsByKeyValueTriedItem `json:"tried,omitempty"`
|
||||
}
|
||||
|
||||
// The values of ConditionsByKeyValue's severity.
|
||||
const (
|
||||
ConditionsByKeyValueSeverityUrgent = "urgent"
|
||||
ConditionsByKeyValueSeverityWarning = "warning"
|
||||
)
|
||||
|
||||
// FindingsByKeyValue is one value of the state findings under the key <key>.
|
||||
type FindingsByKeyValue struct {
|
||||
Actions []Action `json:"actions,omitempty"`
|
||||
At string `json:"at"`
|
||||
// newest first, at most 10
|
||||
Evidence []Evidence `json:"evidence,omitempty"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
Headline string `json:"headline,omitempty"`
|
||||
// scope.id.token
|
||||
Key string `json:"key"`
|
||||
Kind string `json:"kind"`
|
||||
Needs string `json:"needs,omitempty"`
|
||||
// the module that wrote it
|
||||
Observer string `json:"observer"`
|
||||
// the key's last part when it is not the kind
|
||||
Ref string `json:"ref,omitempty"`
|
||||
Resolved string `json:"resolved,omitempty"`
|
||||
// self, operator, agent or healer:<name>
|
||||
Resolver string `json:"resolver,omitempty"`
|
||||
// what of its own saw it last
|
||||
Run string `json:"run,omitempty"`
|
||||
Severity string `json:"severity"`
|
||||
// the row, probe or event that saw it
|
||||
Source string `json:"source"`
|
||||
Subject Subject `json:"subject"`
|
||||
// one line
|
||||
Summary string `json:"summary"`
|
||||
// layout version, 1
|
||||
V int64 `json:"v"`
|
||||
}
|
||||
|
||||
// The values of FindingsByKeyValue's severity.
|
||||
const (
|
||||
FindingsByKeyValueSeverityUrgent = "urgent"
|
||||
FindingsByKeyValueSeverityWarning = "warning"
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,222 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshhandacts is the contract of the seat "mesh-hand-acts", defined whole (seats/mesh-hand-acts/seat.json): Acts done by hand, recorded with who, why and cause (ADR 0565): the log every module records through.
|
||||
package meshhandacts
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-hand-acts"
|
||||
|
||||
const (
|
||||
VerbHandAct = "hand-act"
|
||||
VerbHandActs = "hand-acts"
|
||||
VerbWarranted = "warranted"
|
||||
)
|
||||
|
||||
const (
|
||||
EventActRecorded = "act-recorded"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbHandAct, VerbHandActs, VerbWarranted}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventActRecorded}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-hand-acts.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// SubjectActRecorded is where act-recorded is published.
|
||||
const SubjectActRecorded = "mesh.seat.mesh-hand-acts.event.act-recorded"
|
||||
|
||||
const (
|
||||
StateActs = "acts"
|
||||
StateWarrants = "warrants"
|
||||
)
|
||||
|
||||
// ActsByIDKey is the key of one value of the state acts under the form "<id>".
|
||||
func ActsByIDKey(id string) string { return id }
|
||||
|
||||
// ParseActsByIDKey reads the parts of a key of the form "<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseActsByIDKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeActsByIDValue reads one value of the state acts under the form "<id>", refusing a field ActsByIDValue does not know and any text after the value.
|
||||
func DecodeActsByIDValue(raw []byte) (ActsByIDValue, error) {
|
||||
var v ActsByIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// WarrantsByAskerAskKey is the key of one value of the state warrants under the form "<asker>.<ask>".
|
||||
func WarrantsByAskerAskKey(asker, ask string) string { return asker + "." + ask }
|
||||
|
||||
// ParseWarrantsByAskerAskKey reads the parts of a key of the form "<asker>.<ask>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseWarrantsByAskerAskKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeWarrantsByAskerAskValue reads one value of the state warrants under the form "<asker>.<ask>", refusing a field WarrantsByAskerAskValue does not know and any text after the value.
|
||||
func DecodeWarrantsByAskerAskValue(raw []byte) (WarrantsByAskerAskValue, error) {
|
||||
var v WarrantsByAskerAskValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Act is one act done by hand.
|
||||
type Act struct {
|
||||
Arguments []string `json:"arguments,omitempty"`
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At string `json:"at"`
|
||||
// the caller the runtime proved
|
||||
By string `json:"by"`
|
||||
Carried []string `json:"carried,omitempty"`
|
||||
Cause string `json:"cause"`
|
||||
Condition string `json:"condition,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// what the act was read to be from what it did
|
||||
Kind string `json:"kind,omitempty"`
|
||||
// which log holds it, set when it is read
|
||||
Log string `json:"log,omitempty"`
|
||||
Outcome string `json:"outcome,omitempty"`
|
||||
Proofs []string `json:"proofs,omitempty"`
|
||||
RequestedBy string `json:"requested-by,omitempty"`
|
||||
Verb string `json:"verb"`
|
||||
Via string `json:"via,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// HandActInput is what hand-act takes.
|
||||
type HandActInput struct {
|
||||
// the cause in a word, or a condition's kind
|
||||
Cause string `json:"cause,omitempty"`
|
||||
// the key of the condition it addressed, if any (optional)
|
||||
Condition string `json:"condition,omitempty"`
|
||||
// the act's verb in the log: a repair when absent, `hand-act drill` for a drill, or a recorder's own
|
||||
Verb string `json:"verb,omitempty"`
|
||||
// what was done, in a line
|
||||
What string `json:"what"`
|
||||
// why it had to be done by hand
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// HandActAnswer is what hand-act answers.
|
||||
type HandActAnswer = map[string]any
|
||||
|
||||
// HandActsInput is what hand-acts takes.
|
||||
type HandActsInput struct {
|
||||
// only this cause
|
||||
Cause string `json:"cause,omitempty"`
|
||||
// how many days back (default 14)
|
||||
Days string `json:"days,omitempty"`
|
||||
// "true": every warrant recorded
|
||||
Warrants string `json:"warrants,omitempty"`
|
||||
// only acts whose who contains this
|
||||
Who string `json:"who,omitempty"`
|
||||
}
|
||||
|
||||
// The values of HandActsInput's warrants.
|
||||
const (
|
||||
HandActsInputWarrantsTrue = "true"
|
||||
HandActsInputWarrantsFalse = "false"
|
||||
)
|
||||
|
||||
// HandActsAnswer is what hand-acts answers.
|
||||
type HandActsAnswer = map[string]any
|
||||
|
||||
// WarrantedInput is what warranted takes.
|
||||
type WarrantedInput struct {
|
||||
// its ask's id
|
||||
Ask string `json:"ask"`
|
||||
// the module that asked
|
||||
Asker string `json:"asker"`
|
||||
}
|
||||
|
||||
// WarrantedAnswer is what warranted answers.
|
||||
type WarrantedAnswer = map[string]any
|
||||
|
||||
// ActRecordedEvent is the body of the event act-recorded.
|
||||
type ActRecordedEvent = Act
|
||||
|
||||
// ActsByIDValue is one value of the state acts under the key <id>.
|
||||
type ActsByIDValue struct {
|
||||
Arguments []string `json:"arguments,omitempty"`
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At string `json:"at"`
|
||||
// the caller the runtime proved
|
||||
By string `json:"by"`
|
||||
Carried []string `json:"carried,omitempty"`
|
||||
Cause string `json:"cause"`
|
||||
Condition string `json:"condition,omitempty"`
|
||||
ID string `json:"id"`
|
||||
// what the act was read to be from what it did
|
||||
Kind string `json:"kind,omitempty"`
|
||||
// which log holds it, set when it is read
|
||||
Log string `json:"log,omitempty"`
|
||||
Outcome string `json:"outcome,omitempty"`
|
||||
Proofs []string `json:"proofs,omitempty"`
|
||||
RequestedBy string `json:"requested-by,omitempty"`
|
||||
Verb string `json:"verb"`
|
||||
Via string `json:"via,omitempty"`
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// WarrantsByAskerAskValue is one value of the state warrants under the key <asker>.<ask>.
|
||||
type WarrantsByAskerAskValue struct {
|
||||
Ask string `json:"ask"`
|
||||
Asker string `json:"asker"`
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Option string `json:"option,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhandacts
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,197 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshhealers is the contract of the seat "mesh-healers", defined whole (seats/mesh-healers/seat.json): The healers (ADR 0564): each a registered response to one kind of condition, within a budget and the mesh-wide brake.
|
||||
package meshhealers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-healers"
|
||||
|
||||
const (
|
||||
VerbHealers = "healers"
|
||||
VerbHeal = "heal"
|
||||
VerbDrill = "drill"
|
||||
)
|
||||
|
||||
const (
|
||||
EventHealerActed = "healer-acted"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbHealers, VerbHeal, VerbDrill}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventHealerActed}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-healers.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// SubjectHealerActed is where healer-acted is published.
|
||||
const SubjectHealerActed = "mesh.seat.mesh-healers.event.healer-acted"
|
||||
|
||||
const (
|
||||
StateAttempts = "attempts"
|
||||
StateWould = "would"
|
||||
)
|
||||
|
||||
// AttemptsByAttemptKey is the key of one value of the state attempts under the form "<attempt>".
|
||||
func AttemptsByAttemptKey(attempt string) string { return attempt }
|
||||
|
||||
// ParseAttemptsByAttemptKey reads the parts of a key of the form "<attempt>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAttemptsByAttemptKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeAttemptsByAttemptValue reads one value of the state attempts under the form "<attempt>", refusing a field AttemptsByAttemptValue does not know and any text after the value.
|
||||
func DecodeAttemptsByAttemptValue(raw []byte) (AttemptsByAttemptValue, error) {
|
||||
var v AttemptsByAttemptValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// WouldByWouldKey is the key of one value of the state would under the form "<would>".
|
||||
func WouldByWouldKey(would string) string { return would }
|
||||
|
||||
// ParseWouldByWouldKey reads the parts of a key of the form "<would>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseWouldByWouldKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodeWouldByWouldValue reads one value of the state would under the form "<would>", refusing a field WouldByWouldValue does not know and any text after the value.
|
||||
func DecodeWouldByWouldValue(raw []byte) (WouldByWouldValue, error) {
|
||||
var v WouldByWouldValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// HealersInput is what healers takes.
|
||||
type HealersInput struct {
|
||||
// how many days of acts back (default 7)
|
||||
Days string `json:"days,omitempty"`
|
||||
}
|
||||
|
||||
// HealersAnswer is what healers answers.
|
||||
type HealersAnswer = map[string]any
|
||||
|
||||
// HealInput is what heal takes.
|
||||
type HealInput struct {
|
||||
// the condition's key
|
||||
Key string `json:"key"`
|
||||
// why now, kept with the act
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// HealAnswer is what heal answers.
|
||||
type HealAnswer = map[string]any
|
||||
|
||||
// DrillInput is what drill takes.
|
||||
type DrillInput struct {
|
||||
// the key of the condition the drill is meant to raise, if any (optional)
|
||||
Condition string `json:"condition,omitempty"`
|
||||
// what was done on purpose, in a line
|
||||
What string `json:"what"`
|
||||
// what the drill tests
|
||||
Why string `json:"why"`
|
||||
}
|
||||
|
||||
// DrillAnswer is what drill answers.
|
||||
type DrillAnswer = map[string]any
|
||||
|
||||
// HealerActedEvent is the body of the event healer-acted.
|
||||
type HealerActedEvent struct {
|
||||
Act string `json:"act,omitempty"`
|
||||
At string `json:"at"`
|
||||
Budget string `json:"budget,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Condition string `json:"condition"`
|
||||
Event string `json:"event"`
|
||||
Healer string `json:"healer"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Outcome string `json:"outcome"`
|
||||
Said string `json:"said,omitempty"`
|
||||
Show string `json:"show,omitempty"`
|
||||
}
|
||||
|
||||
// The values of HealerActedEvent's outcome.
|
||||
const (
|
||||
HealerActedEventOutcomeActing = "acting"
|
||||
HealerActedEventOutcomeActed = "acted"
|
||||
HealerActedEventOutcomeFailed = "failed"
|
||||
HealerActedEventOutcomeEscalated = "escalated"
|
||||
)
|
||||
|
||||
// AttemptsByAttemptValue is one value of the state attempts under the key <attempt>.
|
||||
type AttemptsByAttemptValue struct {
|
||||
Act string `json:"act"`
|
||||
Begun string `json:"begun"`
|
||||
// what the budget counts by: the condition's key unless the healer says another
|
||||
BudgetKey string `json:"budget-key"`
|
||||
Condition string `json:"condition"`
|
||||
Finished string `json:"finished,omitempty"`
|
||||
Healer string `json:"healer"`
|
||||
Kind string `json:"kind"`
|
||||
Outcome string `json:"outcome"`
|
||||
Said string `json:"said,omitempty"`
|
||||
}
|
||||
|
||||
// The values of AttemptsByAttemptValue's outcome.
|
||||
const (
|
||||
AttemptsByAttemptValueOutcomeActing = "acting"
|
||||
AttemptsByAttemptValueOutcomeActed = "acted"
|
||||
AttemptsByAttemptValueOutcomeFailed = "failed"
|
||||
AttemptsByAttemptValueOutcomeEscalated = "escalated"
|
||||
)
|
||||
|
||||
// WouldByWouldValue is one value of the state would under the key <would>.
|
||||
type WouldByWouldValue struct {
|
||||
Act string `json:"act"`
|
||||
At string `json:"at"`
|
||||
Condition string `json:"condition"`
|
||||
Healer string `json:"healer"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshhealers
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,101 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshselfcheck is the contract of the seat "mesh-self-check", defined whole (seats/mesh-self-check/seat.json): The mesh checking itself (ADR 0564): probes run every five minutes, each failure a finding the seat's conditions raise.
|
||||
package meshselfcheck
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-self-check"
|
||||
|
||||
const (
|
||||
VerbDoctor = "doctor"
|
||||
VerbProbes = "probes"
|
||||
)
|
||||
|
||||
const (
|
||||
EventChecked = "checked"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbDoctor, VerbProbes}
|
||||
}
|
||||
|
||||
// Events is every event published on the seat's subject: a new copy each call.
|
||||
func Events() []string {
|
||||
return []string{EventChecked}
|
||||
}
|
||||
|
||||
// Family is where the seat's events are kept: the shared events stream, filtered to the seat's subjects.
|
||||
const (
|
||||
Family = "mesh-self-check.events"
|
||||
FamilyMaxAgeDays = 7
|
||||
)
|
||||
|
||||
// SubjectChecked is where checked is published.
|
||||
const SubjectChecked = "mesh.seat.mesh-self-check.event.checked"
|
||||
|
||||
// ProbeVerdict is one probe's verdict.
|
||||
type ProbeVerdict struct {
|
||||
Error string `json:"error,omitempty"`
|
||||
Found []string `json:"found,omitempty"`
|
||||
FoundCount int64 `json:"found-count,omitempty"`
|
||||
ID string `json:"id"`
|
||||
More string `json:"more,omitempty"`
|
||||
Took string `json:"took,omitempty"`
|
||||
Unconfirmed []string `json:"unconfirmed,omitempty"`
|
||||
Verdict string `json:"verdict"`
|
||||
}
|
||||
|
||||
// The values of ProbeVerdict's verdict.
|
||||
const (
|
||||
ProbeVerdictVerdictPassed = "passed"
|
||||
ProbeVerdictVerdictFailed = "failed"
|
||||
ProbeVerdictVerdictFailedToRun = "failed-to-run"
|
||||
ProbeVerdictVerdictDeferred = "deferred"
|
||||
)
|
||||
|
||||
// DoctorInput is what doctor takes.
|
||||
type DoctorInput struct {
|
||||
// one probe's id (D6): its verdict alone, with every finding
|
||||
Probe string `json:"probe,omitempty"`
|
||||
// "true": run every probe now and answer the verdict
|
||||
Run string `json:"run,omitempty"`
|
||||
}
|
||||
|
||||
// The values of DoctorInput's run.
|
||||
const (
|
||||
DoctorInputRunTrue = "true"
|
||||
DoctorInputRunFalse = "false"
|
||||
)
|
||||
|
||||
// DoctorAnswer is what doctor answers.
|
||||
type DoctorAnswer = map[string]any
|
||||
|
||||
// ProbesInput is what probes takes.
|
||||
type ProbesInput struct {
|
||||
}
|
||||
|
||||
// ProbesAnswer is what probes answers.
|
||||
type ProbesAnswer = map[string]any
|
||||
|
||||
// CheckedEventCounts is a type of the contract.
|
||||
type CheckedEventCounts struct {
|
||||
Deferred int64 `json:"deferred,omitempty"`
|
||||
Failed int64 `json:"failed,omitempty"`
|
||||
FailedToRun int64 `json:"failed-to-run,omitempty"`
|
||||
Passed int64 `json:"passed,omitempty"`
|
||||
}
|
||||
|
||||
// CheckedEvent is the body of the event checked.
|
||||
type CheckedEvent struct {
|
||||
At string `json:"at"`
|
||||
Controller string `json:"controller,omitempty"`
|
||||
Counts *CheckedEventCounts `json:"counts,omitempty"`
|
||||
IntervalSeconds int64 `json:"interval-seconds,omitempty"`
|
||||
Probes []ProbeVerdict `json:"probes"`
|
||||
Run string `json:"run"`
|
||||
Started string `json:"started,omitempty"`
|
||||
Took string `json:"took,omitempty"`
|
||||
Unsaid int64 `json:"unsaid,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshselfcheck
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,266 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshwatchdogs is the contract of the seat "mesh-watchdogs", defined whole (seats/mesh-watchdogs/seat.json): The watchman's seat (ADR 0564, ADR 0433): signals that expire unless renewed, what stopped moving, who is present, the dead letters.
|
||||
package meshwatchdogs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-watchdogs"
|
||||
|
||||
const (
|
||||
VerbSignals = "signals"
|
||||
VerbStuck = "stuck"
|
||||
VerbPresence = "presence"
|
||||
VerbDeadLetters = "dead-letters"
|
||||
VerbResync = "resync"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbSignals, VerbStuck, VerbPresence, VerbDeadLetters, VerbResync}
|
||||
}
|
||||
|
||||
const (
|
||||
StatePresence = "presence"
|
||||
StatePulse = "pulse"
|
||||
StateStuck = "stuck"
|
||||
)
|
||||
|
||||
// PresenceByNodeKey is the key of one value of the state presence under the form "<node>".
|
||||
func PresenceByNodeKey(node string) string { return node }
|
||||
|
||||
// ParsePresenceByNodeKey reads the parts of a key of the form "<node>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePresenceByNodeKey(key string) (string, bool) {
|
||||
rest := key
|
||||
if rest == "" {
|
||||
return "", false
|
||||
}
|
||||
v0 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", false
|
||||
}
|
||||
return v0, true
|
||||
}
|
||||
|
||||
// DecodePresenceByNodeValue reads one value of the state presence under the form "<node>", refusing a field PresenceByNodeValue does not know and any text after the value.
|
||||
func DecodePresenceByNodeValue(raw []byte) (PresenceByNodeValue, error) {
|
||||
var v PresenceByNodeValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PresenceByPartPartInstanceKey is the key of one value of the state presence under the form "part.<part>.<instance>".
|
||||
func PresenceByPartPartInstanceKey(part, instance string) string {
|
||||
return "part." + part + "." + instance
|
||||
}
|
||||
|
||||
// ParsePresenceByPartPartInstanceKey reads the parts of a key of the form "part.<part>.<instance>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePresenceByPartPartInstanceKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
if !strings.HasPrefix(rest, "part.") {
|
||||
return "", "", false
|
||||
}
|
||||
rest = rest[5:]
|
||||
v1, after1, found1 := strings.Cut(rest, ".")
|
||||
if !found1 || v1 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after1
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v3 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v1, v3, true
|
||||
}
|
||||
|
||||
// DecodePresenceByPartPartInstanceValue reads one value of the state presence under the form "part.<part>.<instance>", refusing a field PresenceByPartPartInstanceValue does not know and any text after the value.
|
||||
func DecodePresenceByPartPartInstanceValue(raw []byte) (PresenceByPartPartInstanceValue, error) {
|
||||
var v PresenceByPartPartInstanceValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// PulseByBucketKeyKey is the key of one value of the state pulse under the form "<bucket>.<key>".
|
||||
func PulseByBucketKeyKey(bucket, key string) string { return bucket + "." + key }
|
||||
|
||||
// ParsePulseByBucketKeyKey reads the parts of a key of the form "<bucket>.<key>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePulseByBucketKeyKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodePulseByBucketKeyValue reads one value of the state pulse under the form "<bucket>.<key>", refusing a field PulseByBucketKeyValue does not know and any text after the value.
|
||||
func DecodePulseByBucketKeyValue(raw []byte) (PulseByBucketKeyValue, error) {
|
||||
var v PulseByBucketKeyValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// StuckByBucketKeyKey is the key of one value of the state stuck under the form "<bucket>.<key>".
|
||||
func StuckByBucketKeyKey(bucket, key string) string { return bucket + "." + key }
|
||||
|
||||
// ParseStuckByBucketKeyKey reads the parts of a key of the form "<bucket>.<key>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseStuckByBucketKeyKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeStuckByBucketKeyValue reads one value of the state stuck under the form "<bucket>.<key>", refusing a field StuckByBucketKeyValue does not know and any text after the value.
|
||||
func DecodeStuckByBucketKeyValue(raw []byte) (StuckByBucketKeyValue, error) {
|
||||
var v StuckByBucketKeyValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// SignalsInput is what signals takes.
|
||||
type SignalsInput struct {
|
||||
// one row, e.g. S1
|
||||
Row string `json:"row,omitempty"`
|
||||
}
|
||||
|
||||
// SignalsAnswer is what signals answers.
|
||||
type SignalsAnswer = map[string]any
|
||||
|
||||
// StuckInput is what stuck takes.
|
||||
type StuckInput struct {
|
||||
// only those on this machine
|
||||
Machine string `json:"machine,omitempty"`
|
||||
}
|
||||
|
||||
// StuckAnswer is what stuck answers.
|
||||
type StuckAnswer = map[string]any
|
||||
|
||||
// PresenceInput is what presence takes.
|
||||
type PresenceInput struct {
|
||||
// one machine
|
||||
Machine string `json:"machine,omitempty"`
|
||||
}
|
||||
|
||||
// PresenceAnswer is what presence answers.
|
||||
type PresenceAnswer = map[string]any
|
||||
|
||||
// DeadLettersInput is what dead-letters takes.
|
||||
type DeadLettersInput struct {
|
||||
// with deliver or drop: the cause in a word (dead-letter when absent)
|
||||
Cause string `json:"cause,omitempty"`
|
||||
// a consumer's name, or <stream>.<consumer>: only what that one gave up on
|
||||
Consumer string `json:"consumer,omitempty"`
|
||||
// a dead letter's id: deliver it again to the consumer that gave it up (needs why)
|
||||
Deliver string `json:"deliver,omitempty"`
|
||||
// a dead letter's id: drop it for good (needs why)
|
||||
Drop string `json:"drop,omitempty"`
|
||||
// a dead letter's id, as the list gives it: that one whole, with its message
|
||||
ID string `json:"id,omitempty"`
|
||||
// how many to list, newest first (default 50); only when listing
|
||||
Limit string `json:"limit,omitempty"`
|
||||
// with deliver or drop: why, required and recorded
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// DeadLettersAnswer is what dead-letters answers.
|
||||
type DeadLettersAnswer = map[string]any
|
||||
|
||||
// ResyncInput is what resync takes.
|
||||
type ResyncInput struct {
|
||||
}
|
||||
|
||||
// ResyncAnswer is what resync answers.
|
||||
type ResyncAnswer = map[string]any
|
||||
|
||||
// PresenceByNodeValue is one value of the state presence under the key <node>.
|
||||
type PresenceByNodeValue struct {
|
||||
Online bool `json:"online"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// PresenceByPartPartInstanceValue is one value of the state presence under the key part.<part>.<instance>.
|
||||
type PresenceByPartPartInstanceValue struct {
|
||||
Online bool `json:"online"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// PulseByBucketKeyValue is one value of the state pulse under the key <bucket>.<key>.
|
||||
type PulseByBucketKeyValue struct {
|
||||
Bucket string `json:"bucket"`
|
||||
Key string `json:"key"`
|
||||
Owes string `json:"owes,omitempty"`
|
||||
Revision int64 `json:"revision"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// StuckByBucketKeyValue is one value of the state stuck under the key <bucket>.<key>.
|
||||
type StuckByBucketKeyValue struct {
|
||||
Bucket string `json:"bucket"`
|
||||
Key string `json:"key"`
|
||||
// it has moved again
|
||||
Moved bool `json:"moved,omitempty"`
|
||||
Since string `json:"since"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
// what it waited for, in words
|
||||
Waited string `json:"waited,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshwatchdogs
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"format": 1,
|
||||
"seats": [
|
||||
"mesh-conditions",
|
||||
"mesh-hand-acts",
|
||||
"mesh-healers",
|
||||
"mesh-self-check",
|
||||
"mesh-watchdogs"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-conditions, generated from its definition.",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-health-and-repair-contracts-mesh-conditions",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-conditions", defined whole (seats/mesh-conditions/seat.json): What is wrong with the mesh now (ADR 0564): the open conditions raised from the observers' findings and cleared when a finding goes.
|
||||
|
||||
export const seat = "mesh-conditions";
|
||||
|
||||
export const verbs = {
|
||||
conditions: "conditions",
|
||||
silence: "silence",
|
||||
resync: "resync",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
conditionRaised: "condition-raised",
|
||||
conditionChanged: "condition-changed",
|
||||
conditionCleared: "condition-cleared",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "mesh-conditions.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export const conditionRaisedSubject = "mesh.seat.mesh-conditions.event.condition-raised";
|
||||
|
||||
export const conditionChangedSubject = "mesh.seat.mesh-conditions.event.condition-changed";
|
||||
|
||||
export const conditionClearedSubject = "mesh.seat.mesh-conditions.event.condition-cleared";
|
||||
|
||||
export const states = {
|
||||
conditions: "conditions",
|
||||
findings: "findings",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state conditions under the form "<key>". */
|
||||
export function conditionsByKeyKey(key: string): string {
|
||||
return key;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<key>", or undefined for a key of another form. */
|
||||
export function parseConditionsByKeyKey(key: string): { key: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const key = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { key };
|
||||
}
|
||||
|
||||
/** The key of one value of the state findings under the form "<key>". */
|
||||
export function findingsByKeyKey(key: string): string {
|
||||
return key;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<key>", or undefined for a key of another form. */
|
||||
export function parseFindingsByKeyKey(key: string): { key: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const key = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { key };
|
||||
}
|
||||
|
||||
/** one answer the operator may give from a notification */
|
||||
export interface Action {
|
||||
"arguments"?: Record<string, string>;
|
||||
"label": string;
|
||||
"level"?: "acknowledge" | "approve";
|
||||
"machine"?: string;
|
||||
/** the seat verb the operator channel calls */
|
||||
"verb": string;
|
||||
}
|
||||
|
||||
export interface ConditionEventGapsItem {
|
||||
"cleared"?: string;
|
||||
"reopened"?: string;
|
||||
}
|
||||
|
||||
export interface ConditionEventSilenced {
|
||||
"by"?: string;
|
||||
"since"?: string;
|
||||
"until"?: string;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
export interface ConditionEventTriedItem {
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"outcome"?: string;
|
||||
"what"?: string;
|
||||
}
|
||||
|
||||
/** a condition and what changed */
|
||||
export interface ConditionEvent {
|
||||
"actions"?: Action[];
|
||||
"at": string;
|
||||
"change": "raised" | "reopened" | "severity" | "resolver" | "silenced" | "silence-ended" | "cleared" | "words";
|
||||
"cleared"?: string;
|
||||
"count"?: number;
|
||||
"epoch"?: number;
|
||||
"event": string;
|
||||
/** newest first, at most 10 */
|
||||
"evidence"?: Evidence[];
|
||||
"explanation"?: string;
|
||||
"first"?: string;
|
||||
"gaps"?: ConditionEventGapsItem[];
|
||||
"headline"?: string;
|
||||
/** scope.id.token */
|
||||
"key": string;
|
||||
"kind"?: string;
|
||||
"last-observed"?: string;
|
||||
"looks-unread"?: string;
|
||||
"needs"?: string;
|
||||
"observations"?: number;
|
||||
"raised"?: string;
|
||||
"resolved"?: string;
|
||||
/** self, operator, agent or healer:<name> */
|
||||
"resolver"?: string;
|
||||
"severity"?: "urgent" | "warning";
|
||||
/** the tool call that shows it */
|
||||
"show"?: string;
|
||||
"silenced"?: ConditionEventSilenced;
|
||||
/** the row, probe or event that saw it */
|
||||
"source"?: string;
|
||||
"subject"?: Subject;
|
||||
/** one line */
|
||||
"summary"?: string;
|
||||
"tried"?: ConditionEventTriedItem[];
|
||||
"was"?: string;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** one observation, as it was said */
|
||||
export interface Evidence {
|
||||
"at": string;
|
||||
"said": string;
|
||||
}
|
||||
|
||||
/** what the condition is about */
|
||||
export interface Subject {
|
||||
/** the other machines it concerns */
|
||||
"also"?: string[];
|
||||
/** its id within the scope */
|
||||
"id": string;
|
||||
/** the machine it concerns, when there is one */
|
||||
"machine"?: string;
|
||||
/** machine, plan, call, build, merge, provider, seat, bus, core, probe, mesh, delivery or module */
|
||||
"scope": string;
|
||||
}
|
||||
|
||||
/** is what conditions takes. */
|
||||
export interface ConditionsInput {
|
||||
/** with history: how many days back (default 7, at most 90) */
|
||||
"days"?: string;
|
||||
/** "true": every raising, change, silence and clearing lately, oldest first */
|
||||
"history"?: "true" | "false";
|
||||
/** a condition's key: that one whole; with history, only its transitions */
|
||||
"key"?: string;
|
||||
/** only those about this machine */
|
||||
"machine"?: string;
|
||||
/** only this scope: machine, plan, call, build, merge, provider, seat, bus, core, probe, mesh, delivery or module */
|
||||
"scope"?: string;
|
||||
/** only urgent, or only warning */
|
||||
"severity"?: string;
|
||||
}
|
||||
|
||||
/** is what conditions answers. */
|
||||
export type ConditionsAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what silence takes. */
|
||||
export interface SilenceInput {
|
||||
/** the cause in a word (the condition's kind when absent) */
|
||||
"cause"?: string;
|
||||
/** how long: 30m, 4h, 2d; at most 7d */
|
||||
"for": string;
|
||||
/** the condition's key */
|
||||
"key": string;
|
||||
/** why, required and recorded */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what silence answers. */
|
||||
export type SilenceAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what resync takes. */
|
||||
export interface ResyncInput {
|
||||
}
|
||||
|
||||
/** is what resync answers. */
|
||||
export type ResyncAnswer = Record<string, unknown>;
|
||||
|
||||
/** is the body of the event condition-raised. */
|
||||
export type ConditionRaisedEvent = ConditionEvent;
|
||||
|
||||
/** is the body of the event condition-changed. */
|
||||
export type ConditionChangedEvent = ConditionEvent;
|
||||
|
||||
/** is the body of the event condition-cleared. */
|
||||
export type ConditionClearedEvent = ConditionEvent;
|
||||
|
||||
export interface ConditionsByKeyValueGapsItem {
|
||||
"cleared"?: string;
|
||||
"reopened"?: string;
|
||||
}
|
||||
|
||||
export interface ConditionsByKeyValueSilenced {
|
||||
"by"?: string;
|
||||
"since"?: string;
|
||||
"until"?: string;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
export interface ConditionsByKeyValueTriedItem {
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"outcome"?: string;
|
||||
"what"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state conditions under the key <key>. */
|
||||
export interface ConditionsByKeyValue {
|
||||
"actions"?: Action[];
|
||||
"count"?: number;
|
||||
"epoch"?: number;
|
||||
/** newest first, at most 10 */
|
||||
"evidence"?: Evidence[];
|
||||
"explanation"?: string;
|
||||
"first"?: string;
|
||||
"gaps"?: ConditionsByKeyValueGapsItem[];
|
||||
"headline"?: string;
|
||||
/** scope.id.token */
|
||||
"key": string;
|
||||
"kind": string;
|
||||
"last-observed": string;
|
||||
"looks-unread"?: string;
|
||||
"needs"?: string;
|
||||
"observations"?: number;
|
||||
"raised": string;
|
||||
"resolved"?: string;
|
||||
/** self, operator, agent or healer:<name> */
|
||||
"resolver"?: string;
|
||||
"severity": "urgent" | "warning";
|
||||
"silenced"?: ConditionsByKeyValueSilenced;
|
||||
/** the row, probe or event that saw it */
|
||||
"source"?: string;
|
||||
"subject": Subject;
|
||||
/** one line */
|
||||
"summary"?: string;
|
||||
"tried"?: ConditionsByKeyValueTriedItem[];
|
||||
}
|
||||
|
||||
/** is one value of the state findings under the key <key>. */
|
||||
export interface FindingsByKeyValue {
|
||||
"actions"?: Action[];
|
||||
"at": string;
|
||||
/** newest first, at most 10 */
|
||||
"evidence"?: Evidence[];
|
||||
"explanation"?: string;
|
||||
"headline"?: string;
|
||||
/** scope.id.token */
|
||||
"key": string;
|
||||
"kind": string;
|
||||
"needs"?: string;
|
||||
/** the module that wrote it */
|
||||
"observer": string;
|
||||
/** the key's last part when it is not the kind */
|
||||
"ref"?: string;
|
||||
"resolved"?: string;
|
||||
/** self, operator, agent or healer:<name> */
|
||||
"resolver"?: string;
|
||||
/** what of its own saw it last */
|
||||
"run"?: string;
|
||||
"severity": "urgent" | "warning";
|
||||
/** the row, probe or event that saw it */
|
||||
"source": string;
|
||||
"subject": Subject;
|
||||
/** one line */
|
||||
"summary": string;
|
||||
/** layout version, 1 */
|
||||
"v": number;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-hand-acts, generated from its definition.",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-health-and-repair-contracts-mesh-hand-acts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-hand-acts", defined whole (seats/mesh-hand-acts/seat.json): Acts done by hand, recorded with who, why and cause (ADR 0565): the log every module records through.
|
||||
|
||||
export const seat = "mesh-hand-acts";
|
||||
|
||||
export const verbs = {
|
||||
handAct: "hand-act",
|
||||
handActs: "hand-acts",
|
||||
warranted: "warranted",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
actRecorded: "act-recorded",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "mesh-hand-acts.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export const actRecordedSubject = "mesh.seat.mesh-hand-acts.event.act-recorded";
|
||||
|
||||
export const states = {
|
||||
acts: "acts",
|
||||
warrants: "warrants",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state acts under the form "<id>". */
|
||||
export function actsByIDKey(id: string): string {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<id>", or undefined for a key of another form. */
|
||||
export function parseActsByIDKey(key: string): { id: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const id = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { id };
|
||||
}
|
||||
|
||||
/** The key of one value of the state warrants under the form "<asker>.<ask>". */
|
||||
export function warrantsByAskerAskKey(asker: string, ask: string): string {
|
||||
return asker + "." + ask;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<asker>.<ask>", or undefined for a key of another form. */
|
||||
export function parseWarrantsByAskerAskKey(key: string): { asker: string; ask: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const asker = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const ask = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { asker, ask };
|
||||
}
|
||||
|
||||
/** one act done by hand */
|
||||
export interface Act {
|
||||
"arguments"?: string[];
|
||||
"ask"?: string;
|
||||
"at": string;
|
||||
/** the caller the runtime proved */
|
||||
"by": string;
|
||||
"carried"?: string[];
|
||||
"cause": string;
|
||||
"condition"?: string;
|
||||
"id": string;
|
||||
/** what the act was read to be from what it did */
|
||||
"kind"?: string;
|
||||
/** which log holds it, set when it is read */
|
||||
"log"?: string;
|
||||
"outcome"?: string;
|
||||
"proofs"?: string[];
|
||||
"requested-by"?: string;
|
||||
"verb": string;
|
||||
"via"?: string;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what hand-act takes. */
|
||||
export interface HandActInput {
|
||||
/** the cause in a word, or a condition's kind */
|
||||
"cause"?: string;
|
||||
/** the key of the condition it addressed, if any (optional) */
|
||||
"condition"?: string;
|
||||
/** the act's verb in the log: a repair when absent, `hand-act drill` for a drill, or a recorder's own */
|
||||
"verb"?: string;
|
||||
/** what was done, in a line */
|
||||
"what": string;
|
||||
/** why it had to be done by hand */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what hand-act answers. */
|
||||
export type HandActAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what hand-acts takes. */
|
||||
export interface HandActsInput {
|
||||
/** only this cause */
|
||||
"cause"?: string;
|
||||
/** how many days back (default 14) */
|
||||
"days"?: string;
|
||||
/** "true": every warrant recorded */
|
||||
"warrants"?: "true" | "false";
|
||||
/** only acts whose who contains this */
|
||||
"who"?: string;
|
||||
}
|
||||
|
||||
/** is what hand-acts answers. */
|
||||
export type HandActsAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what warranted takes. */
|
||||
export interface WarrantedInput {
|
||||
/** its ask's id */
|
||||
"ask": string;
|
||||
/** the module that asked */
|
||||
"asker": string;
|
||||
}
|
||||
|
||||
/** is what warranted answers. */
|
||||
export type WarrantedAnswer = Record<string, unknown>;
|
||||
|
||||
/** is the body of the event act-recorded. */
|
||||
export type ActRecordedEvent = Act;
|
||||
|
||||
/** is one value of the state acts under the key <id>. */
|
||||
export interface ActsByIDValue {
|
||||
"arguments"?: string[];
|
||||
"ask"?: string;
|
||||
"at": string;
|
||||
/** the caller the runtime proved */
|
||||
"by": string;
|
||||
"carried"?: string[];
|
||||
"cause": string;
|
||||
"condition"?: string;
|
||||
"id": string;
|
||||
/** what the act was read to be from what it did */
|
||||
"kind"?: string;
|
||||
/** which log holds it, set when it is read */
|
||||
"log"?: string;
|
||||
"outcome"?: string;
|
||||
"proofs"?: string[];
|
||||
"requested-by"?: string;
|
||||
"verb": string;
|
||||
"via"?: string;
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is one value of the state warrants under the key <asker>.<ask>. */
|
||||
export interface WarrantsByAskerAskValue {
|
||||
"ask": string;
|
||||
"asker": string;
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"option"?: string;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"description": "The mesh's seat set, generated from every seat's definition.",
|
||||
"description": "The contract of the seat mesh-healers, generated from its definition.",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
@@ -9,7 +9,7 @@
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-contracts",
|
||||
"name": "@novox/mesh-health-and-repair-contracts-mesh-healers",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
@@ -0,0 +1,127 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-healers", defined whole (seats/mesh-healers/seat.json): The healers (ADR 0564): each a registered response to one kind of condition, within a budget and the mesh-wide brake.
|
||||
|
||||
export const seat = "mesh-healers";
|
||||
|
||||
export const verbs = {
|
||||
healers: "healers",
|
||||
heal: "heal",
|
||||
drill: "drill",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
healerActed: "healer-acted",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "mesh-healers.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export const healerActedSubject = "mesh.seat.mesh-healers.event.healer-acted";
|
||||
|
||||
export const states = {
|
||||
attempts: "attempts",
|
||||
would: "would",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state attempts under the form "<attempt>". */
|
||||
export function attemptsByAttemptKey(attempt: string): string {
|
||||
return attempt;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<attempt>", or undefined for a key of another form. */
|
||||
export function parseAttemptsByAttemptKey(key: string): { attempt: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const attempt = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { attempt };
|
||||
}
|
||||
|
||||
/** The key of one value of the state would under the form "<would>". */
|
||||
export function wouldByWouldKey(would: string): string {
|
||||
return would;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<would>", or undefined for a key of another form. */
|
||||
export function parseWouldByWouldKey(key: string): { would: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const would = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { would };
|
||||
}
|
||||
|
||||
/** is what healers takes. */
|
||||
export interface HealersInput {
|
||||
/** how many days of acts back (default 7) */
|
||||
"days"?: string;
|
||||
}
|
||||
|
||||
/** is what healers answers. */
|
||||
export type HealersAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what heal takes. */
|
||||
export interface HealInput {
|
||||
/** the condition's key */
|
||||
"key": string;
|
||||
/** why now, kept with the act */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what heal answers. */
|
||||
export type HealAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what drill takes. */
|
||||
export interface DrillInput {
|
||||
/** the key of the condition the drill is meant to raise, if any (optional) */
|
||||
"condition"?: string;
|
||||
/** what was done on purpose, in a line */
|
||||
"what": string;
|
||||
/** what the drill tests */
|
||||
"why": string;
|
||||
}
|
||||
|
||||
/** is what drill answers. */
|
||||
export type DrillAnswer = Record<string, unknown>;
|
||||
|
||||
/** is the body of the event healer-acted. */
|
||||
export interface HealerActedEvent {
|
||||
"act"?: string;
|
||||
"at": string;
|
||||
"budget"?: string;
|
||||
"by"?: string;
|
||||
"condition": string;
|
||||
"event": string;
|
||||
"healer": string;
|
||||
"kind"?: string;
|
||||
"outcome": "acting" | "acted" | "failed" | "escalated";
|
||||
"said"?: string;
|
||||
"show"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state attempts under the key <attempt>. */
|
||||
export interface AttemptsByAttemptValue {
|
||||
"act": string;
|
||||
"begun": string;
|
||||
/** what the budget counts by: the condition's key unless the healer says another */
|
||||
"budget-key": string;
|
||||
"condition": string;
|
||||
"finished"?: string;
|
||||
"healer": string;
|
||||
"kind": string;
|
||||
"outcome": "acting" | "acted" | "failed" | "escalated";
|
||||
"said"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state would under the key <would>. */
|
||||
export interface WouldByWouldValue {
|
||||
"act": string;
|
||||
"at": string;
|
||||
"condition": string;
|
||||
"healer": string;
|
||||
"kind"?: string;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-self-check, generated from its definition.",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-health-and-repair-contracts-mesh-self-check",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-self-check", defined whole (seats/mesh-self-check/seat.json): The mesh checking itself (ADR 0564): probes run every five minutes, each failure a finding the seat's conditions raise.
|
||||
|
||||
export const seat = "mesh-self-check";
|
||||
|
||||
export const verbs = {
|
||||
doctor: "doctor",
|
||||
probes: "probes",
|
||||
} as const;
|
||||
|
||||
export const events = {
|
||||
checked: "checked",
|
||||
} as const;
|
||||
|
||||
export const family = { name: "mesh-self-check.events", maxAgeDays: 7 } as const;
|
||||
|
||||
export const checkedSubject = "mesh.seat.mesh-self-check.event.checked";
|
||||
|
||||
/** one probe's verdict */
|
||||
export interface ProbeVerdict {
|
||||
"error"?: string;
|
||||
"found"?: string[];
|
||||
"found-count"?: number;
|
||||
"id": string;
|
||||
"more"?: string;
|
||||
"took"?: string;
|
||||
"unconfirmed"?: string[];
|
||||
"verdict": "passed" | "failed" | "failed-to-run" | "deferred";
|
||||
}
|
||||
|
||||
/** is what doctor takes. */
|
||||
export interface DoctorInput {
|
||||
/** one probe's id (D6): its verdict alone, with every finding */
|
||||
"probe"?: string;
|
||||
/** "true": run every probe now and answer the verdict */
|
||||
"run"?: "true" | "false";
|
||||
}
|
||||
|
||||
/** is what doctor answers. */
|
||||
export type DoctorAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what probes takes. */
|
||||
export interface ProbesInput {
|
||||
}
|
||||
|
||||
/** is what probes answers. */
|
||||
export type ProbesAnswer = Record<string, unknown>;
|
||||
|
||||
export interface CheckedEventCounts {
|
||||
"deferred"?: number;
|
||||
"failed"?: number;
|
||||
"failed-to-run"?: number;
|
||||
"passed"?: number;
|
||||
}
|
||||
|
||||
/** is the body of the event checked. */
|
||||
export interface CheckedEvent {
|
||||
"at": string;
|
||||
"controller"?: string;
|
||||
"counts"?: CheckedEventCounts;
|
||||
"interval-seconds"?: number;
|
||||
"probes": ProbeVerdict[];
|
||||
"run": string;
|
||||
"started"?: string;
|
||||
"took"?: string;
|
||||
"unsaid"?: number;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-watchdogs, generated from its definition.",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-health-and-repair-contracts-mesh-watchdogs",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-watchdogs", defined whole (seats/mesh-watchdogs/seat.json): The watchman's seat (ADR 0564, ADR 0433): signals that expire unless renewed, what stopped moving, who is present, the dead letters.
|
||||
|
||||
export const seat = "mesh-watchdogs";
|
||||
|
||||
export const verbs = {
|
||||
signals: "signals",
|
||||
stuck: "stuck",
|
||||
presence: "presence",
|
||||
deadLetters: "dead-letters",
|
||||
resync: "resync",
|
||||
} as const;
|
||||
|
||||
export const states = {
|
||||
presence: "presence",
|
||||
pulse: "pulse",
|
||||
stuck: "stuck",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state presence under the form "<node>". */
|
||||
export function presenceByNodeKey(node: string): string {
|
||||
return node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>", or undefined for a key of another form. */
|
||||
export function parsePresenceByNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state presence under the form "part.<part>.<instance>". */
|
||||
export function presenceByPartPartInstanceKey(part: string, instance: string): string {
|
||||
return "part." + part + "." + instance;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "part.<part>.<instance>", or undefined for a key of another form. */
|
||||
export function parsePresenceByPartPartInstanceKey(key: string): { part: string; instance: string } | undefined {
|
||||
let rest = key;
|
||||
if (!rest.startsWith("part.")) return undefined;
|
||||
rest = rest.slice(5);
|
||||
const at1 = rest.indexOf(".");
|
||||
if (at1 <= 0) return undefined;
|
||||
const part = rest.slice(0, at1);
|
||||
rest = rest.slice(at1 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const instance = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { part, instance };
|
||||
}
|
||||
|
||||
/** The key of one value of the state pulse under the form "<bucket>.<key>". */
|
||||
export function pulseByBucketKeyKey(bucket: string, key: string): string {
|
||||
return bucket + "." + key;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<bucket>.<key>", or undefined for a key of another form. */
|
||||
export function parsePulseByBucketKeyKey(key: string): { bucket: string; key: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const bucket = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const key = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { bucket, key };
|
||||
}
|
||||
|
||||
/** The key of one value of the state stuck under the form "<bucket>.<key>". */
|
||||
export function stuckByBucketKeyKey(bucket: string, key: string): string {
|
||||
return bucket + "." + key;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<bucket>.<key>", or undefined for a key of another form. */
|
||||
export function parseStuckByBucketKeyKey(key: string): { bucket: string; key: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const bucket = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const key = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { bucket, key };
|
||||
}
|
||||
|
||||
/** is what signals takes. */
|
||||
export interface SignalsInput {
|
||||
/** one row, e.g. S1 */
|
||||
"row"?: string;
|
||||
}
|
||||
|
||||
/** is what signals answers. */
|
||||
export type SignalsAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what stuck takes. */
|
||||
export interface StuckInput {
|
||||
/** only those on this machine */
|
||||
"machine"?: string;
|
||||
}
|
||||
|
||||
/** is what stuck answers. */
|
||||
export type StuckAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what presence takes. */
|
||||
export interface PresenceInput {
|
||||
/** one machine */
|
||||
"machine"?: string;
|
||||
}
|
||||
|
||||
/** is what presence answers. */
|
||||
export type PresenceAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what dead-letters takes. */
|
||||
export interface DeadLettersInput {
|
||||
/** with deliver or drop: the cause in a word (dead-letter when absent) */
|
||||
"cause"?: string;
|
||||
/** a consumer's name, or <stream>.<consumer>: only what that one gave up on */
|
||||
"consumer"?: string;
|
||||
/** a dead letter's id: deliver it again to the consumer that gave it up (needs why) */
|
||||
"deliver"?: string;
|
||||
/** a dead letter's id: drop it for good (needs why) */
|
||||
"drop"?: string;
|
||||
/** a dead letter's id, as the list gives it: that one whole, with its message */
|
||||
"id"?: string;
|
||||
/** how many to list, newest first (default 50); only when listing */
|
||||
"limit"?: string;
|
||||
/** with deliver or drop: why, required and recorded */
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
/** is what dead-letters answers. */
|
||||
export type DeadLettersAnswer = Record<string, unknown>;
|
||||
|
||||
/** is what resync takes. */
|
||||
export interface ResyncInput {
|
||||
}
|
||||
|
||||
/** is what resync answers. */
|
||||
export type ResyncAnswer = Record<string, unknown>;
|
||||
|
||||
/** is one value of the state presence under the key <node>. */
|
||||
export interface PresenceByNodeValue {
|
||||
"online": boolean;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state presence under the key part.<part>.<instance>. */
|
||||
export interface PresenceByPartPartInstanceValue {
|
||||
"online": boolean;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state pulse under the key <bucket>.<key>. */
|
||||
export interface PulseByBucketKeyValue {
|
||||
"bucket": string;
|
||||
"key": string;
|
||||
"owes"?: string;
|
||||
"revision": number;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state stuck under the key <bucket>.<key>. */
|
||||
export interface StuckByBucketKeyValue {
|
||||
"bucket": string;
|
||||
"key": string;
|
||||
/** it has moved again */
|
||||
"moved"?: boolean;
|
||||
"since": string;
|
||||
"v"?: number;
|
||||
/** what it waited for, in words */
|
||||
"waited"?: string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
||||
seat "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
)
|
||||
|
||||
// The levels an option is answered at: how much proof its answer needs (novox/hq ADR 0234 §8, the glossary's
|
||||
+1
-1
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
||||
seat "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
)
|
||||
|
||||
var now = time.Date(2026, 10, 8, 14, 0, 0, 0, time.UTC)
|
||||
+1
-1
@@ -17,7 +17,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
||||
seat "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
||||
seat "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
)
|
||||
+1
-1
@@ -7,7 +7,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
||||
seat "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
)
|
||||
|
||||
// ConditionSubject is where a module says a condition to the operator: the seat's by-caller condition accept
|
||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
seat "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
||||
seat "git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel"
|
||||
)
|
||||
|
||||
func TestConditionSubject(t *testing.T) { // 1202/AC1
|
||||
+2
-3
@@ -1,14 +1,13 @@
|
||||
module git.novox.be/novox/mesh-contracts/go/clients/operatorchannelclient
|
||||
module git.novox.be/novox/mesh-contracts/operator-and-conversation/go/clients/operatorchannelclient
|
||||
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-contracts/go/seats/operatorchannel v0.0.0-20261104172218-347a3053580a
|
||||
git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel v0.0.0-20261104172218-347a3053580a
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261104174118-f94abb95aaef
|
||||
)
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-contracts/go v0.0.0-20261104172218-347a3053580a // indirect
|
||||
github.com/klauspost/compress v1.20.1 // indirect
|
||||
github.com/nats-io/nats.go v1.54.0 // indirect
|
||||
github.com/nats-io/nkeys v0.4.16 // indirect
|
||||
+46
-3
@@ -3,6 +3,13 @@
|
||||
// Package operatorchannel is the contract of the seat "operator-channel", defined whole (seats/operator-channel/seat.json): Asking a person and answering on a channel (ADR 0259): held by the router, the messenger module, whose manifest declares the seat; written from that seat entry (design 26).
|
||||
package operatorchannel
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "operator-channel"
|
||||
|
||||
@@ -75,9 +82,45 @@ func HolderSubjectOffered(holder string) string { return "mesh.stream." + holder
|
||||
func HolderSubjectClosed(holder string) string { return "mesh.stream." + holder + ".event.closed" }
|
||||
|
||||
const (
|
||||
RecordAsks = "asks"
|
||||
StateAsks = "asks"
|
||||
)
|
||||
|
||||
// AsksByAskerIDKey is the key of one value of the state asks under the form "<asker>.<id>".
|
||||
func AsksByAskerIDKey(asker, id string) string { return asker + "." + id }
|
||||
|
||||
// ParseAsksByAskerIDKey reads the parts of a key of the form "<asker>.<id>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseAsksByAskerIDKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodeAsksByAskerIDValue reads one value of the state asks under the form "<asker>.<id>", refusing a field AsksByAskerIDValue does not know and any text after the value.
|
||||
func DecodeAsksByAskerIDValue(raw []byte) (AsksByAskerIDValue, error) {
|
||||
var v AsksByAskerIDValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Ask is a type of the contract.
|
||||
type Ask struct {
|
||||
// what it is about: a newer ask about it replaces the older
|
||||
@@ -328,5 +371,5 @@ const (
|
||||
ClosedHolderEventHowUnlinked = "unlinked"
|
||||
)
|
||||
|
||||
// AsksRecord is one value of the record asks.
|
||||
type AsksRecord = map[string]any
|
||||
// AsksByAskerIDValue is one value of the state asks under the key <asker>.<id>.
|
||||
type AsksByAskerIDValue = map[string]any
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/operator-and-conversation/go/seats/operatorchannel
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"format": 1,
|
||||
"seats": [
|
||||
"operator-channel"
|
||||
]
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-contracts-operator-channel",
|
||||
"name": "@novox/mesh-operator-and-conversation-contracts-operator-channel",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
+25
-2
@@ -58,6 +58,29 @@ export function closedHolderSubject(holder: string): string {
|
||||
return "mesh.stream." + holder + ".event.closed";
|
||||
}
|
||||
|
||||
export const states = {
|
||||
asks: "asks",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state asks under the form "<asker>.<id>". */
|
||||
export function asksByAskerIDKey(asker: string, id: string): string {
|
||||
return asker + "." + id;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<asker>.<id>", or undefined for a key of another form. */
|
||||
export function parseAsksByAskerIDKey(key: string): { asker: string; id: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const asker = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const id = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { asker, id };
|
||||
}
|
||||
|
||||
export interface Ask {
|
||||
/** what it is about: a newer ask about it replaces the older */
|
||||
"about"?: string;
|
||||
@@ -277,6 +300,6 @@ export interface ClosedHolderEvent {
|
||||
"id": string;
|
||||
}
|
||||
|
||||
/** is one value of the record asks. */
|
||||
export type AsksRecord = Record<string, unknown>;
|
||||
/** is one value of the state asks under the key <asker>.<id>. */
|
||||
export type AsksByAskerIDValue = Record<string, unknown>;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// Package meshprovisioner is the contract of the seat "mesh-provisioner", defined whole (seats/mesh-provisioner/seat.json): The provisioner (ADR 0349): which domain answers which kind of placeholder, what each module needs, what is applied where.
|
||||
package meshprovisioner
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Seat is the seat's name.
|
||||
const Seat = "mesh-provisioner"
|
||||
|
||||
const (
|
||||
VerbProvisioning = "provisioning"
|
||||
)
|
||||
|
||||
// Verbs is every verb the seat serves, in its definition's order: a new copy each call.
|
||||
func Verbs() []string {
|
||||
return []string{VerbProvisioning}
|
||||
}
|
||||
|
||||
const (
|
||||
StatePlans = "plans"
|
||||
StateProvisions = "provisions"
|
||||
)
|
||||
|
||||
// PlansByNodeModuleKey is the key of one value of the state plans under the form "<node>.<module>".
|
||||
func PlansByNodeModuleKey(node, module string) string { return node + "." + module }
|
||||
|
||||
// ParsePlansByNodeModuleKey reads the parts of a key of the form "<node>.<module>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParsePlansByNodeModuleKey(key string) (string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", false
|
||||
}
|
||||
rest = after0
|
||||
if rest == "" {
|
||||
return "", "", false
|
||||
}
|
||||
v2 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", false
|
||||
}
|
||||
return v0, v2, true
|
||||
}
|
||||
|
||||
// DecodePlansByNodeModuleValue reads one value of the state plans under the form "<node>.<module>", refusing a field PlansByNodeModuleValue does not know and any text after the value.
|
||||
func DecodePlansByNodeModuleValue(raw []byte) (PlansByNodeModuleValue, error) {
|
||||
var v PlansByNodeModuleValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionKey is the key of one value of the state provisions under the form "<node>.<consumer>.<provision>".
|
||||
func ProvisionsByNodeConsumerProvisionKey(node, consumer, provision string) string {
|
||||
return node + "." + consumer + "." + provision
|
||||
}
|
||||
|
||||
// ParseProvisionsByNodeConsumerProvisionKey reads the parts of a key of the form "<node>.<consumer>.<provision>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseProvisionsByNodeConsumerProvisionKey(key string) (string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
if rest == "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
v4 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, true
|
||||
}
|
||||
|
||||
// DecodeProvisionsByNodeConsumerProvisionValue reads one value of the state provisions under the form "<node>.<consumer>.<provision>", refusing a field ProvisionsByNodeConsumerProvisionValue does not know and any text after the value.
|
||||
func DecodeProvisionsByNodeConsumerProvisionValue(raw []byte) (ProvisionsByNodeConsumerProvisionValue, error) {
|
||||
var v ProvisionsByNodeConsumerProvisionValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalKey is the key of one value of the state provisions under the form "<node>.<consumer>.<provision>.<local>".
|
||||
func ProvisionsByNodeConsumerProvisionLocalKey(node, consumer, provision, local string) string {
|
||||
return node + "." + consumer + "." + provision + "." + local
|
||||
}
|
||||
|
||||
// ParseProvisionsByNodeConsumerProvisionLocalKey reads the parts of a key of the form "<node>.<consumer>.<provision>.<local>", in the order of the form; the last result is false for a key of another form.
|
||||
func ParseProvisionsByNodeConsumerProvisionLocalKey(key string) (string, string, string, string, bool) {
|
||||
rest := key
|
||||
v0, after0, found0 := strings.Cut(rest, ".")
|
||||
if !found0 || v0 == "" {
|
||||
return "", "", "", "", false
|
||||
}
|
||||
rest = after0
|
||||
v2, after2, found2 := strings.Cut(rest, ".")
|
||||
if !found2 || v2 == "" {
|
||||
return "", "", "", "", false
|
||||
}
|
||||
rest = after2
|
||||
v4, after4, found4 := strings.Cut(rest, ".")
|
||||
if !found4 || v4 == "" {
|
||||
return "", "", "", "", false
|
||||
}
|
||||
rest = after4
|
||||
if rest == "" {
|
||||
return "", "", "", "", false
|
||||
}
|
||||
v6 := rest
|
||||
rest = ""
|
||||
if rest != "" {
|
||||
return "", "", "", "", false
|
||||
}
|
||||
return v0, v2, v4, v6, true
|
||||
}
|
||||
|
||||
// DecodeProvisionsByNodeConsumerProvisionLocalValue reads one value of the state provisions under the form "<node>.<consumer>.<provision>.<local>", refusing a field ProvisionsByNodeConsumerProvisionLocalValue does not know and any text after the value.
|
||||
func DecodeProvisionsByNodeConsumerProvisionLocalValue(raw []byte) (ProvisionsByNodeConsumerProvisionLocalValue, error) {
|
||||
var v ProvisionsByNodeConsumerProvisionLocalValue
|
||||
dec := json.NewDecoder(bytes.NewReader(raw))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&v); err != nil {
|
||||
return v, err
|
||||
}
|
||||
if dec.More() {
|
||||
return v, errors.New("text after the value")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// ProvisioningInput is what provisioning takes.
|
||||
type ProvisioningInput struct {
|
||||
// for collect: a collection
|
||||
Collection string `json:"collection,omitempty"`
|
||||
// a module: for collect, a contributor
|
||||
Module string `json:"module,omitempty"`
|
||||
// a node
|
||||
Node string `json:"node,omitempty"`
|
||||
// registry (when not given), needs, applied or collect
|
||||
What string `json:"what,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisioningAnswer is what provisioning answers.
|
||||
type ProvisioningAnswer = map[string]any
|
||||
|
||||
// PlansByNodeModuleValue is one value of the state plans under the key <node>.<module>.
|
||||
type PlansByNodeModuleValue struct {
|
||||
Module string `json:"module"`
|
||||
Node string `json:"node"`
|
||||
// the module's plan
|
||||
Plan map[string]any `json:"plan"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValueConsumer is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionValueConsumer struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValueProvider is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionValueProvider struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValueReference is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionValueReference struct {
|
||||
Generation int64 `json:"generation,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValueWarrant is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionValueWarrant struct {
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Option string `json:"option,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionValue is one value of the state provisions under the key <node>.<consumer>.<provision>.
|
||||
type ProvisionsByNodeConsumerProvisionValue struct {
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At string `json:"at"`
|
||||
Consumer ProvisionsByNodeConsumerProvisionValueConsumer `json:"consumer"`
|
||||
DependsOn []string `json:"depends-on,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
// the plan's provision
|
||||
Plan map[string]any `json:"plan,omitempty"`
|
||||
Provider ProvisionsByNodeConsumerProvisionValueProvider `json:"provider"`
|
||||
Provision string `json:"provision"`
|
||||
Reference *ProvisionsByNodeConsumerProvisionValueReference `json:"reference,omitempty"`
|
||||
State string `json:"state"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
Warrant *ProvisionsByNodeConsumerProvisionValueWarrant `json:"warrant,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// The values of ProvisionsByNodeConsumerProvisionValue's state.
|
||||
const (
|
||||
ProvisionsByNodeConsumerProvisionValueStateAsked = "asked"
|
||||
ProvisionsByNodeConsumerProvisionValueStateProvided = "provided"
|
||||
ProvisionsByNodeConsumerProvisionValueStateWaits = "waits"
|
||||
ProvisionsByNodeConsumerProvisionValueStateFailed = "failed"
|
||||
ProvisionsByNodeConsumerProvisionValueStateRetiring = "retiring"
|
||||
)
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValueConsumer is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionLocalValueConsumer struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValueProvider is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionLocalValueProvider struct {
|
||||
Module string `json:"module,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValueReference is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionLocalValueReference struct {
|
||||
Generation int64 `json:"generation,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValueWarrant is a type of the contract.
|
||||
type ProvisionsByNodeConsumerProvisionLocalValueWarrant struct {
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At string `json:"at,omitempty"`
|
||||
By string `json:"by,omitempty"`
|
||||
Option string `json:"option,omitempty"`
|
||||
}
|
||||
|
||||
// ProvisionsByNodeConsumerProvisionLocalValue is one value of the state provisions under the key <node>.<consumer>.<provision>.<local>.
|
||||
type ProvisionsByNodeConsumerProvisionLocalValue struct {
|
||||
Ask string `json:"ask,omitempty"`
|
||||
At string `json:"at"`
|
||||
Consumer ProvisionsByNodeConsumerProvisionLocalValueConsumer `json:"consumer"`
|
||||
DependsOn []string `json:"depends-on,omitempty"`
|
||||
Local string `json:"local,omitempty"`
|
||||
// the plan's provision
|
||||
Plan map[string]any `json:"plan,omitempty"`
|
||||
Provider ProvisionsByNodeConsumerProvisionLocalValueProvider `json:"provider"`
|
||||
Provision string `json:"provision"`
|
||||
Reference *ProvisionsByNodeConsumerProvisionLocalValueReference `json:"reference,omitempty"`
|
||||
State string `json:"state"`
|
||||
V int64 `json:"v,omitempty"`
|
||||
Warrant *ProvisionsByNodeConsumerProvisionLocalValueWarrant `json:"warrant,omitempty"`
|
||||
Why string `json:"why,omitempty"`
|
||||
}
|
||||
|
||||
// The values of ProvisionsByNodeConsumerProvisionLocalValue's state.
|
||||
const (
|
||||
ProvisionsByNodeConsumerProvisionLocalValueStateAsked = "asked"
|
||||
ProvisionsByNodeConsumerProvisionLocalValueStateProvided = "provided"
|
||||
ProvisionsByNodeConsumerProvisionLocalValueStateWaits = "waits"
|
||||
ProvisionsByNodeConsumerProvisionLocalValueStateFailed = "failed"
|
||||
ProvisionsByNodeConsumerProvisionLocalValueStateRetiring = "retiring"
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
module git.novox.be/novox/mesh-contracts/provisioning/go/seats/meshprovisioner
|
||||
|
||||
go 1.26.0
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"format": 1,
|
||||
"seats": [
|
||||
"mesh-provisioner",
|
||||
"node-mounts",
|
||||
"node-nfs-server",
|
||||
"node-provisioner"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"description": "The contract of the seat mesh-provisioner, generated from its definition.",
|
||||
"devDependencies": {
|
||||
"typescript": "^5.6.0"
|
||||
},
|
||||
"exports": {
|
||||
".": "./dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"name": "@novox/mesh-provisioning-contracts-mesh-provisioner",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "tsc"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
// The contract of the seat "mesh-provisioner", defined whole (seats/mesh-provisioner/seat.json): The provisioner (ADR 0349): which domain answers which kind of placeholder, what each module needs, what is applied where.
|
||||
|
||||
export const seat = "mesh-provisioner";
|
||||
|
||||
export const verbs = {
|
||||
provisioning: "provisioning",
|
||||
} as const;
|
||||
|
||||
export const states = {
|
||||
plans: "plans",
|
||||
provisions: "provisions",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state plans under the form "<node>.<module>". */
|
||||
export function plansByNodeModuleKey(node: string, module: string): string {
|
||||
return node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
|
||||
export function parsePlansByNodeModuleKey(key: string): { node: string; module: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const module = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state provisions under the form "<node>.<consumer>.<provision>". */
|
||||
export function provisionsByNodeConsumerProvisionKey(node: string, consumer: string, provision: string): string {
|
||||
return node + "." + consumer + "." + provision;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<consumer>.<provision>", or undefined for a key of another form. */
|
||||
export function parseProvisionsByNodeConsumerProvisionKey(key: string): { node: string; consumer: string; provision: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
const at2 = rest.indexOf(".");
|
||||
if (at2 <= 0) return undefined;
|
||||
const consumer = rest.slice(0, at2);
|
||||
rest = rest.slice(at2 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const provision = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, consumer, provision };
|
||||
}
|
||||
|
||||
/** The key of one value of the state provisions under the form "<node>.<consumer>.<provision>.<local>". */
|
||||
export function provisionsByNodeConsumerProvisionLocalKey(node: string, consumer: string, provision: string, local: string): string {
|
||||
return node + "." + consumer + "." + provision + "." + local;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<consumer>.<provision>.<local>", or undefined for a key of another form. */
|
||||
export function parseProvisionsByNodeConsumerProvisionLocalKey(key: string): { node: string; consumer: string; provision: string; local: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
const at2 = rest.indexOf(".");
|
||||
if (at2 <= 0) return undefined;
|
||||
const consumer = rest.slice(0, at2);
|
||||
rest = rest.slice(at2 + 1);
|
||||
const at4 = rest.indexOf(".");
|
||||
if (at4 <= 0) return undefined;
|
||||
const provision = rest.slice(0, at4);
|
||||
rest = rest.slice(at4 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const local = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, consumer, provision, local };
|
||||
}
|
||||
|
||||
/** is what provisioning takes. */
|
||||
export interface ProvisioningInput {
|
||||
/** for collect: a collection */
|
||||
"collection"?: string;
|
||||
/** a module: for collect, a contributor */
|
||||
"module"?: string;
|
||||
/** a node */
|
||||
"node"?: string;
|
||||
/** registry (when not given), needs, applied or collect */
|
||||
"what"?: string;
|
||||
}
|
||||
|
||||
/** is what provisioning answers. */
|
||||
export type ProvisioningAnswer = Record<string, unknown>;
|
||||
|
||||
/** is one value of the state plans under the key <node>.<module>. */
|
||||
export interface PlansByNodeModuleValue {
|
||||
"module": string;
|
||||
"node": string;
|
||||
/** the module's plan */
|
||||
"plan": Record<string, unknown>;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionValueConsumer {
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionValueProvider {
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionValueReference {
|
||||
"generation"?: number;
|
||||
"id"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionValueWarrant {
|
||||
"ask"?: string;
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"option"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state provisions under the key <node>.<consumer>.<provision>. */
|
||||
export interface ProvisionsByNodeConsumerProvisionValue {
|
||||
"ask"?: string;
|
||||
"at": string;
|
||||
"consumer": ProvisionsByNodeConsumerProvisionValueConsumer;
|
||||
"depends-on"?: string[];
|
||||
"local"?: string;
|
||||
/** the plan's provision */
|
||||
"plan"?: Record<string, unknown>;
|
||||
"provider": ProvisionsByNodeConsumerProvisionValueProvider;
|
||||
"provision": string;
|
||||
"reference"?: ProvisionsByNodeConsumerProvisionValueReference;
|
||||
"state": "asked" | "provided" | "waits" | "failed" | "retiring";
|
||||
"v"?: number;
|
||||
"warrant"?: ProvisionsByNodeConsumerProvisionValueWarrant;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValueConsumer {
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValueProvider {
|
||||
"module"?: string;
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValueReference {
|
||||
"generation"?: number;
|
||||
"id"?: string;
|
||||
}
|
||||
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValueWarrant {
|
||||
"ask"?: string;
|
||||
"at"?: string;
|
||||
"by"?: string;
|
||||
"option"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state provisions under the key <node>.<consumer>.<provision>.<local>. */
|
||||
export interface ProvisionsByNodeConsumerProvisionLocalValue {
|
||||
"ask"?: string;
|
||||
"at": string;
|
||||
"consumer": ProvisionsByNodeConsumerProvisionLocalValueConsumer;
|
||||
"depends-on"?: string[];
|
||||
"local"?: string;
|
||||
/** the plan's provision */
|
||||
"plan"?: Record<string, unknown>;
|
||||
"provider": ProvisionsByNodeConsumerProvisionLocalValueProvider;
|
||||
"provision": string;
|
||||
"reference"?: ProvisionsByNodeConsumerProvisionLocalValueReference;
|
||||
"state": "asked" | "provided" | "waits" | "failed" | "retiring";
|
||||
"v"?: number;
|
||||
"warrant"?: ProvisionsByNodeConsumerProvisionLocalValueWarrant;
|
||||
"why"?: string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "NodeNext",
|
||||
"moduleResolution": "NodeNext",
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -32,6 +32,33 @@ export function retiredHolderSubject(holder: string): string {
|
||||
return "mesh.stream." + holder + ".event.retired";
|
||||
}
|
||||
|
||||
export const states = {
|
||||
resolved: "resolved",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state resolved under the form "<node>.<module>.<key>". */
|
||||
export function resolvedByNodeModuleKeyKey(node: string, module: string, key: string): string {
|
||||
return node + "." + module + "." + key;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>.<key>", or undefined for a key of another form. */
|
||||
export function parseResolvedByNodeModuleKeyKey(key: string): { node: string; module: string; key: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
const at2 = rest.indexOf(".");
|
||||
if (at2 <= 0) return undefined;
|
||||
const module = rest.slice(0, at2);
|
||||
rest = rest.slice(at2 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const key = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, module, key };
|
||||
}
|
||||
|
||||
/** is what config takes. */
|
||||
export interface ConfigInput {
|
||||
/** list (when not given), set, clear or history */
|
||||
@@ -117,3 +144,17 @@ export interface RetiredHolderEvent {
|
||||
"node"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state resolved under the key <node>.<module>.<key>. */
|
||||
export interface ResolvedByNodeModuleKeyValue {
|
||||
"key": string;
|
||||
"module": string;
|
||||
"node": string;
|
||||
/** the predefined key the value falls back to */
|
||||
"predefined"?: string;
|
||||
/** an unset value is the operator's own to set */
|
||||
"required"?: boolean;
|
||||
"source": string;
|
||||
"trusted"?: boolean;
|
||||
"value"?: unknown;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,121 @@ export function manifestReadsChangedSubject(caller: string): string {
|
||||
return "mesh.seat.node-engine.event.manifest-reads-changed." + caller;
|
||||
}
|
||||
|
||||
export const states = {
|
||||
have: "have",
|
||||
composed: "composed",
|
||||
data: "data",
|
||||
packages: "packages",
|
||||
health: "health",
|
||||
} as const;
|
||||
|
||||
/** The key of one value of the state have under the form "<node>.<module>". */
|
||||
export function haveByNodeModuleKey(node: string, module: string): string {
|
||||
return node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
|
||||
export function parseHaveByNodeModuleKey(key: string): { node: string; module: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const module = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state have under the form "<node>.node". */
|
||||
export function haveByNodeNodeKey(node: string): string {
|
||||
return node + ".node";
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.node", or undefined for a key of another form. */
|
||||
export function parseHaveByNodeNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".node");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 5);
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state composed under the form "<node>.<module>.<fingerprint>". */
|
||||
export function composedByNodeModuleFingerprintKey(node: string, module: string, fingerprint: string): string {
|
||||
return node + "." + module + "." + fingerprint;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>.<fingerprint>", or undefined for a key of another form. */
|
||||
export function parseComposedByNodeModuleFingerprintKey(key: string): { node: string; module: string; fingerprint: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
const at2 = rest.indexOf(".");
|
||||
if (at2 <= 0) return undefined;
|
||||
const module = rest.slice(0, at2);
|
||||
rest = rest.slice(at2 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const fingerprint = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, module, fingerprint };
|
||||
}
|
||||
|
||||
/** The key of one value of the state data under the form "<node>.<module>". */
|
||||
export function dataByNodeModuleKey(node: string, module: string): string {
|
||||
return node + "." + module;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>.<module>", or undefined for a key of another form. */
|
||||
export function parseDataByNodeModuleKey(key: string): { node: string; module: string } | undefined {
|
||||
let rest = key;
|
||||
const at0 = rest.indexOf(".");
|
||||
if (at0 <= 0) return undefined;
|
||||
const node = rest.slice(0, at0);
|
||||
rest = rest.slice(at0 + 1);
|
||||
if (rest === "") return undefined;
|
||||
const module = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node, module };
|
||||
}
|
||||
|
||||
/** The key of one value of the state packages under the form "<node>". */
|
||||
export function packagesByNodeKey(node: string): string {
|
||||
return node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>", or undefined for a key of another form. */
|
||||
export function parsePackagesByNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** The key of one value of the state health under the form "<node>". */
|
||||
export function healthByNodeKey(node: string): string {
|
||||
return node;
|
||||
}
|
||||
|
||||
/** The parts of a key of the form "<node>", or undefined for a key of another form. */
|
||||
export function parseHealthByNodeKey(key: string): { node: string } | undefined {
|
||||
let rest = key;
|
||||
if (rest === "") return undefined;
|
||||
const node = rest;
|
||||
rest = "";
|
||||
if (rest !== "") return undefined;
|
||||
return { node };
|
||||
}
|
||||
|
||||
/** one act asked through the seat, as acts reads it (ADR 0563 §9) */
|
||||
export interface Act {
|
||||
/** the act: hand-over, access-act, judge-directories or setuid-search */
|
||||
@@ -505,3 +620,103 @@ export type RefusedEvent = ActSaid;
|
||||
/** is the body of the event manifest-reads-changed. */
|
||||
export type ManifestReadsChangedEvent = ManifestReadsChanged;
|
||||
|
||||
/** is one value of the state have under the key <node>.<module>. */
|
||||
export interface HaveByNodeModuleValue {
|
||||
"build"?: string;
|
||||
"build-alone"?: boolean;
|
||||
/** the composition's digest */
|
||||
"composed"?: string;
|
||||
"detail"?: string;
|
||||
/** the fingerprint held */
|
||||
"fp"?: string;
|
||||
/** the accounts handed */
|
||||
"handed"?: Record<string, unknown>;
|
||||
/** how it is */
|
||||
"health": string;
|
||||
"judgement"?: string;
|
||||
"kept"?: string[];
|
||||
/** how far it has come */
|
||||
"phase": string;
|
||||
/** a pull the engine waits for */
|
||||
"pull-wait"?: Record<string, unknown>;
|
||||
"sealed"?: string[];
|
||||
"sealed-at"?: Record<string, unknown>;
|
||||
/** the user list written */
|
||||
"user-list"?: Record<string, unknown>;
|
||||
"v": number;
|
||||
/** what it waits for */
|
||||
"waits"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state have under the key <node>.node. */
|
||||
export interface HaveByNodeNodeValue {
|
||||
"busy"?: Record<string, unknown>;
|
||||
"candidates"?: Record<string, Record<string, unknown>>;
|
||||
"composed"?: string;
|
||||
/** own, or the controller's */
|
||||
"composes"?: string;
|
||||
"composes-why"?: string;
|
||||
"filters"?: Record<string, unknown>;
|
||||
"profile"?: Record<string, unknown>;
|
||||
/** the node's record: its tunnel and certificate */
|
||||
"record"?: Record<string, unknown>;
|
||||
"sealed"?: string[];
|
||||
"sealed-at"?: Record<string, unknown>;
|
||||
"strays"?: Record<string, unknown>;
|
||||
"v": number;
|
||||
"windows"?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/** is one value of the state composed under the key <node>.<module>.<fingerprint>. */
|
||||
export interface ComposedByNodeModuleFingerprintValue {
|
||||
"Data"?: boolean;
|
||||
"FP": string;
|
||||
"Filled"?: string[];
|
||||
"Module": string;
|
||||
"Node": string;
|
||||
/** the node's own adoption, identities, groups, libraries and provisioner account */
|
||||
"Own"?: Record<string, unknown>;
|
||||
/** the module's plan */
|
||||
"Plan"?: Record<string, unknown>;
|
||||
/** why the composition was refused */
|
||||
"Refused"?: string;
|
||||
"Resources"?: Record<string, unknown>[];
|
||||
"V"?: number;
|
||||
}
|
||||
|
||||
/** is one value of the state data under the key <node>.<module>. */
|
||||
export interface DataByNodeModuleValue {
|
||||
"digest": string;
|
||||
"items": Record<string, unknown>[];
|
||||
"module": string;
|
||||
"node": string;
|
||||
"v"?: number;
|
||||
}
|
||||
|
||||
export interface PackagesByNodeValuePackagesItem {
|
||||
"absent"?: boolean;
|
||||
"modules"?: string[];
|
||||
"package"?: string;
|
||||
}
|
||||
|
||||
/** is one value of the state packages under the key <node>. */
|
||||
export interface PackagesByNodeValue {
|
||||
"node": string;
|
||||
"packages": PackagesByNodeValuePackagesItem[];
|
||||
}
|
||||
|
||||
/** is one value of the state health under the key <node>. */
|
||||
export interface HealthByNodeValue {
|
||||
"at": string;
|
||||
"contract"?: number;
|
||||
"fallback"?: Record<string, unknown>;
|
||||
"found"?: Record<string, unknown>[];
|
||||
"network"?: Record<string, unknown>;
|
||||
"node": string;
|
||||
"peers"?: Record<string, unknown>[];
|
||||
"relogin"?: Record<string, unknown>[];
|
||||
"root"?: Record<string, unknown>[];
|
||||
"units"?: Record<string, unknown>;
|
||||
"v": number;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// Code generated by seatgen from the seat definitions; DO NOT EDIT.
|
||||
|
||||
export * as seats from "./seats.js";
|
||||
-8185
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user