Review: module issue's pre-check factored and tested; a pair delivery for a requirement the module keeps no secret for is refused; builder issue's usage says the module comes first

This commit is contained in:
2026-09-21 23:58:36 +02:00
parent 66332705cd
commit 0d1f2a4152
5 changed files with 61 additions and 10 deletions
+2 -1
View File
@@ -168,7 +168,8 @@ func usage() {
build <repository> [--ref R] have a build machine build it, and record what came out
build --behind build every module the mesh holds older than its source
builds [<module>] what has been built lately, and what came of it
builder issue <name> a broker account for a build machine, scoped to build work
builder issue <name> a broker account for a build machine, scoped to build work,
delivered as the builder module's broker secret (module add it first)
licence add|list|use|key model access, under the name a person calls it
licence manager <name> <node> the node that holds a refreshable licence's refresh token
licence refresh <name> mint a new access token and seal it to every holder
+14 -6
View File
@@ -253,12 +253,8 @@ func moduleCommand(ctx context.Context, args []string) error {
if !ok {
return fmt.Errorf("this mesh knows no module %q; `module add` it first", module)
}
// The account is delivered as the module's own secret named broker; a module that declares
// none has nothing to read it with, and an account nothing reads is an orphan on the bus
// (novox/hq 04-ISSUES/078). Said before the account is made, not after.
if _, reads := m.OwnSecrets["broker"]; !reads {
return fmt.Errorf("%s declares no own secret named broker, so there is nowhere to deliver "+
"an account; a module that speaks on the bus declares \"own-secrets\": {\"broker\": <path>}", module)
if err := mayIssue(m); err != nil {
return err
}
management, err := broker.ManagementFromEnvironment()
@@ -559,3 +555,15 @@ func brokerReachableAt(ctx context.Context, inv *inventory.Inventory, known brok
}
return net.JoinHostPort(brokerAt, port), nil
}
// mayIssue says whether a module can be given a broker account. The account is delivered as the
// module's own secret named broker; a module that declares none has nothing to read it with, and
// an account nothing reads is an orphan on the bus (novox/hq 04-ISSUES/078). Said before the
// account is made, not after.
func mayIssue(m catalogue.Manifest) error {
if _, reads := m.OwnSecrets["broker"]; !reads {
return fmt.Errorf("%s declares no own secret named broker, so there is nowhere to deliver "+
"an account; a module that speaks on the bus declares \"own-secrets\": {\"broker\": <path>}", m.Module)
}
return nil
}
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"strings"
"testing"
"github.com/novox/mesh-controller/internal/catalogue"
)
// `module issue` makes a broker account and delivers it as the module's own secret named broker.
// A module that declares none is refused before the account exists, so the bus never carries an
// account nothing reads (novox/hq 04-ISSUES/078).
func TestAModuleWithNoBrokerSecretCannotBeIssued(t *testing.T) {
err := mayIssue(catalogue.Manifest{Module: "step-ca", OwnSecrets: map[string]string{"password": "/run/password"}})
if err == nil {
t.Fatal("a module with no broker own secret was issued an account")
}
for _, want := range []string{"step-ca", "broker", "own-secrets"} {
if !strings.Contains(err.Error(), want) {
t.Errorf("the refusal does not say %q: %v", want, err)
}
}
if err := mayIssue(catalogue.Manifest{Module: "redis", OwnSecrets: map[string]string{"broker": "/run/broker"}}); err != nil {
t.Errorf("a module declaring its broker secret was refused: %v", err)
}
}