Keep serving the consumers postgres's grant file gives on its moved path (issue 937)
mesh/merge-gate head 41cdd032084e merged into trunk 6268f8f94bda — pass: builds keycloak, postgres, sent nowhere; no bus step; 3 wait(s) for a person; ever…
mesh/repo-check head 41cdd032084e merged into trunk 6268f8f94bda — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered

Only a moved consumer's plan names postgres, so on the moved path every
consumer still given by the controller's grant file was counted unasked
and offered for retirement (ace 5 of 5, novox 7 of 9), and could have
been retired unasked where the bound allowed. The moved path now reads
MESH_RECEIVES again: its logins are asked, the ones no plan names are
made and checked by the harness's grant pass until R1 (issue 682), and
an unreadable grant file retires nothing (issue 241). The harness's
grant pass becomes apply, identically in keycloak's copy.
This commit is contained in:
2026-10-16 16:25:52 +00:00
parent 08188663fa
commit 41cdd03208
5 changed files with 216 additions and 39 deletions
@@ -8,6 +8,12 @@ package main
// here: Make brings the consumer's database and role into being exactly as the harness's adapter does, and Gone
// retires what was kept for a consumer that no longer binds, the reversible way (retire_pg.go): the login is
// locked and marked to delete, nothing is dropped.
//
// **A consumer not moved is still the grant file's** (issue 937, ADR 0349 clause 17): only a moved consumer's plan
// names its provider, so the controller still gives every other consumer through postgres's grant file
// (MESH_RECEIVES) until R1 (issue 682). Each login it gives is asked for, and one no plan names is made and checked
// by the harness's grant pass exactly as on the grant path; a login a plan names is the helper's alone. A grant file
// that cannot be read is not nobody asking (issue 241): nothing is retired until it is read again.
import (
"context"
@@ -102,11 +108,14 @@ func (m *movedRun) Gone(_ context.Context, e provider.Entry) error {
if as == "" {
return nil // refused: nothing was made for it
}
// The plans as they are now, not as the last retirement pass read them: with none read, nothing is let go.
// The plans and the grant file as they are now, not as the last retirement pass read them: with either not
// read, nothing is let go.
want, read := m.asked(h.Node)
asked := want[as]
h.mu.Lock()
defer h.mu.Unlock()
_, granted, ok := m.granted(want)
read = read && ok
asked := want[as] || granted[as]
_, held := h.applied[as]
_, retired := h.r.retired[as]
switch {
@@ -165,18 +174,50 @@ func (m *movedRun) asked(node string) (map[string]bool, bool) {
return want, true
}
// retire is one pass of the harness's retirement over what the plans bind now.
// granted is what the grant file gives that no plan names (issue 937), and every login it gives; and whether it
// could be read. The caller holds h.mu. With no grant file named there is nothing given, and that is a read.
func (m *movedRun) granted(planned map[string]bool) ([]contribution, map[string]bool, bool) {
h := m.h
if h.Receives == "" {
return nil, map[string]bool{}, true
}
given := h.readContributions()
if given == nil {
return nil, nil, false
}
var own []contribution
logins := map[string]bool{}
for _, g := range given {
logins[g.As] = true
if !planned[g.As] {
own = append(own, g)
}
}
return own, logins, true
}
// retire is one pass of the harness's retirement over what the plans bind and the grant file gives now; the logins
// only the grant file gives are made and checked first, as the grant path does.
func (m *movedRun) retire(ctx context.Context) {
h := m.h
want, ok := m.asked(h.Node)
h.mu.Lock()
defer h.mu.Unlock()
var given []contribution
if ok {
var granted map[string]bool
given, granted, ok = m.granted(want)
for as := range granted {
want[as] = true
}
}
if !ok {
// Not a result: the passes that must agree before anything is retired start again.
h.r.key, h.r.count = "", 0
return
}
h.seed(ctx, want)
h.apply(ctx, given)
h.retireUnasked(ctx, want)
h.r.lastWant = want
for as := range h.failing {