docs(alarms): wnwrap live-probe findings — GUID identity, ALARM_RECORDS COUNT
Both questions stay open, and the reason is the finding: the dev rig's alarm UDAs reject a plain MXAccess Write with SecurityError/detail=1008 from the responding automation object, so no alarm instance can be created to follow through an acknowledge and no population can be built to overflow a capped fetch. The rig is otherwise live — objects deployed and on scan, wnwrap subscribed, GetXmlCurrentAlarms2 returning well-formed XML — which is what makes the blocker specific and the unblock (engine-side script, or AuthenticateUser + WriteSecured, or reclassifying the UDAs) actionable. Comment-only changes in WnWrapAlarmConsumer: scope the GUID-identity claim to the leg live capture actually covers, and record that ALARM_RECORDS/@COUNT exists as a candidate exact truncation signal but is deliberately not trusted because its semantics under a capped reply are unverified. No behavior change.
This commit is contained in:
@@ -402,11 +402,15 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
|
||||
Dictionary<Guid, MxAlarmSnapshotRecord> next = ParseSnapshotXml(xml, out int fetchedRecordCount);
|
||||
|
||||
// TRUNCATION CLIFF. GetXmlCurrentAlarms2 caps its reply at maxAlmCnt
|
||||
// and gives no "there is more" flag, so a reply holding exactly the
|
||||
// cap is indistinguishable from a galaxy that happens to have exactly
|
||||
// that many active alarms. Treat the ambiguous case as truncated: the
|
||||
// false-positive cost is a snapshot that stays stale for one poll, the
|
||||
// false-negative cost is every alarm past the cap reading as cleared.
|
||||
// and gives no *verified* "there is more" flag, so a reply holding
|
||||
// exactly the cap is indistinguishable from a galaxy that happens to
|
||||
// have exactly that many active alarms. Treat the ambiguous case as
|
||||
// truncated: the false-positive cost is a snapshot that stays stale for
|
||||
// one poll, the false-negative cost is every alarm past the cap reading
|
||||
// as cleared. (The reply's ALARM_RECORDS/@COUNT attribute is a
|
||||
// candidate exact signal, but only if it reports the total rather than
|
||||
// the records in the reply — untested on a live rig, see
|
||||
// docs/AlarmProbeFindings.md.)
|
||||
bool truncated = IsTruncatedFetch(fetchedRecordCount, maxAlarmsPerFetch);
|
||||
|
||||
IReadOnlyList<MxAlarmTransitionEvent> transitions;
|
||||
@@ -436,11 +440,15 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
|
||||
/// Decides whether a fetch that came back holding
|
||||
/// <paramref name="fetchedRecordCount"/> records hit the cap.
|
||||
/// <c>GetXmlCurrentAlarms2</c> caps its reply at <c>maxAlmCnt</c> and
|
||||
/// offers no "more available" flag, so a reply at exactly the cap is
|
||||
/// indistinguishable from a galaxy that happens to hold exactly that
|
||||
/// many active alarms; both are treated as truncated. Exposed as
|
||||
/// <c>internal static</c> so the rule is unit-testable without the
|
||||
/// wnwrapConsumer COM object.
|
||||
/// offers no confirmed "more available" flag, so a reply at exactly the
|
||||
/// cap is indistinguishable from a galaxy that happens to hold exactly
|
||||
/// that many active alarms; both are treated as truncated. The reply
|
||||
/// root carries an <c>ALARM_RECORDS/@COUNT</c> attribute that would make
|
||||
/// the test exact if it reported the total active count rather than the
|
||||
/// records in this reply; a live probe could not discriminate the two
|
||||
/// (see <c>docs/AlarmProbeFindings.md</c>), so the count is deliberately
|
||||
/// not trusted here. Exposed as <c>internal static</c> so the rule is
|
||||
/// unit-testable without the wnwrapConsumer COM object.
|
||||
/// </summary>
|
||||
/// <param name="fetchedRecordCount">ALARM records the reply carried.</param>
|
||||
/// <param name="maxAlarmsPerFetch">The cap that was passed to the fetch.</param>
|
||||
@@ -599,6 +607,17 @@ public sealed class WnWrapAlarmConsumer : IMxAccessAlarmConsumer
|
||||
/// stays correct for the alarms it does carry — first sightings
|
||||
/// and state changes are computed from presence alone.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Every rule above assumes the GUID identifies the alarm
|
||||
/// <em>instance</em> rather than the state it is in: a re-minted
|
||||
/// GUID would read as the old alarm vanishing and a new one
|
||||
/// appearing, i.e. a spurious Clear plus a spurious Raise. Live
|
||||
/// capture confirms stability across the active→returned leg only
|
||||
/// (<c>docs/AlarmClientDiscovery.md</c>); the acknowledge leg and
|
||||
/// re-raise-after-clear are assumed, not observed, because the dev
|
||||
/// rig's alarm attributes reject unauthenticated writes — see
|
||||
/// <c>docs/AlarmProbeFindings.md</c>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="previous">The snapshot from the previous poll (or empty on first call).</param>
|
||||
/// <param name="next">The snapshot just parsed from <c>GetXmlCurrentAlarms2</c>.</param>
|
||||
|
||||
Reference in New Issue
Block a user