Let the genesis test accept a degradable grant missing from the installer's list (issue 835)
mesh/merge-gate head 5cf8938f55b3 merged into trunk 0ab61d1be8c5 — pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus…
mesh/repo-check head 5cf8938f55b3 merged into trunk 0ab61d1be8c5 — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group feat/mail-seats delivered: every member is delivered
mesh/merge-gate head 5cf8938f55b3 merged into trunk 0ab61d1be8c5 — pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus…
mesh/repo-check head 5cf8938f55b3 merged into trunk 0ab61d1be8c5 — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/delivery-group group feat/mail-seats delivered: every member is delivered
Forge check of mesh-controller#345: the merge check clones mesh-host at the commit the machines run, not its main, so a change that only edits mesh-host's examples (the operator-channel.tell grant) can never be seen there until mesh-host's own module next builds. operator-channel.tell is the one grant with a fallback for a refusal (the secret-given condition, ADR 0380 §9), so mark it degradable and let TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose pass without it while every other grant stays required.
This commit is contained in:
@@ -35,7 +35,7 @@ func TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose(t *testing.T)
|
||||
carriedPub := subjectsIn(accounts, "publish")
|
||||
carriedSub := subjectsIn(accounts, "subscribe")
|
||||
|
||||
if diff := missing(want.Publish, carriedPub); len(diff) > 0 {
|
||||
if diff := requiredPublishGap(t, want.Publish, carriedPub); len(diff) > 0 {
|
||||
t.Errorf("the installer's user list does not let the controller publish %v — it would come up "+
|
||||
"and be refused on the first thing it tried", diff)
|
||||
}
|
||||
@@ -62,6 +62,59 @@ func TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose(t *testing.T)
|
||||
}
|
||||
}
|
||||
|
||||
// requiredPublishGap is what in want is missing from carried, leaving out a grant DegradableGrants names
|
||||
// and saying why in the test log instead (novox/hq issue 835, the forge check of mesh-controller#345): the
|
||||
// merge check reads mesh-host at the commit the machines run, which a change to mesh-host's examples alone
|
||||
// never moves, so the carried list can lag the controller's derived one without the controller refusing to
|
||||
// come up.
|
||||
func requiredPublishGap(t *testing.T, want, carried []string) []string {
|
||||
t.Helper()
|
||||
diff := missing(want, carried)
|
||||
var required []string
|
||||
for _, subject := range diff {
|
||||
if reason, ok := degradableReason(subject); ok {
|
||||
t.Logf("the installer's user list does not let the controller publish %s, but that falls back "+
|
||||
"rather than refuses: %s", subject, reason)
|
||||
continue
|
||||
}
|
||||
required = append(required, subject)
|
||||
}
|
||||
return required
|
||||
}
|
||||
|
||||
// degradableReason says whether a subject is one of DegradableGrants, and why.
|
||||
func degradableReason(subject string) (string, bool) {
|
||||
for _, g := range DegradableGrants {
|
||||
if g.Subject == subject {
|
||||
return g.Reason, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// TestADegradableGrantMissingFromTheInstallersListPasses is the forge check's own case (mesh-controller#345,
|
||||
// novox/hq issue 835): an installer list that lacks operator-channel.tell alone, because mesh-host has not
|
||||
// yet built with the grant, still passes — the controller falls back to the secret-given condition rather
|
||||
// than coming up refused.
|
||||
func TestADegradableGrantMissingFromTheInstallersListPasses(t *testing.T) {
|
||||
want := []string{"mesh.seat.operator-channel.tool.tell", "mesh.seat.node-service-manager.tool.restart.*"}
|
||||
carried := []string{"mesh.seat.node-service-manager.tool.restart.*"}
|
||||
if diff := requiredPublishGap(t, want, carried); len(diff) > 0 {
|
||||
t.Errorf("a degradable grant missing from the installer's list must not fail the genesis test, got %v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// TestANonDegradableGrantMissingFromTheInstallersListStillFails proves the exemption is named, not general:
|
||||
// every other grant the controller derives stays required.
|
||||
func TestANonDegradableGrantMissingFromTheInstallersListStillFails(t *testing.T) {
|
||||
want := []string{"mesh.seat.operator-channel.tool.tell", "mesh.seat.node-service-manager.tool.restart.*"}
|
||||
carried := []string{"mesh.seat.operator-channel.tool.tell"}
|
||||
diff := requiredPublishGap(t, want, carried)
|
||||
if len(diff) != 1 || diff[0] != "mesh.seat.node-service-manager.tool.restart.*" {
|
||||
t.Errorf("a missing grant that is not degradable must still fail the genesis test, got %v", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// theCarriedAccounts is the accounts file the installer's template writes at genesis.
|
||||
func theCarriedAccounts(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
@@ -284,6 +284,29 @@ var VerbsTheControllerActsOnAWarrant = []SeatVerb{{Seat: "node-service-manager",
|
||||
// where and when and by whom, asking nothing. A mesh seat's verb is flat: no machine in the subject.
|
||||
var VerbsTheControllerAsksTheOperatorChannel = []SeatVerb{{Seat: "operator-channel", Verb: "tell"}}
|
||||
|
||||
// DegradableGrant is a publish grant whose absence from the installer's carried first-user list is not a
|
||||
// bug in the template: a fallback covers the refusal.
|
||||
type DegradableGrant struct {
|
||||
Subject string
|
||||
Reason string
|
||||
}
|
||||
|
||||
// DegradableGrants are the only publish grants TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose
|
||||
// may find missing from the installer's carried list without failing (novox/hq issue 835, the forge check
|
||||
// of mesh-controller#345): a change that only edits mesh-host's examples can never satisfy a check that
|
||||
// reads the mesh-host commit the machines actually run, so the carried list lags behind the controller's
|
||||
// derived one until mesh-host's own module next builds. operator-channel.tell is the one grant the
|
||||
// controller already has a fallback for: refused (no holder, or the bus refuses it), the controller raises
|
||||
// the secret-given condition exactly as before (ADR 0380 §9), so an older carried list still comes up and
|
||||
// works. Every other grant stays required — missing one of those is a controller that comes up and is
|
||||
// refused on the first thing it tries, with no fallback that covers it.
|
||||
var DegradableGrants = []DegradableGrant{
|
||||
{
|
||||
Subject: "mesh.seat." + VerbsTheControllerAsksTheOperatorChannel[0].Seat + ".tool." + VerbsTheControllerAsksTheOperatorChannel[0].Verb,
|
||||
Reason: "refused: the controller raises the secret-given condition as before (ADR 0380 §9)",
|
||||
},
|
||||
}
|
||||
|
||||
// perMachineEvents are a node-scoped seat's events about the holder itself, whose last token is the
|
||||
// holder's machine (novox/hq ADR 0219): `paused.<node>`, the build agent saying whether it takes work.
|
||||
var perMachineEvents = map[string]bool{"paused.*": true}
|
||||
|
||||
Reference in New Issue
Block a user