Read stored manifests leniently and mark the defaults layer (hq ADR 0262 review)

A strict read of the stored catalogue fails every plan and send once a manifest uses a field an older
controller lacks; registration stays strict. A node named default lost its layer to the name check.
Judge the operator's keys by whole words, and scan a default under any key.
This commit is contained in:
jochen
2026-10-08 17:24:32 +02:00
parent e41b78cd77
commit 76babaea52
9 changed files with 208 additions and 23 deletions
+22
View File
@@ -5,15 +5,35 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/jackc/pgx/v5"
"github.com/novox/mesh-controller/internal/catalogue"
)
// noted is each stored manifest's unknown key already said, so a catalogue read on every plan says it once.
var noted sync.Map
// noteUnknown says, once per module and key, that a stored manifest has a key this controller does not
// know and that it was read without it (novox/hq ADR 0262). A manifest registered under a newer
// controller is read by an older one after a rollback; refusing it here failed the whole catalogue.
func noteUnknown(m catalogue.Manifest) {
u := m.UnknownField()
if u == "" {
return
}
if _, said := noted.LoadOrStore(m.Module+"\x00"+u, true); said {
return
}
log.Printf("the stored manifest of %s has a key this controller does not know (%s); read without it — "+
"a newer controller registered it (novox/hq ADR 0262)", m.Module, u)
}
// ErrNoSuchModule is what the mesh says about a module it has never been told about.
var ErrNoSuchModule = errors.New("no module of that name")
@@ -259,6 +279,7 @@ func (i *Inventory) Catalogue(ctx context.Context) (map[string]catalogue.Manifes
if err := json.Unmarshal(raw, &m); err != nil {
return nil, err
}
noteUnknown(m)
out[m.Module] = m
}
return out, rows.Err()
@@ -1217,6 +1238,7 @@ func (i *Inventory) Catalogued(ctx context.Context) ([]Entry, error) {
if err := json.Unmarshal(raw, &m); err != nil {
return nil, err
}
noteUnknown(m)
entry := Entry{Manifest: m, Source: source, On: on}
if source.Repository == providedBy {
// It came with the control plane. Not a repository, and showing it as one would have