91 lines
3.4 KiB
Go
91 lines
3.4 KiB
Go
package grants
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/buscompose"
|
|
)
|
|
|
|
// The hearings the part withholds (novox/hq ADR 0376 §2; issue 1955 L7, the lead 2026-10-29): a module granted to hear a
|
|
// restricted stream that runs in its machine's tool runner (no runs-as) hears none of it, since nothing is composed for
|
|
// the account every session there shares. The part writes each such hearing to its state `withheld`, on change only, so the
|
|
// self-check's probe D-heard reads it from the bus in place of the controller's store.
|
|
//
|
|
// Layout (mesh-sdk buscompose): key `<module>.<stream, lower case>.<machine>` (the controller's condition id of it); value
|
|
// buscompose.WithheldHearing; readers name buscompose.GrantsWithheldRead.
|
|
const StateWithheld = buscompose.GrantsWithheldState
|
|
|
|
// WithheldHearing is one withheld hearing, as mesh-sdk lays it (buscompose.WithheldHearing).
|
|
type WithheldHearing = buscompose.WithheldHearing
|
|
|
|
// WithheldKey is a withheld hearing's key in StateWithheld (buscompose.WithheldKey).
|
|
func WithheldKey(w buscompose.Withheld) string { return buscompose.WithheldKey(w) }
|
|
|
|
// WithheldWritten is what one pass did to StateWithheld.
|
|
type WithheldWritten struct {
|
|
Withheld int `json:"withheld"`
|
|
Written []string `json:"written,omitempty"`
|
|
Deleted []string `json:"deleted,omitempty"`
|
|
// Kept is set when a read of the pass failed: no key of a hearing no longer withheld is deleted then.
|
|
Kept string `json:"kept,omitempty"`
|
|
}
|
|
|
|
// writeWithheld writes each withheld hearing of what runs whose key differs (its At aside), and deletes the key of one no
|
|
// longer withheld when every input of the pass was read.
|
|
func (p *Part) writeWithheld(res *Result, in Inputs, recs buscompose.Records) {
|
|
now := buscompose.WithheldOf(recs)
|
|
done := &WithheldWritten{Withheld: len(now)}
|
|
res.Withheld = done
|
|
want := map[string]WithheldHearing{}
|
|
for _, w := range now {
|
|
want[WithheldKey(w)] = WithheldHearing{V: buscompose.WithheldVersion, Node: w.Node, Module: w.Module, Stream: w.Stream, Emitter: w.Emitter, Said: w.Said()}
|
|
}
|
|
for _, key := range sortedKeys(want) {
|
|
h := want[key]
|
|
raw, _, found, err := p.Store.Get(StateWithheld, key)
|
|
if err != nil {
|
|
res.Errors = append(res.Errors, fmt.Sprintf("its own %s %s cannot be read: %v", StateWithheld, key, err))
|
|
continue
|
|
}
|
|
if found {
|
|
var was WithheldHearing
|
|
if json.Unmarshal(raw, &was) == nil {
|
|
was.At = time.Time{}
|
|
if was == h {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
h.At = p.now()
|
|
data, _ := json.Marshal(h)
|
|
if _, err := p.Store.Put(StateWithheld, key, data); err != nil {
|
|
res.Errors = append(res.Errors, fmt.Sprintf("its own %s %s cannot be written: %v", StateWithheld, key, err))
|
|
continue
|
|
}
|
|
done.Written = append(done.Written, key)
|
|
}
|
|
held, err := p.Store.Keys(StateWithheld)
|
|
if err != nil {
|
|
res.Errors = append(res.Errors, fmt.Sprintf("its own %s cannot be listed, so no hearing no longer withheld is deleted: %v", StateWithheld, err))
|
|
return
|
|
}
|
|
if len(in.ReadFailures()) > 0 {
|
|
done.Kept = "a read of this pass failed, so no hearing no longer withheld is deleted"
|
|
return
|
|
}
|
|
sort.Strings(held)
|
|
for _, key := range held {
|
|
if _, still := want[key]; still {
|
|
continue
|
|
}
|
|
if err := p.Store.Delete(StateWithheld, key); err != nil {
|
|
res.Errors = append(res.Errors, fmt.Sprintf("its own %s %s cannot be deleted: %v", StateWithheld, key, err))
|
|
continue
|
|
}
|
|
done.Deleted = append(done.Deleted, key)
|
|
}
|
|
}
|