docs+test(closeout): final-review reservations — stale ACL prose, worker test gaps, config sample fix
ci / nightly-windev (push) Has been skipped
ci / windows-x86 (push) Successful in 1m14s
ci / java (push) Successful in 2m10s
ci / portable (push) Successful in 8m31s

This commit is contained in:
Joseph Doherty
2026-08-17 05:23:23 -04:00
parent f5a58d884b
commit b621d692d0
18 changed files with 167 additions and 46 deletions
@@ -40,11 +40,21 @@ public interface IGatewayAlarmService
/// <summary>
/// True when the worker's most recent reconcile fetch hit the provider's
/// per-fetch cap, so <see cref="CurrentAlarms"/> may be missing active
/// alarms. The monitor is otherwise healthy — this is not a fault, it is
/// a completeness caveat, which is why it is separate from
/// per-fetch cap, so the active-alarm set may be missing alarms. The
/// monitor is otherwise healthy — this is not a fault, it is a
/// completeness caveat, which is why it is separate from
/// <see cref="State"/> and <see cref="LastError"/>. Cleared by the first
/// reconcile whose fetch comes back under the cap.
/// <para>
/// Read it as "as of the last full reconcile, the fetch was capped", not as
/// a property of a particular <see cref="CurrentAlarms"/> array: the two are
/// separate reads, and live transitions keep moving the cached set between
/// reconciles. A consumer that reads both — the dashboard poll does — can
/// therefore straddle a reconcile, in which case its caveat describes the
/// adjacent generation and the banner is at worst one poll stale. That is
/// the intended granularity for a completeness hint; pairing them exactly
/// would need a combined accessor this seam deliberately does not have.
/// </para>
/// </summary>
bool SnapshotTruncated { get; }
@@ -20,9 +20,12 @@ namespace ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;
/// values are stripped from a redacted copy of the event before it reaches any
/// dashboard client. The source <see cref="MxEvent"/> is shared with the gRPC
/// event path and the reconnect replay ring, so it is never mutated in place —
/// the redaction is applied to a deep clone. This closes the value-leak seam at
/// the mirror independently of the still-outstanding per-session hub ACL
/// (see <see cref="EventsHub"/>).
/// the redaction is applied to a deep clone. This is the second of two
/// independent layers: <see cref="IDashboardSessionAcl"/> decides at the
/// subscribe seam <em>which</em> sessions a caller may observe at all (see
/// <see cref="EventsHub"/>), while the redaction decides what a permitted
/// subscriber sees — so the value-leak seam stays closed whatever the ACL
/// admits.
/// </remarks>
/// <param name="hubContext">Hub context used to send to the session's group.</param>
/// <param name="viewerRegistry">
@@ -23,9 +23,12 @@ public interface IDashboardSessionAcl
/// session identified by <paramref name="sessionId"/>.
/// </summary>
/// <param name="principal">
/// The dashboard caller. <see langword="null"/>, unauthenticated, or claim-less
/// principals (including the anonymous-localhost path) are treated as Viewers
/// holding an empty tag grant.
/// The dashboard caller. <see langword="null"/> is denied outright — there is no
/// caller to grant tags to, so it never reaches the untagged-session branch and is
/// refused even under <c>UntaggedSessionVisibility=AllViewers</c>. An
/// unauthenticated or claim-less principal (the anonymous-localhost path included)
/// is a Viewer holding an empty tag grant, which denies every tagged session but
/// still follows that branch.
/// </param>
/// <param name="sessionId">Session id the caller wants to observe.</param>
/// <returns><see langword="true"/> when the caller may observe the session; otherwise <see langword="false"/>.</returns>