From bbfda29b49d89eb0e8c5cee0948e324c6d0e1b18 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 2 Nov 2026 00:37:04 +0100 Subject: [PATCH] The watchman hears the lease write's events and the stream ASSIGNMENTS deleted ADR 0582 clauses 4 and 6 have mesh-grants say lease-altered and removal-failed "as a finding the watchman raises". WatchmanHears, the one list its grant and its subscriptions come from, gains the seat mesh-grants' three events and the advisory of ASSIGNMENTS deleted (which, with the controller's consumer deleted that it hears already, clears a failed removal). Core subjects, read-only, no durable consumer. Test: rows added to the watchman's subjects in TestTheCopiedComposerComposesAsTheControllers; no new function. (issue 774, 774/S22) Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL --- go/buscompose/buscompose_test.go | 5 ++++- go/buscompose/health_grants.go | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/go/buscompose/buscompose_test.go b/go/buscompose/buscompose_test.go index 1075f8a..913a30a 100644 --- a/go/buscompose/buscompose_test.go +++ b/go/buscompose/buscompose_test.go @@ -951,7 +951,10 @@ func healthChecks(t *testing.T) { // It hears its watchdogs' words on core subjects (Limits 3, 11). for _, subject := range []string{"mesh.mod.power.event.sleeping", "mesh.control.g14.tools-alive", "mesh.seat.mesh-self-check.event.checked", "mesh.mod.keycloak.event.provisioner.failing", - "mesh.mod.nats.event.bus.slow-consumer", "prov.applied.g14.keycloak"} { + "mesh.mod.nats.event.bus.slow-consumer", "prov.applied.g14.keycloak", + // ADR 0582 clauses 4, 6 (issue 774, 774/S22): the lease write's events, and ASSIGNMENTS deleted. + "mesh.seat.mesh-grants.event.lease-altered", "mesh.seat.mesh-grants.event.removal-failed", + "mesh.seat.mesh-grants.event.lease-handed", "$JS.EVENT.ADVISORY.STREAM.DELETED.ASSIGNMENTS"} { if !MaySubscribe(perms, subject) { t.Errorf("the watchman may not hear %s", subject) } diff --git a/go/buscompose/health_grants.go b/go/buscompose/health_grants.go index 7225b6e..925b248 100644 --- a/go/buscompose/health_grants.go +++ b/go/buscompose/health_grants.go @@ -114,7 +114,7 @@ func WatchmanDeadLetterGrants(sources []string) []string { // WatchmanHears are the core subjects the watchman subscribes, with no durable consumer (ADR 0564 clauses 4, 5 and // Limits 3, 11): the power seat's words (S1, ADR 0211), the providers' failing and recovered words (S8), each tool // runner's beat (S11), the self-check's checked (S10), a consumer deleted and the bus module's slow consumers and closed -// connections (S9), the provisioner clients' reports (S21), and the dead letters kept. Never the bus's API audit +// connections (S9), the provisioner clients' reports (S21), the dead letters kept, and the lease write's events. Never the bus's API audit // (`$JS.EVENT.ADVISORY.API`): it carries every API call's request and answer in the account, the vault's hashes among // them (the lead, 2026-10-29). func WatchmanHears() []string { @@ -129,6 +129,12 @@ func WatchmanHears() []string { "mesh.mod.nats.event.bus.connection-closed", ProvAppliedSubjects, deadLetterPrefix + ">", + // And the lease write's (ADR 0582 clauses 4, 6; issue 774): the seat mesh-grants' three events, and the stream + // ASSIGNMENTS deleted, which with the controller's consumer deleted clears a removal that failed. + "mesh.seat." + catalogue.GrantsSeat + ".event." + catalogue.GrantsEventLeaseHanded, + "mesh.seat." + catalogue.GrantsSeat + ".event." + catalogue.GrantsEventLeaseAltered, + "mesh.seat." + catalogue.GrantsSeat + ".event." + catalogue.GrantsEventRemovalFailed, + "$JS.EVENT.ADVISORY.STREAM.DELETED." + AssignmentsStream, } }