Merge branch 'feat/47-G-judge5' into feat/47-G-join8

# Conflicts:
#	modules/mesh-delivery-pipeline/manifest_test.go
This commit is contained in:
2026-11-12 00:14:13 +01:00
17 changed files with 190 additions and 67 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"module": "mesh-delivery-contracts",
"version": "1",
"version": "0.1",
"build": {
"artifacts": [
{
+1 -1
View File
@@ -1,6 +1,6 @@
{
"module": "mesh-delivery-assigner",
"version": "1",
"version": "0.1",
"slug": "assigner",
"runs-as": "mesh-delivery-assigner",
"claims": [
+1 -1
View File
@@ -1,6 +1,6 @@
{
"module": "mesh-delivery-builder",
"version": "1",
"version": "0.1",
"slug": "builder",
"claims": [
{
@@ -1,6 +1,6 @@
{
"module": "mesh-delivery-forge-bridge",
"version": "1",
"version": "0.1",
"slug": "forge-bridge",
"consumes": [
"git.pull-updated",
@@ -371,8 +371,8 @@ func TestTheIndexerJudgesEveryManifestOnce(t *testing.T) {
}
}
if !slices.Equal(judge.Foundation, []string{"nats", "mesh-grants", "mesh-delivery-indexer", "mesh-delivery-assigner", "node-tools",
"mesh-delivery-builder", "mesh-delivery-checker", "mesh-config", "mesh-vault", "mesh-delivery-pipeline", "gitea", "distribution"}) {
t.Fatalf("the foundation is %v, want exactly the nine of ADR 0619, the pipeline runner (ADR 0666 §4) and the forge and image registry modules (design 47 G §584)", judge.Foundation)
"mesh-delivery-builder", "mesh-delivery-checker", "mesh-config", "mesh-vault", "mesh-delivery-pipeline", "gitea", "distribution", "mesh-host"}) {
t.Fatalf("the foundation is %v, want exactly the nine of ADR 0619, the pipeline runner (ADR 0666 §4) and the forge and image registry modules (design 47 G §584) and the node-engine's module (§627)", judge.Foundation)
}
late := hold("late", `{"module":"late","version":"1.0","logs":[{"name":"l"}]}`)
grants := hold("mesh-grants", `{"module":"mesh-grants","version":"2.0","logs":[{"name":"l"},{"name":"m"}]}`)
@@ -22,6 +22,11 @@ func TestTheJudgeReadsMilestoneGsWords(t *testing.T) {
`"streams":[{"name":"gitea-findings","events":["finding-written"],"retention":"history"}],"consumes":["mesh-conditions.findings-asked"]}`},
{name: "the image registry is a foundation part too (§584)", raw: `{"module":"distribution","version":"1.0","state":["findings"],` +
`"streams":[{"name":"distribution-findings","events":["finding-written"],"retention":"history"}],"consumes":["mesh-conditions.findings-asked"]}`},
{name: "the node-engine's module is a foundation part (§627)", raw: `{"module":"mesh-host","version":"1.0","state":["findings"],` +
`"streams":[{"name":"mesh-host-findings","events":["finding-written.*","finding-cleared.*","findings-stated.*"],"max-age-days":7,"max-mib":16}],"consumes":["mesh-conditions.findings-asked"]}`},
{name: "an old state section entry with max-mib in its bounds (§469, §695)", raw: `{"module":"a","version":"1.0","state":[{"name":"s","max-mib":128}]}`},
{name: "an old state section entry with max-mib at zero (§469)", raw: `{"module":"a","version":"1.0","state":[{"name":"s","max-mib":0}]}`, want: "max-mib"},
{name: "an old state section entry with max-mib past the bound (§469)", raw: `{"module":"a","version":"1.0","state":[{"name":"s","max-mib":9000}]}`, want: "max-mib"},
{name: "another part's old findings and stream (§529, §577)", raw: `{"module":"a","version":"1.0","state":["findings"],` +
`"streams":[{"name":"a-findings","events":["finding-written"],"retention":"history"}],"consumes":["mesh-conditions.findings-asked"]}`, want: "old sections"},
{name: "another part's findings in its requires (§529)", raw: `{"module":"a","version":"1.0","consumes":["mesh-conditions.findings-asked"],"requires":[` +
@@ -20,10 +20,10 @@ var OldSections = []string{"state", "logs", "streams", "objects"}
// composition, assignments, build or delivery needs before it can answer (novox/hq ADR 0619 §1, §3, as ADR 0666 §4 changes
// them): the bus module, the grants part, the indexer, the assigner, the tool runner, the builder, the checker, mesh-config,
// the vault, the pipeline runner, which runs the bus module's own pipeline, and the forge module and the image registry
// module, which its build calls (design 47 G §584). Their new state goes on their old sections
// module, which its build calls (design 47 G §584), and the node-engine's module, which composes every part (§627). Their new state goes on their old sections
// too, so a foundation manifest asking bus state in the new form is refused.
var Foundation = []string{"nats", "mesh-grants", "mesh-delivery-indexer", "mesh-delivery-assigner", "node-tools",
"mesh-delivery-builder", "mesh-delivery-checker", "mesh-config", "mesh-vault", "mesh-delivery-pipeline", "gitea", "distribution"}
"mesh-delivery-builder", "mesh-delivery-checker", "mesh-config", "mesh-vault", "mesh-delivery-pipeline", "gitea", "distribution", "mesh-host"}
// ViewOwners are the two owners whose state every reader reads through their first views and read tools, never by a
// `reads` entry (novox/hq ADR 0615 §1): CountOwnerReads counts what is left of those entries.
@@ -5567,6 +5567,11 @@ var seatStreamsKeptUntilMoved = map[string][]string{
// keptUntilMoved is whether a stream of a manifest is one kept until its module moves it: by the module's name, or by a
// seat it claims.
func keptUntilMoved(m catalogue.Manifest, stream string) bool {
// A foundation part keeps its old sections for good, its streams among them: its findings stream `<module>-findings`
// (design 47 G §529, A-30) and the image registry's `distribution-events` (§584, A-54).
if slices.Contains(Foundation, m.Module) {
return true
}
if slices.Contains(streamsKeptUntilMoved[m.Module], stream) {
return true
}
@@ -4683,7 +4683,7 @@ func caseTheMeshsOwnSeatsAreStillClaimable(t *testing.T) {
// It delivers the bus, so its holder provides the bus — the rule this check now enforces.
m := catalogue.Manifest{Module: "nats",
Provides: []catalogue.Offer{{Name: "mesh-bus", Scope: catalogue.ScopeMesh, Credential: &catalogue.OfferCredential{Form: catalogue.CredentialFormNone}}},
Claims: []catalogue.Claim{{Name: "mesh-broker", Scope: catalogue.ScopeMesh, Serves: []string{"snapshot-kept", "restore-kept"}}}}
Claims: []catalogue.Claim{{Name: "mesh-broker", Scope: catalogue.ScopeMesh, Serves: []string{"snapshot-get", "snapshot-restore", "snapshot-restore-cancel", "snapshot-remove"}}}}
if got := problemsFor(t, catalogue.Shelf{"nats": m}); got != "" {
t.Fatalf("a mesh seat was refused by the derived check: %s", got)
}
@@ -5121,6 +5121,18 @@ func caseTwoModulesCannotDeclareOneStream(t *testing.T) {
if got := PredefinedFormProblems(catalogue.Manifest{Module: "mesh-build-go", Streams: toolchains}); len(got) != 1 {
t.Fatalf("a toolchain stream of a module claiming no build seat was kept by its name: %v", got)
}
// A foundation part keeps its old streams for good: its findings stream `<module>-findings` (design 47 G §529, A-30) and
// distribution's `distribution-events` (§584, A-54); a part that is no foundation part keeps none.
findings := []catalogue.StreamDeclaration{{Name: "mesh-config-findings", Events: []string{"finding-written.*"}}}
if got := PredefinedFormProblems(catalogue.Manifest{Module: "mesh-config", Streams: findings}); len(got) != 0 {
t.Fatalf("a foundation part's findings stream was refused: %v", got)
}
if got := PredefinedFormProblems(catalogue.Manifest{Module: "distribution", Streams: []catalogue.StreamDeclaration{{Name: "distribution-events", Events: []string{"old-name-closed"}}}}); len(got) != 0 {
t.Fatalf("a foundation part's events stream was refused: %v", got)
}
if got := PredefinedFormProblems(catalogue.Manifest{Module: "mesh-config-b", Streams: []catalogue.StreamDeclaration{{Name: "mesh-config-b-findings", Events: []string{"finding-written.*"}}}}); len(got) != 1 {
t.Fatalf("a findings stream of a part outside the foundation was kept: %v", got)
}
}
// A seat name meaning two protocols is the failure nobody could diagnose afterwards.
@@ -53,12 +53,13 @@ func TestManifest(t *testing.T) {
{"old state sections", equalSets(states, []string{seat.StatePipelines, seat.StateKept, "aged", "bounds", "toolchains", "findings", "first-views"})},
// §535, §647, A-77, A-104: an ask no holder takes is bound by a key with its own time to live.
{"bounds is key-ttl", keyTTL["bounds"]},
// §27, §85: the step log on an old stream, its outputs in an old objects section.
// RN24 (§383, §387): beside it, the finding stream its findings are said on.
{"old streams section", equalSets(streams, []string{seat.StateStepLog, "mesh-delivery-pipeline-findings"})},
{"step-log 128 MiB", len(m.Streams) == 2 && m.Streams[0].MaxMiB == 128},
{"finding stream 7 days 16 MiB", len(m.Streams) == 2 && m.Streams[1].MaxAgeDays == 7 && m.Streams[1].MaxMiB == 16 &&
equalSets(m.Streams[1].Events, []string{"finding-written.*", "finding-cleared.*", "findings-stated.*"})},
// §470 (amending §27, §85): the step log is an old logs section kept 100 days, 128 MiB; RN24 (§383, §387): the finding
// stream its findings are said on is the one old stream.
{"old streams section", equalSets(streams, []string{"mesh-delivery-pipeline-findings"})},
{"step-log an old logs section of 100 days and 128 MiB", len(m.Logs) == 1 && m.Logs[0].Name == seat.StateStepLog &&
m.Logs[0].MaxAgeDays == 100 && m.Logs[0].MaxMiB == 128},
{"finding stream 7 days 16 MiB", len(m.Streams) == 1 && m.Streams[0].MaxAgeDays == 7 && m.Streams[0].MaxMiB == 16 &&
equalSets(m.Streams[0].Events, []string{"finding-written.*", "finding-cleared.*", "findings-stated.*"})},
// RN24 (§368): the version as MAJOR.MINOR, 0.1 with none published.
{"version 0.1", m.Version == "0.1"},
{"old objects section", equalSets(objects, []string{seat.StateStepOutputs})},
+8 -8
View File
@@ -90,13 +90,6 @@
}
],
"streams": [
{
"name": "step-log",
"events": [
"step-log.**"
],
"max-mib": 128
},
{
"name": "mesh-delivery-pipeline-findings",
"events": [
@@ -176,5 +169,12 @@
]
}
]
}
},
"logs": [
{
"name": "step-log",
"max-age-days": 100,
"max-mib": 128
}
]
}
+41 -14
View File
@@ -16,24 +16,27 @@
"mesh-conditions.findings-asked",
"mesh-delivery-assigner.views.asks"
],
"streams": [
{
"name": "mesh-delivery-teller-findings",
"events": ["finding-written.*", "finding-cleared.*", "findings-stated.*"],
"max-age-days": 7,
"max-mib": 16
}
],
"emits": [
"answered",
"ask-ended"
],
"state": [
{ "name": "answers", "history": 5 },
{ "name": "asked", "history": 1 },
{ "name": "ends", "history": 1 },
{ "name": "first-views", "history": 1 },
{ "name": "findings", "history": 1 }
{
"name": "answers",
"history": 5
},
{
"name": "asked",
"history": 1
},
{
"name": "ends",
"history": 1
},
{
"name": "first-views",
"history": 1
}
],
"reads": [
"mesh-delivery-gate.asks",
@@ -101,5 +104,29 @@
]
}
]
}
},
"requires": [
{
"name": "findings",
"storage": "key-value",
"template": "state",
"options": {
"history": 1
}
},
{
"name": "finding-events",
"storage": "stream",
"template": "events",
"options": {
"events": [
"finding-written.*",
"finding-cleared.*",
"findings-stated.*"
],
"max-age-days": 7,
"max-mib": 16
}
}
]
}
+37 -13
View File
@@ -37,10 +37,18 @@
"stuck"
],
"state": [
{ "name": "answers", "history": 5 },
{ "name": "reach", "history": 1 },
{ "name": "first-views", "history": 1 },
{ "name": "findings", "history": 1 }
{
"name": "answers",
"history": 5
},
{
"name": "reach",
"history": 1
},
{
"name": "first-views",
"history": 1
}
],
"consumes": [
"mesh-conditions.findings-asked",
@@ -51,14 +59,6 @@
"mesh-delivery-indexer.views.candidates",
"mesh-delivery-indexer.views.taken"
],
"streams": [
{
"name": "mesh-delivery-view-findings",
"events": ["finding-written.*", "finding-cleared.*", "findings-stated.*"],
"max-age-days": 7,
"max-mib": 16
}
],
"invokes": [
"mesh-delivery-assigner.assigner_read_asks",
"mesh-delivery-assigner.assigner_read_differences",
@@ -198,5 +198,29 @@
"from": "files"
}
]
}
},
"requires": [
{
"name": "findings",
"storage": "key-value",
"template": "state",
"options": {
"history": 1
}
},
{
"name": "finding-events",
"storage": "stream",
"template": "events",
"options": {
"events": [
"finding-written.*",
"finding-cleared.*",
"findings-stated.*"
],
"max-age-days": 7,
"max-mib": 16
}
}
]
}
+41 -9
View File
@@ -30,9 +30,6 @@
"mesh-delivery-indexer.indexer_read_modules",
"seat:mesh-hand-acts.hand-act"
],
"streams": [
{ "name": "mesh-delivery-watchman-findings", "events": ["finding-written.*", "finding-cleared.*", "findings-stated.*"], "max-age-days": 7, "max-mib": 16 }
],
"consumes": [
"mesh-delivery-assigner.views.wants",
"mesh-delivery-indexer.take-in.pending",
@@ -73,11 +70,22 @@
"watchman_first_view_again"
],
"state": [
{ "name": "presence", "history": 20 },
{ "name": "pulse", "key-ttl": true },
{ "name": "stuck", "history": 20 },
{ "name": "findings", "history": 5 },
{ "name": "first-views", "history": 1 }
{
"name": "presence",
"history": 20
},
{
"name": "pulse",
"key-ttl": true
},
{
"name": "stuck",
"history": 20
},
{
"name": "first-views",
"history": 1
}
],
"own-secrets": {
"broker": "${dir:state}/broker"
@@ -146,5 +154,29 @@
]
}
]
}
},
"requires": [
{
"name": "findings",
"storage": "key-value",
"template": "state",
"options": {
"history": 5
}
},
{
"name": "finding-events",
"storage": "stream",
"template": "events",
"options": {
"events": [
"finding-written.*",
"finding-cleared.*",
"findings-stated.*"
],
"max-age-days": 7,
"max-mib": 16
}
}
]
}
+23 -6
View File
@@ -16,9 +16,6 @@
]
}
],
"streams": [
{ "name": "mesh-enrolment-findings", "events": ["finding-written.*", "finding-cleared.*", "findings-stated.*"], "max-age-days": 7, "max-mib": 16 }
],
"consumes": [
"mesh-node-enroller.node-enrolled",
"mesh-node-enroller.enrolment-refused",
@@ -52,8 +49,7 @@
{
"name": "asked",
"history": 5
},
"findings"
}
],
"tools": [
"enrolment_first_views",
@@ -94,5 +90,26 @@
]
}
]
}
},
"requires": [
{
"name": "findings",
"storage": "key-value",
"template": "state"
},
{
"name": "finding-events",
"storage": "stream",
"template": "events",
"options": {
"events": [
"finding-written.*",
"finding-cleared.*",
"findings-stated.*"
],
"max-age-days": 7,
"max-mib": 16
}
}
]
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"module": "mesh-grants",
"version": "1",
"version": "0.1",
"slug": "grants",
"reads": [
"mesh-config.resolved",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"module": "mesh-delivery-sdk",
"version": "1",
"version": "0.1",
"build": {
"artifacts": [
{