package broker // **The grants part's user list, sealed to the bus node** (novox/hq ADR 0547 clause 7, issue 1945): the operator's // second exception to the frozen controller (the first, memberships, 2026-10-25 22:31). The controller's copy of the bus // composer grants what mesh-sdk's copy grants, byte for byte, and nothing else: the node-engine of the node holding // mesh-broker reads the grants part's one key `user-list.sealed`, watched, and an object of its bucket by name; the // grants part writes that bucket. Without it the bus node could never read the first list the grants part writes, since // until take-over the list the bus loads is this one (mesh-sdk go/buscompose/userlist_switch.go keeps the other copy). // The grants part's user list on the bus (mesh-sdk go/delivery userlist.go names them). const ( GrantsUserListBucket = "mesh-grants_user-list" GrantsUserListKey = "sealed" GrantsUserListObjects = "mesh-grants-user-list" GrantsUserListObjectStream = "OBJ_" + GrantsUserListObjects ) // GrantsUserListFollows is what the node-engine of the node holding mesh-broker may publish to follow the grants part's // list: the one key read and watched, and an object of the bucket by its name (as ADR 0486 ยง2 reads a declaration's // files: never the object stream's info, which lists every name, never a message by sequence). func GrantsUserListFollows() []string { kv := "KV_" + GrantsUserListBucket key := "$KV." + GrantsUserListBucket + "." + GrantsUserListKey obj, s := GrantsUserListObjects, GrantsUserListObjectStream return []string{ "$JS.API.DIRECT.GET." + kv + "." + key, "$JS.API.CONSUMER.CREATE." + kv + ".*." + key, "$JS.API.CONSUMER.DELETE." + kv + ".*", "$JS.API.STREAM.INFO." + kv, "$JS.FC." + kv + ".>", "$JS.API.DIRECT.GET." + s + ".$O." + obj + ".M.*", "$JS.API.CONSUMER.CREATE." + s + ".*.$O." + obj + ".C.*", "$JS.API.CONSUMER.DELETE." + s + ".*", "$JS.FC." + s + ".>", } } // GrantsUserListWrites is what the grants part may publish to keep its object bucket. func GrantsUserListWrites() []string { obj, s := GrantsUserListObjects, GrantsUserListObjectStream return []string{ "$JS.API.STREAM.CREATE." + s, "$JS.API.STREAM.INFO." + s, "$JS.API.STREAM.PURGE." + s, "$JS.API.DIRECT.GET." + s + ".>", "$JS.API.STREAM.MSG.GET." + s, "$O." + obj + ".>", } } // grantsOwnObjects is the grants part writing its own object bucket, and nothing of another. func grantsOwnObjects(p Principal, pattern string) bool { return p.Kind == KindModule && p.Module == GrantsModule && (pattern == "$O."+GrantsUserListObjects+".>" || pattern == "$JS.API.STREAM.CREATE."+GrantsUserListObjectStream) }