fix(acl): keep the SDK's audit guard and EventsMonitored bookkeeping on Server-object delivery (#586)

Review of 75e559f6:
- OnConditionReportEvent now mirrors MonitoredNode2's AuditEventState guard (only while Server.Auditing,
  over SignAndEncrypt / https-uabinary). Conditions report their Part 9 method audit events through
  themselves, so the first cut queued AuditConditionAcknowledge (i=8944) etc. to every i=2253 item with
  auditing off -- the removed folder->Server forward used to drop them.
- ReconcileAllEventsMonitoring keeps one AreEventsMonitored unit on every materialised condition while any
  i=2253 item exists (called from SubscribeToAllEvents, materialise, removal, rebuild), so
  ConditionState.EventsMonitored() is true on a server whose only subscribers are Server-object items.
  A protected SubscribeToEvents override no-ops all-events items, which stops the SDK's AddRootNotifier
  (unsubscribe: true bug) taking that unit back from conditions rebuilt under a live item.

Flag-off over-the-wire coverage: Acknowledge/AddComment with and without a folder co-subscriber (no audit
event, transitions once each), EventsMonitored on/after-rebuild/off, rebuild survival with one copy per
event, native + scripted conditions once each, refresh once per condition with RefreshStart/End; plus an
ACL-on native-vs-scripted notifier-folder decision. Falsified: removing the audit guard reds both audit
cases; removing the reconcile reds the monitored test.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-08 00:05:12 -04:00
parent 75e559f6d8
commit fe92ff4c34
4 changed files with 460 additions and 6 deletions
+10
View File
@@ -560,6 +560,16 @@ Behaviours worth knowing before enabling it:
check on (once per condition, not once per notifier it is wired to). Without that, a refresh would
replay every condition's current state to any session.
- Inert with the flag off: every Server-object item receives every condition, as before.
- The replacement delivery keeps the two behaviours of the SDK path it replaced. **Audit events** a
condition reports through itself (`AuditConditionAcknowledgeEventType`, Comment, Enable, Shelving)
reach a Server-object item only while the server is auditing, over SignAndEncrypt or https-binary,
which is exactly the SDK's own guard. And while any Server-object item exists, every condition counts as
**monitored** (`ConditionState.EventsMonitored()`), so the SDK still reports its method-driven state
changes on a server whose only subscribers are Server-object items. Both were caught in review: the
first cut queued `i=8944` to every Server-object item with auditing off, and left conditions
unmonitored. The second also needed the SDK's `AddRootNotifier` neutralised: its "subscribe existing
all-events items with `unsubscribe: true`" bug would otherwise take the unit back from every
condition rebuilt under a live item.
Residual, not closed by #586: **audit and model-change events** (`AuditWriteUpdateEvent`,
`GeneralModelChangeEvent`, …) are still reported straight to the Server object and reach every