Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions module/services/accounts/code/fixtures/installations.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,13 @@ func (i *Installations) Converge(ctx context.Context) error {
w.Info("fixture installation installed", wool.Field("installation", row.declared.describe()), wool.Field("installation_id", installation.GetId()))
}
// The authority core holds the same installation, which the host
// interfaces decide with (coreInstall).
if err := i.coreInstall(ctx, row); err != nil {
// interfaces decide with (coreInstall). A target the core has not
// composed yet keeps the row for the next pass.
coreWaits := false
switch err := i.coreInstall(ctx, row); {
case errors.Is(err, errCoreTargetNotComposed):
coreWaits = true
case err != nil:
failures = append(failures, fmt.Errorf("fixture installation %s: %w", row.declared.describe(), err))
}
// Each declared team is exposed once the installation admits it (an
Expand All @@ -164,7 +169,7 @@ func (i *Installations) Converge(ctx context.Context) error {
unexposed = append(unexposed, teamID)
}
}
if row.teamIDs = unexposed; len(row.teamIDs) > 0 {
if row.teamIDs = unexposed; len(row.teamIDs) > 0 || coreWaits {
remaining = append(remaining, row)
}
}
Expand All @@ -173,6 +178,10 @@ func (i *Installations) Converge(ctx context.Context) error {
return errors.Join(failures...)
}

// errCoreTargetNotComposed is a declared installation whose target the
// authority core has not composed yet; the next pass installs it there.
var errCoreTargetNotComposed = errors.New("the authority core has not composed this target yet")

