mesh/delivery merged: source.main moved to novox/mesh-sdk@5a38a1221659
mesh/delivery-group group feat/l3-final merged: every member is merged
mesh/check pass 85ba0a9a70d8 on 52e564845e44 | unit 3760 run, 4992 kept, 56 skipped | integration 3841 run, 5103 kept, 59 skipped | over bound: unit, …
NodeRecord.ManifestReads (`manifest-reads`) and Module.Needs (`needs`) are additive at Version 1, read leniently by every running part. checkRule takes 1 to 10 so a later release may number the verb wait and the capability hold; nothing writes 9 or 10 in this one. kept_until_delivered.go stays: this release still builds beside mesh-host 798d73e, and its head comment names the next mesh-sdk release as the one that removes it. Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
112 lines
5.2 KiB
Go
112 lines
5.2 KiB
Go
package delivery
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// A node's record is what the machine observes of itself (issue 1126, ADR 0555 §3), written by its own agent in its
|
|
// own have key, `<node>.node` of the node-engine's have bucket (HaveNode.Record), whenever an observed fact changes and
|
|
// only when the value differs. The key's change is the event its readers hear: every node and the parts that compose
|
|
// watch it. Where a module runs, and every fact a person decides of the node (its endpoint, site, hub, address on the
|
|
// private network, public domain, accounts, the tunnel found at adoption), are the catalogue's placement
|
|
// (placement.go). Nothing in it is secret: its keys are public halves.
|
|
|
|
// RecordTunnel is a tunnel found on a node when it was adopted, as compose.Tunnel holds it: public keys and addresses
|
|
// only. After the node took it over the tunnel is no longer there to observe, so it is kept as what was decided at
|
|
// adoption, in the node's placement (NodeDecided.Tunnel).
|
|
type RecordTunnel struct {
|
|
Interface string `json:"interface"`
|
|
Unit string `json:"unit,omitempty"`
|
|
Config string `json:"config,omitempty"`
|
|
Port int `json:"port,omitempty"`
|
|
MTU int `json:"mtu,omitempty"`
|
|
Address string `json:"address,omitempty"`
|
|
Range string `json:"range,omitempty"`
|
|
PublicKey string `json:"public-key,omitempty"`
|
|
Peers []RecordTunnelPeer `json:"peers,omitempty"`
|
|
}
|
|
|
|
// RecordTunnelPeer is one peer of a found tunnel.
|
|
type RecordTunnelPeer struct {
|
|
PublicKey string `json:"public-key"`
|
|
Address string `json:"address,omitempty"`
|
|
}
|
|
|
|
// NodeRecord is one node's record: what the machine observes of itself (issue 1126, ADR 0555: what a person decides
|
|
// lives in the catalogue's placement file, Placement.Decided; what the machine observes lives here). TunnelKey is the
|
|
// public key of its private-network tunnel; Certificate the one the mesh issued for its internal name, public, as the
|
|
// node holds it. The tunnel found at adoption and the names given to its peers are decisions kept in the placement;
|
|
// whether the hub took its found tunnel over, and which node enrolled under a carried peer's key, are read from both.
|
|
type NodeRecord struct {
|
|
V int `json:"v"`
|
|
Node string `json:"node"`
|
|
TunnelKey string `json:"tunnel-key,omitempty"`
|
|
Capabilities []string `json:"capabilities,omitempty"`
|
|
SealingKey string `json:"sealing-key,omitempty"`
|
|
ServingKey string `json:"serving-key,omitempty"`
|
|
Certificate string `json:"certificate,omitempty"`
|
|
OutwardLinks []string `json:"outward-links,omitempty"`
|
|
Networks []catalogue.AttachedNetwork `json:"networks,omitempty"`
|
|
NetworksSaid bool `json:"networks-said,omitempty"`
|
|
Contract int `json:"contract,omitempty"`
|
|
// Authority is the mesh's own certificate as this machine holds it (public): the one its declaration last wrote where
|
|
// a module asked for it. A node composing its own composes a certificate with it (compose.Input.Authority).
|
|
Authority string `json:"authority,omitempty"`
|
|
// Trusts is what this machine trusts a mesh signature from now (Trusts in signers.go, ADR 0550 §2): the controller's
|
|
// key until the lease is handed away, and the vault's key and authority once it reads them from `signers`. The gate
|
|
// before the lease write reads every node's from the bus.
|
|
Trusts []string `json:"trusts,omitempty"`
|
|
// ManifestReads are the reader capabilities of the shared contract this machine's node-engine is built with
|
|
// (catalogue.ManifestReads, novox/hq ADR 0614 §4): the manifest words, forms and seat names it reads. Empty for an
|
|
// engine built before it said them, which a reader takes as the baseline (catalogue.StatedManifestReads).
|
|
ManifestReads []string `json:"manifest-reads,omitempty"`
|
|
}
|
|
|
|
func (r NodeRecord) check() error {
|
|
if err := checkName("node", r.Node); err != nil {
|
|
return err
|
|
}
|
|
for _, c := range r.Capabilities {
|
|
if c == "" {
|
|
return fmt.Errorf("delivery: the record of %s names an empty capability", r.Node)
|
|
}
|
|
}
|
|
for _, c := range r.ManifestReads {
|
|
if c == "" {
|
|
return fmt.Errorf("delivery: the record of %s names an empty reader capability", r.Node)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// EncodeNodeRecord is r as JSON at Version; it refuses what DecodeNodeRecord refuses.
|
|
func EncodeNodeRecord(r NodeRecord) ([]byte, error) {
|
|
if err := r.check(); err != nil {
|
|
return nil, err
|
|
}
|
|
r.V = Version
|
|
return json.Marshal(r)
|
|
}
|
|
|
|
// DecodeNodeRecord reads a node record; it refuses an unknown version (ErrUnknownVersion), a node that is not a name, and
|
|
// an empty capability.
|
|
func DecodeNodeRecord(data []byte) (NodeRecord, error) {
|
|
var r NodeRecord
|
|
if err := decode(data, &r); err != nil {
|
|
return NodeRecord{}, err
|
|
}
|
|
if err := r.check(); err != nil {
|
|
return NodeRecord{}, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
// SameNodeRecord says whether two records are the same value, so the agent writes only when they differ.
|
|
func SameNodeRecord(a, b NodeRecord) bool {
|
|
a.V, b.V = 0, 0
|
|
return jsonEqual(a, b)
|
|
}
|