Files
mesh-delivery/modules/mesh-grants/internal/buscompose/withheld.go
T
jschoubben 7bc4836eb0 AM-D3: a runtime whose tool runner does not honour the mark is denied every marked subject
The grants part follows the assignment half, reads each node's reading and the
runner its node-engine says running, and where the runner does not state
approval-mark/1 or the reading is not the running runner's, composes the
subscribe deny of every marked tool and verb the runtime carries, named in
grants_user_list's withheld and answered by the seat's verb withheld.

Builds: design 46 7 §6 (the deny's subjects, its cases, withheld in grants_user_list and the verb withheld), design 47 G §195, §309, lead answer A-203 (the assignment half followed by revision and assignment-revision; withheld's forms, keyed by node in the user list's state as the lead confirmed)

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 06:17:59 +01:00

86 lines
3.6 KiB
Go

package buscompose
import (
"slices"
"sort"
)
// **A machine whose tool runner does not honour the mark serves no marked tool or verb** (design 46 approval mark §6): on
// the account of a node's runtime whose readings lack approval-mark/1, or are not the running runner's, every marked
// subject of every module it carries is denied to subscribe, which outranks its allow of `mesh.mod.<module>.tool.>`, and
// each is named with why.
// ApprovalMark is the capability a tool runner that honours the mark states among its call capabilities (design 46
// approval mark §6).
const ApprovalMark = "approval-mark/1"
// WithheldWhy is why a marked subject is withheld (design 46 approval mark §6).
const WithheldWhy = "its tool runner does not state " + ApprovalMark
// WithheldSubject is one marked subject withheld from a runtime's account: the module it is of, the subject and why
// (lead answer A-203).
type WithheldSubject struct {
Module string `json:"module"`
Subject string `json:"subject"`
Why string `json:"why"`
}
// RunnerReading is a node's capability reading as the assignment half carries it: what its tool runner states of the
// calls it answers, and the fingerprint of the runner that announced it (design 46 approval mark §6).
type RunnerReading struct {
Capabilities []string
Fingerprint string
}
// Withholds says whether a node's runtime withholds the marked subjects: where the node has no reading, the reading
// lacks ApprovalMark, or its fingerprint is absent or differs from the one the node-engine last said running (no time is
// compared, failing closed).
func Withholds(reading RunnerReading, read bool, running string) bool {
return !read || !slices.Contains(reading.Capabilities, ApprovalMark) || reading.Fingerprint == "" ||
reading.Fingerprint != running
}
// MarkedSubjects are the subjects of a module's marked tools and of the marked verbs of the seats it holds, on node: a
// tool's `mesh.mod.<module>.tool.<tool>`, the same followed by `.*`, and the caller-named `mesh.mod.<module>.call.<tool>.>`;
// a verb of a seat held per node `mesh.seat.<seat>.tool.<verb>`, its `.<node>` form and `mesh.seat.<seat>.call.<verb>.<node>.>`;
// a verb of a seat held once for the mesh `mesh.seat.<seat>.tool.<verb>` and `mesh.seat.<seat>.call.<verb>.>`.
func MarkedSubjects(node string, d Declared) []string {
var out []string
for _, t := range d.Marked {
out = append(out, "mesh.mod."+d.Module+".tool."+t, "mesh.mod."+d.Module+".tool."+t+".*",
"mesh.mod."+d.Module+"."+CallKind+"."+t+".>")
}
for _, s := range d.Holds {
for _, v := range s.Marked {
if s.Scope == "node" {
out = append(out, "mesh.seat."+s.Name+".tool."+v, "mesh.seat."+s.Name+".tool."+v+"."+node,
"mesh.seat."+s.Name+"."+CallKind+"."+v+"."+node+".>")
} else {
out = append(out, "mesh.seat."+s.Name+".tool."+v, "mesh.seat."+s.Name+"."+CallKind+"."+v+".>")
}
}
}
return out
}
// MarksWithheld are the subjects withheld from a principal's account, each with its module and why: for a node's runtime that
// withholds, every marked subject of every module it carries; none for any other.
func MarksWithheld(p Principal) []WithheldSubject {
if p.Kind != KindNodeTools || !p.Withholds {
return nil
}
var out []WithheldSubject
for _, d := range p.Carries {
for _, s := range MarkedSubjects(p.Node, d) {
out = append(out, WithheldSubject{Module: d.Module, Subject: s, Why: WithheldWhy})
}
}
sort.Slice(out, func(i, j int) bool {
if out[i].Module != out[j].Module {
return out[i].Module < out[j].Module
}
return out[i].Subject < out[j].Subject
})
return slices.CompactFunc(out, func(a, b WithheldSubject) bool { return a == b })
}