A node record states the reader capabilities its engine reads, a module value the ones its manifest needs, and a want of rule 9 or 10 reads (ADR 0614 §2, §4, issue 774)
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, …
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
This commit is contained in:
@@ -2,10 +2,11 @@ package catalogue
|
|||||||
|
|
||||||
// This file keeps, deprecated, the exported names feat/l3b-bus removed from this package while a running part still
|
// This file keeps, deprecated, the exported names feat/l3b-bus removed from this package while a running part still
|
||||||
// uses them: an exported name is removed only after every user of it is delivered. The checker builds the running
|
// uses them: an exported name is removed only after every user of it is delivered. The checker builds the running
|
||||||
// node-engine's composer (mesh-host main) beside this mesh-sdk (ADR 0548 §6), and mesh-host main, mesh-delivery main
|
// node-engine's composer (mesh-host main) beside this mesh-sdk (ADR 0548 §6), and mesh-host main names them
|
||||||
// (the indexer's judge, the assigner's and mesh-grants' code and tests) and mesh-tools main (node-tools' tests) name
|
// (RuntimeModule, CoreCredentialModules, FromBus). Nothing in the final L3 release's heads uses any of them, but that
|
||||||
// them. Nothing in L3's own heads uses any of them. The second group removes this file, and its exemption in
|
// release still builds beside mesh-host 798d73e, so it keeps this file. The next release that changes mesh-sdk, once
|
||||||
// TestNoCatalogueManifestNamesAmqp, once mesh-host a24a1d72 and L3's mesh-delivery and mesh-tools heads run.
|
// the final L3 release's node-engine runs on every node, removes this file and its exemption in
|
||||||
|
// TestNoCatalogueManifestNamesAmqp.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|||||||
@@ -146,9 +146,15 @@ const (
|
|||||||
RuleProvisions = 8
|
RuleProvisions = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ruleRead is the highest rule a reader takes (novox/hq ADR 0614 §2, §4): 9 and 10 are kept for the verb wait and the
|
||||||
|
// capability hold, which a later release gives numbers of their own, so a want of that release reads on every node
|
||||||
|
// that runs this one. Nothing writes 9 or 10 yet: the verb wait is held under RuleProvisions and the capability hold
|
||||||
|
// under RuleComposed, each with words naming its edge.
|
||||||
|
const ruleRead = 10
|
||||||
|
|
||||||
func checkRule(rule int, of string) error {
|
func checkRule(rule int, of string) error {
|
||||||
if rule < RuleBuildDone || rule > RuleProvisions {
|
if rule < RuleBuildDone || rule > ruleRead {
|
||||||
return fmt.Errorf("delivery: %s names the rule %d, which is not one of the eight (1 to 8)", of, rule)
|
return fmt.Errorf("delivery: %s names the rule %d, which is not one of 1 to %d", of, rule, ruleRead)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ func TestAssignerValuesRoundTrip(t *testing.T) {
|
|||||||
{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: RuleCanary, Words: "the canary ace does not run it healthy yet"},
|
{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: RuleCanary, Words: "the canary ace does not run it healthy yet"},
|
||||||
{Removed: true, Words: "the module left g14"},
|
{Removed: true, Words: "the module left g14"},
|
||||||
{FP: fp2of('a'), Composed: hashOf('1'), Put: true, Hold: true, Words: "put by the operator: the bus's user list"},
|
{FP: fp2of('a'), Composed: hashOf('1'), Put: true, Hold: true, Words: "put by the operator: the bus's user list"},
|
||||||
|
// A rule a later release numbers (9, 10: the verb wait, the capability hold, ADR 0614) reads here already.
|
||||||
|
{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: 10, Words: "the verb x.y it invokes is served by no running build"},
|
||||||
}
|
}
|
||||||
for _, w := range wants {
|
for _, w := range wants {
|
||||||
data, err := EncodeWant(w)
|
data, err := EncodeWant(w)
|
||||||
@@ -147,7 +149,7 @@ func TestAssignerValuesRefused(t *testing.T) {
|
|||||||
{Removed: true, FP: fp2of('a')},
|
{Removed: true, FP: fp2of('a')},
|
||||||
{FP: fp2of('a'), Newest: fp2of('b')},
|
{FP: fp2of('a'), Newest: fp2of('b')},
|
||||||
{FP: fp2of('a'), Newest: fp2of('a'), Rule: 3},
|
{FP: fp2of('a'), Newest: fp2of('a'), Rule: 3},
|
||||||
{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: 9},
|
{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: 11},
|
||||||
{FP: fp2of('a'), Composed: hashOf('1'), Hold: true},
|
{FP: fp2of('a'), Composed: hashOf('1'), Hold: true},
|
||||||
{FP: fp2of('a'), Composed: hashOf('1'), Put: true, Newest: fp2of('b'), Rule: 3},
|
{FP: fp2of('a'), Composed: hashOf('1'), Put: true, Newest: fp2of('b'), Rule: 3},
|
||||||
{Removed: true, Put: true},
|
{Removed: true, Put: true},
|
||||||
@@ -164,7 +166,7 @@ func TestAssignerValuesRefused(t *testing.T) {
|
|||||||
{Want: fp2of('a'), Sent: fp2of('b'), Rule: 3, Unexplained: true},
|
{Want: fp2of('a'), Sent: fp2of('b'), Rule: 3, Unexplained: true},
|
||||||
{Want: fp2of('a'), Sent: fp2of('a'), Rule: 3},
|
{Want: fp2of('a'), Sent: fp2of('a'), Rule: 3},
|
||||||
{},
|
{},
|
||||||
{Want: fp2of('a'), Sent: fp2of('b'), Rule: 9},
|
{Want: fp2of('a'), Sent: fp2of('b'), Rule: 11},
|
||||||
{WantRemoved: true, Want: fp2of('a'), Rule: 1},
|
{WantRemoved: true, Want: fp2of('a'), Rule: 1},
|
||||||
} {
|
} {
|
||||||
if _, err := EncodeDifference(d); err == nil {
|
if _, err := EncodeDifference(d); err == nil {
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ type NodeRecord struct {
|
|||||||
// key until the lease is handed away, and the vault's key and authority once it reads them from `signers`. The gate
|
// 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.
|
// before the lease write reads every node's from the bus.
|
||||||
Trusts []string `json:"trusts,omitempty"`
|
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 {
|
func (r NodeRecord) check() error {
|
||||||
@@ -70,6 +74,11 @@ func (r NodeRecord) check() error {
|
|||||||
return fmt.Errorf("delivery: the record of %s names an empty capability", r.Node)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ var secretNamed = regexp.MustCompile(`(?i)(secret|passw|token|api[-_]?key|privat
|
|||||||
func TestNodeRecord(t *testing.T) {
|
func TestNodeRecord(t *testing.T) {
|
||||||
hub := NodeRecord{Node: "novox", TunnelKey: "k", Capabilities: []string{"docker"}, SealingKey: "age1x", ServingKey: "pub",
|
hub := NodeRecord{Node: "novox", TunnelKey: "k", Capabilities: []string{"docker"}, SealingKey: "age1x", ServingKey: "pub",
|
||||||
Certificate: "cert", OutwardLinks: []string{"eth0"}, Networks: []catalogue.AttachedNetwork{{Link: "eth0", Network: "192.0.2.0/24"}},
|
Certificate: "cert", OutwardLinks: []string{"eth0"}, Networks: []catalogue.AttachedNetwork{{Link: "eth0", Network: "192.0.2.0/24"}},
|
||||||
NetworksSaid: true, Contract: 3, Trusts: []string{"controller key sha256:aa", "vault key sha256:bb"}}
|
NetworksSaid: true, Contract: 3, Trusts: []string{"controller key sha256:aa", "vault key sha256:bb"},
|
||||||
|
ManifestReads: []string{"seat:mesh-catalog", "word:tool-runner"}}
|
||||||
raw, err := EncodeNodeRecord(hub)
|
raw, err := EncodeNodeRecord(hub)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@@ -45,6 +46,7 @@ func TestNodeRecord(t *testing.T) {
|
|||||||
|
|
||||||
for name, r := range map[string]NodeRecord{
|
for name, r := range map[string]NodeRecord{
|
||||||
"empty capability": {Node: "ace", Capabilities: []string{""}},
|
"empty capability": {Node: "ace", Capabilities: []string{""}},
|
||||||
|
"empty reader capability": {Node: "ace", ManifestReads: []string{""}},
|
||||||
"node that is not a name": {Node: "a.b"},
|
"node that is not a name": {Node: "a.b"},
|
||||||
} {
|
} {
|
||||||
if _, err := EncodeNodeRecord(r); err == nil {
|
if _, err := EncodeNodeRecord(r); err == nil {
|
||||||
|
|||||||
@@ -443,6 +443,10 @@ type Module struct {
|
|||||||
// Warnings are the problems of an accepted manifest a stricter judge outgrew (novox/hq ADR 0579 §1): Verdict is then
|
// Warnings are the problems of an accepted manifest a stricter judge outgrew (novox/hq ADR 0579 §1): Verdict is then
|
||||||
// empty (accepted), and the watchman raises delivery.ManifestOutgrown until the manifest is mended.
|
// empty (accepted), and the watchman raises delivery.ManifestOutgrown until the manifest is mended.
|
||||||
Warnings []string `json:"warnings,omitempty"`
|
Warnings []string `json:"warnings,omitempty"`
|
||||||
|
// Needs are the reader capabilities the manifest's own words, forms and seat names need (catalogue.ManifestNeeds,
|
||||||
|
// novox/hq ADR 0614 §4), written by the judge with its verdict: the assigner holds a node's want while that node's
|
||||||
|
// engine does not state one of them. Empty in a value written before, which needs nothing.
|
||||||
|
Needs []string `json:"needs,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerdictOf is the verdict a modules value carries, or nil when it carries none (taken as accepted, TakeManifestVerdict).
|
// VerdictOf is the verdict a modules value carries, or nil when it carries none (taken as accepted, TakeManifestVerdict).
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ func TestSourceValuesRoundTrip(t *testing.T) { // 1200/AC3
|
|||||||
for _, m := range []Module{
|
for _, m := range []Module{
|
||||||
{FP: "src1:abc", Src: 5, FPSrc: 5, Repository: "novox/mesh-sdk", Commit: "cccc"},
|
{FP: "src1:abc", Src: 5, FPSrc: 5, Repository: "novox/mesh-sdk", Commit: "cccc"},
|
||||||
{None: "a build that resolves packages when built", Repository: "novox/mesh-sdk", Commit: "cccc"},
|
{None: "a build that resolves packages when built", Repository: "novox/mesh-sdk", Commit: "cccc"},
|
||||||
|
// The reader capabilities its manifest needs (ADR 0614 §4), written with the verdict.
|
||||||
|
{FP: "src1:abc", Repository: "novox/mesh-sdk", Commit: "cccc", Needs: []string{"seat:mesh-catalog", "word:tool-runner"}},
|
||||||
} {
|
} {
|
||||||
data, err = EncodeModule(m)
|
data, err = EncodeModule(m)
|
||||||
check("module", data, err)
|
check("module", data, err)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func TestAWantNamesItsComposition(t *testing.T) {
|
|||||||
{Want{Removed: true, Composed: hashOf('1')}, "removed want names no"},
|
{Want{Removed: true, Composed: hashOf('1')}, "removed want names no"},
|
||||||
{Want{FP: fp2of('a'), Composed: hashOf('1'), Backup: "later"}, `backup answer "later"`},
|
{Want{FP: fp2of('a'), Composed: hashOf('1'), Backup: "later"}, `backup answer "later"`},
|
||||||
{Want{Removed: true, Backup: BackupAgain}, "removed want names no"},
|
{Want{Removed: true, Backup: BackupAgain}, "removed want names no"},
|
||||||
{Want{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: 9}, "rule 9"},
|
{Want{FP: fp2of('a'), Composed: hashOf('1'), Newest: fp2of('b'), Rule: 11}, "rule 11"},
|
||||||
}
|
}
|
||||||
for _, r := range refusals {
|
for _, r := range refusals {
|
||||||
if _, err := EncodeWant(r.w); err == nil || !strings.Contains(err.Error(), r.why) {
|
if _, err := EncodeWant(r.w); err == nil || !strings.Contains(err.Error(), r.why) {
|
||||||
|
|||||||
Reference in New Issue
Block a user