From 5bd03b3984ef3f62043ce6f35110e78bab7c80e6 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 1 Nov 2026 04:14:44 +0100 Subject: [PATCH] Refuse a send that would seal a placeholder for a bus credential nobody issued (issue 203) mesh-sdk #141 (issue 774) stands an unissued bus account in, in the Foreseeing mode, so a proposal's answer can be asked before the vault mints it; the controller's send then took the stand-in for an own secret to make and would seal a random value where the broker credential belongs. The send and the question refuse it now, in the words the composition used to: module issue, then push. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL --- cmd/mesh-controller/compose_perform.go | 4 +-- cmd/mesh-controller/compose_sdk.go | 36 ++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/cmd/mesh-controller/compose_perform.go b/cmd/mesh-controller/compose_perform.go index 6e05f2bd..dd4ae33e 100644 --- a/cmd/mesh-controller/compose_perform.go +++ b/cmd/mesh-controller/compose_perform.go @@ -86,8 +86,8 @@ func perform(ctx context.Context, open *stores, in *meshInput, node string, d co } } - // The node's own secrets: a module's superuser password, an administrator, an account. The composition refused what the - // send refuses (a bus credential nobody issued, a given value under an old key). + // The node's own secrets: a module's superuser password, an administrator, an account. A bus credential nobody issued is + // refused before this (unissuedBusCredential), a given value under an old key by the composition. for _, one := range d.StoodIn { module, name, ok := strings.Cut(one, "/") if !ok || strings.Contains(one, " ") { diff --git a/cmd/mesh-controller/compose_sdk.go b/cmd/mesh-controller/compose_sdk.go index ff8b2506..a44c4421 100644 --- a/cmd/mesh-controller/compose_sdk.go +++ b/cmd/mesh-controller/compose_sdk.go @@ -184,6 +184,9 @@ func composeQuestion(ctx context.Context, open *stores, node string, mode compos if err := refusedBus(in, node); err != nil { return sendable{}, nil, err } + if err := unissuedBusCredential(in, node, d); err != nil { + return sendable{}, nil, err + } sayFound(ctx, d) out := sendableOf(d) out.fileReferences = readsFileReferences(in.Input, node) @@ -212,6 +215,35 @@ func refusedBus(in *meshInput, node string) error { return nil } +// unissuedBusCredential refuses a composition that stands in for a bus credential nobody issued: the module's `broker` own +// secret (its account `.`) or the provisioner client's (`provisioner.`). A bus credential is minted by +// `module issue`, never invented: a send that made one would seal a placeholder its process cannot read (novox/hq issue +// 203). mesh-sdk's composition stands one in, in the Foreseeing mode, since a node's answer to a proposal is asked before +// the vault mints it (mesh-sdk #141, issue 774), so the send refuses it here, in the words the composition used to. +func unissuedBusCredential(in *meshInput, node string, d compose.Declared) error { + for _, one := range d.StoodIn { + module, name, ok := strings.Cut(one, "/") + if !ok || strings.Contains(one, " ") { + continue + } + var user string + switch name { + case "broker": + user = node + "." + module + case compose.ProvisionerSecret: + user = "provisioner." + node + default: + continue + } + if !slices.Contains(in.Input.BusMinted, user) { + return fmt.Errorf("%s on %s has no bus credential: nothing was issued for %s, and a push would seal a "+ + "placeholder its process cannot read (novox/hq issue 203). `module issue %s --node %s`, then push again", + module, node, user, module, node) + } + } + return nil +} + // markUnresolvable is an error of a node whose own set does not compose, as planFor marked it. func markUnresolvable(err error) error { if compose.IsUnresolvable(err) { @@ -256,6 +288,10 @@ func composeSendValidated(ctx context.Context, open *stores, node string) (senda if err := refusedBus(in, node); err != nil { return sendable{}, nil, err } + // Before perform makes what the composition stands in for: a bus credential is never one of them. + if err := unissuedBusCredential(in, node, d); err != nil { + return sendable{}, nil, err + } if len(byController) > 0 { if d, problems, err = sealedByTheController(in, node, d, byController); err != nil { return sendable{}, nil, err