Grant the builder the build seats' streams' information and messages by name, so its take-over at start can tell an ask its key names is on its stream (issue 1910)
mesh/delivery-group group feat/r4g rejected: a member's own check failed
mesh/delivery superseded: a newer head of the same pull request
mesh/check failed: g14: novox/mesh-catalog#464: checks/health/go.mod names mesh-sdk a9560890ee26, which is neither on mesh-sdk's trunk nor the group's…

This commit is contained in:
2026-10-23 16:59:03 +02:00
parent 4238318601
commit 13842a7234
3 changed files with 39 additions and 0 deletions
+15
View File
@@ -9,8 +9,23 @@ import "git.novox.be/novox/mesh-sdk/go/delivery"
const (
// ViewModule is the module of the delivery view (mesh-delivery-view).
ViewModule = "mesh-delivery-view"
// BuilderModule is the module of the builder (mesh-delivery-builder).
BuilderModule = "mesh-delivery-builder"
)
// BuildAskReads are the API subjects the builder requests when it takes over, at its start, a key naming an ask (issue
// 1910): each build seat's stream's information and its messages by sequence, to tell whether the ask is on its stream.
// Reads only: no consumer, no pull, no acknowledgement; the builder puts its asks by its seat use, as before.
func BuildAskReads() []string {
var out []string
for _, lang := range delivery.AskLanguages {
if stream, err := delivery.AskStream(lang); err == nil {
out = append(out, "$JS.API.STREAM.INFO."+stream, "$JS.API.STREAM.MSG.GET."+stream)
}
}
return out
}
// BuildBacklogReads are the API subjects the view requests: the information of each build seat's stream and of each of its
// shared workers (delivery.AskStream, delivery.AskWorker), and the message of the stream by sequence. Reads only: no
// message is pulled, none acknowledged, none published.
+19
View File
@@ -67,3 +67,22 @@ func TestTheViewReadsTheBuildSeatsWorkersByNameAndPublishesNoAsk(t *testing.T) {
t.Errorf("another module reads the build seats: %v", other)
}
}
// 1910: the builder may read each build seat's stream's information and its messages by sequence, by name, and may not
// pull, acknowledge or make a consumer there, nor list every stream.
func TestTheBuilderReadsTheBuildSeatsStreamsByName(t *testing.T) {
pub, _ := composedFor(t, BuilderModule)
for _, s := range []string{"$JS.API.STREAM.INFO.SEAT_NODE_BUILD_GO", "$JS.API.STREAM.MSG.GET.SEAT_NODE_BUILD_GO",
"$JS.API.STREAM.INFO.SEAT_NODE_BUILD_NODE", "$JS.API.STREAM.MSG.GET.SEAT_NODE_BUILD_IMAGE"} {
if !hasSubject(pub, s) {
t.Errorf("the builder cannot request %s", s)
}
}
perms, _ := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: BuilderModule})
for _, s := range []string{"$JS.API.STREAM.NAMES", "$JS.API.STREAM.INFO.SEAT_OPERATOR_CHANNEL",
"$JS.API.CONSUMER.MSG.NEXT.SEAT_NODE_BUILD_GO.SEAT_NODE_BUILD_GO_CHECK_worker", "$JS.API.CONSUMER.CREATE.SEAT_NODE_BUILD_GO"} {
if MayPublish(perms, s) {
t.Errorf("the builder may publish %s", s)
}
}
}
+5
View File
@@ -860,6 +860,11 @@ func PermissionsFor(p Principal) (Permissions, error) {
if p.Module == ViewModule {
pub = append(pub, BuildBacklogReads()...)
}
// The builder alone reads the build seats' streams by sequence, to put again at its start an ask a key names that no
// stream holds (issue 1910).
if p.Module == BuilderModule {
pub = append(pub, BuildAskReads()...)
}
// 1. Its own namespace: it publishes its events there and serves its tools there. Nothing
// else may publish into it, so an event's source is a fact the server enforces rather
// than a claim in the body (design 29 §2).