Judge every read for its reader where the bus's users are composed (issue 774)

Since 13:25 the vault, the assigner, the watchman, the grants part and the artifact store's tools were refused
mesh-controller.lease, and the vault mesh-grants.accounts, though the composer names them those states' readers
(ADR 0547 clause 9): the controller splits reads with its own copy of the reader-less ReadsAnnounced, which knows
no named readers, and Users only moved reads from granted to refused, never back.

Quick fix: the controller calls ReadsAnnouncedBy with the module. Thorough fix, chosen because the kind was met
on four owners and the judgement had two copies: Users judges every read again for its reader against the
announcements in Records (withAnnouncedReads), whatever split the caller made, and the reader-less
ReadsAnnounced is removed so no caller can judge without the reader. A rule over manifests was not added:
ADR 0495 clauses 1 and 5 keep readability out of the manifest and replaced the merge gate's reads check by each
module's announcement test. gitea.bound and disk-load.readings stay refused: their owners announce them not
readable, which their own code fixes.
This commit is contained in:
2026-10-30 18:08:02 +01:00
parent 7b02f63daf
commit e703e9b0e2
4 changed files with 49 additions and 14 deletions
+4 -4
View File
@@ -205,9 +205,9 @@ func Users(r Records) ([]Principal, error) {
if !Composed(d) {
continue
}
// A state with named readers is read by them alone (ADR 0547 clause 9): a read named for another module is
// granted nothing, here and in the runtime carrying the module.
d = withReadLogs(withNamedReaders(d), logs)
// A state with named readers is read by them alone (ADR 0547 clause 9), and a read is granted what its owner
// announced (ADR 0495 clause 3): judged here, for this reader, whatever split the caller made (issue 774).
d = withReadLogs(withAnnouncedReads(d, r.Announced), logs)
// **A process account is its own, delivered in its own secret** (broker-<process id>, novox/hq
// ADR 0436 §1, §2), never the module's `broker` — so it is composed whether or not the module
// itself has an account, and is never carried by the machine's runtime, which runs as the
@@ -259,7 +259,7 @@ func Users(r Records) ([]Principal, error) {
var carried []Declared
for _, d := range r.Assigned[node] {
if CarriedByRunner(d) {
d = withReadLogs(withNamedReaders(d), logs)
d = withReadLogs(withAnnouncedReads(d, r.Announced), logs)
// Never a restricted stream for what the tool runner carries (novox/hq ADR 0376 §1).
d.Hears = ComposedHears(d)
carried = append(carried, d)