58 lines
2.7 KiB
Go
58 lines
2.7 KiB
Go
package buscompose
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
"sort"
|
|
"strings"
|
|
|
|
sdk "git.novox.be/novox/mesh-sdk/go/buscompose"
|
|
)
|
|
|
|
// A module's ledger and the one account that writes it (issue 1966 D5; novox/hq ADR 0597 §9, design 25 § 12.4).
|
|
//
|
|
// **Only the tool runner's ledger credential publishes on a ledger's history** (ADR 0597 §9): one per module assignment,
|
|
// named ledger.<machine>.<module> (KindLedger), scoped to the subjects of that module's ledger histories and snapshots, and
|
|
// gone when the module is unassigned from the machine. The module's own account, its processes and the machine's tool
|
|
// runner hold no publish there, so a raw publish on a history is refused by the bus. The subjects are named in one place, mesh-sdk's
|
|
// buscompose (LedgerHistorySubject, LedgerSnapshotSubject), `mesh.ledger.<module>.<local name>.history|snapshot` and
|
|
// one subject per instance below it (design 25 § 12.4).
|
|
|
|
// LedgerPublishGrants are the publish patterns a module's ledger account is granted: the histories and the snapshots of the
|
|
// ledgers named, every instance of each, and nothing else. Sorted.
|
|
func LedgerPublishGrants(module string, locals []string) []string {
|
|
var out []string
|
|
for _, local := range locals {
|
|
out = append(out, sdk.LedgerHistorySubject(module, local)+".>", sdk.LedgerSnapshotSubject(module, local)+".>")
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
// writesLedger is a module's ledger account publishing on that module's own ledgers' histories and snapshots, and no other
|
|
// principal (ADR 0597 §9).
|
|
func writesLedger(p Principal, pattern string) bool {
|
|
return p.Kind == KindLedger && slices.Contains(LedgerPublishGrants(p.Module, p.Ledgers), pattern)
|
|
}
|
|
|
|
// ledgerSubjects are the subjects no principal but a ledger account may publish on, for the writers table.
|
|
var ledgerSubjects = []string{"mesh.ledger.*.*.history.>", "mesh.ledger.*.*.snapshot.>"}
|
|
|
|
// ledgerPermissions are a ledger account's whole authority: publishing on its module's ledgers, and its own reply space for
|
|
// the stream's acknowledgements. Refused when it names no ledger or a name that is no subject token.
|
|
func ledgerPermissions(p Principal) (Permissions, error) {
|
|
pub := LedgerPublishGrants(p.Module, p.Ledgers)
|
|
if len(p.Ledgers) == 0 {
|
|
return Permissions{}, fmt.Errorf("%s asks for no ledger, so its account would publish nowhere", p.Username())
|
|
}
|
|
for _, l := range p.Ledgers {
|
|
if !safeSubject.MatchString(l) || strings.Contains(l, "_") {
|
|
return Permissions{}, fmt.Errorf("%s: %q cannot be part of a subject: a permission is a subject pattern, and this would widen it", p.Username(), l)
|
|
}
|
|
}
|
|
if err := CheckWriters(p, pub); err != nil {
|
|
return Permissions{}, err
|
|
}
|
|
return Permissions{Publish: pub, Subscribe: []string{p.inbox()}}, nil
|
|
}
|