Append and snapshot a ledger on mesh-sdk's ledger subjects, the ones its account is granted, refusing a binding naming others (issue 1966 T6)

This commit is contained in:
2026-11-03 15:17:12 +01:00
parent 5a9e997349
commit 961ec0ef96
5 changed files with 38 additions and 23 deletions
+16 -7
View File
@@ -10,6 +10,7 @@ import (
"strings"
"time"
"git.novox.be/novox/mesh-sdk/go/buscompose"
"git.novox.be/novox/mesh-sdk/go/membership"
"github.com/nats-io/nats.go"
"github.com/nats-io/nats.go/jetstream"
@@ -18,17 +19,25 @@ import (
)
// A ledger on the bus (novox/hq ADR 0597, design 25 § 12.4; issue 1966): its history a stream with a subject per
// instance under the binding's subject, its state a key-value bucket, its snapshots a subject per instance under the
// binding's snapshot subject, the latest only (the stream that holds them keeps one per subject, as the bus module
// instance under mesh-sdk's buscompose.LedgerHistorySubject, its state a key-value bucket, its snapshots a subject per
// instance under buscompose.LedgerSnapshotSubject, the latest only (the stream that holds them keeps one per subject, as the bus module
// creates it). **Only the module's ledger connection publishes on its history and its snapshots** (ADR 0597 §9): what
// is read, and the state, go on the runner's own.
// LedgerStores are the stores of one ledger binding: reads and the state on c, the history's appends and the snapshots'
// writes on writer, the module's ledger connection.
func (c *Conn) LedgerStores(b membership.BusBinding, writer *Conn) (ledger.History, ledger.State, ledger.Snapshots) {
return &busHistory{read: c, write: writer, stream: b.History, prefix: prefixOf(b.Subject)},
// LedgerStores are the stores of a module's ledger binding: reads and the state on c, the history's appends and the
// snapshots' writes on writer, the module's ledger connection. The subjects are mesh-sdk's, the ones the grants part
// grants the module's ledger account byte for byte; a binding naming others is refused, naming both.
func (c *Conn) LedgerStores(module string, b membership.BusBinding, writer *Conn) (ledger.History, ledger.State, ledger.Snapshots, error) {
history, snapshot := buscompose.LedgerHistorySubject(module, b.Local), buscompose.LedgerSnapshotSubject(module, b.Local)
for _, named := range []struct{ what, bound, want string }{{"history", b.Subject, history}, {"snapshot", b.Snapshot, snapshot}} {
if named.bound != "" && prefixOf(named.bound) != named.want {
return nil, nil, nil, fmt.Errorf("%s's ledger %q is bound with the %s subject %s, and its ledger account is granted "+
"%s alone (mesh-sdk buscompose); the binding is refused", module, b.Local, named.what, named.bound, named.want)
}
}
return &busHistory{read: c, write: writer, stream: b.History, prefix: history},
&busState{c: c, bucket: b.State},
&busSnapshots{read: c, write: writer, prefix: prefixOf(b.Snapshot)}
&busSnapshots{read: c, write: writer, prefix: snapshot}, nil
}
// prefixOf is a binding's subject as the prefix an instance's key is added to: written with or without its `.>`.