The R2-06 live gate found the historian's Int1 analog-tag creation path
is server-degenerate; filed gateway-side as historiangw #11 (documented
as an explicit exclusion, PR #16), routed back as lmxopcua #441.
OtOpcUa's HistorianTypeMapper now maps Boolean → Int2. Updates the
OtOpcUa entry: master tip 7f79cd59 → 38e21df2, live gate 6/6.
HistorianGateway's Later tier (roadmap 16-21) landed on main via a coordinated
two-PR merge (origin/main @ 6a24a30); update the umbrella index from the stale
'open PRs pending merge' framing to merged. Only the 1.0.0 TLS-default flip remains.
ApiKeyRecord/ApiKeyListItem gain a nullable ExpiresUtc (NULL = never
expires); ApiKeyFailure gains KeyExpired. ApiKeyVerifier rejects a key
whose ExpiresUtc is at-or-before now (inclusive, injected clock), before
the secret comparison. CreateKeyAsync gets an expiresUtc overload; rotate
preserves existing expiry. SQLite schema bumps to v3: a nullable
expires_utc column, added to fresh DBs via CREATE and to existing v1/v2
DBs via an idempotent guarded ALTER — donor v2 gateway-auth.db upgrades
in place, no key invalidated. Version 0.1.3 -> 0.1.4 (not yet published;
nuget push is human-gated). Consumers (HistorianGateway, mxaccessgw) bump
to 0.1.4 to set/enforce expiry. 146 Auth.ApiKeys tests pass.
histsdk is now owned/imported (not vendored) — retire the 'vendored/re-vendor'
language; add the Client.Cli smoke CLI and record origin/main @ 93c6051 (the
repo-wide XML-doc sweep).
The ScadaBridge entry showed a `_git_` placeholder in the Repo column; set it
to the actual remote (gitea.dohertylan.com/dohertj2/ScadaBridge) to match the
peer rows. Keeps the umbrella index in sync with the repo, per the reciprocal
propagate-cross-repo-changes rule now recorded in ScadaBridge's CLAUDE.md.
Record the new HistorianGateway/docker/ local container deployment in the
umbrella inventory: HistorianGateway table row (real wonder datasources,
login + gRPC API-key auth disabled, runtime-only image / VPN / isolated
compose project) + a publish+compose recipe in the per-project commands.
OtOpcUa now consumes HistorianGateway as its sole historian read/write backend
(ZB.MOM.WW.HistorianGateway.Client; continuous historization + alarms), retiring
its bespoke Wonderware historian driver — merged to OtOpcUa master (PR #423).
Gateway follow-ups merged to historiangw main: WriteLiveValues UTC->server-local
timestamp fix + SendEvent Source_Object protocol-limitation doc (PR #6, pending.md
C4), the Plan-1 client lib + packable Contracts (PR #5), and a C2 cross-ref docs
PR (#4). Updated the OtOpcUa + HistorianGateway entries and the coupling note from
"independent / not a dependency" to "OtOpcUa depends on HistorianGateway".
Pre-existing OtOpcUa test failure tracked as lmxopcua issue #424.
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
Part C + C2 + the SQL-path ReadEvents are all merged to origin/main (gateway
fabab1a, histsdk f0a1b04). Event reads now work via Runtime.dbo.Events behind
RuntimeDb:EventReadsEnabled (the practical workaround for the C2 server gate).
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
Replaces the wrong "WCF not served on 2023 R2" (a test error vs the reverse
tunnel). WCF cert transport + auth reach the historian; rows are server-gated on
both transports (same per-connection gate as gRPC). Not client-fixable.
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
Event reads unavailable on the 2023 R2 historian over both transports — gRPC
retrieval-server-gated, legacy WCF net.tcp not served (live-disproven 2026-06-25).
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
Records the Part C minimal work landed on the gateway's local main (unpushed):
Int8/UInt8 live write types un-gated + live-proven; 2023 R2 gRPC interface-version
evidence recorded; UInt1 server-blocked (degenerate analog tag) → re-gated.
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
Ports the alarm-attribute row type and its internal mapping helper from
mxaccessgw (ZB.MOM.WW.MxGateway.Server.Galaxy) into the shared lib as
the first step of the galaxy-0.2.0-mxaccessgw-gaps feature branch.
Adds InternalsVisibleTo so the test project can exercise MapAlarmRow
without a database. Five unit tests all pass; zero-warning build.
Dev two plaintext endpoints (appsettings.Development.json) unchanged;
production now uses a single Kestrel Https Http1AndHttp2 endpoint (ALPN)
multiplexing dashboard + gRPC over one port; warn-only without TLS (valid
behind reverse proxy / Kubernetes ingress).
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
HistorianGateway is now pushed to gitea (gitea.dohertylan.com/dohertj2/historiangw), and
ZB.MOM.WW.GalaxyRepository is published to the Gitea feed and consumed as a PackageReference
(no longer a cross-repo ProjectReference). Updates the sister-project row, the component
table, and the GalaxyRepository narrative; test figure 584 green -> 590 total (584 on macOS).
- Add HistorianGateway to the Runtime/implementation table (single-process
.NET 10 x64 gRPC sidecar; no COM/x86; 584 tests; local only, not yet
pushed to gitea)
- Update "What this repository is" count (five → six pieces of source;
add GalaxyRepository)
- Add HistorianGateway paragraph to Cross-project relationships / Net effect
(independent sidecar; no runtime coupling to the other three; depends on
shared GalaxyRepository lib via ProjectReference)
- Add ZB.MOM.WW.GalaxyRepository row to Component normalization table +
full description paragraph (built 0.1.0; consumed by HistorianGateway;
mxaccessgw adoption is a follow-on; not yet published to Gitea feed)
- Add HistorianGateway primary commands block (build/test/run/live-integration)
- Extend Shared GLAuth note to cover HistorianGateway
The RemoteGrpc orchestrator drove the SSPI/NTLM token loop through
HistoryService.ExchangeKey, which the 2023 R2 contract analysis shows is a
separate key-exchange/cert op — not the credential handshake. The server
rejected the NTLM Type-1 token at round 0. The Negotiate loop belongs on
StorageService.ValidateClientCredential (Handle/InBuff -> Status/OutBuff;
field names match the 2020 native contract). Live-verified end-to-end against
a 2023 R2 Historian (wonder-sql-vd03): SysTimeSec raw read returns correct
timestamped values.