A-1 marks: the tool runner derives each served module's marks from the catalog half

The gate (node-tools/internal/approval) derives a module's marked tools and verbs, and the
subjects of its marked events and restricted streams, from its served entry (the build its
composed environment's fingerprint names) and the newest, unioned while they differ, and
the seat definitions' verb marks, which no holder unmarks. A bundle whose marks name a tool
it does not register is not loaded, its finding mark-unserved raised through the runner's
held writer and cleared when a bundle serves it. The first views now start whether or not
the console listens, since the gate reads the catalog half too.

Builds: design 46 7-approval-mark §5, §4 (at load), §3; design 34 every-event §33; lead answer A-154

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 05:05:13 +01:00
parent 5bf7a4b656
commit 827628164a
9 changed files with 603 additions and 6 deletions
+10 -5
View File
@@ -26,6 +26,7 @@ import (
"time"
"github.com/novox/mesh-tools/node-tools/internal/alive"
"github.com/novox/mesh-tools/node-tools/internal/approval"
"github.com/novox/mesh-tools/node-tools/internal/bus"
"github.com/novox/mesh-tools/node-tools/internal/console"
"github.com/novox/mesh-tools/node-tools/internal/firstview"
@@ -51,7 +52,7 @@ func main() {
cred := credential(until)
conn := connectPatiently(cred, until)
// And the seat list it describes the seats by, read through the seat mesh-catalog (novox/hq ADR 0636 §4).
_ = startSeatList(conn)
seatList := startSeatList(conn)
served, err := runtime.ServedModulesFrom(os.Getenv(runtime.ToolModules), cred.Module)
if err != nil {
@@ -69,6 +70,14 @@ func main() {
defer ledgers.Stop()
opts = append(opts, runtime.WithLedgerWriters(ledgers.Writer))
}
// The indexer's and the assigner's states the console indexes the mesh by, and the gate reads its marks from, come to it as
// first views, asked of the owners' own tools and followed on their views families, never read from their state (novox/hq
// ADR 0615 §1; design 46 7-approval-mark §5).
source, stopViews := firstview.Start(context.Background(), conn, log.Printf)
defer stopViews()
gate := approval.New(approval.Deps{Node: conn.Node(), Runner: cred.Module, Catalog: source.ApprovalCatalog(definitionsOf(seatList)),
Findings: source.Findings(), Logf: log.Printf})
opts = append(opts, runtime.WithGate(gate))
stop, err := runtime.Run(conn, served, envs, log.Printf, opts...)
if err != nil {
log.Fatalf("node-tools: %v", err)
@@ -90,10 +99,6 @@ func main() {
}
var up *console.Listening
if listen != "" {
// The indexer's and the assigner's states the console indexes the mesh by come to it as first views, asked of the owners'
// own tools and followed on their views families, never read from their state (novox/hq ADR 0615 §1).
source, stopViews := firstview.Start(context.Background(), conn, log.Printf)
defer stopViews()
node := cred.Node
if node == "" {
node = "?"
+11
View File
@@ -71,3 +71,14 @@ func startSeatListOn(b seatlist.Bus, bound <-chan time.Time, logf func(string, .
}
return reader
}
// definitionsOf is the seat definitions the reader holds, by seat, which carry the verbs' marks (design 46 7-approval-mark
// §2, §5); none while the reader did not start.
func definitionsOf(reader *seatlist.Reader) func() map[string]seatdef.Definition {
return func() map[string]seatdef.Definition {
if reader == nil {
return nil
}
return reader.Definitions()
}
}