From 5e276bf32424e13dbf2f4a0725b89eb76867364e Mon Sep 17 00:00:00 2001 From: antoinetoussaint-byte <312536060+antoinetoussaint-byte@users.noreply.github.com> Date: Fri, 30 Oct 2026 11:09:28 -0400 Subject: [PATCH] fix(core): a module page's offer review finds the installation a host named itself ReviewOffer looked a target's installation up by the stable id the core mints. A host that installs modules (Config.HostInstallsModules) names a module installation itself, so a module page's review there answered no installation, and the Setup UI had no installation to grant roles on. Such a host's installation is now found by its target, as held() finds it. Co-Authored-By: Claude Fable 5.1 --- .../authority-core/go/authority/consent.go | 5 +++++ .../go/authority/host_installs_modules_test.go | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/libraries/authority-core/go/authority/consent.go b/libraries/authority-core/go/authority/consent.go index 4620e43..028c314 100644 --- a/libraries/authority-core/go/authority/consent.go +++ b/libraries/authority-core/go/authority/consent.go @@ -84,6 +84,11 @@ func (s *Service) reviewOffer(ctx context.Context, caller Person, org, target st return refused } inst, err := tx.Installation(s.cfg.InstallationID(org, target)) + if errors.Is(err, domain.ErrNotFound) && s.cfg.HostInstallsModules { + // A host that installs modules names a module page's + // installation itself, so it is found by its target. + inst, err = installationOf(tx, org, target) + } if errors.Is(err, domain.ErrNotFound) { inst, err = domain.Installation{}, nil } diff --git a/libraries/authority-core/go/authority/host_installs_modules_test.go b/libraries/authority-core/go/authority/host_installs_modules_test.go index 49b814b..f57e8e9 100644 --- a/libraries/authority-core/go/authority/host_installs_modules_test.go +++ b/libraries/authority-core/go/authority/host_installs_modules_test.go @@ -301,3 +301,21 @@ func sameActions(got, want []string) bool { } return true } + +// A module page's installation a host names itself is the one its offer +// review reads, as the role holder's capability does. +func TestAHostNamedModulePageInstallationIsReviewed(t *testing.T) { + h := newHostInstalled(t) + if _, err := h.svc.ApplyModule(h.ctx, pageModule(1, true)); err != nil { + t.Fatal(err) + } + if err := h.store.Write(h.ctx, func(tx authority.Tx) error { + return tx.PutInstallation(domain.Installation{ID: "host-pages", Organization: acme, Target: "pages", Status: domain.Active, Revision: 1}) + }); err != nil { + t.Fatal(err) + } + offer, err := h.svc.ReviewOffer(h.ctx, authority.Person{ID: "alex", Organization: acme, SessionID: "s"}, acme, "pages") + if err != nil || offer.Installation.ID != "host-pages" || len(offer.Module.Roles) != 2 { + t.Fatalf("the administrator reviews %+v, %v; want the host's installation host-pages", offer.Installation, err) + } +}