A-233 (grants): a hearer of a seat's kept event is granted the ordered consumer of its whole read
As STREAM.INFO is, for every heard SEAT_ stream whatever its keep, so a part hearing an event kept by age reads it whole from its first message at each start (mesh-sdk process.FromFirst); no manifest word. Builds: design 47 G A-233, A-189 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -273,15 +273,18 @@ func heardGrants(p Principal, hears []Heard) []string {
|
||||
"$JS.API.CONSUMER.INFO."+h.Stream+"."+durable,
|
||||
"$JS.API.CONSUMER.MSG.NEXT."+h.Stream+"."+durable,
|
||||
"$JS.ACK."+h.Stream+"."+durable+".>")
|
||||
if strings.HasPrefix(h.Stream, seatdef.KeptStreamPrefix) || h.LastPerSubject {
|
||||
seatKept := strings.HasPrefix(h.Stream, seatdef.KeptStreamPrefix)
|
||||
if seatKept || h.LastPerSubject {
|
||||
// A seat's kept event, and a module's own stream kept last per subject, are heard through process.HearSeatEvents and
|
||||
// process.HearStream, which reads the stream's own info to see whether it is
|
||||
// kept last per subject (design 47 G §641, A-19): the info of this stream alone.
|
||||
out = append(out, "$JS.API.STREAM.INFO."+h.Stream)
|
||||
}
|
||||
if h.LastPerSubject {
|
||||
if seatKept || h.LastPerSubject {
|
||||
// A stream kept last per subject is read whole at each start through an ordered consumer, made for that one read
|
||||
// and with no durable name: its creation, its next message, its info and the deletion of its own (design 47 G §556, A-4).
|
||||
// So is every seat's kept event, whatever its keep: one kept by age is read whole from its first message with
|
||||
// process.FromFirst, with no manifest word (A-233).
|
||||
out = append(out,
|
||||
"$JS.API.CONSUMER.CREATE."+h.Stream, "$JS.API.CONSUMER.CREATE."+h.Stream+".>",
|
||||
"$JS.API.CONSUMER.MSG.NEXT."+h.Stream+".*", "$JS.API.CONSUMER.INFO."+h.Stream+".*",
|
||||
|
||||
@@ -20,6 +20,14 @@ func TestAReaderOfAStreamKeptLastPerSubjectIsGrantedItsOrderedConsumer(t *testin
|
||||
if slices.Contains(plain, ordered[0]) {
|
||||
t.Errorf("a reader of another stream is granted an ordered consumer: %v", plain)
|
||||
}
|
||||
// A seat's kept event kept by age is read whole from its first message (process.FromFirst, A-233): its ordered consumer too.
|
||||
byAge := heardGrants(p, []Heard{{Stream: "SEAT_mesh-catalog_version-released", Filters: []string{"f"}}})
|
||||
for _, w := range []string{"$JS.API.CONSUMER.CREATE.SEAT_mesh-catalog_version-released", "$JS.API.CONSUMER.MSG.NEXT.SEAT_mesh-catalog_version-released.*",
|
||||
"$JS.API.CONSUMER.INFO.SEAT_mesh-catalog_version-released.*", "$JS.API.CONSUMER.DELETE.SEAT_mesh-catalog_version-released.*"} {
|
||||
if !slices.Contains(byAge, w) {
|
||||
t.Errorf("a reader of a seat's event kept by age is not granted %s: %v", w, byAge)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A reader of a seat's kept event is granted the info of that stream, which process.HearSeatEvents reads to see whether the
|
||||
|
||||
Reference in New Issue
Block a user