e3c003d978f91f5252548de0c4be2eb703e532b2
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e3c003d978 |
write-commands plan: execute Phase 1 discovery (no DB writes)
Phase 1 of docs/plans/write-commands-reverse-engineering.md is purely
discovery — static IL inspection, public-API enumeration, scope
elimination — and produces no DB writes. Phase 2 requires extending
NativeTraceHarness with a write scenario AND explicit operator approval
per the plan's safety rule §1, so it is deferred to a separate session.
Phase 1 findings recorded inline in the plan's status header:
1. §3.4 ModifyData/DeleteData eliminated — no managed wrapper exists.
`methods` returns zero hits for EditValue, ModifyValue, EditData,
DeleteData, ModifyData, OverwriteData. Per the plan's own §3.4
disposition rule, this op is REST/SMC-only.
2. §4.a native serializer tokens identified for Phase 2:
Public managed-wrapper write API in ArchestrA.HistorianAccess:
- AddTag (0x0600619A)
- AddStreamedValue × 3 overloads (0x0600618C/D/E)
- AddNonStreamedValue × 2 overloads (0x0600618F/90)
- DeleteTags (0x060061A4)
- AddRevisionValuesBegin / AddRevisionValue / AddRevisionValuesEnd
/ AddRevisionValues (0x06006175-77, 0x0600617F)
— covers the bulk-modify use case the eliminated ModifyData would
have served. Worth folding into Phase 2 scope.
Native serializers:
- CTagUtil.ConvertTagMetadataToHistorianTag (0x060055CE) — 412 IL
instructions; builds CTagMetadata for analog/discrete/string.
Calls every CTagMetadata accessor we'd need to surface
(Min/MaxRaw, Min/MaxEU, Unit, Message0/1, MaxLength,
IntegralDivisor, DefaultTagRate, RolloverValue) plus all the
CDataType predicates already decoded.
- CHistoryConnectionWCF.AddStreamValuesToHistorian (0x0600404C)
— confirms the on-wire shape matches our existing
IHistoryServiceContract2.AddStreamValues2 declaration.
3. Chicken-and-egg resolved: the first §3.1 EnsT2 test creates the
sandbox tag itself, so no SMC step is needed.
4. Open question §8.6 answered — the wrapper exposes both
AddStreamedValue and AddNonStreamedValue, so the SDK should
eventually surface both real-time and backfill write modes.
Phase 2 next steps recorded inline in the plan as a 5-item executable
checklist (extend harness with --scenario write, capture, decode
EnsT2(analog) + AddS2 bytes, implement public surface, gated live
tests).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
6888b8c55a |
Wire SDK for remote-TCP end to end; live-verify RemoteTcpIntegrated
Executes docs/plans/tcp-connection-validation.md. Full read-only SDK
surface now works against a remote AVEVA Historian over Net.TCP with
Windows transport authentication. 124/124 tests pass; the +10 new live
integration tests in RemoteTcpIntegrationTests.cs are gated by
HISTORIAN_REMOTE_TCP_HOST + HISTORIAN_REMOTE_TCP_TAG.
Two SDK bugs found while executing the plan:
1. Historian2020ProtocolDialect.ReadRawAsync / ReadAggregateAsync /
ReadAtTimeAsync / ReadEventsAsync had explicit
`if (_options.Transport != HistorianTransport.LocalPipe) return Missing<T>`
guards. These were a guardrail from before the orchestrators handled
TCP; the orchestrators have always used CreateBindingPair(options)
which dispatches on transport correctly. Gates removed.
2. HistorianWcfStatusClient and HistorianWcfEventOrchestrator hardcoded
HistorianWcfBindingFactory.CreatePipeEndpointAddress for the auxiliary
services (Stat, Trx, Retr). Worked for LocalPipe; for TCP it produced
an EndpointAddress with scheme net.pipe attached to a TCP binding
(channel factory rejected the URI). Worse, when only the endpoint was
transport-aware, the binding still requested a Windows-transport-
security upgrade that the Stat endpoint over TCP doesn't support
(auxiliaries don't repeat the auth — the Hist session is already
authenticated). Added two helpers:
- HistorianWcfBindingFactory.CreateAuxiliaryEndpointAddress(options, name)
-> net.pipe for LocalPipe, net.tcp for remote
- HistorianWcfBindingFactory.CreateAuxiliaryBinding(options)
-> NamedPipe for LocalPipe, plain MdasNetTcpBinding for remote
Both call sites updated.
Live verification against the remote (probed previously in prior
sessions; reachability re-confirmed today):
- ProbeAsync over RemoteTcpIntegrated and RemoteTcpCertificate
- ReadRawAsync (8 samples returned for SysTimeSec)
- ReadAggregateAsync (TimeWeightedAverage, 1-min cycle, 10-min window)
- ReadAtTimeAsync (3 timestamps)
- BrowseTagNamesAsync (finds the test tag)
- GetTagMetadataAsync (full metadata populated)
- ReadEventsAsync (chain runs without throwing)
- GetConnectionStatusAsync (ConnectedToServer=true)
- GetSystemParameterAsync (HistorianVersion="20,0,000,000")
The default 'NT SERVICE\aahClientAccessPoint' SPN turned out to work
for the remote too — discovery workstream A (SPN-finding) was not
needed in practice.
README and the TCP plan doc updated to reflect the executed status.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
1b31c24c8d |
Plan TCP connection validation (live verification of the existing remote-TCP plumbing)
docs/plans/tcp-connection-validation.md (308 lines): Plan to live-verify the RemoteTcpIntegrated and RemoteTcpCertificate transports against an actual remote AVEVA Historian. The SDK's HistorianWcfBindingFactory already builds all three bindings (CreateMdasNetTcpBinding, CreateMdasNetTcpWindowsBinding, CreateMdasNetTcpCertificateBinding) but only LocalPipe has been exercised end-to-end. Wire format is identical across transports; only WCF binding shape and credential negotiation differ. Discovery workstreams A/B/C run in parallel (SPN discovery via static IL + WCF probe; cert binding requirements via wcf-cert-probe; operator preconditions checklist). D blocks on A. Verification tracks V1-V5 also parallelize once V1 (ProbeAsync) confirms the transport is reachable. Includes risks (SPN mismatch, cert chain validation, idle disconnect, Open2 response delta, compression negotiation, time skew, false-positive empty reads), success criteria, eight open questions, and explicit out-of-scope items filed under the existing write-commands and store-forward plans. No code changes; no preconditions assumed met. Implementer must satisfy §2 preconditions (reachable remote Historian, port 32568 open, test account, SPN registered, etc.) before §4 discovery starts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
6f01b83313 |
Plan two reverse-engineering campaigns: write commands + store/forward cache
docs/plans/write-commands-reverse-engineering.md (425 lines): Plan for adding WriteValueAsync (AddS2 stream values), EnsureTags2 for analog/discrete/string tags, and DelT for sandbox cleanup. Hard safety rules center on a dedicated sandbox tag gated by env var, time-bounded writes, SQL ground-truth verification per session, explicit rollback. Five-step RE workflow mirrors the read/event decode (static IL discovery -> instrument-wcf-writemessage capture -> instrument-wcf-readmessage capture -> byte/IL alignment -> managed serializer + golden-byte tests). Risks call out auth-chain unknowns, parameter-name-mismatch class, silent-success failure modes, History-vs-Storage service question. docs/plans/store-forward-cache-reverse-engineering.md (501 lines): Plan for replacing the synthesized GetStoreForwardStatusAsync with a real implementation. Architecture investigation already partially answered via IL inspection during planning: ArchestrA.HistorianAccess. GetStoreForwardStatus (token 0x06006187) reads an in-process C struct via calli to mdas_GetStorageStatus, kept current by server-pushed WCF callbacks (IStatusServiceContract2.SetStoreForwardEvent). CSFConnection. GetSFPipeName indicates a separate Named Pipe sidecar exists when SF is configured. Five parallelizable discovery workstreams, six concrete RE steps with cited tokens, eight risks, eight success criteria. Both plans deliberately produce no code changes and no captures. They exist so the next implementer can start with full context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c95824a65d |
Initial commit: managed .NET 10 AVEVA Historian SDK + reverse-engineering toolkit
Full read-only SDK (src/AVEVA.Historian.Client) implementing the CLAUDE.md required
surface against AVEVA Historian's binary WCF protocol — no native AVEVA runtime
dependency. All operations live-verified against a local Historian:
- ProbeAsync, ReadRawAsync, ReadAggregateAsync, ReadAtTimeAsync, ReadEventsAsync
- BrowseTagNamesAsync, GetTagMetadataAsync (17 native data-type codes mapped)
- GetConnectionStatusAsync, GetStoreForwardStatusAsync, GetSystemParameterAsync
- 108/108 unit + integration tests pass
Includes the reverse-engineering toolkit (tools/AVEVA.Historian.ReverseEngineering)
used to decode the protocol: WCF probes, IL inspection via dnlib, and IL-rewrite
instrumentation (instrument-wcf-{write,read}message etc.) plus the .NET Framework
trace harness (tools/AVEVA.Historian.NativeTraceHarness) for parity testing.
Sanitized handoff evidence under docs/reverse-engineering/. Native AVEVA binaries
(current/, aveva-install-x64/, aveva-install-x86/) are gitignored — fetch separately
from the AVEVA installer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|