package broker import "testing" // The build agent's credential is the module principal `.build-agent` (Username, KindModule): its manifest's // `reads: ["mesh-delivery.pulls"]` reaches that principal as a read and a watch of mesh-delivery's bucket of pull requests' // keys — the direct get of a key, the consumer a watch makes, the stream's info — and as no write and no direct // subscription of the bucket's subjects (novox/hq ADR 0406 §4, issue 974). func TestTheBuildAgentReadsAndWatchesThePullRequestsKeys(t *testing.T) { seat := Seat{Name: TheBuildSeat, Scope: "node", Accepts: []string{"build"}, Emits: []string{"built", "started"}} p := Principal{Kind: KindModule, Node: "one", Module: "build-agent", Holds: []Seat{seat}, Reads: []string{"mesh-delivery.pulls"}, PasswordHash: "x"} if got := p.Username(); got != "one.build-agent" { t.Fatalf("the build agent's credential is %q", got) } perms, err := PermissionsFor(p) if err != nil { t.Fatal(err) } for _, s := range []string{ "$JS.API.STREAM.INFO.KV_mesh-delivery_pulls", "$JS.API.DIRECT.GET.KV_mesh-delivery_pulls.>", "$JS.API.CONSUMER.CREATE.KV_mesh-delivery_pulls.>", "$JS.API.CONSUMER.DELETE.KV_mesh-delivery_pulls.>", // And the two check workers it takes from. "$JS.API.CONSUMER.MSG.NEXT.CHECKS_READY.CHECKS_READY_worker", "$JS.API.CONSUMER.MSG.NEXT.CHECKS_OTHER.CHECKS_OTHER_worker", "$JS.ACK.CHECKS_OTHER.CHECKS_OTHER_worker.>", // And the bucket of the checks running, which it writes and reads (ADR 0406 §3). "$KV." + CheckRunningBucket + ".>", "$JS.API.DIRECT.GET.KV_" + CheckRunningBucket + ".>", } { has(t, perms.Publish, s) } hasNot(t, perms.Publish, "$KV."+PullsBucket+".>") hasNot(t, perms.Publish, "mesh.seat.node-build-agent.check.>") for _, s := range perms.Subscribe { if s == "$KV."+PullsBucket+".>" { t.Fatalf("the build agent subscribes the bucket's subjects directly: %v", perms.Subscribe) } } } // Issue 1687 (ADR 0483 clause 2): a holder of the build seat reads the bucket of the plans building and writes none of it, and // reads the oldest waiting ask of each check queue by a direct get, which takes nothing from the queue. func TestTheBuildSeatsHoldersReadThePlansBuildingAndWriteNone(t *testing.T) { seat := Seat{Name: TheBuildSeat, Scope: "node", Accepts: []string{"build"}, Emits: []string{"built", "started"}} p := Principal{Kind: KindModule, Node: "one", Module: "build-agent", Holds: []Seat{seat}, PasswordHash: "x"} perms, err := PermissionsFor(p) if err != nil { t.Fatal(err) } stream := "KV_" + PlansBuildingBucket for _, s := range []string{ "$JS.API.STREAM.INFO." + stream, "$JS.API.DIRECT.GET." + stream + ".>", "$JS.API.CONSUMER.CREATE." + stream + ".>", "$JS.API.DIRECT.GET.CHECKS_READY", "$JS.API.DIRECT.GET.CHECKS_OTHER", } { has(t, perms.Publish, s) } for _, s := range perms.Publish { if SubjectsOverlap(s, "$KV."+PlansBuildingBucket+".plan-1") { t.Errorf("a holder of the build seat may write %s through %q", PlansBuildingBucket, s) } } // And the controller alone writes it, as the writers table says. for _, row := range WritersTable { for _, s := range row.Subjects { if s == "$KV."+PlansBuildingBucket+".>" && row.Writes(p, "$KV."+PlansBuildingBucket+".plan-1") { t.Errorf("%q lets the build seat's holder write the plans building", row.State) } } } }