// coreInstall performs the declared installation in the authority core as the
// host's own setup (InstallAsHost), then grants the installer role to its
// owner and its role to each declared team (GrantRoleAsHost), as the local
Expand All @@ -187,8 +196,17 @@ func (i *Installations) coreInstall(ctx context.Context, row pendingInstallation
return err
}
// A module's installation is accounts' own record, which Converge's install
// made; the core reads it and installs no module itself.
if m, err := core.Composed(ctx, row.declared.Target); err == nil && m.Kind != domain.KindSolution {
// made; the core reads it and installs no module itself. A target the core
// has not composed yet is waited on: the pass that applies its delivery
// composes it.
m, err := core.Composed(ctx, row.declared.Target)
if code, ok := domain.CodeOf(err); ok && code == domain.NotFound {
return fmt.Errorf("%w: %s", errCoreTargetNotComposed, row.declared.Target)
}
if err != nil {
return fmt.Errorf("the authority core: %w", err)
}
if m.Kind != domain.KindSolution {
return nil
}
inst, err := core.InstallAsHost(ctx, row.orgID, row.declared.Target, row.declared.Role, row.ownerID, i.service.AuthorityInstallStep())
Expand Down Expand Up @@ -224,7 +242,7 @@ func (i *Installations) ConvergeAuthority(ctx context.Context) error {
var failures []error
for _, row := range i.pending {
err := i.coreInstall(ctx, row)
if code, ok := domain.CodeOf(err); ok && code == domain.NotFound {
if code, ok := domain.CodeOf(err); errors.Is(err, errCoreTargetNotComposed) || ok && code == domain.NotFound {
continue
}
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,39 @@ func runHostInterfaceFixture(t *testing.T) {
require.Greater(t, count, 0, "the suite's revocations are audited")
})

// A solution the composition delivers once the host is running is composed
// in the authority core by the pass that applies it, before the fixture's
// installations converge in that same pass: the declared installation is
// then the core's too, active at the declaring organization alone, and the
// declared team holds its role there.
t.Run("a solution delivered to a running host is installed where the fixture declares it", func(t *testing.T) {
reconciler.AfterEachPass(installations.Converge)
t.Cleanup(func() { reconciler.AfterEachPass(nil) })
note := wireScope("conformance-late.note", "read")
deliverSolution(t, ctx, conn, signer, conformanceSolution{alias: "conformance-late", generation: 1, ceilings: []*authorityv1.WorkScopeV1{note},
roles: map[string][]*authorityv1.WorkScopeV1{"installer": {note}, "viewer": {note}}})
installed := func(caller authority.Person, org string) (domain.Installation, bool) {
t.Helper()
all, err := core.Installations(ctx, caller, org)
require.NoError(t, err)
for _, inst := range all {
if inst.Target == "conformance-late" {
return inst, true
}
}
return domain.Installation{}, false
}
inst, ok := installed(alex, fixtureOrganization)
require.True(t, ok, "the pass that applied the delivery installed it in the core")
require.Equal(t, domain.Active, inst.Status)
_, ok = installed(authority.Person{ID: conformanceZoe, Organization: globexOrganization, SessionID: "conformance-harness"}, globexOrganization)
require.False(t, ok, "and nowhere the fixture does not declare it")
grants, err := core.ListRoleGrants(ctx, alex, fixtureOrganization, inst.ID)
require.NoError(t, err)
finance := teamNamed(t, ctx, svc, fixtureOrganization, "Finance")
require.Contains(t, grants, domain.RoleGrant{InstallationID: inst.ID, Role: "viewer", TeamID: finance}, "the declared team holds its role")
})

// Last, because the envelope it writes becomes every module's ceiling: a
// real envelope write that narrows a module's binding (the write
// PutModuleEnvelope makes, without its platform administrator check) is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,6 @@ installations:
- {org: Acme Corp, target: conformance-proposals, role: viewer, owner: alex@acme.test, teams: [Finance]}
# The assistant solution acts for itself down a chain of modules.
- {org: Acme Corp, target: conformance-assistant, role: viewer, owner: alex@acme.test}
# Delivered only once the host is running, as a composition delivers a
# solution after boot: installed at Acme alone, and reached by its finance team.
- {org: Acme Corp, target: conformance-late, role: viewer, owner: alex@acme.test, teams: [Finance]}
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ func coreDeliveryError(err error) error {
// reconcileAuthorityCore composes, in the core, every delivery accounts has
// applied: what a host runs once its core is built, so a module delivered
// before this host decided through the core, or while its core could not be
// built, is composed there too. Each is read from the inbox's exact applied
// generation, the signed documents accounts verified when it took them.
// built, is composed there too.
func (s *Service) reconcileAuthorityCore(ctx context.Context) error {
if s.deliveryStore == nil {
return nil
Expand All @@ -150,29 +149,57 @@ func (s *Service) reconcileAuthorityCore(ctx context.Context) error {
}
var failures []error
for _, record := range records {
manifest, err := record.AppliedManifest()
if err != nil || manifest == nil {
continue
}
var delivered *SolutionDeliveryRecord
if err := s.store.WithControlPlane(ctx, func(ctx context.Context) error {
var err error
delivered, err = s.deliveryStore.ReadDeliveredDocument(ctx, record.BindingID, record.Applied.Generation)
return err
}); err != nil {
failures = append(failures, fmt.Errorf("binding %s: %w", record.BindingID, err))
continue
}
if delivered == nil {
continue
}
var signed *compositionv1.SignedManifestV1
if len(delivered.AuthorityDocument) > 0 {
signed = &compositionv1.SignedManifestV1{Document: delivered.AuthorityDocument, Envelope: delivered.AuthorityEnvelope}
}
if _, err := s.applyCoreModule(ctx, manifest, delivered.Payload, signed); err != nil {
if err := s.composeAppliedDelivery(ctx, record); err != nil {
failures = append(failures, fmt.Errorf("binding %s: %w", record.BindingID, err))
}
}
return errors.Join(failures...)
}

// composeAppliedDelivery composes one binding's applied generation in the
// core, read from the inbox's exact applied generation: the signed documents
// accounts verified when it took them. Every delivery path reaches the core
// this way, the composition interface's and the host's delivery endpoint
// alike, so a solution delivered to a running host is one the core can
// install. A generation the core already holds changes nothing.
func (s *Service) composeAppliedDelivery(ctx context.Context, record *SolutionHostBindingRecord) error {
if s.deliveryStore == nil || record == nil {
return nil
}
manifest, err := record.AppliedManifest()
if err != nil || manifest == nil {
return nil
}
var delivered *SolutionDeliveryRecord
if err := s.store.WithControlPlane(ctx, func(ctx context.Context) error {
var err error
delivered, err = s.deliveryStore.ReadDeliveredDocument(ctx, record.BindingID, record.Applied.Generation)
return err
}); err != nil {
return err
}
if delivered == nil {
return nil
}
var signed *compositionv1.SignedManifestV1
if len(delivered.AuthorityDocument) > 0 {
signed = &compositionv1.SignedManifestV1{Document: delivered.AuthorityDocument, Envelope: delivered.AuthorityEnvelope}
}
_, err = s.applyCoreModule(ctx, manifest, delivered.Payload, signed)
return err
}

// composeAppliedBinding composes binding's applied generation in the core,
// right after a pass applied it.
func (s *Service) composeAppliedBinding(ctx context.Context, binding string) error {
records, err := s.ListSolutionHostBindings(ctx)
if err != nil {
return err
}
for _, record := range records {
if record.BindingID == binding {
return s.composeAppliedDelivery(ctx, record)
}
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,14 @@ func (r *SolutionHostBindingReconciler) RunOnce(ctx context.Context) error {
}
failures = append(failures, fmt.Errorf("apply binding %q generation %d: %w",
applied.Document.Binding, applied.Document.Generation, err))
continue
}
// The applied generation is composed in the authority core at once,
// whichever path delivered it: a solution the host's delivery endpoint
// took is then one the core installs and the host interfaces decide.
if err := r.service.composeAppliedBinding(ctx, applied.Document.Binding); err != nil {
failures = append(failures, fmt.Errorf("compose binding %q generation %d in the authority core: %w",
applied.Document.Binding, applied.Document.Generation, err))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pkg/auth/pg/session_store.go: (*SessionStore).RotateRefresh: WithControlPlane
pkg/business/audit.go: (*DurableAuditEmitter).Emit: WithControlPlane
pkg/business/audit.go: (*Service).AggregateAuditLog: WithControlPlane
pkg/business/audit.go: (*Service).QueryAuditLog: WithControlPlane
pkg/business/authority_core_delivery.go: (*Service).reconcileAuthorityCore: WithControlPlane
pkg/business/authority_core_delivery.go: (*Service).composeAppliedDelivery: WithControlPlane
pkg/business/authority_delivery.go: (*Service).verifyAppliedAuthorityDocument: WithControlPlane
pkg/business/connector_credentials.go: (*Service).SourceSigningSecret: WithControlPlane
pkg/business/current_installation.go: (*Service).ModuleCurrentInstallation: WithControlPlane
Expand Down
Loading