A ledger's binding carries its types (issue 1966 S3)

The grants part copies them from the manifest-accepted entry, so the tool
runner checks an operation against its type without reading another
part's state (ADR 0596; the lead's ruling on issue 1966 B1).
This commit is contained in:
2026-11-03 15:12:19 +01:00
parent cc64794d4c
commit 092260870b
2 changed files with 11 additions and 2 deletions
+5
View File
@@ -7,6 +7,8 @@ package membership
import (
"encoding/json"
"strings"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// AssignmentsStream holds every assignment's membership, the newest per subject.
@@ -84,6 +86,9 @@ type BusBinding struct {
State string `json:"state,omitempty"`
Indexes map[string]string `json:"indexes,omitempty"`
Snapshot string `json:"snapshot,omitempty"`
// Types are a ledger's types, copied by the grants part from the entry the manifest-accepted event carries, so the
// tool runner checks an operation against its type without reading another part's state (ADR 0596, ADR 0597 §1).
Types []catalogue.LedgerType `json:"types,omitempty"`
}
// Served is one address a tool is answered on.
+6 -2
View File
@@ -4,6 +4,8 @@ import (
"encoding/json"
"reflect"
"testing"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// A credential is read out of a bus address, and the bare address carries no credential and a scheme.
@@ -57,11 +59,13 @@ func TestAMembershipRoundTripsAsIssued(t *testing.T) {
if !reflect.DeepEqual(in, out) {
t.Fatalf("round trip changed it:\n%+v\n%+v", in, out)
}
// 1966/AC4: a membership with a ledger binding round-trips; one without bindings encodes as before, byte for byte.
// 1966/AC4: a membership with a ledger binding, its types among it, round-trips; one without bindings encodes as before, byte for byte.
bound := in
bound.Bindings = []BusBinding{{Local: "records", Storage: "ledger", Template: "ledger", History: "forge_records",
Subject: "forge_records.>", State: "forge_records_state", Indexes: map[string]string{"search": "forge_records_search"},
Snapshot: "forge_records_snapshot.>"}}
Snapshot: "forge_records_snapshot.>",
Types: []catalogue.LedgerType{{Name: "decision", Schema: map[string]catalogue.LedgerField{"title": {Type: "text"}},
Operations: []catalogue.LedgerOperation{{Name: "propose", Effect: catalogue.EffectSetFields, Fields: []string{"title"}}}}}}}
boundRaw, err := json.Marshal(bound)
if err != nil {
t.Fatal(err)