mesh/delivery merged: source.main moved to novox/mesh-delivery@7c0492b06c37
mesh/delivery-group group feature/1979-zfs-owns-zfs merged: every member is merged
mesh/check being carried to ad7e58091801 on 7c0492b06c37 | from 7221a1e5cd7f, mesh-catalog 117f933dacf0, mesh-host 0193949efe9f, mesh-sdk e42b9491c931…
Builds: design 42 zfs-owns-zfs §25, §26, A-37, A-38
82 lines
4.1 KiB
Go
82 lines
4.1 KiB
Go
package buscompose
|
|
|
|
import "strings"
|
|
|
|
// The bus account of one process of a module that declares bus (novox/hq ADR 0436 §1, §2, §3, §5).
|
|
//
|
|
// **Never the module's own account's grants, never the tool runner's.** A process's authority is read
|
|
// straight from its bus declaration — its emits, its queue's consumer, its state, whether it reads the
|
|
// records of its module's own asks, and the tools and seat verbs it calls — and nothing else: it holds no
|
|
// seat, serves no tool, hears no module stream, and answers nothing a caller asked (§3). Modelled on
|
|
// provisionerGrants, the other kind of process account the mesh mints (ADR 0349 clauses 6 and 11).
|
|
|
|
// processGrants is one process's whole authority: to publish, and to subscribe.
|
|
func processGrants(p Principal) (pub, sub []string, err error) {
|
|
// 1. Its own events, under its module's own namespace — the same subjects the module's own principal
|
|
// would publish them on, had it declared them there instead (novox/hq ADR 0436 §1).
|
|
own := "mesh.mod." + p.Module
|
|
for _, e := range p.Emits {
|
|
pub = append(pub, own+".event."+e)
|
|
}
|
|
|
|
// 1b. The events of its module's events streams asked for in `requires` (design 42 zfs-owns-zfs, lead answer A-38; ADR
|
|
// 0595 §1, §2): publish on each stream's subjects, the subject boundOf gives the module's own account, and nothing of
|
|
// its reading. A name that cannot be one token is granted nothing.
|
|
for _, local := range p.BusStreams {
|
|
if safeSubject.MatchString(p.Module) && safeSubject.MatchString(local) && !strings.Contains(local, "_") && !strings.Contains(p.Module, "_") {
|
|
pub = append(pub, "mesh.bus."+p.Module+"."+local+".>")
|
|
}
|
|
}
|
|
|
|
// 2. The one durable consumer of each work-queue stream its bus names (novox/hq ADR 0436 §1, §2, §6):
|
|
// asked about, pulled from and acknowledged, by the same name ConsumersOf composes the consumer under
|
|
// (QueueConsumer) — and no other stream's.
|
|
for _, q := range p.Queues {
|
|
consumer := p.Node + "_" + p.Module + "_" + q.Process
|
|
pub = append(pub,
|
|
"$JS.API.CONSUMER.INFO."+q.Stream+"."+consumer,
|
|
"$JS.API.CONSUMER.MSG.NEXT."+q.Stream+"."+consumer,
|
|
"$JS.ACK."+q.Stream+"."+consumer+".>")
|
|
}
|
|
|
|
// 3. Its module's own state, by the local names its bus names alone — never the whole of what the
|
|
// module keeps (novox/hq ADR 0436 §1), read and written as stateGrants gives any module's own bucket.
|
|
kept := stateAccess{Module: p.Module, Node: p.Node, Keeps: p.State}
|
|
pub = append(pub, stateGrants(kept)...)
|
|
// And it hears each of them created, so one not on the bus at its start is bound when it appears (novox/hq issue
|
|
// 1790; process.AwaitBucket).
|
|
sub = append(sub, stateCreatedHeard(kept)...)
|
|
|
|
// 4. The router's records of its module's own asks (novox/hq ADR 0436 §1, ADR 0259 §3): the same
|
|
// direct-get subjects a module's own principal reads for the seats its Uses names that keep them —
|
|
// read here from the one list, so the two cannot disagree.
|
|
if p.Asks {
|
|
pub = append(pub, SeatTrafficOf(p.Module, nil, p.Uses, nil).Records...)
|
|
}
|
|
|
|
// 5. The tools and seat verbs it calls (novox/hq ADR 0152, ADR 0436 §1): the same derivation a
|
|
// module's own principal's invokes takes, so `callerNamed` (applied to every non-controller principal)
|
|
// adds the caller-named `call` variants for it exactly as it would for a module.
|
|
invoked, err := invokedSubjects(p.Invokes)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
pub = append(pub, invoked...)
|
|
|
|
// 6. The bus module's process (busstate.go, ADR 0595 §4, §5): every module's bus state it keeps, by name; its own
|
|
// consumer of what its module consumes; its module's own stream's events; and its conditions through the seats its
|
|
// module uses (the operator channel's accept.condition in its module's name).
|
|
if p.KeepsBus {
|
|
pub = append(pub, busStateKeeperGrants(p.KeepsBusState)...)
|
|
if c, ok := keeperConsumer(p); ok {
|
|
pub = append(pub, keeperConsumerGrants(c)...)
|
|
}
|
|
pub = append(pub, ownStreamGrants(p.Module, p.Streams)...)
|
|
pub = append(pub, p.SaysSeatEvents...)
|
|
tp, ts := seatTrafficGrants(SeatTrafficOf(p.Module, nil, p.Uses, nil))
|
|
pub, sub = append(pub, tp...), append(sub, ts...)
|
|
}
|
|
|
|
return pub, sub, nil
|
|
}
|