Keep what an adopted node was found holding until its module is taken, and report it held (hq ADR 0100)

This commit is contained in:
2026-09-22 17:14:04 +02:00
parent fcc447c216
commit 3a613113be
5 changed files with 714 additions and 3 deletions
+83
View File
@@ -77,6 +77,89 @@ type State struct {
// undoing in reverse is the only ordering the host can derive without deciding anything.
Resources []Applied `json:"resources"`
UpdatedAt time.Time `json:"updated_at"`
// Held is what this host found on the machine and is keeping as it is, until the module
// declaring it is taken (novox/hq ADR 0100). Never a Resource: nothing here was applied, so
// nothing here is ever removed as an orphan — what is held is not the host's to remove, even
// when its module is unassigned.
Held []Held `json:"held,omitempty"`
}
// Held is one file or container found on an adopted node — present at a declared path or name,
// with no record of this host having made it — and kept as it was found.
type Held struct {
ID string `json:"id"`
Module string `json:"module"`
Kind string `json:"kind"`
Target string `json:"target"`
// Since is when it was first found. It stays held from then until its module is taken, even
// if it disappears: a vanished file is reported, not recreated.
Since time.Time `json:"since"`
// A file's content as found, by digest; its mode and owner; and where the original was kept
// before anything else could happen to it.
Digest string `json:"digest,omitempty"`
Mode string `json:"mode,omitempty"`
Owner string `json:"owner,omitempty"`
Kept string `json:"kept,omitempty"`
// A container's id as found, and whether it was running.
Container string `json:"container,omitempty"`
Running bool `json:"running,omitempty"`
// Changed is what something other than the mesh has done to it since it was found —
// rewritten, stopped, replaced or gone — and empty while it is as found. Reported, never
// reverted: that is how a predecessor still writing is caught.
Changed string `json:"changed,omitempty"`
ChangedAt time.Time `json:"changed_at,omitempty"`
}
// Recorded reports whether this host has a record, of any origin, of putting something of this
// kind at this target. What it has a record of is not found: it wrote it, in this life of the node
// or an earlier one — including a foundation raised from the bundle and adopted as modules later
// (novox/hq ADR 0078).
func (s State) Recorded(kind, target string) bool {
for _, r := range s.Resources {
if r.Type == kind && r.Target == target {
return true
}
}
return false
}
// HeldAt returns what is held under a resource id.
func (s State) HeldAt(id string) (Held, bool) {
for _, h := range s.Held {
if h.ID == id {
return h, true
}
}
return Held{}, false
}
// RecordHeld adds or replaces what is held under one id, preserving order.
func (s *State) RecordHeld(h Held) {
for i, existing := range s.Held {
if existing.ID == h.ID {
s.Held[i] = h
return
}
}
s.Held = append(s.Held, h)
}
// Release drops a hold, once its module is taken and the host has converged what was held.
func (s *State) Release(id string) {
kept := s.Held[:0]
for _, h := range s.Held {
if h.ID != id {
kept = append(kept, h)
}
}
s.Held = kept
if len(s.Held) == 0 {
s.Held = nil
}
}
// Find returns what was applied under an identity.