The account of the module claiming the seat mesh-recovery is granted the stream snapshot and restore subjects with their chunk subjects, a stream's deletion and a durable consumer's creation, only for the bus names of every kept data of every manifest the part holds and of every restore point or aside kept-points names; never a stream of the mesh's own (CONTROL, NODES, EVENTS, DEAD_LETTER*, PROV_APPLIED, CHECKS_*, SEAT_*, a seat's KV_). The writers table names the account as a deleter of kept data's streams (ADR 0672 §4). Builds: design 47 G §554, §565, A-230 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
68 lines
3.1 KiB
Go
68 lines
3.1 KiB
Go
package buscompose
|
|
|
|
import (
|
|
"slices"
|
|
"sort"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-contracts/go/seats/meshrecovery"
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// **The recovery module's account** (design 47 G §554, §565; ADR 0672 §4): the account of the module holding the seat mesh-recovery
|
|
// (the seat, never a module's name) is granted the bus's stream snapshot and restore subjects with their chunk subjects, a stream's
|
|
// deletion and a durable consumer's creation, only for the bus names of kept data: those of every kept data of every catalog graph
|
|
// entry and of every entry a restore point names (an old section's name before a form change, a template's binding after), the
|
|
// second read by the grants part through `kept-points`. The subjects its seat says, its hand-act log write, its consumes of
|
|
// `node-backup` and its calls come from its manifest as any module's. No stream of the mesh's own is ever granted.
|
|
|
|
// RecoverySeat is the seat whose holder's account is granted the bus names of kept data.
|
|
const RecoverySeat = meshrecovery.Seat
|
|
|
|
// meshStreams are the streams of the mesh's own, never granted to the recovery module's account (§554); every `SEAT_` stream and
|
|
// every `KV_` bucket of a seat (KV_SEAT_…) are refused by their prefix.
|
|
var meshStreams = []string{"CONTROL", "NODES", "EVENTS", "DEAD_LETTER_NOTICES", "DEAD_LETTERS", "PROV_APPLIED", "CHECKS_READY", "CHECKS_OTHER"}
|
|
|
|
// RecoveryNameRefused says a bus name is one of the mesh's own streams, or no plain subject token.
|
|
func RecoveryNameRefused(name string) bool {
|
|
return !safeSubject.MatchString(name) || strings.Contains(name, ".") || slices.Contains(meshStreams, name) ||
|
|
strings.HasPrefix(name, "SEAT_") || strings.HasPrefix(name, "KV_SEAT_") || name == "KV_CONTROL" || name == "KV_NODES"
|
|
}
|
|
|
|
// RecoveryGrants are what the account publishes for each bus name of kept data: the stream's snapshot and its chunks'
|
|
// acknowledgements, its restore and the chunks sent to it, its deletion, and the creation of a durable consumer on it.
|
|
func RecoveryGrants(names []string) []string {
|
|
var out []string
|
|
for _, n := range names {
|
|
if RecoveryNameRefused(n) {
|
|
continue
|
|
}
|
|
out = append(out, "$JS.API.STREAM.SNAPSHOT."+n, "$JS.SNAPSHOT.ACK."+n+".>", "$JS.API.STREAM.RESTORE."+n,
|
|
"$JS.SNAPSHOT.RESTORE."+n+".>", "$JS.API.STREAM.DELETE."+n, "$JS.API.CONSUMER.DURABLE.CREATE."+n+".*")
|
|
}
|
|
return unique(out)
|
|
}
|
|
|
|
// KeptBusNames are the bus names of every kept data a manifest declares: the old sections' (a state's `KV_<module>_<name>`, a log's,
|
|
// a stream's, an object store's) and each entry of `requires` by `<module>_<local>` (BusStateStreams). Sorted, once each. Pure.
|
|
func KeptBusNames(m catalogue.Manifest) []string {
|
|
var out []string
|
|
for _, s := range m.State {
|
|
out = append(out, "KV_"+m.Module+"_"+s.Name)
|
|
}
|
|
for _, l := range m.Logs {
|
|
out = append(out, "LOG_"+m.Module+"_"+l.Name)
|
|
}
|
|
for _, s := range m.Streams {
|
|
out = append(out, s.BusName())
|
|
}
|
|
for _, o := range m.Objects {
|
|
out = append(out, "OBJ_"+catalogue.ObjectsBucket(m.Module, o.Name))
|
|
}
|
|
for _, e := range m.BusState {
|
|
out = append(out, BusStateStreams(m.Module, e)...)
|
|
}
|
|
sort.Strings(out)
|
|
return slices.Compact(out)
|
|
}
|