The engine composes its node's wants itself, so the derivation the controller keeps privately moves beside the layout: DeclaredPackagesOf gives the mirror's bytes from the compositions, DiffDeclaredPackages what the node seat's verb packages compares until the lease write, and EnginePackagesRead names the state as readers declare it (mesh-host.packages, as mesh-host.data). Each engine may read the controller mirror's key of its own node alone. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
85 lines
4.7 KiB
Go
85 lines
4.7 KiB
Go
package buscompose
|
|
|
|
import (
|
|
"git.novox.be/novox/mesh-sdk/go/asks"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
"git.novox.be/novox/mesh-sdk/go/provisions"
|
|
)
|
|
|
|
// The node seat node-engine (novox/hq ADR 0563 §1): every node's engine holds it on its own bus account, and no module
|
|
// claims it. Its verbs and events are the catalogue's (catalogue.EngineVerbs), read here rather than copied.
|
|
|
|
// EngineSeat is the seat.
|
|
const EngineSeat = catalogue.EngineSeat
|
|
|
|
// EngineModule is the node-engine's manifest's module name, and EngineActsState its state the acts asked through the
|
|
// node seat and its own asks are kept in (ADR 0563 §2, §3: "the engine's own state"): the bucket mesh-host_acts, keys
|
|
// `<node>.act.<id>`, `<node>.open.<act>.<digest>` and `<node>.ask.<id>`, each written by that node's engine alone.
|
|
const (
|
|
EngineModule = "mesh-host"
|
|
EngineActsState = "acts"
|
|
)
|
|
|
|
// EngineActsBucket is that state's bucket.
|
|
var EngineActsBucket = BucketName(EngineModule, EngineActsState)
|
|
|
|
// EnginePackagesBucket is the engine's state of its node's declared packages (novox/hq ADR 0565 clause 6): one key, the
|
|
// node's name, written by that node's engine alone.
|
|
var EnginePackagesBucket = BucketName(EngineModule, delivery.EnginePackagesState)
|
|
|
|
// EngineDataBucket is the engine's state of its node's placed modules' data items (novox/hq ADR 0577 clause 1): one
|
|
// key `<node>.<module>` per module, written by that node's engine alone.
|
|
var EngineDataBucket = delivery.EngineDataBucket
|
|
|
|
// EnginePackagesGrants is what a node's engine publishes to keep its node's key of the packages bucket: the key alone,
|
|
// and its read.
|
|
func EnginePackagesGrants(node string) []string {
|
|
return append([]string{"$KV." + EnginePackagesBucket + "." + node}, readGrants(EnginePackagesBucket, node)...)
|
|
}
|
|
|
|
// engineGrants is what a node's engine is granted to hold its node seat and to ask the operator (ADR 0563 §1, §3): it
|
|
// answers its own node's verbs (the caller-named subjects are added beside them with every principal's), says the
|
|
// seat's events about its node, answers discovery for the seat, asks who answers what (the login shell's execute, ADR
|
|
// 0563 §6), and asks the operator under asks.EngineAsker(node) on the router's seat as its holder declares it, as any
|
|
// user of that seat is granted.
|
|
//
|
|
// Its verbs and events are granted as any verb and any event of the seat on its own node, not as the contract's list:
|
|
// the list is compiled into whichever mesh-sdk the grants part pins, so a verb the engine gained before the grants part
|
|
// was released was refused on every node and the engine reopened its link every few minutes (2026-10-31, the optional
|
|
// verb composition of mesh-host #184). As a module answers `mesh.mod.<module>.tool.>`, nothing is given away: no other
|
|
// principal may subscribe this seat's subjects of this node, and a caller is still granted each verb by name.
|
|
func engineGrants(p Principal) (pub, sub []string) {
|
|
sub = append(sub, "mesh.seat."+EngineSeat+".tool.*."+p.Node)
|
|
pub = append(pub, "mesh.seat."+EngineSeat+".event.*."+p.Node)
|
|
sub = append(sub, announcing(EngineSeat)...)
|
|
pub = append(pub, discovering()...)
|
|
tp, ts := seatTrafficGrants(SeatTrafficOf(asks.EngineAsker(p.Node), nil, p.Uses, nil))
|
|
// And its acts and asks, under its own node's keys alone; never the bucket's creation, which is the grants part's.
|
|
if own, err := NodeKeysGrants(EngineActsBucket, p.Node); err == nil {
|
|
pub = append(pub, own...)
|
|
}
|
|
// And the provisions its node's modules consume, its own node's keys alone, read (novox/hq ADR 0570 clause 6: the
|
|
// consuming engine checks the vault's name and generation of what it is handed).
|
|
if safeSubject.MatchString(p.Node) {
|
|
pub = append(pub, readGrants(provisions.ProvisionsBucket, p.Node+".>")...)
|
|
}
|
|
// And its node's own health report, its key `<node>` alone (issue 774, the operator's alert table): what the watchman
|
|
// reads for the machine's alerts.
|
|
if safeSubject.MatchString(p.Node) {
|
|
pub = append(pub, append([]string{"$KV." + delivery.NodeHealthBucket + "." + p.Node},
|
|
readGrants(delivery.NodeHealthBucket, p.Node)...)...)
|
|
}
|
|
// And its node's placed modules' data items, its own node's keys alone (ADR 0577 clause 1).
|
|
if own, err := NodeKeysGrants(EngineDataBucket, p.Node); err == nil {
|
|
pub = append(pub, own...)
|
|
}
|
|
// And its node's declared packages, its own key alone (ADR 0565 clause 6); and, read, the controller's mirror's key
|
|
// of its node, which the node seat's verb packages compares it with until the lease write ends the mirror.
|
|
if safeSubject.MatchString(p.Node) {
|
|
pub = append(pub, EnginePackagesGrants(p.Node)...)
|
|
pub = append(pub, readGrants(DeclaredPackagesBucket, p.Node)...)
|
|
}
|
|
return append(pub, tp...), append(sub, ts...)
|
|
}
|