# Follow-up batch #674–#678 — design (2026-10-11) Follow-ups filed after the #667–#673 batch. Base: master `bc03adb1`. User-approved; recommended choices throughout. Investigation found three new defects (client endpoint port not rewritten; role overlays never load on cluster-role nodes; Gateway Count/Average mode mapping) — the first two are fixed here, the third is filed. | Lane | Scope | Model | |---|---|---| | L1 | #674 HistoryUpdate posture | opus | | L2 | #675 reverse event paging | opus | | L3 | #677 aggregates | opus | | L4 | client (#677.5, #678.5/.6, #674.6) | sonnet | | L5 | #676 OpcUaClient | opus | | L6 | #678.1–.4 + role-overlay bug | sonnet | ## L1 — #674 - **674.1:** spike on QuestDB 10.0.1 showed TTL is judged against `min(maxTs, wall clock)` (`cairo.ttl.use.wall.clock=true` default) — a 2066 row evicted nothing. Add a QuestDB integration test pinning that + a docs note. HistoryUpdate refuses a SourceTimestamp beyond `now + ServerHistorian:HistoryUpdateMaxFutureSkew` (default 1 day) with `BadOutOfRange`; the recorder is not bounded. - **674.2:** SqlServer base schema requirement back to v1; `SupportsModifiedTrail` (v ≥ 2). On v1: modified reads and HistoryUpdate ⇒ `BadHistoryOperationUnsupported` (nothing sent), retention skips `SampleModified`, one Warning per boot. - **674.3:** HistoryUpdate Primary-gated (off-Primary ⇒ `BadInvalidState`, same shape as `NativeAlarmAckPrimaryGate`). Retry duplicates on QuestDB documented; no DEDUP key. - 674.4/674.5 documented only. ## L2 — #675 - Reverse event reads: `reverse` flag on `IHistorianDataSource.ReadEventsAsync`; SqlServer/QuestDB order DESC and take the top N; direction-aware cursor (reuse raw `SliceTieCluster(reverse:)`); Gateway ⇒ `BadHistoryOperationUnsupported` for reverse. - End-only event read ⇒ backward (mirrors raw). - Offline test pinning `DateTime.MaxValue` through the Gateway proto/FILETIME encoding; live AVEVA leg stays open (VPN). ## L3 — #677 - Reverse processed reads per SDK/Part 13: buckets anchored at the later (start) time stepping back, partial bucket earliest, bucket timestamp = later edge. Parity test vs SDK `AggregateCalculator`. Client-visible, release-noted. - Partial bit also when the data starts inside a bucket (no bounding prior). - `AggregateConfiguration`: `UseServerCapabilitiesDefaults` or values equal to the server defaults ⇒ served; otherwise per-node `BadAggregateConfigurationRejected`. - Gateway provisioner sends `IntegralDivisor = 1` (proto3 default 0). Live magnitude check stays open (VPN). ## L4 — client - `EndpointSelector.SelectBest` rewrites host **and** port of the advertised endpoint (fixes rig `:4841` cert error). - Client aggregate enum/mapper/CLI/UI gain TimeAverage, TimeAverage2, Total, Total2, Interpolative. - History read refusal ⇒ one-line `CommandException`, no stack trace. - `NodeManagerHistoryReadTests` non-historized case sets `IsReadModified=false`. ## L5 — #676 - Driver endpoint host+port rewrite; in-process TCP-stall proxy wire test (in-place blip, same session, Good republish, no regression). - Remove dead `ReconnectPeriod` (options, AdminUI form, docs, tests); stored JSON with it still parses. - New opt-in `IDriverConnectionLossSource` (Core.Abstractions): raised once per session by OpcUaClient only on a definitive loss (`BadSessionIdInvalid`/`BadSessionClosed`/`BadSessionNotActivated`/subscription lost); `DriverInstanceActor` (attach PreStart, detach PostStop) turns it into `DisconnectObserved` only while Connected. Ambiguous codes keep going through the #527 watchdog. - Information-level per-recovery replay-drop summary. Equal-timestamp drop documented. ## L6 — small - Retention: mid-command cancel test + `ClearPool` fallback test with falsification control. - #672 tests: initial-state unreachable path; strengthen `Self_unreachable_is_ignored`; edge-triggered Debug log. - FOCAS `WireBackendTests`: wait for motor speeds too; `WaitFor` fails on timeout. - QuestDB TTL-cleared log wording; `docker-dev/docker-compose.debug.yml` Debug recipe. - Role overlay suffix built from plain roles only — after auditing each `appsettings..json` and stripping anything that would change production behaviour on activation. ## Live gates (docker-dev) 1. opc-plc `docker restart` recovers in seconds (was ~100 s); pause-blip re-check. 2. Client.CLI connects to `:4841`–`:4845`. 3. HistoryUpdate refused on the Secondary, accepted on the Primary; v1-schema DB keeps historizing. 4. Reverse event paging and reverse processed reads over the wire, SqlServer + QuestDB.