package frombus import ( "encoding/json" "fmt" "maps" "slices" "sort" "git.novox.be/novox/mesh-sdk/go/catalogue" "git.novox.be/novox/mesh-sdk/go/declaration" "git.novox.be/novox/mesh-sdk/go/delivery" "github.com/novox/mesh-host/internal/compose" "github.com/novox/mesh-host/internal/compose/resolution" ) // **What runs is kept while a manifest does not yet say what shared code no longer infers** (novox/hq ADR 0601 §4). mesh-sdk // knows the tool runner and the modules whose own secrets are the core's credentials only by what their manifests say // (`tool-runner`, `core-credentials`), no longer by their names. A module placed on the composing node whose manifest (an // older build's) does not say so yet, while what the node runs of it shows it (the tool runner's process, `.runtime`; // an own secret carried as the vault's box, the file's `vault-sealed`), is composed as what runs shows: its tool runner // process and its sealed secrets alike are kept, never composed away, and the node says so until the manifest says it. // Known by what runs, never by a module's name. // keepWhatRuns marks, in in, each module placed on node that what runs shows is the tool runner or carries the core's // credentials, where its manifest does not say so; it returns, sorted by module, what it marked, in words. The tool runner is // marked only where no placed module's manifest says it is one. func keepWhatRuns(in *compose.Input, node string, running []delivery.Composed) []KeptAsRuns { placed := assignedOn(*in, node) if len(placed) == 0 || len(running) == 0 { return nil } runner, sealed := "", map[string]bool{} for _, run := range running { for _, raw := range run.Resources { var r struct { ID string `json:"id"` Type string `json:"type"` } if json.Unmarshal(raw, &r) != nil || r.ID == "" { continue } owner := run.Module if owner == "" { owner, _ = declaration.ModuleGuess(r.ID) } if owner == "" || !slices.Contains(placed, owner) { continue } if r.Type == "process" && r.ID == owner+"."+resolution.RuntimeProcessID() { runner = owner } if r.Type == "file" { var fields map[string]json.RawMessage if json.Unmarshal(raw, &fields) == nil { if _, ok := fields[catalogue.VaultSealedField]; ok { sealed[owner] = true } } } } } var said []KeptAsRuns saysRunner := false for _, m := range placed { if man, ok := manifestOn(*in, node, m); ok && catalogue.IsToolRunner(man) { saysRunner = true } } mark := func(module string, set func(*catalogue.Manifest), words string) { k := KeptAsRuns{Module: module, Words: words} for i := range in.Nodes { if in.Nodes[i].Name != node { continue } if man, ok := in.Nodes[i].Kept[module]; ok { set(&man) in.Nodes[i].Kept[module] = man said = append(said, k) return } } if man, ok := in.Catalogue[module]; ok { set(&man) in.Catalogue[module] = man said = append(said, k) } } if runner != "" && !saysRunner { mark(runner, func(m *catalogue.Manifest) { m.ToolRunner = true }, fmt.Sprintf("%s runs the tool runner's process here and its "+ "manifest does not say it is the tool runner (tool-runner): it is composed as the tool runner it runs as, until its manifest says so", runner)) } for _, m := range slices.Sorted(maps.Keys(sealed)) { if man, ok := manifestOn(*in, node, m); ok && !catalogue.CarriesCoreCredentials(man) { mark(m, func(m *catalogue.Manifest) { m.CoreCredentials = true }, fmt.Sprintf("%s carries its own secrets sealed by the vault here "+ "and its manifest does not say they are the core's credentials (core-credentials): they stay sealed, until its manifest says so", m)) } } sort.SliceStable(said, func(i, j int) bool { return said[i].Module < said[j].Module }) return said } // KeptAsRuns is one module composed as what runs shows, and why, in words (ADR 0601 §4): its have carries the words. type KeptAsRuns struct { Module, Words string }