broker: a module account scopes its tool serve queues and mesh.rpc (ADR 0052)

CreateModuleAccount now also grants serve.<module>.* (declare, bind, consume its
own tool queues) and mesh.rpc (bind them on, publish replies) — so a module can
serve its tools and reply, scoped to exactly its own, and no other module's. The
broker tests still hold a module out of another's queue.
This commit is contained in:
2026-09-04 21:56:05 +02:00
parent b306c74467
commit b1bf1659d9
+14 -7
View File
@@ -92,20 +92,27 @@ func ModuleQueueFor(node, module string) string { return node + "." + module + "
func modulePermissions(node, module string, emits, consumes []string) (configure, write, read string) { func modulePermissions(node, module string, emits, consumes []string) (configure, write, read string) {
queue := regexp.QuoteMeta(ModuleQueueFor(node, module)) queue := regexp.QuoteMeta(ModuleQueueFor(node, module))
events := regexp.QuoteMeta(EventsExchangeName) events := regexp.QuoteMeta(EventsExchangeName)
rpc := regexp.QuoteMeta(RPCExchangeName)
// A module serves each of its tools on its own queue, namespaced by the module (novox/hq
// ADR 0052) — serve.<module>.<tool> — so the account may declare, bind and read exactly its own,
// and no other module's.
serve := "serve\\." + regexp.QuoteMeta(module) + "\\..*"
// Declare only its own queue. // Declare its own events queue and its own tool serve queues.
configure = "^" + queue + "$" configure = "^(" + queue + "|" + serve + ")$"
// Write to its own queue — binding a queue to an exchange is a write on the queue — and to the // Write to bind its queue and serve queues (binding is a write on the queue), and to the RPC
// events exchange only if it emits. // exchange to publish replies (ADR 0052: replies ride mesh.rpc, never the default exchange, which
writes := []string{queue} // would let it publish into any queue). To the events exchange only if it emits.
writes := []string{queue, serve, rpc}
if len(emits) > 0 { if len(emits) > 0 {
writes = append(writes, events) writes = append(writes, events)
} }
write = "^(" + strings.Join(writes, "|") + ")$" write = "^(" + strings.Join(writes, "|") + ")$"
// Read its own queue to consume it, and the events exchange to bind onto, only if it consumes. // Read its own queue and serve queues to consume them, and the RPC exchange to bind its serve
reads := []string{queue} // queues onto. The events exchange to bind onto only if it consumes.
reads := []string{queue, serve, rpc}
if len(consumes) > 0 { if len(consumes) > 0 {
reads = append(reads, events) reads = append(reads, events)
} }