From fbec27ff8c7d034fb04cfc1bd77eace657819297 Mon Sep 17 00:00:00 2001 From: Jonas Bengtsson Date: Mon, 5 Oct 2026 20:32:13 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=89=20Initial=20commit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 2038 +++ ARCHITECTURE.md | 3602 +++++ docs/configuration/configuration-reference.md | 5758 ++++++++ .../codex-implementation-specification.md | 10830 ++++++++++++++++ docs/product/software-specification.md | 3288 +++++ 5 files changed, 25516 insertions(+) create mode 100644 AGENTS.md create mode 100644 ARCHITECTURE.md create mode 100644 docs/configuration/configuration-reference.md create mode 100644 docs/product/codex-implementation-specification.md create mode 100644 docs/product/software-specification.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cb13302 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,2038 @@ +\# AquaCom Integration Gateway – Codex Instructions + + + +This repository implements the \*\*AquaCom Integration Gateway\*\*. + + + +The gateway communicates with AquaCom-compatible field equipment, normalizes live and historical process data, exposes data through OPC UA, and supports one or more historical storage destinations. + + + +Before making architectural or behavioral changes, read: + + + +\- `ARCHITECTURE.md` + +\- `docs/product/software-specification.md` + +\- `docs/architecture/` + +\- `docs/protocol/` + +\- `docs/configuration/configuration-reference.md` + + + +For substantial work, also read or create the applicable ExecPlan under: + + + +```text + +docs/exec-plans/ + +``` + + + +\--- + + + +\## 1. Primary architecture + + + +The intended architecture is: + + + +```text + +AquaCom + + │ + + ▼ + +Transport + + │ + + ▼ + +AquaCom Protocol Engine + + │ + + ▼ + +Station / Session Manager + + │ + + ▼ + +Canonical Data Model + + │ + + ├──────────────► Current-State Service + + │ │ + + │ ▼ + + │ OPC UA + + │ Data Access + + │ + + └──────────────► Historical Pipeline + + │ + + ┌──────────┼──────────┐ + + │ │ │ + + ▼ ▼ ▼ + + Repository Sink A Sink B + + │ + + ▼ + + OPC UA + + Historical Access + +``` + + + +Maintain these boundaries. + + + +\--- + + + +\## 2. Non-negotiable architecture rules + + + +The following rules are mandatory. + + + +\### 2.1 AquaCom isolation + + + +All AquaCom-specific parsing, encoding, framing, checksum handling and protocol behavior belongs in the AquaCom modules. + + + +No OPC UA, history repository or storage adapter shall parse AquaCom telegrams. + + + +\### 2.2 OPC UA isolation + + + +The OPC UA implementation shall consume canonical gateway data. + + + +The OPC UA implementation shall not: + + + +\- construct AquaCom requests; + +\- decode AquaCom responses; + +\- perform direct AquaCom history retrieval; + +\- depend upon AquaCom telegram structures. + + + +\### 2.3 Storage isolation + + + +Storage implementations shall consume canonical historical records. + + + +Storage adapters shall not depend upon: + + + +\- AquaCom telegrams; + +\- AquaCom addressing; + +\- AquaCom command structures; + +\- OPC UA node implementations. + + + +\### 2.4 Canonical model + + + +Data shall cross subsystem boundaries through the canonical gateway model. + + + +Do not bypass the canonical model for convenience. + + + +\### 2.5 Live and historical data are different + + + +Historical samples shall never be replayed as current values merely because they were recently received. + + + +For example: + + + +```text + +Gateway receives at: 18:30 + +Historical sample timestamp: 14:05 + +``` + + + +The value belongs to history at `14:05`. + + + +It is not a new live value at `18:30`. + + + +\### 2.6 Preserve timestamps + + + +Keep at least the following concepts separate: + + + +```text + +SourceTimestamp + +ReceivedTimestamp + +``` + + + +Where applicable also maintain: + + + +```text + +ServerTimestamp + +UpdatedTimestamp + +``` + + + +Never silently replace a valid AquaCom source timestamp with gateway receipt time. + + + +\### 2.7 Stable identifiers + + + +`StationId`, `PointId` and OPC UA NodeIds must remain stable across: + + + +\- process restart; + +\- gateway restart; + +\- software upgrade; + +\- display-name changes; + +\- transport-address changes. + + + +Display names are not stable identifiers. + + + +\### 2.8 Live acquisition priority + + + +Normal live acquisition shall take priority over bulk historical backfill where both compete for limited AquaCom communication capacity. + + + +\--- + + + +\## 3. Critical AquaCom rule + + + +\*\*Never invent AquaCom protocol behavior.\*\* + + + +Do not infer undocumented protocol fields merely because an implementation appears plausible. + + + +Do not invent: + + + +\- telegram fields; + +\- byte positions; + +\- ASCII fields; + +\- framing rules; + +\- checksum algorithms; + +\- addressing behavior; + +\- command codes; + +\- response codes; + +\- value scaling; + +\- timestamp encoding; + +\- alarm semantics; + +\- historical-data semantics. + + + +AquaCom behavior may only be implemented when supported by evidence. + + + +Acceptable evidence includes: + + + +1\. authoritative AquaCom documentation; + +2\. validated traffic captures; + +3\. validated behavior from an existing known-good implementation; + +4\. approved protocol test vectors. + + + +If required protocol information is unavailable: + + + +1\. do not guess; + +2\. leave the feature unimplemented; + +3\. add an entry to: + + + +```text + +docs/protocol/protocol-gaps.md + +``` + + + +4\. add interfaces, fixtures or simulation support around the missing implementation where useful. + + + +Compilation success is not evidence that an AquaCom implementation is correct. + + + +\--- + + + +\## 4. Protocol traceability + + + +Every implemented AquaCom operation shall be traceable to its evidence. + + + +Document protocol implementation under: + + + +```text + +docs/protocol/ + +``` + + + +Where practical record: + + + +```text + +Operation + +Evidence source + +Specification section + +Capture/test-vector reference + +Supported controller types + +Implementation status + +Associated tests + +Known limitations + +``` + + + +Every implemented telegram type shall have automated test vectors. + + + +\--- + + + +\## 5. Protocol fixtures + + + +Protocol fixtures belong under: + + + +```text + +fixtures/aquacom/ + +``` + + + +Fixtures derived from operational traffic shall be sanitized before being committed. + + + +Do not commit unnecessary: + + + +\- production IP addresses; + +\- phone numbers; + +\- station identifiers; + +\- credentials; + +\- private network information; + +\- other operationally sensitive information. + + + +Reference fixtures used for protocol validation should remain immutable unless there is a documented reason to change them. + + + +\--- + + + +\## 6. Core data model + + + +The core domain shall remain independent of AquaCom, OPC UA and storage technology. + + + +Core concepts include: + + + +```text + +StationId + +PointId + +CurrentValue + +HistoricalSample + +DataQuality + +AcquisitionSource + +CommunicationState + +StationState + +HistorySynchronizationState + +``` + + + +The core layer must not reference an OPC UA library or database-specific API. + + + +\--- + + + +\## 7. CurrentValue requirements + + + +A canonical current value shall conceptually contain: + + + +```text + +StationId + +PointId + +Value + +DataType + +Quality + +SourceTimestamp? + +ReceivedTimestamp + +UpdatedTimestamp + +AcquisitionSource + +``` + + + +A missing source timestamp must remain distinguishable from a gateway-generated timestamp. + + + +\--- + + + +\## 8. HistoricalSample requirements + + + +A canonical historical sample shall conceptually contain: + + + +```text + +StationId + +PointId + +Value + +DataType + +Quality + +SourceTimestamp + +ReceivedTimestamp + +AcquisitionSource + +AcquisitionId? + +Metadata? + +``` + + + +A normal historical process sample requires a meaningful `SourceTimestamp`. + + + +Do not fabricate one solely to make storage easier. + + + +\--- + + + +\## 9. Historical processing + + + +The historical pipeline shall logically follow: + + + +```text + +HistoricalSample + + │ + + ▼ + +Validation + + │ + + ▼ + +Normalization + + │ + + ▼ + +Deduplication + + │ + + ▼ + +Durable Spool + + │ + + ├────► Repository + + ├────► Storage Sink A + + └────► Storage Sink B + +``` + + + +Historical delivery shall be restart-safe. + + + +\--- + + + +\## 10. Deduplication + + + +Default historical identity is conceptually: + + + +```text + +StationId + +\+ + +PointId + +\+ + +SourceTimestamp + +``` + + + +Use a stronger device-provided identity if verified and available. + + + +Duplicate handling must be deterministic. + + + +Do not silently overwrite conflicting historical values. + + + +The preferred default for conflicting values is: + + + +```text + +REJECT\_CONFLICT + +``` + + + +and generate diagnostics. + + + +\--- + + + +\## 11. History synchronization + + + +Historical synchronization state shall survive restart. + + + +Do not advance a synchronization watermark until the implementation has sufficient evidence that the corresponding data interval has been successfully processed. + + + +Historical synchronization shall support interruption and continuation. + + + +Large backfills shall be throttleable. + + + +\--- + + + +\## 12. OPC UA rules + + + +OPC UA is a northbound interface to gateway information. + + + +\### Current data + + + +Map canonical current information approximately as: + + + +```text + +Value + + → OPC UA Value + + + +SourceTimestamp + + → OPC UA SourceTimestamp + + + +Gateway processing timestamp + + → OPC UA ServerTimestamp + + + +DataQuality + + → OPC UA StatusCode + +``` + + + +\### Historical data + + + +OPC UA Historical Access shall query a History Repository abstraction. + + + +Never implement: + + + +```text + +OPC UA HistoryRead + + ↓ + +synchronous AquaCom request + + ↓ + +wait for RTU + +``` + + + +Implement: + + + +```text + +AquaCom history synchronization + + ↓ + +Historical Repository + + + +OPC UA HistoryRead + + ↓ + +Historical Repository + +``` + + + +The client-visible OPC UA history interface must remain decoupled from field-device communication latency. + + + +\### NodeIds + + + +OPC UA NodeIds shall be deterministic and stable. + + + +Changing a point's display name shall not normally change its NodeId. + + + +\### Writes + + + +Process-control writes are outside the initial production scope unless explicitly approved. + + + +OPC UA Historical Update shall be disabled by default. + + + +\--- + + + +\## 13. Storage rules + + + +Distinguish: + + + +```text + +Repository + +``` + + + +from: + + + +```text + +Storage Sink + +``` + + + +A \*\*Repository\*\* supports historical queries. + + + +A \*\*Storage Sink\*\* accepts historical delivery but does not necessarily support queries. + + + +One component may implement both. + + + +Do not require every storage destination to become an OPC UA Historical Access source. + + + +\--- + + + +\## 14. Multiple storage destinations + + + +Historical data may be delivered to multiple destinations. + + + +Each destination shall maintain independent: + + + +\- health; + +\- acknowledgement; + +\- retry state; + +\- diagnostics. + + + +Failure of one storage destination shall not unnecessarily stop other destinations. + + + +A destination may be configured as: + + + +```text + +REQUIRED + +``` + + + +or: + + + +```text + +OPTIONAL + +``` + + + +Required delivery behavior shall be explicit. + + + +\--- + + + +\## 15. Durable spool + + + +Historical data pending storage shall use persistent buffering. + + + +The spool must not be an unbounded in-memory queue. + + + +Spool state shall survive process restart. + + + +Each destination shall acknowledge delivery independently. + + + +Do not delete a record solely because one of several required destinations accepted it. + + + +\--- + + + +\## 16. Configuration + + + +Configuration shall be external, machine-readable and schema-validated. + + + +Validate configuration before activating it. + + + +Invalid configuration shall not silently replace the last known valid configuration. + + + +Configuration shall support concepts including: + + + +```text + +gateway + +stations + +transports + +points + +live acquisition + +historical acquisition + +OPC UA + +history repository + +storage destinations + +security + +logging + +diagnostics + +``` + + + +Do not hard-code station-specific process definitions into protocol code. + + + +\--- + + + +\## 17. Secrets + + + +Never commit production: + + + +\- passwords; + +\- API tokens; + +\- private keys; + +\- OPC UA private keys; + +\- database credentials; + +\- secret connection strings. + + + +Example configuration shall use placeholders. + + + +\--- + + + +\## 18. Security + + + +Production OPC UA configuration shall use secure endpoints by default. + + + +Do not make insecure OPC UA operation the default merely to simplify development. + + + +Keep development-only insecure behavior clearly separated and documented. + + + +Administrative capabilities shall be authorized separately from ordinary data access. + + + +If uncertain between a permissive and restrictive security behavior, prefer the restrictive behavior and document the decision. + + + +\--- + + + +\## 19. Diagnostics + + + +New failure modes shall include meaningful diagnostics where practical. + + + +Diagnostics should allow operators to distinguish: + + + +```text + +transport failure + +protocol failure + +station offline + +invalid response + +history synchronization failure + +storage failure + +spool backlog + +OPC UA failure + +configuration failure + +``` + + + +Avoid generic errors where useful context is available. + + + +\--- + + + +\## 20. Logging + + + +Prefer structured logging. + + + +Include contextual information where available: + + + +```text + +component + +stationId + +pointId + +operation + +correlationId + +error + +``` + + + +Raw AquaCom telegram logging shall be separately configurable. + + + +Do not enable full telegram logging as the normal production default. + + + +\--- + + + +\## 21. Correlation + + + +AquaCom request/response transactions should have correlation identifiers. + + + +Where practical, propagate the correlation identifier into: + + + +\- transport diagnostics; + +\- protocol logs; + +\- station diagnostics; + +\- processing errors. + + + +\--- + + + +\## 22. Simulator + + + +The AquaCom simulator is a first-class project component. + + + +Development and CI shall not require operational field equipment. + + + +The simulator shall eventually support: + + + +\- normal communication; + +\- configurable live values; + +\- historical values; + +\- delayed response; + +\- timeout; + +\- disconnect; + +\- malformed telegram; + +\- invalid checksum; + +\- duplicate history; + +\- conflicting history; + +\- clock anomalies; + +\- reconnect/backfill. + + + +Do not implement the simulator so that it merely calls the same decoder being tested to construct all expected protocol behavior. Avoid self-validating tests. + + + +\--- + + + +\## 23. Testing rules + + + +Every functional change shall have applicable automated tests. + + + +Every bug fix should include a regression test where practical. + + + +Do not weaken or remove tests merely to make a change pass. + + + +Tests shall include appropriate combinations of: + + + +```text + +unit tests + +protocol fixture tests + +integration tests + +restart/recovery tests + +acceptance tests + +``` + + + +Protocol tests must run without external network access. + + + +\--- + + + +\## 24. Mandatory architecture tests + + + +Maintain tests that demonstrate at least: + + + +```text + +AquaCom simulator + + → AquaCom decoder + + + +AquaCom live acquisition + + → Current-State Service + + + +Current-State Service + + → OPC UA current value + + + +AquaCom history + + → Historical Pipeline + + + +Historical Pipeline + + → Repository + + + +Historical Pipeline + + → multiple storage destinations + + + +Repository + + → OPC UA HistoryRead + +``` + + + +\--- + + + +\## 25. Critical historical acceptance behavior + + + +The following behavior must always remain valid: + + + +```text + +1\. Station communicates normally. + + + +2\. Current value is exposed through OPC UA. + + + +3\. Communication is lost. + + + +4\. The device retains historical information. + + + +5\. Communication returns. + + + +6\. Live acquisition resumes. + + + +7\. Missing history is retrieved. + + + +8\. Historical samples retain original timestamps. + + + +9\. Recovered historical samples are persisted. + + + +10\. Recovered historical samples do NOT overwrite + + current state simply because they were just received. + + + +11\. OPC UA HistoryRead returns the recovered values + + at their original timestamps. + + + +12\. Re-retrieving the same historical interval does + + not produce unintended duplicates. + +``` + + + +Any change that breaks this scenario is an architectural regression. + + + +\--- + + + +\## 26. Bounded resources + + + +Do not introduce unbounded: + + + +\- queues; + +\- history buffers; + +\- retry lists; + +\- logs; + +\- response payloads; + +\- continuation state; + +\- caches. + + + +Resource limits and overflow behavior shall be explicit. + + + +\--- + + + +\## 27. Graceful shutdown + + + +Shutdown shall preserve consistency. + + + +Conceptual order: + + + +```text + +stop new administrative work + + ↓ + +stop scheduling new acquisition + + ↓ + +complete or cancel active transactions safely + + ↓ + +persist synchronization state + + ↓ + +flush durable state where possible + + ↓ + +stop OPC UA + + ↓ + +close storage destinations + + ↓ + +terminate + +``` + + + +\--- + + + +\## 28. Restart behavior + + + +Following restart: + + + +```text + +load configuration + + ↓ + +validate persistent state + + ↓ + +recover spool + + ↓ + +restore history watermarks + + ↓ + +resume AquaCom communication + + ↓ + +resume live acquisition + + ↓ + +resume historical synchronization + +``` + + + +Prioritize restoration of live operation before large history recovery jobs. + + + +\--- + + + +\## 29. Documentation requirements + + + +Update documentation when observable behavior changes. + + + +Relevant locations include: + + + +```text + +ARCHITECTURE.md + +docs/architecture/ + +docs/protocol/ + +docs/configuration/ + +docs/operations/ + +``` + + + +Do not leave major architectural decisions only in source-code comments. + + + +\--- + + + +\## 30. ExecPlan requirement + + + +Create or update an ExecPlan for substantial work involving: + + + +\- new AquaCom operations; + +\- historical synchronization; + +\- persistence; + +\- storage architecture; + +\- OPC UA namespace changes; + +\- security; + +\- configuration format changes; + +\- cross-module refactoring; + +\- data migration; + +\- significant recovery behavior. + + + +Store active plans under: + + + +```text + +docs/exec-plans/active/ + +``` + + + +Move completed plans to: + + + +```text + +docs/exec-plans/completed/ + +``` + + + +An ExecPlan should contain: + + + +```text + +Purpose + +Current state + +Desired state + +Constraints + +Affected components + +Implementation sequence + +Data-model changes + +Failure handling + +Testing + +Compatibility/migration + +Progress + +Decisions + +Unexpected findings + +Acceptance evidence + +``` + + + +Keep the plan current as implementation progresses. + + + +\--- + + + +\## 31. Handling uncertainty + + + +Classify uncertainties as: + + + +\### A. Local implementation detail + + + +Choose the simplest solution consistent with existing architecture. + + + +\### B. Architectural decision + + + +Record the decision and reasoning in the current ExecPlan. + + + +\### C. AquaCom protocol uncertainty + + + +Do not guess. + + + +Record it in: + + + +```text + +docs/protocol/protocol-gaps.md + +``` + + + +\### D. Security or safety uncertainty + + + +Prefer the safer behavior and document the decision. + + + +\--- + + + +\## 32. Task completion + + + +Do not consider a task complete until applicable conditions are satisfied: + + + +\- implementation is complete; + +\- relevant tests exist; + +\- tests pass; + +\- lint/static checks pass; + +\- configuration validation passes; + +\- relevant documentation is updated; + +\- architecture boundaries remain intact; + +\- new AquaCom behavior has evidence; + +\- new failure modes have diagnostics; + +\- no secrets were introduced. + + + +\--- + + + +\## 33. Initial scope + + + +The initial production goal is primarily read-oriented integration. + + + +Expected scope includes: + + + +```text + +AquaCom live acquisition + +AquaCom historical acquisition + +multiple stations + +canonical data model + +current-state cache + +historical pipeline + +deduplication + +persistent synchronization state + +durable spool + +historical repository + +multiple storage destinations + +OPC UA Data Access + +OPC UA Historical Access + +security + +diagnostics + +simulation + +automated testing + +restart recovery + +``` + + + +Unless explicitly approved, do not implement: + + + +```text + +remote pump control + +setpoint changes + +generic OPC UA process writes + +OPC UA Methods for process control + +OPC UA HistoryUpdate + +``` + + + +\--- + + + +\## 34. Future control functionality + + + +If process control is later introduced, use a separate command architecture: + + + +```text + +OPC UA/API + + │ + + ▼ + +Authorization + + │ + + ▼ + +Command validation + + │ + + ▼ + +Command service + + │ + + ▼ + +AquaCom control operation + + │ + + ▼ + +Confirmation / readback + + │ + + ▼ + +Audit + +``` + + + +Never implement process control as: + + + +```text + +OPC UA write + + ↓ + +raw AquaCom telegram + +``` + + + +without an explicit command-validation and authorization layer. + + + +\--- + + + +\## 35. Guiding implementation principle + + + +Optimize for: + + + +1\. correctness; + +2\. traceability; + +3\. recoverability; + +4\. testability; + +5\. maintainability; + +6\. operational diagnostics. + + + +Do not optimize for implementation speed at the expense of protocol correctness. + + + +When AquaCom knowledge is incomplete, build the interfaces, simulation, data model and tests around the missing area first. + + + +Then implement real protocol behavior only when adequate evidence exists. + + + +The central architectural rule remains: + + + +> A historical value describes the process at its source timestamp, not at the time the gateway happened to receive it. + + + +And the central protocol rule remains: + + + +> Never invent undocumented AquaCom behavior. + diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..4fb2dc5 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,3602 @@ +# \# AquaCom Integration Gateway – Architecture + +# + +# \## 1. Purpose + +# + +# This document defines the high-level software architecture of the \*\*AquaCom Integration Gateway\*\*. + +# + +# It describes: + +# + +# \- major system components; + +# \- dependency direction; + +# \- data flows; + +# \- architectural boundaries; + +# \- live-data handling; + +# \- historical-data handling; + +# \- OPC UA integration; + +# \- storage integration; + +# \- diagnostics; + +# \- security boundaries; + +# \- extension points. + +# + +# Detailed functional requirements are defined in: + +# + +# ```text + +# docs/product/software-specification.md + +# ``` + +# + +# Implementation requirements and Codex-specific development rules are defined in: + +# + +# ```text + +# docs/product/codex-implementation-specification.md + +# AGENTS.md + +# ``` + +# + +# Detailed subsystem architecture is documented under: + +# + +# ```text + +# docs/architecture/ + +# ``` + +# + +# AquaCom-specific protocol knowledge is documented under: + +# + +# ```text + +# docs/protocol/ + +# ``` + +# + +# \--- + +# + +# \# 2. System purpose + +# + +# The AquaCom Integration Gateway provides a modern integration boundary between AquaCom-compatible field equipment and higher-level systems. + +# + +# The gateway shall: + +# + +# \- communicate with AquaCom field devices; + +# \- acquire current process values; + +# \- retrieve historical process values; + +# \- normalize AquaCom-specific information into a protocol-independent model; + +# \- expose current values using OPC UA; + +# \- expose historical values using OPC UA Historical Access; + +# \- store historical data in one or more configurable destinations; + +# \- recover historical information following communication interruptions; + +# \- provide operational and protocol diagnostics. + +# + +# The gateway shall not make higher-level systems dependent on AquaCom-specific behavior. + +# + +# \--- + +# + +# \# 3. Architectural principle + +# + +# The central architecture is: + +# + +# ```text + +# AquaCom field device + +# │ + +# ▼ + +# AquaCom Transport + +# │ + +# ▼ + +# AquaCom Protocol Engine + +# │ + +# ▼ + +# Station / Session Manager + +# │ + +# ▼ + +# Canonical Data Model + +# │ + +# ├─────────────────────► Current-State Service + +# │ │ + +# │ ▼ + +# │ OPC UA Data Access + +# │ + +# └─────────────────────► Historical Pipeline + +# │ + +# ┌───────────┼────────────┐ + +# │ │ │ + +# ▼ ▼ ▼ + +# Repository Storage A Storage B + +# │ + +# ▼ + +# OPC UA Historical Access + +# ``` + +# + +# The canonical data model forms the boundary between AquaCom-specific functionality and all northbound integrations. + +# + +# \--- + +# + +# \# 4. Architectural goals + +# + +# The architecture shall support: + +# + +# \- protocol isolation; + +# \- storage independence; + +# \- stable internal identifiers; + +# \- stable OPC UA NodeIds; + +# \- correct handling of source timestamps; + +# \- reliable history recovery; + +# \- multiple historical storage destinations; + +# \- store-and-forward; + +# \- independent subsystem testing; + +# \- restart recovery; + +# \- future replacement of individual technologies; + +# \- future addition of other northbound interfaces. + +# + +# The architecture shall avoid tight coupling between: + +# + +# ```text + +# AquaCom + +# OPC UA + +# Database technology + +# Historian technology + +# SCADA platform + +# ``` + +# + +# \--- + +# + +# \# 5. Architectural boundaries + +# + +# The following boundaries are mandatory. + +# + +# \## 5.1 AquaCom boundary + +# + +# Only the AquaCom subsystem may: + +# + +# \- encode AquaCom telegrams; + +# \- decode AquaCom telegrams; + +# \- calculate or verify AquaCom checksums; + +# \- interpret AquaCom operation codes; + +# \- interpret AquaCom addressing; + +# \- interpret AquaCom-specific value formats. + +# + +# No OPC UA or storage module shall perform AquaCom protocol processing. + +# + +# \--- + +# + +# \## 5.2 Canonical model boundary + +# + +# AquaCom data shall be converted into canonical gateway objects before being forwarded to: + +# + +# \- current-state handling; + +# \- history handling; + +# \- OPC UA; + +# \- storage systems; + +# \- diagnostics where appropriate. + +# + +# The canonical model shall remain independent of AquaCom and OPC UA. + +# + +# \--- + +# + +# \## 5.3 OPC UA boundary + +# + +# The OPC UA subsystem shall consume canonical gateway information. + +# + +# It shall not: + +# + +# \- communicate directly with AquaCom stations; + +# \- decode telegrams; + +# \- synchronously request historical data from an RTU; + +# \- depend upon a particular storage technology. + +# + +# \--- + +# + +# \## 5.4 Storage boundary + +# + +# Storage destinations shall receive canonical historical records. + +# + +# Storage implementations shall not depend upon: + +# + +# \- AquaCom telegrams; + +# \- AquaCom transport; + +# \- OPC UA server internals. + +# + +# \--- + +# + +# \# 6. Source tree + +# + +# The logical source structure is: + +# + +# ```text + +# src/ + +# ├── core/ + +# ├── aquacom/ + +# ├── history/ + +# ├── storage/ + +# ├── opcua/ + +# ├── diagnostics/ + +# └── host/ + +# ``` + +# + +# The exact language-specific package or project structure may differ, but the architectural responsibilities shall remain equivalent. + +# + +# \--- + +# + +# \# 7. Dependency direction + +# + +# Allowed dependencies shall broadly follow: + +# + +# ```text + +# host + +# │ + +# ┌───────────┼─────────────┐ + +# │ │ │ + +# ▼ ▼ ▼ + +# opcua history diagnostics + +# │ │ + +# │ storage + +# │ │ + +# └──────┬────┘ + +# ▼ + +# core + +# ▲ + +# │ + +# aquacom + +# ``` + +# + +# The most important rule is: + +# + +# ```text + +# core + +# ``` + +# + +# shall not depend upon: + +# + +# ```text + +# aquacom + +# opcua + +# storage technology + +# ``` + +# + +# \--- + +# + +# \# 8. Core subsystem + +# + +# The `core` subsystem contains protocol-independent domain concepts. + +# + +# Examples include: + +# + +# ```text + +# StationId + +# PointId + +# CurrentValue + +# HistoricalSample + +# DataQuality + +# AcquisitionSource + +# CommunicationState + +# StationState + +# HistorySynchronizationState + +# ``` + +# + +# The core subsystem defines shared contracts used between other modules. + +# + +# It shall contain no AquaCom protocol logic. + +# + +# It shall contain no OPC UA-specific types. + +# + +# It shall contain no database-specific types. + +# + +# \--- + +# + +# \# 9. AquaCom subsystem + +# + +# The AquaCom subsystem contains: + +# + +# ```text + +# Transport + +# Protocol codec + +# Telegram validation + +# Station/session handling + +# Live acquisition + +# Historical acquisition + +# Protocol diagnostics + +# ``` + +# + +# Logical structure: + +# + +# ```text + +# AquaCom Transport + +# │ + +# ▼ + +# Protocol Codec + +# │ + +# ▼ + +# Protocol Operations + +# │ + +# ▼ + +# Station Session + +# │ + +# ├── Live Acquisition + +# └── Historical Acquisition + +# ``` + +# + +# Protocol implementation shall be evidence-based. + +# + +# Undocumented AquaCom behavior shall not be guessed. + +# + +# \--- + +# + +# \# 10. AquaCom transport + +# + +# The transport layer is responsible for communication only. + +# + +# It may support implementations such as: + +# + +# ```text + +# TCP + +# Serial + +# Serial-over-IP + +# Other supported AquaCom transport + +# ``` + +# + +# The transport layer shall not interpret process values. + +# + +# Conceptual interface: + +# + +# ```text + +# open + +# close + +# send + +# receive + +# health + +# ``` + +# + +# \--- + +# + +# \# 11. AquaCom protocol engine + +# + +# The protocol engine is responsible for: + +# + +# \- framing; + +# \- telegram validation; + +# \- checksum handling; + +# \- request encoding; + +# \- response decoding; + +# \- protocol error interpretation. + +# + +# Conceptual transformation: + +# + +# ```text + +# raw bytes + +# │ + +# ▼ + +# AquaCom message + +# │ + +# ▼ + +# logical protocol result + +# ``` + +# + +# The codec shall be independently testable without a physical AquaCom device. + +# + +# \--- + +# + +# \# 12. Station/session manager + +# + +# Each AquaCom station has an independent logical session. + +# + +# Conceptual station states: + +# + +# ```text + +# DISABLED + +# INITIALIZING + +# CONNECTING + +# ONLINE + +# DEGRADED + +# OFFLINE + +# RECOVERING + +# ``` + +# + +# One failing station shall not stop communication with unrelated stations. + +# + +# The Station Manager owns: + +# + +# \- station lifecycle; + +# \- communication status; + +# \- retries; + +# \- scheduling; + +# \- station diagnostics; + +# \- history recovery coordination. + +# + +# \--- + +# + +# \# 13. Canonical data model + +# + +# The gateway uses a protocol-independent canonical model. + +# + +# \## 13.1 CurrentValue + +# + +# Conceptually: + +# + +# ```text + +# CurrentValue + +# StationId + +# PointId + +# Value + +# DataType + +# Quality + +# SourceTimestamp + +# ReceivedTimestamp + +# UpdatedTimestamp + +# AcquisitionSource + +# ``` + +# + +# \--- + +# + +# \## 13.2 HistoricalSample + +# + +# Conceptually: + +# + +# ```text + +# HistoricalSample + +# StationId + +# PointId + +# Value + +# DataType + +# Quality + +# SourceTimestamp + +# ReceivedTimestamp + +# AcquisitionSource + +# AcquisitionId + +# ``` + +# + +# Historical samples shall retain the timestamp associated with the process state. + +# + +# \--- + +# + +# \# 14. Timestamp model + +# + +# The gateway shall distinguish at least: + +# + +# ```text + +# SourceTimestamp + +# ReceivedTimestamp + +# ``` + +# + +# Where applicable also: + +# + +# ```text + +# UpdatedTimestamp + +# ServerTimestamp + +# ``` + +# + +# Their meanings are: + +# + +# | Timestamp | Meaning | + +# |---|---| + +# | SourceTimestamp | Time associated with the value at the source | + +# | ReceivedTimestamp | Time the gateway received the information | + +# | UpdatedTimestamp | Time current gateway state was changed | + +# | ServerTimestamp | Timestamp used by the OPC UA server | + +# + +# The following must never be assumed: + +# + +# ```text + +# ReceivedTimestamp = SourceTimestamp + +# ``` + +# + +# \--- + +# + +# \# 15. Fundamental historical rule + +# + +# The fundamental historical-data rule is: + +# + +# > A historical sample represents the process at its SourceTimestamp, not at the time the gateway receives the sample. + +# + +# Example: + +# + +# ```text + +# Historical value: + +# SourceTimestamp = 14:05 + +# ReceivedTimestamp = 18:30 + +# ``` + +# + +# The value belongs to history at: + +# + +# ```text + +# 14:05 + +# ``` + +# + +# It shall not become a new current process value at: + +# + +# ```text + +# 18:30 + +# ``` + +# + +# \--- + +# + +# \# 16. Live-data architecture + +# + +# Live AquaCom values follow: + +# + +# ```text + +# AquaCom response + +# │ + +# ▼ + +# Protocol decode + +# │ + +# ▼ + +# Point mapping + +# │ + +# ▼ + +# Canonical CurrentValue + +# │ + +# ▼ + +# Current-State Service + +# │ + +# ├────────► OPC UA + +# │ + +# └────────► Historical pipeline + +# if live historization is enabled + +# ``` + +# + +# The Current-State Service maintains the latest accepted value for each configured point. + +# + +# \--- + +# + +# \# 17. Current-State Service + +# + +# Responsibilities: + +# + +# \- maintain the latest current value; + +# \- reject obsolete current-state updates where applicable; + +# \- expose current values to OPC UA; + +# \- notify subscribers of valid changes; + +# \- preserve quality and timestamps. + +# + +# Conceptual interface: + +# + +# ```text + +# update(CurrentValue) + +# + +# get(PointId) + +# + +# getAll(StationId) + +# + +# subscribe(PointId) + +# ``` + +# + +# Historical backfill shall not directly call `update(CurrentValue)`. + +# + +# \--- + +# + +# \# 18. Historical-data architecture + +# + +# Historical AquaCom data follows: + +# + +# ```text + +# AquaCom history + +# │ + +# ▼ + +# Historical Acquisition Manager + +# │ + +# ▼ + +# Canonical HistoricalSample + +# │ + +# ▼ + +# Historical Pipeline + +# │ + +# ├────────► History Repository + +# ├────────► Storage Sink A + +# ├────────► Storage Sink B + +# └────────► Other configured destinations + +# ``` + +# + +# The historical pipeline is independent from OPC UA. + +# + +# \--- + +# + +# \# 19. Historical Acquisition Manager + +# + +# The Historical Acquisition Manager is responsible for: + +# + +# \- determining missing intervals; + +# \- requesting AquaCom history; + +# \- processing historical responses; + +# \- maintaining synchronization state; + +# \- managing watermarks; + +# \- performing reconnect/backfill; + +# \- throttling history retrieval; + +# \- avoiding interference with live polling. + +# + +# Live acquisition shall normally have higher communication priority than bulk history recovery. + +# + +# \--- + +# + +# \# 20. Historical synchronization + +# + +# Each station may maintain persistent synchronization state. + +# + +# Conceptually: + +# + +# ```text + +# StationId + +# HistoryStreamId + +# LastCompleteTimestamp + +# LastAttemptTimestamp + +# LastSuccessfulTimestamp + +# SynchronizationState + +# ``` + +# + +# Example: + +# + +# ```text + +# 12:00 history synchronized + +# + +# 12:03 communication lost + +# + +# 17:24 communication restored + +# + +# 12:00 → 17:24 + +# identified as recovery interval + +# ``` + +# + +# The gateway then retrieves available AquaCom history for that interval. + +# + +# \--- + +# + +# \# 21. Watermark rule + +# + +# A history synchronization watermark shall only advance after the corresponding interval has been successfully handled according to the configured persistence policy. + +# + +# The following is prohibited: + +# + +# ```text + +# receive historical packet + +# │ + +# ▼ + +# advance watermark + +# │ + +# ▼ + +# storage fails + +# ``` + +# + +# Preferred behavior is: + +# + +# ```text + +# receive + +# ↓ + +# validate + +# ↓ + +# persist/durably queue + +# ↓ + +# advance synchronization state + +# ``` + +# + +# \--- + +# + +# \# 22. Historical pipeline + +# + +# The historical pipeline shall conceptually perform: + +# + +# ```text + +# HistoricalSample + +# │ + +# ▼ + +# Validation + +# │ + +# ▼ + +# Normalization + +# │ + +# ▼ + +# Deduplication + +# │ + +# ▼ + +# Durable Spool + +# │ + +# ▼ + +# Distribution + +# ``` + +# + +# This pipeline provides a stable boundary between acquisition and storage. + +# + +# \--- + +# + +# \# 23. Deduplication + +# + +# The default historical logical identity is: + +# + +# ```text + +# StationId + +# \+ + +# PointId + +# \+ + +# SourceTimestamp + +# ``` + +# + +# A stronger AquaCom-provided identifier may be used where verified. + +# + +# Identical samples shall not create unintended duplicate history. + +# + +# Conflicting samples sharing the same logical identity shall generate diagnostics. + +# + +# The default conflict strategy should favor explicit conflict detection rather than silent overwrite. + +# + +# \--- + +# + +# \# 24. Durable spool + +# + +# The historical spool provides restart-safe delivery. + +# + +# Conceptually: + +# + +# ```text + +# HistoricalSample + +# │ + +# ▼ + +# Persistent spool + +# │ + +# ├────► Repository + +# ├────► Sink A + +# └────► Sink B + +# ``` + +# + +# Each destination maintains independent acknowledgement. + +# + +# Example: + +# + +# ```text + +# Record 4711 + +# + +# Repository ACK + +# CentralHistorian ACK + +# Archive PENDING + +# ``` + +# + +# The record remains until configured delivery requirements have been fulfilled. + +# + +# \--- + +# + +# \# 25. History Repository + +# + +# A History Repository is a queryable historical source. + +# + +# It provides operations conceptually equivalent to: + +# + +# ```text + +# store + +# storeBatch + +# readRaw + +# readAtTime + +# getBounds + +# health + +# ``` + +# + +# The repository used by OPC UA Historical Access is selected by configuration. + +# + +# The OPC UA implementation shall not know whether the repository is: + +# + +# ```text + +# relational database + +# time-series database + +# embedded historian + +# industrial historian + +# other queryable implementation + +# ``` + +# + +# \--- + +# + +# \# 26. Storage Sink + +# + +# A Storage Sink is a destination receiving historical records. + +# + +# Conceptual interface: + +# + +# ```text + +# initialize + +# write + +# writeBatch + +# flush + +# health + +# shutdown + +# ``` + +# + +# A sink does not need to support historical queries. + +# + +# Examples: + +# + +# ```text + +# SQL database + +# time-series database + +# enterprise historian + +# file archive + +# message broker + +# data lake connector + +# ``` + +# + +# \--- + +# + +# \# 27. Repository versus sink + +# + +# These shall remain separate concepts: + +# + +# ```text + +# Repository + +# = query historical data + +# + +# Sink + +# = receive historical data + +# ``` + +# + +# One implementation may support both. + +# + +# Example: + +# + +# ```text + +# Local historian + +# Repository: yes + +# Sink: yes + +# + +# Archive export + +# Repository: no + +# Sink: yes + +# ``` + +# + +# \--- + +# + +# \# 28. Multiple storage destinations + +# + +# A historical record may be delivered to multiple independent destinations. + +# + +# Example: + +# + +# ```text + +# Historical Pipeline + +# │ + +# ┌───────────────┼────────────────┐ + +# │ │ │ + +# ▼ ▼ ▼ + +# Local Repository Central DB Archive + +# ``` + +# + +# Failure of one destination shall not unnecessarily block successful destinations. + +# + +# \--- + +# + +# \# 29. OPC UA architecture + +# + +# The OPC UA subsystem provides northbound access to normalized gateway information. + +# + +# Logical components: + +# + +# ```text + +# OPC UA Server + +# │ + +# ├── Namespace Manager + +# ├── Current Value Provider + +# ├── Historical Provider + +# ├── Quality Mapper + +# ├── Diagnostics Provider + +# └── Security + +# ``` + +# + +# \--- + +# + +# \# 30. OPC UA current data + +# + +# Current values are exposed through normal OPC UA Data Access. + +# + +# Mapping: + +# + +# ```text + +# CurrentValue.Value + +# ↓ + +# OPC UA Value + +# + +# CurrentValue.SourceTimestamp + +# ↓ + +# OPC UA SourceTimestamp + +# + +# Gateway server time + +# ↓ + +# OPC UA ServerTimestamp + +# + +# CurrentValue.Quality + +# ↓ + +# OPC UA StatusCode + +# ``` + +# + +# \--- + +# + +# \# 31. OPC UA Historical Access + +# + +# Historical Access shall query the configured History Repository. + +# + +# Correct flow: + +# + +# ```text + +# OPC UA Client + +# │ + +# │ HistoryRead + +# ▼ + +# OPC UA Server + +# │ + +# ▼ + +# Historical Provider + +# │ + +# ▼ + +# History Repository + +# │ + +# ▼ + +# HistoricalSample\[] + +# │ + +# ▼ + +# OPC UA DataValue\[] + +# ``` + +# + +# \--- + +# + +# \# 32. Prohibited HistoryRead architecture + +# + +# The following architecture is prohibited: + +# + +# ```text + +# OPC UA HistoryRead + +# │ + +# ▼ + +# AquaCom request + +# │ + +# ▼ + +# wait for RTU + +# │ + +# ▼ + +# OPC UA response + +# ``` + +# + +# Historical synchronization and historical client access must be decoupled. + +# + +# \--- + +# + +# \# 33. OPC UA namespace + +# + +# The default logical namespace shall resemble: + +# + +# ```text + +# AquaCom + +# │ + +# ├── Gateway + +# │ ├── Status + +# │ ├── Version + +# │ ├── StartTime + +# │ ├── ConfigurationVersion + +# │ ├── HistoricalQueueDepth + +# │ └── Storage + +# │ + +# └── Stations + +# │ + +# ├── PS001 + +# │ ├── Process + +# │ │ ├── Level + +# │ │ ├── Pump01Running + +# │ │ └── Pump02Running + +# │ │ + +# │ └── Diagnostics + +# │ ├── CommunicationState + +# │ ├── LastCommunication + +# │ ├── HistoryState + +# │ └── HistoryWatermark + +# │ + +# └── PS002 + +# ``` + +# + +# Exact organization may be configurable. + +# + +# \--- + +# + +# \# 34. Stable OPC UA NodeIds + +# + +# OPC UA NodeIds shall derive from stable engineering identifiers. + +# + +# Example: + +# + +# ```text + +# station/PS001/point/LEVEL + +# ``` + +# + +# Changing: + +# + +# ```text + +# Wet well level + +# ``` + +# + +# to: + +# + +# ```text + +# Inlet sump level + +# ``` + +# + +# shall not normally change the NodeId. + +# + +# Stable NodeIds are required to preserve client configuration. + +# + +# \--- + +# + +# \# 35. Diagnostics architecture + +# + +# Diagnostics are separate from process data. + +# + +# Conceptually: + +# + +# ```text + +# Diagnostics + +# │ + +# ├── Gateway + +# │ + +# ├── Station + +# │ + +# ├── AquaCom Protocol + +# │ + +# ├── History + +# │ + +# ├── Storage + +# └── OPC UA + +# ``` + +# + +# Diagnostics may be exposed through: + +# + +# \- logs; + +# \- metrics; + +# \- OPC UA diagnostic nodes; + +# \- future management interfaces. + +# + +# \--- + +# + +# \# 36. Gateway diagnostics + +# + +# Examples: + +# + +# ```text + +# GatewayState + +# Version + +# ConfigurationVersion + +# StartTime + +# Uptime + +# StationCount + +# OnlineStationCount + +# HistoricalQueueDepth + +# SpoolDiskUsage + +# OPCUAState + +# ``` + +# + +# \--- + +# + +# \# 37. Station diagnostics + +# + +# Examples: + +# + +# ```text + +# CommunicationState + +# LastRequest + +# LastResponse + +# LastSuccessfulCommunication + +# ConsecutiveFailures + +# ProtocolErrors + +# HistorySynchronizationState + +# HistoryWatermark + +# HistoricalBacklog + +# ``` + +# + +# \--- + +# + +# \# 38. Storage diagnostics + +# + +# Per destination: + +# + +# ```text + +# State + +# LastSuccessfulWrite + +# LastFailure + +# PendingRecords + +# RetryCount + +# Latency + +# ``` + +# + +# A storage failure shall be identifiable independently from an AquaCom communication failure. + +# + +# \--- + +# + +# \# 39. Logging + +# + +# Structured logging is preferred. + +# + +# Useful context includes: + +# + +# ```text + +# timestamp + +# severity + +# component + +# stationId + +# pointId + +# operation + +# correlationId + +# message + +# error + +# ``` + +# + +# Raw AquaCom telegram logging shall be separately configurable. + +# + +# \--- + +# + +# \# 40. Configuration architecture + +# + +# Configuration shall be external and machine-readable. + +# + +# Conceptual structure: + +# + +# ```text + +# Gateway Configuration + +# │ + +# ├── Gateway + +# ├── AquaCom + +# ├── Stations + +# ├── Points + +# ├── History + +# ├── Storage + +# ├── OPC UA + +# ├── Security + +# ├── Diagnostics + +# └── Logging + +# ``` + +# + +# Configuration validation occurs before activation. + +# + +# \--- + +# + +# \# 41. Station configuration + +# + +# A station definition contains concepts equivalent to: + +# + +# ```text + +# StationId + +# Enabled + +# Transport + +# AquaComAddress + +# ProtocolProfile + +# LiveAcquisition + +# HistoricalAcquisition + +# PointDefinitionSource + +# Timezone + +# ``` + +# + +# Station configuration shall not be embedded directly in protocol source code. + +# + +# \--- + +# + +# \# 42. Point configuration + +# + +# A point contains concepts equivalent to: + +# + +# ```text + +# PointId + +# DisplayName + +# Description + +# SourceReference + +# DataType + +# EngineeringUnit + +# Scaling + +# LiveEnabled + +# HistoryEnabled + +# OPCUAEnabled + +# Historizing + +# StoragePolicy + +# ``` + +# + +# `PointId` shall remain stable even if presentation metadata changes. + +# + +# \--- + +# + +# \# 43. Security boundaries + +# + +# The architecture assumes AquaCom is a legacy field protocol. + +# + +# Security shall therefore be applied around the AquaCom communication environment. + +# + +# Conceptually: + +# + +# ```text + +# SCADA / client network + +# │ + +# ▼ + +# Firewall / segmentation + +# │ + +# ▼ + +# AquaCom Gateway + +# │ + +# ▼ + +# OT communication network + +# │ + +# ▼ + +# Site firewall/router/VPN + +# │ + +# ▼ + +# AquaCom RTU + +# ``` + +# + +# The gateway shall not assume that AquaCom itself provides modern confidentiality, authentication or authorization. + +# + +# \--- + +# + +# \# 44. OPC UA security + +# + +# OPC UA security is handled within the OPC UA subsystem. + +# + +# Production architecture shall support: + +# + +# ```text + +# application certificates + +# trusted client management + +# secure channels + +# authentication + +# authorization + +# encrypted communication + +# ``` + +# + +# Insecure endpoints shall not be the normal production default. + +# + +# \--- + +# + +# \# 45. Secrets boundary + +# + +# Secrets shall not form part of normal version-controlled configuration. + +# + +# Examples: + +# + +# ```text + +# database passwords + +# API tokens + +# private keys + +# certificate private keys + +# ``` + +# + +# These shall be injected through an external secret mechanism. + +# + +# \--- + +# + +# \# 46. Host subsystem + +# + +# The `host` subsystem composes the application. + +# + +# Responsibilities include: + +# + +# \- configuration loading; + +# \- dependency construction; + +# \- subsystem startup; + +# \- lifecycle management; + +# \- shutdown; + +# \- top-level health state. + +# + +# The host shall not become a location for protocol or business logic. + +# + +# \--- + +# + +# \# 47. Startup architecture + +# + +# Conceptual startup sequence: + +# + +# ```text + +# Load configuration + +# │ + +# ▼ + +# Validate configuration + +# │ + +# ▼ + +# Load persistent state + +# │ + +# ▼ + +# Initialize storage + +# │ + +# ▼ + +# Initialize historical services + +# │ + +# ▼ + +# Initialize OPC UA + +# │ + +# ▼ + +# Initialize AquaCom stations + +# │ + +# ▼ + +# Start live acquisition + +# │ + +# ▼ + +# Start historical synchronization + +# ``` + +# + +# A temporary failure of a non-critical secondary storage destination should not necessarily prevent the gateway from starting. + +# + +# \--- + +# + +# \# 48. Shutdown architecture + +# + +# Conceptual controlled shutdown: + +# + +# ```text + +# Stop accepting administrative changes + +# │ + +# ▼ + +# Stop scheduling new acquisition + +# │ + +# ▼ + +# Complete/cancel active transactions safely + +# │ + +# ▼ + +# Persist synchronization state + +# │ + +# ▼ + +# Flush durable state + +# │ + +# ▼ + +# Stop OPC UA + +# │ + +# ▼ + +# Close storage + +# │ + +# ▼ + +# Terminate + +# ``` + +# + +# \--- + +# + +# \# 49. Restart recovery + +# + +# After an unclean restart: + +# + +# ```text + +# Load configuration + +# │ + +# ▼ + +# Recover persistent spool + +# │ + +# ▼ + +# Restore synchronization watermarks + +# │ + +# ▼ + +# Reconnect AquaCom stations + +# │ + +# ▼ + +# Resume live acquisition + +# │ + +# ▼ + +# Resume historical recovery + +# ``` + +# + +# Live acquisition should resume before large backlog processing. + +# + +# \--- + +# + +# \# 50. Scheduling priorities + +# + +# Where AquaCom communication capacity is limited, scheduling shall conceptually prioritize: + +# + +# ```text + +# 1\. communication/session health + +# 2\. current/live acquisition + +# 3\. alarms/events when implemented + +# 4\. explicit configuration operations + +# 5\. historical backfill + +# 6\. low-priority maintenance + +# ``` + +# + +# Historical synchronization shall be throttleable. + +# + +# \--- + +# + +# \# 51. Resource boundaries + +# + +# All queues and caches shall be bounded. + +# + +# This applies to: + +# + +# ```text + +# AquaCom request queues + +# history queues + +# storage retry queues + +# OPC UA historical result sets + +# continuation state + +# logging buffers + +# spool storage + +# ``` + +# + +# Overflow behavior shall be explicit and observable. + +# + +# \--- + +# + +# \# 52. Testing architecture + +# + +# The system shall support independent testing of each architectural boundary. + +# + +# Conceptually: + +# + +# ```text + +# Protocol Fixtures + +# │ + +# ▼ + +# AquaCom Codec Tests + +# + +# Simulator + +# │ + +# ▼ + +# Session / Acquisition Tests + +# + +# Historical Fixtures + +# │ + +# ▼ + +# History Pipeline Tests + +# + +# Repository + +# │ + +# ▼ + +# OPC UA HA Tests + +# + +# Current-State Service + +# │ + +# ▼ + +# OPC UA DA Tests + +# ``` + +# + +# \--- + +# + +# \# 53. AquaCom simulator + +# + +# The simulator shall permit development without operational AquaCom equipment. + +# + +# Supported scenarios shall eventually include: + +# + +# ```text + +# normal live values + +# normal history + +# timeouts + +# disconnects + +# delayed response + +# malformed telegram + +# bad checksum + +# duplicate history + +# conflicting history + +# clock error + +# reconnect + +# backfill + +# ``` + +# + +# The simulator is part of the architecture, not merely a temporary development tool. + +# + +# \--- + +# + +# \# 54. Protocol evidence architecture + +# + +# AquaCom implementation is linked to documented evidence. + +# + +# Relevant repository area: + +# + +# ```text + +# docs/protocol/ + +# ``` + +# + +# Recommended structure: + +# + +# ```text + +# aquacom.md + +# known-operations.md + +# protocol-gaps.md + +# test-vectors.md + +# ``` + +# + +# Every implemented AquaCom behavior should be traceable to: + +# + +# ```text + +# Specification + +# Capture + +# Known-good implementation + +# Approved test vector + +# ``` + +# + +# Unknown behavior remains explicitly unresolved. + +# + +# \--- + +# + +# \# 55. Error isolation + +# + +# Failures shall remain contained where possible. + +# + +# Examples: + +# + +# | Failure | Expected isolation | + +# |---|---| + +# | Station A offline | Station B continues | + +# | Storage A offline | Storage B continues | + +# | OPC UA client disconnect | Acquisition continues | + +# | OPC UA server problem | AquaCom acquisition should continue where possible | + +# | Historical backfill fails | Live acquisition continues | + +# | Malformed AquaCom telegram | Telegram rejected, station diagnostics updated | + +# | Secondary storage failure | Durable spool retains pending delivery | + +# + +# \--- + +# + +# \# 56. Future extension points + +# + +# The architecture shall permit future addition of: + +# + +# ```text + +# OPC UA Alarms \& Conditions + +# AquaCom alarms/events + +# AquaCom commands + +# setpoint changes + +# MQTT + +# REST API + +# external analytics + +# central configuration + +# redundant gateways + +# high availability + +# additional history repositories + +# additional storage sinks + +# ``` + +# + +# These shall be added behind explicit subsystem interfaces. + +# + +# \--- + +# + +# \# 57. Future process-control architecture + +# + +# If control functionality is introduced later, it shall use a separate command pipeline: + +# + +# ```text + +# Northbound request + +# │ + +# ▼ + +# Authentication + +# │ + +# ▼ + +# Authorization + +# │ + +# ▼ + +# Command validation + +# │ + +# ▼ + +# Command service + +# │ + +# ▼ + +# AquaCom command + +# │ + +# ▼ + +# Confirmation / readback + +# │ + +# ▼ + +# Audit + +# ``` + +# + +# A direct mapping from arbitrary OPC UA writes to raw AquaCom telegrams is not an acceptable control architecture. + +# + +# \--- + +# + +# \# 58. Architectural invariants + +# + +# The following invariants shall hold throughout implementation. + +# + +# \## INV-001 + +# + +# AquaCom-specific logic exists only behind the AquaCom abstraction. + +# + +# \## INV-002 + +# + +# The canonical model contains no AquaCom telegram representation. + +# + +# \## INV-003 + +# + +# The canonical model contains no OPC UA-specific representation. + +# + +# \## INV-004 + +# + +# Historical samples do not update current state solely because they were recently retrieved. + +# + +# \## INV-005 + +# + +# Historical SourceTimestamp is preserved. + +# + +# \## INV-006 + +# + +# OPC UA HistoryRead queries a repository, not an AquaCom device. + +# + +# \## INV-007 + +# + +# A storage failure does not directly stop unrelated live AquaCom acquisition. + +# + +# \## INV-008 + +# + +# Point identity remains stable across display-name changes. + +# + +# \## INV-009 + +# + +# OPC UA NodeIds remain stable across restart and normal upgrades. + +# + +# \## INV-010 + +# + +# Unverified AquaCom protocol details are not implemented as guesses. + +# + +# \## INV-011 + +# + +# Synchronization state required for recovery is persistent. + +# + +# \## INV-012 + +# + +# Historical delivery supports bounded persistent buffering. + +# + +# \--- + +# + +# \# 59. Primary end-to-end data flows + +# + +# \## 59.1 Live data + +# + +# ```text + +# AquaCom RTU + +# │ + +# ▼ + +# Transport + +# │ + +# ▼ + +# Protocol Engine + +# │ + +# ▼ + +# Station Manager + +# │ + +# ▼ + +# CurrentValue + +# │ + +# ▼ + +# Current-State Service + +# │ + +# ├────► OPC UA + +# │ + +# └────► Historical Pipeline + +# when live historization is enabled + +# ``` + +# + +# \--- + +# + +# \## 59.2 AquaCom historical recovery + +# + +# ```text + +# AquaCom RTU + +# │ + +# ▼ + +# Historical Acquisition + +# │ + +# ▼ + +# HistoricalSample + +# │ + +# ▼ + +# Validation + +# │ + +# ▼ + +# Deduplication + +# │ + +# ▼ + +# Durable Spool + +# │ + +# ├────► Repository + +# ├────► Storage A + +# └────► Storage B + +# ``` + +# + +# \--- + +# + +# \## 59.3 OPC UA historical request + +# + +# ```text + +# OPC UA Client + +# │ + +# ▼ + +# HistoryRead + +# │ + +# ▼ + +# OPC UA Historical Provider + +# │ + +# ▼ + +# History Repository + +# │ + +# ▼ + +# HistoricalSample\[] + +# │ + +# ▼ + +# OPC UA DataValue\[] + +# ``` + +# + +# \--- + +# + +# \# 60. Reference architecture + +# + +# The complete reference architecture is: + +# + +# ```text + +# FIELD / AQUACOM + +# │ + +# ▼ + +# ┌─────────────────────┐ + +# │ AquaCom Transport │ + +# └──────────┬──────────┘ + +# │ + +# ▼ + +# ┌─────────────────────┐ + +# │ Protocol Engine │ + +# └──────────┬──────────┘ + +# │ + +# ▼ + +# ┌─────────────────────┐ + +# │ Station Manager │ + +# └──────────┬──────────┘ + +# │ + +# ▼ + +# ┌─────────────────────┐ + +# │ Canonical Model │ + +# └───────┬───────┬─────┘ + +# │ │ + +# LIVE HISTORY + +# │ │ + +# ▼ ▼ + +# ┌──────────────┐ ┌──────────────────┐ + +# │Current-State │ │Historical │ + +# │Service │ │Acquisition │ + +# └──────┬───────┘ └────────┬─────────┘ + +# │ │ + +# │ ▼ + +# │ ┌──────────────────┐ + +# │ │Historical │ + +# │ │Pipeline │ + +# │ └────────┬─────────┘ + +# │ │ + +# │ ┌──────────┼───────────┐ + +# │ │ │ │ + +# │ ▼ ▼ ▼ + +# │ Repository Sink A Sink B + +# │ │ + +# │ │ + +# ▼ ▼ + +# ┌────────────────────────────┐ + +# │ OPC UA Server │ + +# │ │ + +# │ Data Access │ + +# │ Historical Access │ + +# │ Diagnostics │ + +# └──────────────┬─────────────┘ + +# │ + +# ▼ + +# SCADA / Clients + +# ``` + +# + +# \--- + +# + +# \# 61. Architecture decision summary + +# + +# The gateway is intentionally designed as an: + +# + +# ```text + +# AquaCom Integration Gateway + +# ``` + +# + +# rather than merely an: + +# + +# ```text + +# AquaCom OPC UA Server + +# ``` + +# + +# This allows: + +# + +# \- OPC UA to be replaced or supplemented; + +# \- storage technology to change; + +# \- multiple historians to coexist; + +# \- AquaCom equipment to be gradually retired; + +# \- other northbound interfaces to be added; + +# \- historical acquisition to continue independently of OPC UA clients. + +# + +# The long-term architectural asset is therefore the normalized integration layer and historical recovery mechanism, not any single external interface. + +# + +# \--- + +# + +# \# 62. Final architectural rule + +# + +# The most important data rule is: + +# + +# > Historical data is stored and exposed according to when the process value was valid, not when the gateway happened to retrieve it. + +# + +# The most important protocol rule is: + +# + +# > AquaCom behavior must be based on verified protocol knowledge and must never be invented merely to complete an implementation. + +# + +# The most important software rule is: + +# + +# > AquaCom, canonical data handling, historical persistence and OPC UA shall remain separate architectural concerns. + diff --git a/docs/configuration/configuration-reference.md b/docs/configuration/configuration-reference.md new file mode 100644 index 0000000..b662466 --- /dev/null +++ b/docs/configuration/configuration-reference.md @@ -0,0 +1,5758 @@ +\# AquaCom Integration Gateway – Configuration Reference + + + +\## 1. Purpose + + + +This document defines the configuration model for the \*\*AquaCom Integration Gateway\*\*. + + + +It is the authoritative human-readable reference for: + + + +\- configuration sections; + +\- configuration fields; + +\- required and optional values; + +\- defaults; + +\- validation rules; + +\- relationships between configuration areas; + +\- example configuration. + + + +The configuration model shall remain implementation-language independent. + + + +Machine-readable validation schemas shall be maintained separately under: + + + +```text + +schemas/ + +``` + + + +This document explains what the configuration means. + + + +The schema files define what configuration is syntactically and structurally valid. + + + +\--- + + + +\# 2. Configuration principles + + + +Gateway configuration shall be: + + + +\- external to the application executable; + +\- machine-readable; + +\- versioned; + +\- schema-validated; + +\- suitable for source control; + +\- portable between environments; + +\- explicit about identifiers; + +\- independent of runtime object allocation. + + + +Production secrets shall not be stored directly in normal version-controlled configuration. + + + +Configuration syntax shown in this document uses YAML for readability. + + + +The final implementation may use YAML, JSON, TOML, or another structured format, provided that the semantic model defined here is preserved. + + + +\--- + + + +\# 3. Configuration hierarchy + + + +The gateway configuration shall conceptually contain: + + + +```yaml + +configVersion: 1 + + + +gateway: + + ... + + + +logging: + + ... + + + +diagnostics: + + ... + + + +security: + + ... + + + +opcua: + + ... + + + +history: + + ... + + + +storage: + + ... + + + +stations: + + ... + +``` + + + +The top-level configuration sections are: + + + +| Section | Purpose | + +|---|---| + +| `configVersion` | Configuration schema version | + +| `gateway` | Gateway identity and runtime behavior | + +| `logging` | Logging configuration | + +| `diagnostics` | Diagnostics and metrics behavior | + +| `security` | Shared security configuration | + +| `opcua` | OPC UA server configuration | + +| `history` | Historical subsystem configuration | + +| `storage` | Historical repositories and storage destinations | + +| `stations` | AquaCom station definitions | + + + +\--- + + + +\# 4. Configuration version + + + +\## 4.1 `configVersion` + + + +\*\*Type:\*\* integer + +\*\*Required:\*\* yes + + + +Defines the version of the gateway configuration schema. + + + +Example: + + + +```yaml + +configVersion: 1 + +``` + + + +The application shall reject configuration using an unsupported schema version. + + + +Configuration migration between incompatible schema versions shall be explicit. + + + +The application shall not silently reinterpret an incompatible configuration format. + + + +\--- + + + +\# 5. Gateway configuration + + + +Example: + + + +```yaml + +gateway: + + id: aquacom-gateway-01 + + displayName: Central AquaCom Gateway + + timezone: Europe/Stockholm + + + + startup: + + allowDegradedStartup: true + + + + shutdown: + + gracefulTimeout: 30s + +``` + + + +\--- + + + +\## 5.1 `gateway.id` + + + +\*\*Type:\*\* string + +\*\*Required:\*\* yes + + + +Stable identifier for this gateway instance. + + + +Example: + + + +```yaml + +id: aquacom-gateway-01 + +``` + + + +Requirements: + + + +\- must be unique within the relevant operational environment; + +\- shall remain stable across software restart; + +\- shall normally remain stable across software upgrade; + +\- shall not be based on runtime-generated identifiers. + + + +This identifier may be used in: + + + +\- diagnostics; + +\- logging; + +\- historical metadata; + +\- OPC UA namespace generation; + +\- audit records. + + + +\--- + + + +\## 5.2 `gateway.displayName` + + + +\*\*Type:\*\* string + +\*\*Required:\*\* no + + + +Human-readable name. + + + +Example: + + + +```yaml + +displayName: Central AquaCom Gateway + +``` + + + +Changing this value shall not change the gateway's stable identity. + + + +\--- + + + +\## 5.3 `gateway.timezone` + + + +\*\*Type:\*\* timezone identifier + +\*\*Required:\*\* yes + + + +Defines the gateway's configured local timezone. + + + +Example: + + + +```yaml + +timezone: Europe/Stockholm + +``` + + + +UTC shall normally be used internally. + + + +This timezone may be used for: + + + +\- presentation; + +\- interpretation of timestamps where the source does not include timezone information; + +\- diagnostics. + + + +A station may override this value. + + + +\--- + + + +\# 6. Startup configuration + + + +\## 6.1 `gateway.startup.allowDegradedStartup` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Defines whether the gateway may start when non-critical external dependencies are unavailable. + + + +Example: + + + +```yaml + +startup: + + allowDegradedStartup: true + +``` + + + +If enabled, failures such as an unavailable optional storage destination shall not necessarily prevent live AquaCom acquisition or OPC UA startup. + + + +Critical configuration errors shall always prevent startup. + + + +\--- + + + +\# 7. Shutdown configuration + + + +\## 7.1 `gateway.shutdown.gracefulTimeout` + + + +\*\*Type:\*\* duration + +\*\*Default:\*\* implementation-defined + + + +Defines the maximum time allowed for controlled shutdown. + + + +Example: + + + +```yaml + +shutdown: + + gracefulTimeout: 30s + +``` + + + +During this period the gateway should attempt to: + + + +```text + +stop new acquisition + +finish or cancel active transactions + +persist synchronization state + +flush durable state + +stop OPC UA + +close storage + +``` + + + +\--- + + + +\# 8. Logging configuration + + + +Example: + + + +```yaml + +logging: + + level: information + + + + structured: true + + + + telegramLogging: + + enabled: false + + includePayload: false + + + + retention: + + maxFiles: 14 + + maxFileSize: 100MB + +``` + + + +\--- + + + +\## 8.1 `logging.level` + + + +\*\*Type:\*\* enumeration + +\*\*Required:\*\* no + + + +Typical values: + + + +```text + +trace + +debug + +information + +warning + +error + +critical + +``` + + + +Production default should normally be: + + + +```yaml + +level: information + +``` + + + +\--- + + + +\## 8.2 `logging.structured` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Enables structured logging where supported by the implementation. + + + +Structured log records should support fields such as: + + + +```text + +timestamp + +severity + +component + +stationId + +pointId + +operation + +correlationId + +message + +error + +``` + + + +\--- + + + +\# 9. AquaCom telegram logging + + + +Example: + + + +```yaml + +telegramLogging: + + enabled: false + + includePayload: false + +``` + + + +Telegram logging shall be treated as a diagnostic capability. + + + +It shall not be enabled by default in production. + + + +\--- + + + +\## 9.1 `logging.telegramLogging.enabled` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `false` + + + +Enables AquaCom telegram-level logging. + + + +\--- + + + +\## 9.2 `logging.telegramLogging.includePayload` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `false` + + + +Defines whether raw telegram payload is included. + + + +If enabled, operators shall consider: + + + +\- storage consumption; + +\- operational sensitivity; + +\- possible exposure of process information. + + + +\--- + + + +\# 10. Diagnostics configuration + + + +Example: + + + +```yaml + +diagnostics: + + enabled: true + + + + opcua: + + exposeGatewayDiagnostics: true + + exposeStationDiagnostics: true + + exposeStorageDiagnostics: true + + + + metrics: + + enabled: true + +``` + + + +\--- + + + +\## 10.1 `diagnostics.enabled` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Enables gateway diagnostics. + + + +Disabling this shall not disable required internal error handling. + + + +\--- + + + +\## 10.2 `diagnostics.opcua.exposeGatewayDiagnostics` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Exposes gateway-level diagnostic nodes through OPC UA. + + + +\--- + + + +\## 10.3 `diagnostics.opcua.exposeStationDiagnostics` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Exposes per-station communication and synchronization diagnostics. + + + +\--- + + + +\## 10.4 `diagnostics.opcua.exposeStorageDiagnostics` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Exposes historical-storage diagnostics. + + + +\--- + + + +\## 10.5 `diagnostics.metrics.enabled` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* implementation-defined + + + +Enables runtime metrics. + + + +The metrics transport or technology is implementation-specific. + + + +\--- + + + +\# 11. Shared security configuration + + + +Example: + + + +```yaml + +security: + + secretsProvider: + + type: environment + + + + certificates: + + directory: ./certificates + +``` + + + +This section contains shared security behavior. + + + +Protocol-specific settings belong under their corresponding subsystem. + + + +\--- + + + +\# 12. Secret handling + + + +\## 12.1 `security.secretsProvider.type` + + + +Defines how secrets are supplied. + + + +Possible implementations may include: + + + +```text + +environment + +file + +operating-system secret store + +container secret + +external secret service + +``` + + + +Production secrets shall not normally appear directly in the gateway configuration. + + + +Example: + + + +```yaml + +database: + + username: gateway\_user + + passwordSecret: HISTORY\_DB\_PASSWORD + +``` + + + +rather than: + + + +```yaml + +password: SuperSecretPassword123 + +``` + + + +\--- + + + +\# 13. OPC UA configuration + + + +Example: + + + +```yaml + +opcua: + + enabled: true + + + + application: + + name: AquaCom Integration Gateway + + uri: urn:example:aquacom-gateway + + + + endpoint: + + bindAddress: 0.0.0.0 + + port: 4840 + + path: /aquacom + + + + namespace: + + uri: urn:example:aquacom + + rootName: AquaCom + + + + dataAccess: + + enabled: true + + + + historicalAccess: + + enabled: true + + repository: local-history + + maxValuesPerRead: 10000 + + maxConcurrentReads: 10 + + + + security: + + allowNone: false + + certificate: gateway-opcua + + trustMode: explicit + +``` + + + +\--- + + + +\# 14. `opcua.enabled` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Controls whether the OPC UA server is started. + + + +The gateway architecture shall permit AquaCom acquisition and historical storage to operate independently where practical if OPC UA is disabled. + + + +\--- + + + +\# 15. OPC UA application identity + + + +\## 15.1 `opcua.application.name` + + + +Human-readable OPC UA application name. + + + +Example: + + + +```yaml + +name: AquaCom Integration Gateway + +``` + + + +\--- + + + +\## 15.2 `opcua.application.uri` + + + +Stable application URI. + + + +Example: + + + +```yaml + +uri: urn:example:aquacom-gateway + +``` + + + +The URI should remain stable for an installed gateway instance. + + + +\--- + + + +\# 16. OPC UA endpoint + + + +Example: + + + +```yaml + +endpoint: + + bindAddress: 0.0.0.0 + + port: 4840 + + path: /aquacom + +``` + + + +\--- + + + +\## 16.1 `opcua.endpoint.bindAddress` + + + +Defines the interface on which the OPC UA endpoint listens. + + + +Production deployments should consider binding only to the required OT network interface. + + + +\--- + + + +\## 16.2 `opcua.endpoint.port` + + + +\*\*Type:\*\* integer + + + +Example: + + + +```yaml + +port: 4840 + +``` + + + +Port conflict shall be detected during startup. + + + +\--- + + + +\## 16.3 `opcua.endpoint.path` + + + +Optional OPC UA endpoint path. + + + +Example: + + + +```yaml + +path: /aquacom + +``` + + + +\--- + + + +\# 17. OPC UA namespace + + + +Example: + + + +```yaml + +namespace: + + uri: urn:example:aquacom + + rootName: AquaCom + +``` + + + +\--- + + + +\## 17.1 `opcua.namespace.uri` + + + +Stable namespace URI used for gateway-specific nodes. + + + +Changing this value may affect client configurations and shall therefore be treated as a compatibility-impacting change. + + + +\--- + + + +\## 17.2 `opcua.namespace.rootName` + + + +Human-readable root object name. + + + +Changing this value shall not automatically alter stable NodeIds. + + + +\--- + + + +\# 18. OPC UA Data Access + + + +\## 18.1 `opcua.dataAccess.enabled` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Enables exposure of configured current values. + + + +\--- + + + +\# 19. OPC UA Historical Access + + + +Example: + + + +```yaml + +historicalAccess: + + enabled: true + + repository: local-history + + maxValuesPerRead: 10000 + + maxConcurrentReads: 10 + +``` + + + +\--- + + + +\## 19.1 `opcua.historicalAccess.enabled` + + + +\*\*Type:\*\* boolean + + + +Enables OPC UA Historical Access. + + + +If enabled, a queryable history repository must be configured. + + + +\--- + + + +\## 19.2 `opcua.historicalAccess.repository` + + + +\*\*Type:\*\* storage repository identifier + +\*\*Required when Historical Access is enabled\*\* + + + +Example: + + + +```yaml + +repository: local-history + +``` + + + +The referenced destination must implement the History Repository capability. + + + +A sink-only destination is invalid here. + + + +\--- + + + +\## 19.3 `opcua.historicalAccess.maxValuesPerRead` + + + +\*\*Type:\*\* positive integer + + + +Limits the number of values returned in one historical response. + + + +Example: + + + +```yaml + +maxValuesPerRead: 10000 + +``` + + + +Larger responses shall use OPC UA continuation where required. + + + +\--- + + + +\## 19.4 `opcua.historicalAccess.maxConcurrentReads` + + + +\*\*Type:\*\* positive integer + + + +Limits concurrent historical requests. + + + +This protects the gateway and historical repository against excessive resource usage. + + + +\--- + + + +\# 20. OPC UA security configuration + + + +Example: + + + +```yaml + +security: + + allowNone: false + + certificate: gateway-opcua + + trustMode: explicit + + + + userAuthentication: + + enabled: false + +``` + + + +\--- + + + +\## 20.1 `opcua.security.allowNone` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `false` + + + +Controls whether an unsecured OPC UA endpoint is permitted. + + + +Production configuration should normally use: + + + +```yaml + +allowNone: false + +``` + + + +\--- + + + +\## 20.2 `opcua.security.certificate` + + + +Reference to an externally configured certificate identity. + + + +Private keys shall not be embedded directly in configuration committed to source control. + + + +\--- + + + +\## 20.3 `opcua.security.trustMode` + + + +Possible values may include: + + + +```text + +explicit + +managed + +``` + + + +`explicit` means client certificates must be explicitly trusted. + + + +The exact supported trust modes depend upon the selected OPC UA implementation. + + + +\--- + + + +\# 21. Historical subsystem configuration + + + +Example: + + + +```yaml + +history: + + enabled: true + + + + liveHistorization: + + enabled: true + + + + deduplication: + + enabled: true + + conflictPolicy: reject + + + + synchronization: + + enabled: true + + resumeAfterRestart: true + + + + backfill: + + enabled: true + + priority: low + + maxRequestsPerSecond: 2 + + + + spool: + + enabled: true + + maxSize: 20GB + + maxAge: 30d + + overflowPolicy: stop-history + +``` + + + +\--- + + + +\# 22. `history.enabled` + + + +\*\*Type:\*\* boolean + + + +Enables the gateway historical subsystem. + + + +This includes historical pipeline functionality. + + + +Individual stations and points may still enable or disable history independently. + + + +\--- + + + +\# 23. Live historization + + + +\## 23.1 `history.liveHistorization.enabled` + + + +\*\*Type:\*\* boolean + + + +Determines whether live current values may also be submitted to the historical pipeline. + + + +Example: + + + +```yaml + +liveHistorization: + + enabled: true + +``` + + + +This setting does not replace per-point history configuration. + + + +Both global and point-level configuration shall permit history before a live value is historized. + + + +\--- + + + +\# 24. Deduplication + + + +Example: + + + +```yaml + +deduplication: + + enabled: true + + conflictPolicy: reject + +``` + + + +\--- + + + +\## 24.1 `history.deduplication.enabled` + + + +\*\*Type:\*\* boolean + +\*\*Recommended:\*\* `true` + + + +Historical processing should normally be idempotent. + + + +\--- + + + +\## 24.2 `history.deduplication.conflictPolicy` + + + +Defines behavior when two different values have the same logical historical identity. + + + +Allowed conceptual values: + + + +```text + +reject + +keep-first + +keep-last + +version + +``` + + + +Recommended default: + + + +```yaml + +conflictPolicy: reject + +``` + + + +A conflict shall generate diagnostics. + + + +\--- + + + +\# 25. History synchronization + + + +Example: + + + +```yaml + +synchronization: + + enabled: true + + resumeAfterRestart: true + +``` + + + +\--- + + + +\## 25.1 `history.synchronization.enabled` + + + +Enables synchronization-state management. + + + +\--- + + + +\## 25.2 `history.synchronization.resumeAfterRestart` + + + +\*\*Type:\*\* boolean + +\*\*Recommended:\*\* `true` + + + +If enabled, the gateway restores historical synchronization watermarks and continues incomplete synchronization after restart. + + + +\--- + + + +\# 26. Backfill configuration + + + +Example: + + + +```yaml + +backfill: + + enabled: true + + priority: low + + maxRequestsPerSecond: 2 + +``` + + + +\--- + + + +\## 26.1 `history.backfill.enabled` + + + +Enables retrieval of missing AquaCom history following communication interruption. + + + +Actual availability depends upon: + + + +\- AquaCom protocol support; + +\- RTU capabilities; + +\- verified station configuration. + + + +\--- + + + +\## 26.2 `history.backfill.priority` + + + +Defines scheduling priority relative to other AquaCom operations. + + + +Supported values may include: + + + +```text + +low + +normal + +``` + + + +Recommended: + + + +```yaml + +priority: low + +``` + + + +Live acquisition shall normally take precedence. + + + +\--- + + + +\## 26.3 `history.backfill.maxRequestsPerSecond` + + + +Optional history-retrieval rate limit. + + + +Used to prevent large backfill operations from consuming all available station communication capacity. + + + +\--- + + + +\# 27. Durable spool configuration + + + +Example: + + + +```yaml + +spool: + + enabled: true + + path: ./data/spool + + maxSize: 20GB + + maxAge: 30d + + overflowPolicy: stop-history + +``` + + + +\--- + + + +\## 27.1 `history.spool.enabled` + + + +\*\*Recommended:\*\* `true` + + + +Enables persistent delivery buffering. + + + +\--- + + + +\## 27.2 `history.spool.path` + + + +Location of persistent spool data where the selected implementation requires an explicit path. + + + +The path must be writable. + + + +\--- + + + +\## 27.3 `history.spool.maxSize` + + + +Maximum spool size. + + + +Example: + + + +```yaml + +maxSize: 20GB + +``` + + + +The gateway shall provide diagnostics before reaching this limit. + + + +\--- + + + +\## 27.4 `history.spool.maxAge` + + + +Optional maximum retention time for pending spool records. + + + +Care shall be taken before enabling automatic age-based deletion. + + + +\--- + + + +\## 27.5 `history.spool.overflowPolicy` + + + +Defines behavior if the spool cannot accept additional data. + + + +Conceptual values: + + + +```text + +stop-history + +reject-new + +drop-oldest + +fail-gateway + +``` + + + +Recommended production default: + + + +```yaml + +overflowPolicy: stop-history + +``` + + + +Dropping historical information silently shall not be permitted. + + + +\--- + + + +\# 28. Storage configuration + + + +Example: + + + +```yaml + +storage: + + destinations: + + + + - id: local-history + + type: repository + + driver: example-local-db + + required: true + + + + capabilities: + + write: true + + query: true + + + + connection: + + path: ./data/history + + + + - id: enterprise-historian + + type: sink + + driver: example-historian + + required: true + + + + connection: + + endpoint: historian.example.local + + credentialSecret: HISTORIAN\_CREDENTIAL + + + + - id: archive + + type: sink + + driver: ndjson + + required: false + + + + connection: + + directory: ./archive + +``` + + + +\--- + + + +\# 29. Storage destination identifiers + + + +\## 29.1 `storage.destinations\[].id` + + + +\*\*Type:\*\* string + +\*\*Required:\*\* yes + + + +Stable identifier for the storage destination. + + + +Example: + + + +```yaml + +id: local-history + +``` + + + +Must be unique. + + + +Other configuration sections reference destinations using this identifier. + + + +\--- + + + +\# 30. Storage destination type + + + +\## 30.1 `storage.destinations\[].type` + + + +Defines the architectural role. + + + +Conceptual values: + + + +```text + +repository + +sink + +repository-and-sink + +``` + + + +Meaning: + + + +| Type | Query | Write | + +|---|---|---| + +| `repository` | yes | implementation-dependent | + +| `sink` | no | yes | + +| `repository-and-sink` | yes | yes | + + + +The exact schema may represent capabilities instead of this combined enumeration. + + + +\--- + + + +\# 31. Storage driver + + + +\## 31.1 `storage.destinations\[].driver` + + + +Defines the implementation adapter. + + + +Example: + + + +```yaml + +driver: example-local-db + +``` + + + +The value is implementation-specific. + + + +Business logic shall not depend directly on this value. + + + +\--- + + + +\# 32. Required and optional destinations + + + +\## 32.1 `storage.destinations\[].required` + + + +\*\*Type:\*\* boolean + + + +Defines whether successful delivery to the destination is required before a spool record may be considered fully delivered. + + + +Example: + + + +```yaml + +required: true + +``` + + + +If: + + + +```yaml + +required: false + +``` + + + +failure shall generate diagnostics but shall not indefinitely block cleanup of records that have reached all required destinations. + + + +\--- + + + +\# 33. Storage capabilities + + + +Example: + + + +```yaml + +capabilities: + + write: true + + query: true + +``` + + + +This may be validated against the selected driver. + + + +A repository used for OPC UA Historical Access must have: + + + +```yaml + +query: true + +``` + + + +\--- + + + +\# 34. Storage retry configuration + + + +A storage destination may contain: + + + +```yaml + +retry: + + enabled: true + + initialDelay: 2s + + maximumDelay: 5m + + multiplier: 2 + +``` + + + +Retry policy shall be independent for each destination. + + + +Storage retries shall not block AquaCom live acquisition. + + + +\--- + + + +\# 35. Station configuration + + + +Example: + + + +```yaml + +stations: + + + + - id: PS001 + + displayName: Wastewater Pump Station 001 + + enabled: true + + timezone: Europe/Stockholm + + + + transport: + + type: tcp + + host: 192.0.2.10 + + port: 1234 + + + + aquacom: + + address: 101 + + profile: default + + + + acquisition: + + live: + + enabled: true + + pollingInterval: 5s + + requestTimeout: 3s + + retryCount: 2 + + + + history: + + enabled: true + + backfillEnabled: true + + + + pointDefinitions: + + sourceType: atf + + path: ./stations/PS001.atf + +``` + + + +\--- + + + +\# 36. `stations\[].id` + + + +\*\*Type:\*\* string + +\*\*Required:\*\* yes + + + +Stable gateway identifier for the station. + + + +Example: + + + +```yaml + +id: PS001 + +``` + + + +Requirements: + + + +\- unique within the gateway; + +\- stable across restart; + +\- stable across IP-address changes; + +\- stable across display-name changes. + + + +The station ID may form part of: + + + +```text + +PointId + +OPC UA NodeId + +historical identity + +logs + +diagnostics + +``` + + + +\--- + + + +\# 37. `stations\[].displayName` + + + +Human-readable station name. + + + +Example: + + + +```yaml + +displayName: Wastewater Pump Station 001 + +``` + + + +Changing this shall not change the stable station identity. + + + +\--- + + + +\# 38. `stations\[].enabled` + + + +\*\*Type:\*\* boolean + +\*\*Default:\*\* `true` + + + +Controls whether the gateway actively communicates with the station. + + + +A disabled station configuration may remain visible diagnostically. + + + +\--- + + + +\# 39. Station timezone + + + +\## 39.1 `stations\[].timezone` + + + +Optional station-specific timezone. + + + +If omitted, the gateway timezone is inherited. + + + +Example: + + + +```yaml + +timezone: Europe/Stockholm + +``` + + + +This configuration is important where AquaCom timestamps lack explicit timezone information. + + + +\--- + + + +\# 40. Transport configuration + + + +Example: + + + +```yaml + +transport: + + type: tcp + + host: 192.0.2.10 + + port: 1234 + + connectTimeout: 5s + + idleTimeout: 30s + +``` + + + +Transport-specific fields are conditional on `type`. + + + +\--- + + + +\# 41. `transport.type` + + + +Defines the AquaCom transport implementation. + + + +Potential supported values may include: + + + +```text + +tcp + +serial + +serial-over-ip + +``` + + + +Only implemented and verified transport types shall be accepted. + + + +\--- + + + +\# 42. TCP transport + + + +Example: + + + +```yaml + +transport: + + type: tcp + + host: 192.0.2.10 + + port: 1234 + + connectTimeout: 5s + +``` + + + +\--- + + + +\## 42.1 `transport.host` + + + +Hostname or IP address. + + + +This value is not the station's stable identity. + + + +\--- + + + +\## 42.2 `transport.port` + + + +TCP port used for AquaCom communication. + + + +The default shall not be invented if it is not formally defined for the target equipment. + + + +Where no verified standard value exists, explicit configuration shall be required. + + + +\--- + + + +\## 42.3 `transport.connectTimeout` + + + +Maximum connection establishment time. + + + +\--- + + + +\# 43. Serial transport + + + +Conceptual example: + + + +```yaml + +transport: + + type: serial + + + + port: /dev/ttyS0 + + baudRate: 9600 + + dataBits: 8 + + stopBits: 1 + + parity: none + +``` + + + +Actual values shall be determined from validated AquaCom documentation and target-device requirements. + + + +Codex shall not insert assumed AquaCom serial defaults without evidence. + + + +\--- + + + +\# 44. AquaCom station protocol configuration + + + +Example: + + + +```yaml + +aquacom: + + address: 101 + + profile: default + +``` + + + +This section contains AquaCom-specific station configuration. + + + +Only verified protocol concepts shall be introduced here. + + + +\--- + + + +\## 44.1 `aquacom.address` + + + +Station address or AquaCom identifier required by the verified protocol implementation. + + + +The representation is protocol-dependent. + + + +It shall not be assumed to be identical to `stations\[].id`. + + + +\--- + + + +\## 44.2 `aquacom.profile` + + + +Optional reference to an AquaCom protocol profile. + + + +Profiles may be useful where different controller generations or configurations require different verified protocol behaviors. + + + +Example: + + + +```yaml + +profile: app700 + +``` + + + +A profile shall never enable guessed protocol behavior. + + + +\--- + + + +\# 45. Acquisition configuration + + + +Each station contains: + + + +```yaml + +acquisition: + + live: + + ... + + + + history: + + ... + +``` + + + +Live acquisition and historical acquisition shall be independently configurable. + + + +\--- + + + +\# 46. Live acquisition + + + +Example: + + + +```yaml + +live: + + enabled: true + + pollingInterval: 5s + + requestTimeout: 3s + + retryCount: 2 + +``` + + + +\--- + + + +\## 46.1 `acquisition.live.enabled` + + + +Enables current-value acquisition for the station. + + + +\--- + + + +\## 46.2 `acquisition.live.pollingInterval` + + + +Defines the normal polling period. + + + +The implementation shall validate unreasonable values. + + + +Example: + + + +```yaml + +pollingInterval: 5s + +``` + + + +\--- + + + +\## 46.3 `acquisition.live.requestTimeout` + + + +Maximum allowed time for an AquaCom live transaction before timeout handling. + + + +\--- + + + +\## 46.4 `acquisition.live.retryCount` + + + +Number of immediate or near-immediate retries permitted before normal communication-failure logic takes over. + + + +Retries shall not create an uncontrolled retry storm. + + + +\--- + + + +\# 47. Station historical acquisition + + + +Example: + + + +```yaml + +history: + + enabled: true + + backfillEnabled: true + + maxBackfillAge: 7d + +``` + + + +\--- + + + +\## 47.1 `acquisition.history.enabled` + + + +Enables AquaCom historical retrieval for the station. + + + +This requires verified support for the station/controller type. + + + +\--- + + + +\## 47.2 `acquisition.history.backfillEnabled` + + + +Enables automatic recovery following communication interruption. + + + +\--- + + + +\## 47.3 `acquisition.history.maxBackfillAge` + + + +Optional limit on how far back the gateway will automatically request history. + + + +Example: + + + +```yaml + +maxBackfillAge: 7d + +``` + + + +This protects against unexpected very large historical queries. + + + +A value beyond this range may require an explicit administrative operation. + + + +\--- + + + +\# 48. Point definition source + + + +Points may originate from sources such as: + + + +```text + +ATF + +static configuration + +engineering data import + +future external configuration service + +``` + + + +Example: + + + +```yaml + +pointDefinitions: + + sourceType: atf + + path: ./stations/PS001.atf + +``` + + + +\--- + + + +\## 48.1 `pointDefinitions.sourceType` + + + +Potential values: + + + +```text + +atf + +inline + +file + +``` + + + +Only implemented source types shall be accepted. + + + +\--- + + + +\## 48.2 `pointDefinitions.path` + + + +Path to an external point-definition file. + + + +File changes shall be validated before activation. + + + +\--- + + + +\# 49. Inline point definitions + + + +Conceptual example: + + + +```yaml + +points: + + + + - id: LEVEL + + displayName: Wet well level + + description: Measured wet well level + + + + source: + + reference: ... + + + + dataType: float + + engineeringUnit: m + + + + scaling: + + enabled: false + + + + live: + + enabled: true + + + + history: + + enabled: true + + + + opcua: + + enabled: true + + historizing: true + + + + storage: + + enabled: true + +``` + + + +The exact AquaCom source-reference syntax shall only be defined when supported by verified protocol or ATF semantics. + + + +\--- + + + +\# 50. Point identifier + + + +\## 50.1 `points\[].id` + + + +\*\*Required:\*\* yes + + + +Stable point identifier within the station. + + + +Example: + + + +```yaml + +id: LEVEL + +``` + + + +Logical identity may become: + + + +```text + +station:PS001/point:LEVEL + +``` + + + +Changing `displayName` shall not change this identifier. + + + +\--- + + + +\# 51. Point display name + + + +\## 51.1 `points\[].displayName` + + + +Human-readable presentation name. + + + +Example: + + + +```yaml + +displayName: Wet well level + +``` + + + +May be changed without creating a new logical process point. + + + +\--- + + + +\# 52. Point source reference + + + +Example: + + + +```yaml + +source: + + reference: ... + +``` + + + +Defines how the point maps to AquaCom. + + + +The content is intentionally unspecified until AquaCom mapping rules are verified. + + + +Codex shall not invent source-reference syntax. + + + +\--- + + + +\# 53. Point data type + + + +\## 53.1 `points\[].dataType` + + + +Logical canonical data type. + + + +Possible values may include: + + + +```text + +boolean + +integer + +unsigned-integer + +float + +double + +string + +``` + + + +The final supported set shall be defined by the canonical data model. + + + +\--- + + + +\# 54. Engineering unit + + + +\## 54.1 `points\[].engineeringUnit` + + + +Optional engineering unit. + + + +Examples: + + + +```yaml + +engineeringUnit: m + +``` + + + +```yaml + +engineeringUnit: l/s + +``` + + + +```yaml + +engineeringUnit: °C + +``` + + + +Engineering units should use a controlled representation where feasible. + + + +\--- + + + +\# 55. Point scaling + + + +Example: + + + +```yaml + +scaling: + + enabled: true + + multiplier: 0.1 + + offset: 0 + +``` + + + +Scaling is applied after verified AquaCom decoding and before creation of the canonical value. + + + +The raw value may optionally be retained diagnostically. + + + +\--- + + + +\# 56. Point live configuration + + + +Example: + + + +```yaml + +live: + + enabled: true + +``` + + + +Controls whether the point participates in current-state processing. + + + +\--- + + + +\# 57. Point history configuration + + + +Example: + + + +```yaml + +history: + + enabled: true + +``` + + + +Controls whether historical information is processed for the point. + + + +\--- + + + +\# 58. Point OPC UA configuration + + + +Example: + + + +```yaml + +opcua: + + enabled: true + + historizing: true + +``` + + + +\--- + + + +\## 58.1 `points\[].opcua.enabled` + + + +Controls whether the point is exposed through OPC UA. + + + +\--- + + + +\## 58.2 `points\[].opcua.historizing` + + + +Controls whether the OPC UA Variable advertises historical capability. + + + +If enabled: + + + +\- point history must be enabled; + +\- OPC UA Historical Access must be enabled; + +\- a queryable repository must be configured. + + + +\--- + + + +\# 59. Explicit NodeId override + + + +Optional example: + + + +```yaml + +opcua: + + enabled: true + + nodeId: station/PS001/point/LEVEL + +``` + + + +Normally the gateway should generate deterministic NodeIds from stable station and point identifiers. + + + +Manual override should only be required for compatibility or migration scenarios. + + + +Duplicate NodeIds shall be rejected. + + + +\--- + + + +\# 60. Point storage configuration + + + +Example: + + + +```yaml + +storage: + + enabled: true + + + + destinations: + + - local-history + + - enterprise-historian + +``` + + + +If `destinations` is omitted, a global/default routing policy may be used. + + + +\--- + + + +\# 61. Storage routing + + + +The system shall support routing history to selected destinations. + + + +Example: + + + +```yaml + +storage: + + enabled: true + + + + destinations: + + - local-history + + - enterprise-historian + +``` + + + +Different points may therefore use different storage policies if required. + + + +\--- + + + +\# 62. History source behavior + + + +A point may theoretically receive historical data from: + + + +```text + +live historization + +AquaCom historical retrieval + +AquaCom report retrieval + +future import + +``` + + + +The canonical `AcquisitionSource` shall preserve the origin. + + + +Storage routing shall not normally depend upon raw AquaCom message types. + + + +\--- + + + +\# 63. Timestamp configuration + + + +Station timestamp behavior may include: + + + +```yaml + +timestamps: + + sourceTimezone: Europe/Stockholm + + maximumFutureDeviation: 5m + + maximumPastDeviation: 365d + + ambiguousDstPolicy: reject + +``` + + + +\--- + + + +\## 63.1 `timestamps.sourceTimezone` + + + +Used to interpret device timestamps without explicit timezone information. + + + +Defaults to: + + + +```text + +station timezone + +``` + + + +then: + + + +```text + +gateway timezone + +``` + + + +if no station timezone exists. + + + +\--- + + + +\## 63.2 `timestamps.maximumFutureDeviation` + + + +Maximum permitted source timestamp ahead of gateway time before it is flagged. + + + +\--- + + + +\## 63.3 `timestamps.maximumPastDeviation` + + + +Optional sanity threshold for implausibly old values. + + + +Historical backfill behavior may legitimately require values much older than normal live values. + + + +The implementation shall distinguish history from erroneous live timestamps. + + + +\--- + + + +\## 63.4 `timestamps.ambiguousDstPolicy` + + + +Defines behavior when a source local timestamp is ambiguous during daylight-saving transition. + + + +Possible conceptual values: + + + +```text + +reject + +prefer-earlier + +prefer-later + +mark-uncertain + +``` + + + +Recommended behavior is either: + + + +```text + +mark-uncertain + +``` + + + +or: + + + +```text + +reject + +``` + + + +depending on operational requirements. + + + +\--- + + + +\# 64. Communication health configuration + + + +A station may define thresholds such as: + + + +```yaml + +health: + + degradedAfterFailures: 2 + + offlineAfterFailures: 5 + + staleAfter: 30s + +``` + + + +\--- + + + +\## 64.1 `health.degradedAfterFailures` + + + +Consecutive failed transactions before communication changes to a degraded state. + + + +\--- + + + +\## 64.2 `health.offlineAfterFailures` + + + +Consecutive failed transactions before the station is considered offline. + + + +This value must be greater than or equal to the degraded threshold. + + + +\--- + + + +\## 64.3 `health.staleAfter` + + + +Maximum age of a current value before quality may be changed to stale/uncertain/bad according to configured behavior. + + + +\--- + + + +\# 65. Retry behavior + + + +Transport, AquaCom transactions and storage destinations may each have separate retry policies. + + + +These retries shall not be combined into an uncontrolled nested retry loop. + + + +Retry configuration should define: + + + +```yaml + +retry: + + initialDelay: 1s + + maximumDelay: 1m + + multiplier: 2 + + jitter: true + +``` + + + +Exact supported fields are implementation-specific. + + + +\--- + + + +\# 66. Configuration inheritance + + + +Where practical, the gateway may support default configuration inheritance. + + + +Example: + + + +```yaml + +defaults: + + station: + + acquisition: + + live: + + pollingInterval: 5s + + + + health: + + degradedAfterFailures: 2 + + offlineAfterFailures: 5 + +``` + + + +Then a station may override: + + + +```yaml + +stations: + + - id: PS001 + + + + acquisition: + + live: + + pollingInterval: 2s + +``` + + + +If implemented, inheritance rules must be deterministic and documented. + + + +Implicit multi-level inheritance should be avoided if it makes effective configuration difficult to understand. + + + +\--- + + + +\# 67. Configuration validation rules + + + +The configuration validator shall detect at least: + + + +```text + +unsupported configVersion + + + +duplicate gateway/station/point/storage identifiers + + + +duplicate OPC UA NodeIds + + + +missing referenced storage destinations + + + +Historical Access enabled without queryable repository + + + +point historizing enabled without history capability + + + +unsupported transport type + + + +unsupported storage driver + + + +invalid timezone + + + +invalid durations + + + +invalid numeric limits + + + +invalid security configuration + + + +required secrets not available + + + +nonexistent required files + + + +invalid ATF or point-definition references + + + +history enabled for unsupported station profile + + + +configuration contradictions + +``` + + + +\--- + + + +\# 68. Cross-field validation + + + +Examples of required relationships follow. + + + +If: + + + +```yaml + +opcua: + + historicalAccess: + + enabled: true + +``` + + + +then: + + + +```text + +a queryable history repository must exist. + +``` + + + +If: + + + +```yaml + +point: + + opcua: + + historizing: true + +``` + + + +then: + + + +```text + +point history must be enabled. + +``` + + + +If: + + + +```yaml + +history: + + enabled: false + +``` + + + +then point-level historical acquisition shall not become active. + + + +If: + + + +```yaml + +station: + + acquisition: + + history: + + enabled: true + +``` + + + +but the configured AquaCom profile has no verified historical implementation, validation shall fail or the station history feature shall be explicitly marked unavailable. + + + +It shall not silently use guessed AquaCom behavior. + + + +\--- + + + +\# 69. Configuration activation + + + +Configuration shall follow: + + + +```text + +Load + + ↓ + +Parse + + ↓ + +Schema validation + + ↓ + +Semantic validation + + ↓ + +Dependency validation + + ↓ + +Activation + +``` + + + +Invalid configuration shall not partially activate. + + + +Where dynamic reload is supported: + + + +```text + +Current valid configuration + + │ + + ▼ + + New configuration + + │ + + ▼ + + Validate + + ┌───────┴────────┐ + + │ │ + + valid invalid + + │ │ + + ▼ ▼ + + activate retain existing + +``` + + + +\--- + + + +\# 70. Dynamic configuration + + + +Changes may be classified as: + + + +```text + +runtime-safe + +controlled-restart + +full-restart + +``` + + + +Examples that may eventually be runtime-safe: + + + +```text + +logging level + +polling intervals + +selected diagnostics + +storage retry intervals + +``` + + + +Changes likely requiring controlled restart or resource reconstruction: + + + +```text + +OPC UA application certificate + +OPC UA namespace URI + +transport type + +storage driver type + +persistent storage path + +``` + + + +Exact behavior shall be defined by the implementation. + + + +\--- + + + +\# 71. Configuration compatibility + + + +The gateway shall distinguish: + + + +```text + +configuration schema compatibility + +OPC UA namespace compatibility + +storage schema compatibility + +protocol profile compatibility + +``` + + + +A configuration schema change shall not automatically require an OPC UA namespace change. + + + +\--- + + + +\# 72. Example minimal configuration + + + +```yaml + +configVersion: 1 + + + +gateway: + + id: aquacom-gateway-01 + + timezone: Europe/Stockholm + + + +logging: + + level: information + + + +diagnostics: + + enabled: true + + + +opcua: + + enabled: true + + + + application: + + name: AquaCom Integration Gateway + + uri: urn:example:aquacom-gateway + + + + endpoint: + + bindAddress: 0.0.0.0 + + port: 4840 + + + + namespace: + + uri: urn:example:aquacom + + + + dataAccess: + + enabled: true + + + + historicalAccess: + + enabled: false + + + + security: + + allowNone: false + + certificate: gateway-opcua + + + +history: + + enabled: false + + + +storage: + + destinations: \[] + + + +stations: + + + + - id: PS001 + + enabled: true + + + + transport: + + type: tcp + + host: 192.0.2.10 + + port: 1234 + + + + aquacom: + + address: 101 + + + + acquisition: + + live: + + enabled: true + + pollingInterval: 5s + + + + pointDefinitions: + + sourceType: atf + + path: ./stations/PS001.atf + +``` + + + +This configuration represents: + + + +```text + +AquaCom live acquisition + + ↓ + +OPC UA current values + +``` + + + +without historical functionality. + + + +\--- + + + +\# 73. Example configuration with history + + + +```yaml + +configVersion: 1 + + + +gateway: + + id: aquacom-gateway-01 + + timezone: Europe/Stockholm + + + +logging: + + level: information + + + +diagnostics: + + enabled: true + + + +opcua: + + enabled: true + + + + application: + + name: AquaCom Integration Gateway + + uri: urn:example:aquacom-gateway + + + + endpoint: + + bindAddress: 0.0.0.0 + + port: 4840 + + + + namespace: + + uri: urn:example:aquacom + + + + dataAccess: + + enabled: true + + + + historicalAccess: + + enabled: true + + repository: local-history + + maxValuesPerRead: 10000 + + + + security: + + allowNone: false + + certificate: gateway-opcua + + + +history: + + enabled: true + + + + liveHistorization: + + enabled: true + + + + deduplication: + + enabled: true + + conflictPolicy: reject + + + + synchronization: + + enabled: true + + resumeAfterRestart: true + + + + backfill: + + enabled: true + + priority: low + + maxRequestsPerSecond: 2 + + + + spool: + + enabled: true + + path: ./data/spool + + maxSize: 20GB + + overflowPolicy: stop-history + + + +storage: + + destinations: + + + + - id: local-history + + type: repository-and-sink + + driver: local-history + + required: true + + + + capabilities: + + write: true + + query: true + + + + connection: + + path: ./data/history + + + + - id: central-historian + + type: sink + + driver: enterprise-historian + + required: true + + + + capabilities: + + write: true + + query: false + + + + connection: + + endpoint: historian.example.local + + credentialSecret: CENTRAL\_HISTORIAN\_CREDENTIAL + + + + - id: archive + + type: sink + + driver: ndjson + + required: false + + + + capabilities: + + write: true + + query: false + + + + connection: + + directory: ./archive + + + +stations: + + + + - id: PS001 + + displayName: Wastewater Pump Station 001 + + enabled: true + + timezone: Europe/Stockholm + + + + transport: + + type: tcp + + host: 192.0.2.10 + + port: 1234 + + connectTimeout: 5s + + + + aquacom: + + address: 101 + + profile: default + + + + acquisition: + + + + live: + + enabled: true + + pollingInterval: 5s + + requestTimeout: 3s + + retryCount: 2 + + + + history: + + enabled: true + + backfillEnabled: true + + maxBackfillAge: 7d + + + + timestamps: + + sourceTimezone: Europe/Stockholm + + maximumFutureDeviation: 5m + + + + health: + + degradedAfterFailures: 2 + + offlineAfterFailures: 5 + + staleAfter: 30s + + + + pointDefinitions: + + sourceType: atf + + path: ./stations/PS001.atf + +``` + + + +\--- + + + +\# 74. Example resulting data flow + + + +Using the configuration above: + + + +```text + +PS001 + + │ + + │ AquaCom + + ▼ + +Gateway + + │ + + ├────────► Current-State Service + + │ │ + + │ ▼ + + │ OPC UA DA + + │ + + └────────► Historical Pipeline + + │ + + ▼ + + Durable Spool + + │ + + ┌─────────┼─────────────┐ + + │ │ │ + + ▼ ▼ ▼ + + Local History Central Archive + + Repository Historian + + │ + + ▼ + + OPC UA HA + +``` + + + +\--- + + + +\# 75. Recommended configuration file organization + + + +Small installations may use one file: + + + +```text + +config/ + +└── gateway.yaml + +``` + + + +Larger installations should be able to split configuration logically: + + + +```text + +config/ + +├── gateway.yaml + +├── opcua.yaml + +├── storage.yaml + +├── defaults.yaml + +│ + +└── stations/ + + ├── PS001.yaml + + ├── PS002.yaml + + ├── PS003.yaml + + └── ... + +``` + + + +The implementation may support file inclusion or configuration-directory loading. + + + +Regardless of physical layout, the resulting configuration model shall be equivalent to the logical model described in this document. + + + +\--- + + + +\# 76. Recommended station-file organization + + + +For a larger number of AquaCom installations: + + + +```text + +config/ + +└── stations/ + + │ + + ├── PS001/ + + │ ├── station.yaml + + │ └── station.atf + + │ + + ├── PS002/ + + │ ├── station.yaml + + │ └── station.atf + + │ + + └── PS003/ + + ├── station.yaml + + └── station.atf + +``` + + + +This allows station-specific engineering configuration to remain grouped. + + + +\--- + + + +\# 77. Relationship to ATF + + + +Where ATF files are used, configuration and ATF have separate responsibilities. + + + +Conceptually: + + + +```text + +station.yaml + + │ + + ├── transport + + ├── communication + + ├── acquisition + + ├── history + + ├── security/context + + └── ATF reference + + │ + + ▼ + + station.atf + + │ + + └── AquaCom station capability / + + point definition + +``` + + + +ATF-specific semantics shall be documented under: + + + +```text + +docs/protocol/ + +``` + + + +once verified. + + + +The generic configuration model shall not duplicate all information contained in the ATF unless required for overrides or normalization. + + + +\--- + + + +\# 78. Point overrides + + + +The architecture should permit gateway-specific metadata to augment imported point definitions. + + + +Conceptual example: + + + +```yaml + +pointOverrides: + + + + LEVEL: + + displayName: Wet well level + + engineeringUnit: m + + + + opcua: + + enabled: true + + historizing: true + + + + INTERNAL\_DIAGNOSTIC\_17: + + opcua: + + enabled: false + + + + history: + + enabled: false + +``` + + + +This permits an imported ATF point model to remain unchanged while gateway behavior is customized. + + + +\--- + + + +\# 79. Configuration precedence + + + +If multiple configuration sources are supported, precedence shall be explicit. + + + +Recommended conceptual order: + + + +```text + +built-in safe defaults + + ↓ + +global configuration + + ↓ + +station configuration + + ↓ + +point definition source + + ↓ + +explicit point override + +``` + + + +Later layers may override earlier values only where permitted. + + + +Secrets are resolved independently and shall not be written back into the effective configuration. + + + +\--- + + + +\# 80. Effective configuration + + + +The gateway should provide a diagnostic mechanism for viewing the effective non-secret configuration. + + + +For example: + + + +```text + +configured polling interval + +effective polling interval + +configured storage routing + +effective point properties + +selected AquaCom profile + +selected OPC UA NodeId + +``` + + + +This significantly improves troubleshooting. + + + +Secret values shall be redacted. + + + +\--- + + + +\# 81. Configuration audit + + + +Changes to active configuration should be auditable. + + + +An audit event should identify: + + + +```text + +configuration version + +previous configuration identity/hash + +new configuration identity/hash + +activation timestamp + +result + +operator/source where known + +``` + + + +The exact implementation is technology-dependent. + + + +\--- + + + +\# 82. Safe configuration behavior + + + +When configuration is incomplete or contradictory, prefer explicit failure over implicit behavior. + + + +Examples: + + + +Do not automatically select an arbitrary repository if: + + + +```yaml + +opcua: + + historicalAccess: + + enabled: true + +``` + + + +and multiple repositories exist but none is identified. + + + +Do not silently enable insecure OPC UA because certificate configuration failed. + + + +Do not invent AquaCom transport defaults if no verified defaults exist. + + + +Do not activate historical retrieval for an unsupported AquaCom controller profile. + + + +\--- + + + +\# 83. Configuration design rule + + + +Configuration should express \*\*intent\*\*, not implementation internals. + + + +Prefer: + + + +```yaml + +history: + + enabled: true + +``` + + + +over implementation-specific concepts such as: + + + +```yaml + +instantiateHistoryWorkerThread: true + +``` + + + +Prefer: + + + +```yaml + +required: true + +``` + + + +over: + + + +```yaml + +deleteSpoolRecordAfterDestination2: false + +``` + + + +The configuration model shall remain understandable independently of implementation language. + + + +\--- + + + +\# 84. Configuration schema files + + + +Machine-readable schemas should be separated approximately as: + + + +```text + +schemas/ + +├── gateway-config.schema.\* + +├── station-config.schema.\* + +├── point-config.schema.\* + +└── storage-config.schema.\* + +``` + + + +Schemas shall encode: + + + +```text + +required properties + +types + +enumerations + +ranges + +formats + +basic structural constraints + +``` + + + +Cross-component semantic validation may require application-level validation in addition to schema validation. + + + +\--- + + + +\# 85. Configuration tests + + + +Automated tests shall verify at least: + + + +```text + +minimal valid configuration accepted + + + +complete valid configuration accepted + + + +duplicate station ID rejected + + + +duplicate point ID rejected + + + +duplicate OPC UA NodeId rejected + + + +missing History Repository rejected when OPC UA HA enabled + + + +unknown storage destination rejected + + + +invalid timezone rejected + + + +invalid duration rejected + + + +unsupported transport rejected + + + +unsupported AquaCom profile rejected + + + +history configuration rejected where implementation support is absent + + + +insecure OPC UA production default prevented + + + +missing required secret reported + + + +point override applied correctly + + + +configuration reload failure leaves previous valid configuration active + +``` + + + +\--- + + + +\# 86. Initial implementation recommendation + + + +The first configuration implementation should support only the fields required for the initial production scope. + + + +The model in this document defines the intended architecture but does not require every optional field to be implemented immediately. + + + +Unsupported fields shall be: + + + +```text + +rejected + +``` + + + +or explicitly documented as: + + + +```text + +not implemented + +``` + + + +They shall not be silently ignored unless the configuration model explicitly permits forward-compatible unknown fields. + + + +\--- + + + +\# 87. Final configuration rule + + + +The configuration system shall preserve the architectural separation of the gateway. + + + +In particular: + + + +```text + +station transport configuration + + ≠ + +station identity + + + +display name + + ≠ + +PointId + + + +OPC UA NodeId + + ≠ + +runtime object identifier + + + +history retrieval + + ≠ + +OPC UA HistoryRead + + + +storage destination + + ≠ + +AquaCom protocol implementation + +``` + + + +The configuration model shall describe how components are connected without coupling those components internally. + + + +The most important configuration principles are: + + + +> Stable identifiers shall remain stable even when presentation or transport details change. + + + +> Invalid or unsupported AquaCom behavior shall never be activated through configuration by relying on guessed protocol semantics. + + + +> Historical acquisition, historical persistence, and OPC UA Historical Access shall remain independently configurable concerns. + diff --git a/docs/product/codex-implementation-specification.md b/docs/product/codex-implementation-specification.md new file mode 100644 index 0000000..2d6248e --- /dev/null +++ b/docs/product/codex-implementation-specification.md @@ -0,0 +1,10830 @@ +\\# Codex Implementation Specification + + + +\\## AquaCom Integration Gateway + + + + + + + +\\\*\\\*Document type:\\\*\\\* Implementation specification + + + +\\\*\\\*Target implementation agent:\\\*\\\* Codex + + + +\\\*\\\*System:\\\*\\\* AquaCom Integration Gateway + + + +\\\*\\\*Primary southbound interface:\\\*\\\* AquaCom + + + +\\\*\\\*Primary northbound interface:\\\*\\\* OPC UA + + + +\\\*\\\*Additional capability:\\\*\\\* Pluggable historical storage + + + +\\\*\\\*Programming language:\\\*\\\* To be selected during implementation planning + + + +\\\*\\\*Version:\\\*\\\* 0.1 + + + +\\\*\\\*Status:\\\*\\\* Draft + + + + + + + +\\--- + + + + + + + +\\# 1. Purpose + + + + + + + +This document defines how Codex shall implement the AquaCom Integration Gateway. + + + + + + + +The gateway shall: + + + + + + + +\\- communicate with AquaCom-compatible devices; + + + +\\- acquire current process information; + + + +\\- acquire historical process information; + + + +\\- maintain a protocol-independent internal data model; + + + +\\- expose current values through OPC UA; + + + +\\- expose historical values through OPC UA Historical Access; + + + +\\- persist historical information through one or several configurable storage providers; + + + +\\- recover historical data after communication interruptions where AquaCom equipment supports this; + + + +\\- maintain diagnostic information; + + + +\\- provide a simulation environment for development and automated testing. + + + + + + + +This document describes: + + + + + + + +\\- repository organization; + + + +\\- architectural boundaries; + + + +\\- required modules; + + + +\\- internal interfaces; + + + +\\- data contracts; + + + +\\- state machines; + + + +\\- configuration; + + + +\\- persistence; + + + +\\- testing; + + + +\\- milestones; + + + +\\- Codex working rules; + + + +\\- acceptance criteria. + + + + + + + +It does not prescribe the implementation programming language. + + + + + + + +\\--- + + + + + + + +\\# 2. Fundamental implementation rule + + + + + + + +The implementation shall be based on the following processing architecture: + + + + + + + +```text + + + +AquaCom + + + +\ │ + + + +\ ▼ + + + +Transport + + + +\ │ + + + +\ ▼ + + + +AquaCom protocol engine + + + +\ │ + + + +\ ▼ + + + +Station/session manager + + + +\ │ + + + +\ ▼ + + + +Canonical data model + + + +\ │ + + + +\ ├──────────────► Current-state service + + + +\ │ │ + + + +\ │ ▼ + + + +\ │ OPC UA DA + + + +\ │ + + + +\ └──────────────► Historical pipeline + + + +\ │ + + + +\ ┌──────────┼──────────────┐ + + + +\ │ │ │ + + + +\ ▼ ▼ ▼ + + + +\ Repository Storage A Storage B + + + +\ │ + + + +\ ▼ + + + +\ OPC UA HA + + + +``` + + + + + + + +No component above the AquaCom protocol layer shall parse or construct AquaCom telegrams. + + + + + + + +No AquaCom component shall depend upon OPC UA. + + + + + + + +No AquaCom component shall depend upon a particular database. + + + + + + + +No storage adapter shall depend upon AquaCom telegram structure. + + + + + + + +\\--- + + + + + + + +\\# 3. Codex implementation principles + + + + + + + +Codex shall follow these principles throughout development. + + + + + + + +\\## 3.1 Do not invent AquaCom protocol details + + + + + + + +Codex shall never invent: + + + + + + + +\\- byte positions; + + + +\\- telegram structure; + + + +\\- field identifiers; + + + +\\- checksums; + + + +\\- addressing rules; + + + +\\- commands; + + + +\\- response codes; + + + +\\- scaling; + + + +\\- timestamp encoding; + + + +\\- historical-data behavior. + + + + + + + +Protocol behavior may only be implemented when supported by at least one of: + + + + + + + +1\\. authoritative AquaCom documentation; + + + +2\\. validated packet/serial captures; + + + +3\\. existing known-good implementation behavior; + + + +4\\. approved test vectors. + + + + + + + +Unknown protocol details shall be represented as: + + + + + + + +```text + + + +NOT\\\_IMPLEMENTED + + + +``` + + + + + + + +or documented protocol gaps. + + + + + + + +A compilation-successful guess is not an acceptable implementation. + + + + + + + +\\--- + + + + + + + +\\# 4. Repository documentation strategy + + + + + + + +The repository shall contain a short root `AGENTS.md`. + + + + + + + +Detailed requirements shall live under `docs/`. + + + + + + + +`AGENTS.md` shall primarily direct Codex to the authoritative project documentation rather than attempt to contain the complete project specification. + + + + + + + +This follows current Codex guidance favoring concise repository instructions with deeper documentation maintained separately. + + + + + + + +Complex implementation work shall use an execution plan maintained in the repository. OpenAI's current Codex guidance explicitly recommends plan documents for significant features or refactors. + + + + + + + +\\--- + + + + + + + +\\# 5. Repository structure + + + + + + + +The initial repository shall use the following logical organization: + + + + + + + +```text + + + +/ + + + +├── AGENTS.md + + + +├── README.md + + + +├── ARCHITECTURE.md + + + +├── CHANGELOG.md + + + +├── LICENSE + + + +│ + + + +├── docs/ + + + +│ ├── product/ + + + +│ │ └── software-specification.md + + + +│ │ + + + +│ ├── architecture/ + + + +│ │ ├── overview.md + + + +│ │ ├── data-flow.md + + + +│ │ ├── live-data.md + + + +│ │ ├── historical-data.md + + + +│ │ ├── opcua.md + + + +│ │ ├── storage.md + + + +│ │ └── security.md + + + +│ │ + + + +│ ├── protocol/ + + + +│ │ ├── aquacom.md + + + +│ │ ├── known-operations.md + + + +│ │ ├── protocol-gaps.md + + + +│ │ └── test-vectors.md + + + +│ │ + + + +│ ├── configuration/ + + + +│ │ └── configuration-reference.md + + + +│ │ + + + +│ ├── operations/ + + + +│ │ ├── deployment.md + + + +│ │ ├── diagnostics.md + + + +│ │ ├── backup-recovery.md + + + +│ │ └── troubleshooting.md + + + +│ │ + + + +│ └── exec-plans/ + + + +│ ├── active/ + + + +│ └── completed/ + + + +│ + + + +├── schemas/ + + + +│ ├── gateway-config.schema.\\\* + + + +│ ├── station-config.schema.\\\* + + + +│ └── point-config.schema.\\\* + + + +│ + + + +├── config/ + + + +│ └── examples/ + + + +│ + + + +├── src/ + + + +│ ├── core/ + + + +│ ├── aquacom/ + + + +│ ├── history/ + + + +│ ├── storage/ + + + +│ ├── opcua/ + + + +│ ├── diagnostics/ + + + +│ └── host/ + + + +│ + + + +├── tests/ + + + +│ ├── unit/ + + + +│ ├── integration/ + + + +│ ├── protocol/ + + + +│ ├── opcua/ + + + +│ ├── history/ + + + +│ └── acceptance/ + + + +│ + + + +├── simulator/ + + + +│ + + + +├── fixtures/ + + + +│ ├── aquacom/ + + + +│ ├── history/ + + + +│ └── configuration/ + + + +│ + + + +├── tools/ + + + +│ + + + +└── deployment/ + + + +``` + + + + + + + +File extensions shall be selected once the implementation language and configuration formats are chosen. + + + + + + + +\\--- + + + + + + + +\\# 6. Root AGENTS.md + + + + + + + +The root `AGENTS.md` shall contain approximately the following instructions. + + + + + + + +```text + + + +\\# AquaCom Integration Gateway + + + + + + + +Read ARCHITECTURE.md and the relevant documents under docs/ before + + + +changing implementation behavior. + + + + + + + +For substantial features, protocol changes, persistence changes, or + + + +cross-module refactors, create or update an ExecPlan under + + + +docs/exec-plans/active/. + + + + + + + +\\## Non-negotiable architecture rules + + + + + + + +1\\. AquaCom protocol parsing belongs only in src/aquacom. + + + +2\\. OPC UA must never parse AquaCom telegrams. + + + +3\\. Storage adapters consume canonical historical records only. + + + +4\\. Historical samples must never be replayed as current process values. + + + +5\\. Preserve source timestamps separately from gateway receipt timestamps. + + + +6\\. Stable point IDs and OPC UA NodeIds must survive restart and renaming. + + + +7\\. Do not invent undocumented AquaCom protocol behavior. + + + +8\\. Every protocol implementation requires automated test vectors. + + + +9\\. Every bug fix requires a regression test where practical. + + + +10\\. Live acquisition takes priority over historical backfill. + + + + + + + +\\## AquaCom protocol evidence + + + + + + + +Protocol behavior may only be implemented using documented or validated + + + +evidence stored or referenced from docs/protocol/. + + + + + + + +If information is insufficient, document the gap in + + + +docs/protocol/protocol-gaps.md instead of guessing. + + + + + + + +\\## Testing + + + + + + + +Run applicable unit, integration and acceptance tests before considering + + + +a task complete. + + + + + + + +Do not weaken or remove tests merely to make a change pass. + + + + + + + +\\## Security + + + + + + + +Never commit secrets, private keys, production certificates, passwords + + + +or production network addresses. + + + + + + + +OPC UA insecure modes must not become the production default. + + + + + + + +\\## Documentation + + + + + + + +Update relevant architecture or configuration documentation whenever + + + +observable behavior changes. + + + +``` + + + + + + + +Nested `AGENTS.md` files may later be added where a specific module requires additional constraints. + + + + + + + +Codex supports hierarchical `AGENTS.md` instructions scoped to directory trees, making this suitable for stricter protocol or storage-specific rules if the repository grows. + + + + + + + +\\--- + + + + + + + +\\# 7. Architecture document + + + + + + + +`ARCHITECTURE.md` shall act as the primary architecture map. + + + + + + + +It shall contain: + + + + + + + +\\- system purpose; + + + +\\- module diagram; + + + +\\- dependency direction; + + + +\\- canonical data model; + + + +\\- live-data flow; + + + +\\- historical-data flow; + + + +\\- security boundaries; + + + +\\- links to detailed documents. + + + + + + + +The following dependency direction is mandatory: + + + + + + + +```text + + + +\ ┌──────────────┐ + + + +\ │ host │ + + + +\ └──────┬───────┘ + + + +\ │ + + + +\ ┌────────────┼────────────┐ + + + +\ ▼ ▼ ▼ + + + +\ OPC UA history diagnostics + + + +\ │ │ + + + +\ │ storage + + + +\ │ │ + + + +\ └──────┬─────┘ + + + +\ ▼ + + + +\ core + + + +\ ▲ + + + +\ │ + + + +\ aquacom + + + +``` + + + + + + + +`core` shall contain no dependencies on AquaCom, OPC UA or a particular storage implementation. + + + + + + + +\\--- + + + + + + + +\\# 8. Core domain module + + + + + + + +The `core` module shall contain protocol-neutral data models. + + + + + + + +Required logical entities include: + + + + + + + +```text + + + +StationId + + + +PointId + + + +CurrentValue + + + +HistoricalSample + + + +DataQuality + + + +AcquisitionSource + + + +StationState + + + +CommunicationState + + + +HistorySynchronizationState + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 9. Stable identifiers + + + + + + + +\\## 9.1 StationId + + + + + + + +`StationId` shall be an immutable logical gateway identifier. + + + + + + + +It shall not depend solely upon: + + + + + + + +\\- IP address; + + + +\\- hostname; + + + +\\- serial port; + + + +\\- display name. + + + + + + + +Example: + + + + + + + +```text + + + +station:PS001 + + + +``` + + + + + + + +\\--- + + + + + + + +\\## 9.2 PointId + + + + + + + +`PointId` shall be an immutable logical identifier. + + + + + + + +Example: + + + + + + + +```text + + + +station:PS001/point:LEVEL + + + +``` + + + + + + + +Changing: + + + + + + + +```text + + + +Wet well level + + + +``` + + + + + + + +to: + + + + + + + +```text + + + +Inlet sump level + + + +``` + + + + + + + +shall not change `PointId`. + + + + + + + +\\--- + + + + + + + +\\# 10. CurrentValue contract + + + + + + + +The canonical current-value model shall conceptually contain: + + + + + + + +```text + + + +CurrentValue + + + + + + + +StationId + + + +PointId + + + +Value + + + +DataType + + + +Quality + + + +SourceTimestamp? + + + +ReceivedTimestamp + + + +UpdatedTimestamp + + + +AcquisitionSource + + + +``` + + + + + + + +`SourceTimestamp` may be absent when AquaCom provides no trustworthy source timestamp. + + + + + + + +`ReceivedTimestamp` shall always be gateway-generated. + + + + + + + +\\--- + + + + + + + +\\# 11. HistoricalSample contract + + + + + + + +Historical samples shall contain: + + + + + + + +```text + + + +HistoricalSample + + + + + + + +StationId + + + +PointId + + + +Value + + + +DataType + + + +Quality + + + +SourceTimestamp + + + +ReceivedTimestamp + + + +AcquisitionSource + + + +AcquisitionId? + + + +Metadata? + + + +``` + + + + + + + +`SourceTimestamp` is mandatory for normal process history. + + + + + + + +A record without a reliable historical timestamp shall not silently be interpreted as historical process data. + + + + + + + +\\--- + + + + + + + +\\# 12. DataQuality + + + + + + + +Internal quality shall be independent of OPC UA. + + + + + + + +At minimum: + + + + + + + +```text + + + +GOOD + + + +UNCERTAIN + + + +BAD + + + +UNKNOWN + + + +``` + + + + + + + +Optional reason/substatus shall support values equivalent to: + + + + + + + +```text + + + +COMMUNICATION\\\_FAILURE + + + +STALE + + + +INVALID\\\_VALUE + + + +INVALID\\\_TIMESTAMP + + + +CONFIGURATION\\\_ERROR + + + +CONVERSION\\\_ERROR + + + +SOURCE\\\_UNCERTAIN + + + +HISTORY\\\_GAP + + + +``` + + + + + + + +The OPC UA module shall map this model to OPC UA StatusCodes. + + + + + + + +\\--- + + + + + + + +\\# 13. AcquisitionSource + + + + + + + +Historical and current information shall identify origin. + + + + + + + +Examples: + + + + + + + +```text + + + +LIVE + + + +AQUACOM\\\_HISTORY + + + +AQUACOM\\\_REPORT + + + +RECOVERY + + + +IMPORT + + + +SIMULATOR + + + +``` + + + + + + + +Implementation shall permit additional values. + + + + + + + +\\--- + + + + + + + +\\# 14. AquaCom transport interface + + + + + + + +The AquaCom transport abstraction shall provide functions equivalent to: + + + + + + + +```text + + + +open() + + + +close() + + + +send(bytes) + + + +receive() + + + +isConnected() + + + +getDiagnostics() + + + +``` + + + + + + + +The interface shall not interpret AquaCom fields. + + + + + + + +Potential transport implementations may include: + + + + + + + +\\- TCP; + + + +\\- serial; + + + +\\- modem abstraction; + + + +\\- serial-over-IP. + + + + + + + +The initial implementation only needs transports required by the target environment. + + + + + + + +\\--- + + + + + + + +\\# 15. AquaCom protocol codec + + + + + + + +The protocol codec shall provide deterministic transformation between: + + + + + + + +```text + + + +raw transport bytes + + + +``` + + + + + + + +and: + + + + + + + +```text + + + +AquaComMessage + + + +``` + + + + + + + +Logical interfaces: + + + + + + + +```text + + + +encode(request) -> bytes + + + + + + + +decode(bytes) -> message + + + + + + + +validate(bytes) -> validation\\\_result + + + +``` + + + + + + + +The codec shall have no network dependency. + + + + + + + +This is required so protocol behavior can be exhaustively unit tested. + + + + + + + +\\--- + + + + + + + +\\# 16. Protocol test vectors + + + + + + + +Every implemented AquaCom telegram type shall have test fixtures. + + + + + + + +Fixture format shall contain conceptually: + + + + + + + +```text + + + +name + + + +source + + + +direction + + + +raw-data + + + +decoded-operation + + + +decoded-fields + + + +expected-validation + + + +notes + + + +``` + + + + + + + +Example source classifications: + + + + + + + +```text + + + +SPECIFICATION + + + +CAPTURE + + + +KNOWN\\\_GOOD\\\_IMPLEMENTATION + + + +SYNTHETIC\\\_FROM\\\_SPECIFICATION + + + +``` + + + + + + + +The test suite shall prove both: + + + + + + + +```text + + + +raw → decoded + + + +``` + + + + + + + +and where applicable: + + + + + + + +```text + + + +object → encoded raw + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 17. Protocol gap registry + + + + + + + +`docs/protocol/protocol-gaps.md` shall maintain unresolved protocol issues. + + + + + + + +Each entry shall contain: + + + + + + + +```text + + + +Gap ID + + + +Description + + + +Affected operation + + + +Evidence available + + + +Evidence missing + + + +Impact + + + +Implementation status + + + +``` + + + + + + + +Example: + + + + + + + +```text + + + +AQ-GAP-007 + + + + + + + +Exact encoding of history timestamp field for controller type X + + + +is not yet verified. + + + + + + + +Impact: + + + +History retrieval cannot be enabled for this controller type. + + + + + + + +Required evidence: + + + +Protocol specification or validated capture. + + + +``` + + + + + + + +Codex shall not close a protocol gap without evidence. + + + + + + + +\\--- + + + + + + + +\\# 18. AquaCom session manager + + + + + + + +Each configured station shall use an independent session/state abstraction. + + + + + + + +Conceptual states: + + + + + + + +```text + + + +DISABLED + + + +INITIALIZING + + + +CONNECTING + + + +ONLINE + + + +DEGRADED + + + +OFFLINE + + + +RECOVERING + + + +``` + + + + + + + +Basic transition: + + + + + + + +```text + + + +\ successful communication + + + +OFFLINE ──────────────────────────────► ONLINE + + + + + + + +ONLINE + + + +\ │ + + + +\ │ repeated communication failures + + + +\ ▼ + + + +DEGRADED + + + +\ │ + + + +\ │ threshold exceeded + + + +\ ▼ + + + +OFFLINE + + + +\ │ + + + +\ │ transport available + + + +\ ▼ + + + +RECOVERING + + + +\ │ + + + +\ │ successful synchronization + + + +\ ▼ + + + +ONLINE + + + +``` + + + + + + + +Thresholds shall be configurable. + + + + + + + +\\--- + + + + + + + +\\# 19. Live acquisition scheduler + + + + + + + +The live acquisition scheduler shall: + + + + + + + +\\- schedule AquaCom live requests; + + + +\\- apply per-station polling configuration; + + + +\\- prevent overlapping invalid station transactions; + + + +\\- prioritize live communication over history backfill; + + + +\\- implement retry policy; + + + +\\- update communication diagnostics. + + + + + + + +The scheduler shall not write directly to OPC UA. + + + + + + + +It shall publish canonical `CurrentValue` updates. + + + + + + + +\\--- + + + + + + + +\\# 20. Current-state service + + + + + + + +The Current-State Service shall maintain the latest accepted current value for each PointId. + + + + + + + +Interface equivalent: + + + + + + + +```text + + + +update(CurrentValue) + + + + + + + +get(PointId) + + + + + + + +getAll(StationId) + + + + + + + +subscribe(PointId) + + + +``` + + + + + + + +The service shall reject obsolete updates where appropriate. + + + + + + + +A recovered historical sample shall not invoke: + + + + + + + +```text + + + +CurrentState.update() + + + +``` + + + + + + + +unless it has independently been determined to represent current state. + + + + + + + +\\--- + + + + + + + +\\# 21. Historical acquisition manager + + + + + + + +The Historical Acquisition Manager shall manage history retrieval from AquaCom stations. + + + + + + + +Responsibilities: + + + + + + + +\\- determine retrieval windows; + + + +\\- initiate historical requests; + + + +\\- maintain synchronization watermark; + + + +\\- process partial responses; + + + +\\- resume interrupted synchronization; + + + +\\- throttle retrieval; + + + +\\- deduplicate; + + + +\\- send canonical historical samples to the historical pipeline. + + + + + + + +Conceptual interface: + + + + + + + +```text + + + +synchronize(station) + + + + + + + +synchronize(station, start, end) + + + + + + + +getSynchronizationState(station) + + + + + + + +pause(station) + + + + + + + +resume(station) + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 22. Synchronization watermark + + + + + + + +Each station shall maintain persistent history synchronization state. + + + + + + + +Example: + + + + + + + +```text + + + +StationId + + + +HistoryStreamId + + + +LastCompleteTimestamp + + + +LastAttemptTimestamp + + + +LastSuccessfulTimestamp + + + +SynchronizationState + + + +``` + + + + + + + +The watermark shall only advance when the implementation has sufficient evidence that the interval has been processed successfully. + + + + + + + +\\--- + + + + + + + +\\# 23. Historical recovery state machine + + + + + + + +Conceptual history states: + + + + + + + +```text + + + +IDLE + + + +CHECK\\\_REQUIRED\\\_RANGE + + + +REQUESTING + + + +RECEIVING + + + +PERSISTING + + + +VERIFYING + + + +COMPLETE + + + +RETRY\\\_WAIT + + + +FAILED + + + +``` + + + + + + + +Typical sequence: + + + + + + + +```text + + + +IDLE + + + +\ │ + + + +\ ▼ + + + +CHECK\\\_REQUIRED\\\_RANGE + + + +\ │ + + + +\ ▼ + + + +REQUESTING + + + +\ │ + + + +\ ▼ + + + +RECEIVING + + + +\ │ + + + +\ ▼ + + + +PERSISTING + + + +\ │ + + + +\ ▼ + + + +VERIFYING + + + +\ │ + + + +\ ├── incomplete ──► REQUESTING + + + +\ │ + + + +\ └── complete ───► COMPLETE + + + +``` + + + + + + + +A restart during synchronization shall resume from persistent state without requiring complete duplication of the historical interval. + + + + + + + +\\--- + + + + + + + +\\# 24. Historical pipeline + + + + + + + +The historical pipeline shall receive: + + + + + + + +```text + + + +HistoricalSample + + + +``` + + + + + + + +and perform: + + + + + + + +```text + + + +validation + + + +\ ↓ + + + +normalization + + + +\ ↓ + + + +deduplication + + + +\ ↓ + + + +durable enqueue + + + +\ ↓ + + + +distribution + + + +``` + + + + + + + +Conceptually: + + + + + + + +```text + + + +HistoricalSample + + + +\ │ + + + +\ ▼ + + + +Validator + + + +\ │ + + + +\ ▼ + + + +Deduplicator + + + +\ │ + + + +\ ▼ + + + +Durable spool + + + +\ │ + + + +\ ┌─────┼─────────┐ + + + +\ ▼ ▼ ▼ + + + +Repo Store A Store B + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 25. Deduplication key + + + + + + + +Default logical identity: + + + + + + + +```text + + + +StationId + + + +\\+ + + + +PointId + + + +\\+ + + + +SourceTimestamp + + + +``` + + + + + + + +If AquaCom supplies a stronger identity such as a sequence number, the implementation may include it. + + + + + + + +The deduplication algorithm shall be deterministic. + + + + + + + +Collision behavior shall be configurable: + + + + + + + +```text + + + +KEEP\\\_FIRST + + + +KEEP\\\_LAST + + + +REJECT\\\_CONFLICT + + + +VERSION\\\_CONFLICT + + + +``` + + + + + + + +Recommended default: + + + + + + + +```text + + + +REJECT\\\_CONFLICT + + + +``` + + + + + + + +where conflicting values are stored diagnostically rather than silently overwritten. + + + + + + + +\\--- + + + + + + + +\\# 26. History repository interface + + + + + + + +A History Repository is a queryable source used by OPC UA Historical Access. + + + + + + + +Required logical interface: + + + + + + + +```text + + + +store(sample) + + + + + + + +storeBatch(samples) + + + + + + + +readRaw( + + + +\ pointId, + + + +\ startTime, + + + +\ endTime, + + + +\ limit, + + + +\ continuation + + + +) + + + + + + + +readAtTime( + + + +\ pointId, + + + +\ timestamps + + + +) + + + + + + + +getBounds(pointId) + + + + + + + +health() + + + +``` + + + + + + + +The repository may be: + + + + + + + +\\- local; + + + +\\- external; + + + +\\- relational; + + + +\\- time-series; + + + +\\- industrial historian. + + + + + + + +OPC UA shall interact only through this abstraction. + + + + + + + +\\--- + + + + + + + +\\# 27. Storage sink interface + + + + + + + +A storage sink is an independent history destination. + + + + + + + +Required interface: + + + + + + + +```text + + + +initialize() + + + + + + + +write(sample) + + + + + + + +writeBatch(samples) + + + + + + + +flush() + + + + + + + +health() + + + + + + + +shutdown() + + + +``` + + + + + + + +A storage sink does not need to support queries. + + + + + + + +Examples: + + + + + + + +```text + + + +SQL sink + + + +time-series sink + + + +industrial historian sink + + + +file/archive sink + + + +message-stream sink + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 28. Repository versus sink + + + + + + + +These concepts shall remain distinct. + + + + + + + +```text + + + +Repository + + + +\ = historical data can be queried + + + + + + + +Sink + + + +\ = historical data can be delivered + + + +``` + + + + + + + +A component may implement both interfaces. + + + + + + + +Example: + + + + + + + +```text + + + +Local historian: + + + +\ Repository = yes + + + +\ Sink = yes + + + + + + + +Archive file: + + + +\ Repository = no + + + +\ Sink = yes + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 29. Durable spool + + + + + + + +Historical delivery shall pass through persistent buffering. + + + + + + + +Conceptual record: + + + + + + + +```text + + + +SpoolRecord + + + + + + + +RecordId + + + +HistoricalSample + + + +CreatedTimestamp + + + +Destinations\\\[] + + + +Acknowledgements\\\[] + + + +RetryState + + + +``` + + + + + + + +Example: + + + + + + + +```text + + + +record 123 + + + + + + + +StorageLocal ACK + + + +CentralHistorian PENDING + + + +Archive ACK + + + +``` + + + + + + + +Record 123 shall remain available until required delivery policy has been fulfilled. + + + + + + + +\\--- + + + + + + + +\\# 30. Delivery policy + + + + + + + +Configuration shall define whether a destination is: + + + + + + + +```text + + + +REQUIRED + + + +OPTIONAL + + + +``` + + + + + + + +Example: + + + + + + + +```text + + + +LocalHistory: + + + +\ REQUIRED + + + + + + + +CentralHistorian: + + + +\ REQUIRED + + + + + + + +ArchiveExport: + + + +\ OPTIONAL + + + +``` + + + + + + + +A failed optional destination shall generate diagnostics but shall not indefinitely block spool cleanup. + + + + + + + +\\--- + + + + + + + +\\# 31. Storage failure handling + + + + + + + +Each storage destination shall implement independent retry. + + + + + + + +Recommended conceptual retry progression: + + + + + + + +```text + + + +immediate + + + +short delay + + + +increasing delay + + + +maximum delay + + + +periodic retry + + + +``` + + + + + + + +Exact timing shall be configurable. + + + + + + + +Retries shall not block live acquisition. + + + + + + + +\\--- + + + + + + + +\\# 32. OPC UA module + + + + + + + +The OPC UA module shall contain: + + + + + + + +```text + + + +Server lifecycle + + + +Namespace manager + + + +Node mapping + + + +Current-value provider + + + +Historical provider + + + +StatusCode mapper + + + +Security configuration + + + +Diagnostics exposure + + + +``` + + + + + + + +It shall depend upon: + + + + + + + +```text + + + +core + + + +current-state service + + + +history repository + + + +diagnostics + + + +``` + + + + + + + +It shall not depend directly upon AquaCom transport or AquaCom codec. + + + + + + + +\\--- + + + + + + + +\\# 33. OPC UA namespace mapping + + + + + + + +Default structure: + + + + + + + +```text + + + +AquaCom + + + +│ + + + +├── Gateway + + + +│ ├── Status + + + +│ ├── Version + + + +│ ├── StartTime + + + +│ ├── ConfigurationVersion + + + +│ ├── HistoricalQueueDepth + + + +│ └── Storage + + + +│ + + + +└── Stations + + + +\ │ + + + +\ ├── PS001 + + + +\ │ ├── Process + + + +\ │ │ ├── Level + + + +\ │ │ ├── Pump01Running + + + +\ │ │ └── Pump02Running + + + +\ │ │ + + + +\ │ └── Diagnostics + + + +\ │ ├── CommunicationState + + + +\ │ ├── LastCommunication + + + +\ │ ├── HistoryState + + + +\ │ └── HistoryWatermark + + + +\ │ + + + +\ └── PS002 + + + +``` + + + + + + + +Namespace generation shall be deterministic. + + + + + + + +\\--- + + + + + + + +\\# 34. OPC UA NodeId generation + + + + + + + +OPC UA NodeIds shall derive from stable internal identifiers. + + + + + + + +Example: + + + + + + + +```text + + + +ns=;s=station/PS001/point/LEVEL + + + +``` + + + + + + + +The exact syntax may differ. + + + + + + + +The critical requirement is: + + + + + + + +```text + + + +same logical point + + + +\ = + + + +same NodeId + + + +``` + + + + + + + +across: + + + + + + + +\\- restart; + + + +\\- upgrade; + + + +\\- rename; + + + +\\- transport address change. + + + + + + + +\\--- + + + + + + + +\\# 35. OPC UA current-value mapping + + + + + + + +For each configured live point: + + + + + + + +```text + + + +CurrentValue.Value + + + +\ → OPC UA Value + + + + + + + +CurrentValue.SourceTimestamp + + + +\ → OPC UA SourceTimestamp + + + + + + + +gateway processing time + + + +\ → OPC UA ServerTimestamp + + + + + + + +CurrentValue.Quality + + + +\ → OPC UA StatusCode + + + +``` + + + + + + + +If communication fails, the node shall transition to a suitable non-Good status according to configuration. + + + + + + + +\\--- + + + + + + + +\\# 36. OPC UA history provider + + + + + + + +When an OPC UA client sends: + + + + + + + +```text + + + +HistoryRead + + + +``` + + + + + + + +the OPC UA layer shall call: + + + + + + + +```text + + + +HistoryRepository.readRaw() + + + +``` + + + + + + + +It shall never directly cause: + + + + + + + +```text + + + +AquaCom history request + + + +``` + + + + + + + +The following is prohibited: + + + + + + + +```text + + + +OPC UA HistoryRead + + + +\ │ + + + +\ ▼ + + + +AquaCom WGH request + + + +\ │ + + + +\ ▼ + + + +wait for RTU + + + +``` + + + + + + + +Correct behavior: + + + + + + + +```text + + + +AquaCom synchronization + + + +\ │ + + + +\ ▼ + + + +Repository + + + + + + + +OPC UA HistoryRead + + + +\ │ + + + +\ ▼ + + + +Repository + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 37. OPC UA historical continuation + + + + + + + +The implementation shall support bounded historical reads. + + + + + + + +Configuration: + + + + + + + +```text + + + +maximumValuesPerHistoryRead + + + +``` + + + + + + + +If more values exist than can be returned: + + + + + + + +```text + + + +HistoryRead + + + +\ │ + + + +\ ▼ + + + +batch 1 + continuation token + + + +\ │ + + + +\ ▼ + + + +HistoryRead continuation + + + +\ │ + + + +\ ▼ + + + +batch 2 + + + +``` + + + + + + + +Continuation state shall be resource-limited. + + + + + + + +\\--- + + + + + + + +\\# 38. Time handling + + + + + + + +Internal canonical timestamps shall be timezone-unambiguous. + + + + + + + +Preferred internal representation: + + + + + + + +```text + + + +UTC timestamp + + + +``` + + + + + + + +Station configuration shall define AquaCom timezone interpretation where required. + + + + + + + +Configuration fields shall include concepts equivalent to: + + + + + + + +```text + + + +timezone + + + +timestampSource + + + +maximumFutureDeviation + + + +maximumPastDeviation + + + +dstPolicy + + + +``` + + + + + + + +The raw source timestamp may optionally also be retained for diagnostics. + + + + + + + +\\--- + + + + + + + +\\# 39. Configuration model + + + + + + + +A gateway configuration shall contain approximately: + + + + + + + +```text + + + +gateway + + + +logging + + + +opcua + + + +history + + + +storage + + + +stations + + + +security + + + +diagnostics + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 40. Gateway configuration + + + + + + + +Conceptual example: + + + + + + + +```text + + + +gateway: + + + +\ id: aquacom-gateway-01 + + + +\ site: central-ot + + + +\ timezone: Europe/Stockholm + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 41. Station configuration + + + + + + + +Conceptual configuration: + + + + + + + +```text + + + +station: + + + +\ id: PS001 + + + +\ enabled: true + + + + + + + +\ transport: + + + +\ type: tcp + + + +\ ... + + + + + + + +\ aquacom: + + + +\ address: ... + + + +\ profile: ... + + + + + + + +\ acquisition: + + + +\ live: + + + +\ enabled: true + + + +\ interval: ... + + + + + + + +\ history: + + + +\ enabled: true + + + +\ synchronization: ... + + + + + + + +\ points: + + + +\ source: ... + + + +``` + + + + + + + +Exact syntax shall be selected during technology selection. + + + + + + + +\\--- + + + + + + + +\\# 42. Point configuration + + + + + + + +Conceptual: + + + + + + + +```text + + + +point: + + + +\ id: LEVEL + + + +\ name: Wet well level + + + + + + + +\ source: + + + +\ aquacomReference: ... + + + + + + + +\ datatype: float + + + +\ engineeringUnit: m + + + + + + + +\ live: + + + +\ enabled: true + + + + + + + +\ history: + + + +\ enabled: true + + + + + + + +\ opcua: + + + +\ enabled: true + + + +\ historizing: true + + + + + + + +\ storage: + + + +\ enabled: true + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 43. Configuration schema validation + + + + + + + +Machine-readable schemas shall validate configuration before startup. + + + + + + + +Validation shall detect: + + + + + + + +\\- duplicate station IDs; + + + +\\- duplicate point IDs; + + + +\\- invalid references; + + + +\\- impossible polling intervals; + + + +\\- unsupported transports; + + + +\\- missing required storage; + + + +\\- invalid timezone; + + + +\\- duplicate OPC UA NodeIds; + + + +\\- invalid security configuration. + + + + + + + +Invalid configuration shall fail safely. + + + + + + + +\\--- + + + + + + + +\\# 44. Secrets + + + + + + + +Secrets shall be supplied through an external secret mechanism appropriate to the selected deployment environment. + + + + + + + +The repository shall never contain production: + + + + + + + +```text + + + +passwords + + + +private keys + + + +API tokens + + + +certificate private keys + + + +database credentials + + + +``` + + + + + + + +Example files shall use placeholders. + + + + + + + +\\--- + + + + + + + +\\# 45. Diagnostics model + + + + + + + +Gateway-level diagnostics: + + + + + + + +```text + + + +GatewayState + + + +Version + + + +ConfigurationVersion + + + +StartTime + + + +Uptime + + + +StationCount + + + +OnlineStationCount + + + +HistoricalQueueDepth + + + +SpoolDiskUsage + + + +OPCUAState + + + +``` + + + + + + + +Per-station: + + + + + + + +```text + + + +CommunicationState + + + +LastRequest + + + +LastResponse + + + +LastSuccessfulCommunication + + + +ConsecutiveFailures + + + +ProtocolErrors + + + +HistorySynchronizationState + + + +HistoryWatermark + + + +HistoricalBacklog + + + +``` + + + + + + + +Per-storage destination: + + + + + + + +```text + + + +State + + + +LastSuccessfulWrite + + + +LastFailure + + + +PendingRecords + + + +Retries + + + +Latency + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 46. Logging requirements + + + + + + + +Structured logging shall be preferred. + + + + + + + +Every log record should support context equivalent to: + + + + + + + +```text + + + +timestamp + + + +severity + + + +component + + + +stationId? + + + +pointId? + + + +operation? + + + +correlationId? + + + +message + + + +error? + + + +``` + + + + + + + +Raw telegram logging shall be a separate debug facility. + + + + + + + +Production default shall not log every telegram. + + + + + + + +\\--- + + + + + + + +\\# 47. Correlation IDs + + + + + + + +AquaCom transactions shall have a transaction/correlation identifier. + + + + + + + +Example flow: + + + + + + + +```text + + + +AQ transaction 81245 + + + +\ │ + + + +\ ├── send request + + + +\ ├── receive response + + + +\ ├── decode + + + +\ ├── update values + + + +\ └── diagnostics + + + +``` + + + + + + + +This ID should be propagated through relevant diagnostics. + + + + + + + +\\--- + + + + + + + +\\# 48. Metrics + + + + + + + +The implementation shall expose or internally maintain metrics equivalent to: + + + + + + + +```text + + + +aquacom\\\_requests\\\_total + + + +aquacom\\\_errors\\\_total + + + +aquacom\\\_request\\\_duration + + + +station\\\_online + + + +live\\\_values\\\_processed + + + +history\\\_samples\\\_received + + + +history\\\_samples\\\_deduplicated + + + +history\\\_samples\\\_pending + + + +storage\\\_writes\\\_total + + + +storage\\\_write\\\_errors + + + +opcua\\\_clients\\\_connected + + + +opcua\\\_history\\\_reads + + + +spool\\\_bytes + + + +``` + + + + + + + +Specific metrics technology shall not be prescribed. + + + + + + + +\\--- + + + + + + + +\\# 49. Simulator + + + + + + + +A simulator shall be treated as a first-class component. + + + + + + + +It shall support scripted station behavior. + + + + + + + +Required simulation scenarios: + + + + + + + +```text + + + +normal live operation + + + +communication timeout + + + +connection loss + + + +malformed response + + + +bad checksum + + + +delayed response + + + +historical values + + + +historical gap + + + +duplicate history + + + +conflicting duplicate + + + +station clock error + + + +reconnect and backfill + + + +``` + + + + + + + +The simulator shall not share parsing code with the production AquaCom decoder in ways that make protocol tests self-validating. + + + + + + + +\\--- + + + + + + + +\\# 50. Test pyramid + + + + + + + +The project shall implement: + + + + + + + +```text + + + +\ Acceptance + + + +\ /\\\\ + + + +\ / \\\\ + + + +\ Integration + + + +\ / \\\\ + + + +\ / \\\\ + + + +\ Unit tests + + + +``` + + + + + + + +The majority of tests should be deterministic unit and component tests. + + + + + + + +\\--- + + + + + + + +\\# 51. Required unit tests + + + + + + + +\\## AquaCom codec + + + + + + + +```text + + + +framing + + + +checksum + + + +address encoding + + + +telegram decoding + + + +invalid telegram rejection + + + +unexpected field handling + + + +``` + + + + + + + +\\## Canonical model + + + + + + + +```text + + + +quality mapping + + + +timestamp validation + + + +stable identifier handling + + + +``` + + + + + + + +\\## History + + + + + + + +```text + + + +deduplication + + + +watermark progression + + + +gap handling + + + +conflict handling + + + +spool acknowledgement + + + +``` + + + + + + + +\\## OPC UA + + + + + + + +```text + + + +NodeId mapping + + + +quality mapping + + + +timestamp mapping + + + +history result conversion + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 52. Required integration tests + + + + + + + +At minimum: + + + + + + + +```text + + + +Simulator → AquaCom engine + + + + + + + +AquaCom engine → Current State + + + + + + + +AquaCom history → Historical pipeline + + + + + + + +Historical pipeline → Repository + + + + + + + +Historical pipeline → multiple sinks + + + + + + + +Repository → OPC UA HistoryRead + + + + + + + +Current state → OPC UA subscription + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 53. Restart recovery tests + + + + + + + +Automated tests shall cover gateway restart during: + + + + + + + +```text + + + +normal operation + + + +history retrieval + + + +database outage + + + +spool backlog + + + +partial delivery + + + +reconnect recovery + + + +``` + + + + + + + +Expected result: + + + + + + + +No acknowledged historical data is silently lost. + + + + + + + +\\--- + + + + + + + +\\# 54. End-to-end mandatory acceptance test + + + + + + + +Scenario: + + + + + + + +```text + + + +T0: + + + +Station online. + + + + + + + +Gateway receives live level values. + + + + + + + +OPC UA client receives current values. + + + + + + + +Values are persisted historically. + + + + + + + +T1: + + + +Station communication is interrupted. + + + + + + + +Gateway marks communication degraded/bad. + + + + + + + +Current OPC UA value is not falsely reported as newly valid. + + + + + + + +T2: + + + +Station continues local historical recording. + + + + + + + +T3: + + + +Communication returns. + + + + + + + +Live acquisition resumes promptly. + + + + + + + +T4: + + + +Gateway identifies missing historical interval. + + + + + + + +Gateway retrieves historical records. + + + + + + + +T5: + + + +Historical records retain their original timestamps. + + + + + + + +They are delivered to all required storage destinations. + + + + + + + +T6: + + + +OPC UA current value remains the actual current process value. + + + + + + + +T7: + + + +OPC UA HistoryRead for T1–T4 returns recovered historical values. + + + + + + + +T8: + + + +Same historical interval is retrieved again. + + + + + + + +No unintended duplicate historical records are created. + + + +``` + + + + + + + +The system shall not be considered production-capable until this test passes. + + + + + + + +\\--- + + + + + + + +\\# 55. Security tests + + + + + + + +Tests shall verify: + + + + + + + +```text + + + +untrusted OPC UA client certificate rejected + + + + + + + +trusted client accepted + + + + + + + +insecure OPC UA endpoint disabled by production configuration + + + + + + + +invalid credentials rejected where user authentication is enabled + + + + + + + +private keys not logged + + + + + + + +unauthorized HistoryUpdate rejected + + + + + + + +configuration containing secret placeholders validated appropriately + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 56. Fault injection + + + + + + + +Integration testing shall permit fault injection including: + + + + + + + +```text + + + +network disconnect + + + +packet loss + + + +delayed responses + + + +storage timeout + + + +storage exception + + + +disk-full simulation + + + +OPC UA client disconnect + + + +process restart + + + +corrupted local spool entry + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 57. CI requirements + + + + + + + +Every change shall run: + + + + + + + +```text + + + +format/lint checks + + + +static validation + + + +unit tests + + + +integration tests suitable for CI + + + +configuration schema validation + + + +dependency/security checks where available + + + +``` + + + + + + + +Protocol fixtures shall be testable without external network access. + + + + + + + +\\--- + + + + + + + +\\# 58. Pull request completion criteria + + + + + + + +Codex shall consider a development task complete only when: + + + + + + + +```text + + + +implementation exists + + + + + + + +tests exist + + + + + + + +tests pass + + + + + + + +relevant documentation is updated + + + + + + + +configuration examples are updated if required + + + + + + + +no known architectural boundary has been violated + + + + + + + +new protocol behavior has supporting evidence + + + + + + + +new failure modes have diagnostics + + + + + + + +no production secrets have been introduced + + + +``` + + + + + + + +Codex task prompts work best when scoped similarly to concrete issues or PRs with explicit files and expected outcomes. + + + + + + + +\\--- + + + + + + + +\\# 59. ExecPlan requirement + + + + + + + +Codex shall create an ExecPlan for work involving: + + + + + + + +\\- new AquaCom operations; + + + +\\- history synchronization; + + + +\\- storage architecture; + + + +\\- OPC UA namespace redesign; + + + +\\- security changes; + + + +\\- cross-module refactoring; + + + +\\- persistent-data migration; + + + +\\- changes affecting more than one architectural boundary. + + + + + + + +ExecPlan structure: + + + + + + + +```text + + + +Title + + + + + + + +Purpose + + + + + + + +Current state + + + + + + + +Desired state + + + + + + + +Constraints + + + + + + + +Files/components affected + + + + + + + +Implementation sequence + + + + + + + +Data model changes + + + + + + + +Failure handling + + + + + + + +Testing + + + + + + + +Migration/compatibility + + + + + + + +Progress + + + + + + + +Decisions + + + + + + + +Unexpected findings + + + + + + + +Acceptance evidence + + + +``` + + + + + + + +The plan shall remain updated while implementation proceeds. + + + + + + + +\\--- + + + + + + + +\\# 60. Development phases + + + + + + + +Implementation shall proceed in controlled phases. + + + + + + + +\\--- + + + + + + + +\\# Phase 0 – Repository and architecture + + + + + + + +Deliver: + + + + + + + +```text + + + +AGENTS.md + + + +README.md + + + +ARCHITECTURE.md + + + +docs structure + + + +CI skeleton + + + +configuration skeleton + + + +``` + + + + + + + +No AquaCom protocol implementation required. + + + + + + + +Acceptance: + + + + + + + +\\- repository builds; + + + +\\- automated test runner works; + + + +\\- architecture dependencies documented. + + + + + + + +\\--- + + + + + + + +\\# Phase 1 – Canonical core + + + + + + + +Implement: + + + + + + + +```text + + + +StationId + + + +PointId + + + +CurrentValue + + + +HistoricalSample + + + +DataQuality + + + +AcquisitionSource + + + +configuration domain + + + +``` + + + + + + + +Acceptance: + + + + + + + +\\- unit tests; + + + +\\- serialization tests where applicable; + + + +\\- stable identifier behavior defined. + + + + + + + +\\--- + + + + + + + +\\# Phase 2 – AquaCom transport abstraction + + + + + + + +Implement: + + + + + + + +```text + + + +transport interface + + + +connection lifecycle + + + +timeouts + + + +retry primitives + + + +diagnostics + + + +``` + + + + + + + +Implement only required initial transport. + + + + + + + +Acceptance: + + + + + + + +\\- mock transport tests; + + + +\\- connection-loss testing; + + + +\\- reconnect testing. + + + + + + + +\\--- + + + + + + + +\\# Phase 3 – AquaCom codec framework + + + + + + + +Implement: + + + + + + + +```text + + + +frame abstraction + + + +message abstraction + + + +codec interfaces + + + +validation framework + + + +fixture framework + + + +``` + + + + + + + +Only protocol elements with evidence may be implemented. + + + + + + + +Acceptance: + + + + + + + +```text + + + +captured/documented telegram + + + +\ ↓ + + + +decoder + + + +\ ↓ + + + +expected structured representation + + + +``` + + + + + + + +\\--- + + + + + + + +\\# Phase 4 – AquaCom simulator + + + + + + + +Implement simulator before depending on field equipment for normal development. + + + + + + + +Acceptance: + + + + + + + +\\- successful transaction; + + + +\\- timeout; + + + +\\- malformed telegram; + + + +\\- configurable process values. + + + + + + + +\\--- + + + + + + + +\\# Phase 5 – Station/session manager + + + + + + + +Implement: + + + + + + + +```text + + + +station lifecycle + + + +communication state + + + +poll scheduling + + + +retry policy + + + +diagnostics + + + +``` + + + + + + + +Acceptance: + + + + + + + +\\- multiple simulated stations; + + + +\\- one station failing does not affect others. + + + + + + + +\\--- + + + + + + + +\\# Phase 6 – Live acquisition + + + + + + + +Implement: + + + + + + + +```text + + + +live AquaCom operation + + + +point mapping + + + +scaling + + + +canonical CurrentValue + + + +current-state cache + + + +``` + + + + + + + +Acceptance: + + + + + + + +```text + + + +simulated AquaCom + + + +\ ↓ + + + +CurrentValue + + + +``` + + + + + + + +with correct value, quality and timestamps. + + + + + + + +\\--- + + + + + + + +\\# Phase 7 – OPC UA live interface + + + + + + + +Implement: + + + + + + + +```text + + + +server + + + +namespace + + + +stable NodeIds + + + +current reads + + + +subscriptions + + + +quality + + + +timestamps + + + +security + + + +``` + + + + + + + +Acceptance: + + + + + + + +An OPC UA test client can browse and subscribe to simulated AquaCom values. + + + + + + + +\\--- + + + + + + + +\\# Phase 8 – Local historical repository + + + + + + + +Implement the first queryable history repository. + + + + + + + +The selected technology may be embedded or external, but shall implement the defined repository abstraction. + + + + + + + +Acceptance: + + + + + + + +```text + + + +store + + + +query interval + + + +query bounds + + + +restart persistence + + + +``` + + + + + + + +\\--- + + + + + + + +\\# Phase 9 – Historical pipeline + + + + + + + +Implement: + + + + + + + +```text + + + +validation + + + +deduplication + + + +durable spool + + + +delivery + + + +repository integration + + + +``` + + + + + + + +Acceptance: + + + + + + + +Multiple submissions of the same sample do not produce unintended duplicate records. + + + + + + + +\\--- + + + + + + + +\\# Phase 10 – AquaCom historical acquisition + + + + + + + +Implement only after sufficient protocol evidence is available. + + + + + + + +Deliver: + + + + + + + +```text + + + +history retrieval + + + +watermark + + + +reconnect synchronization + + + +backfill + + + +throttling + + + +partial recovery + + + +``` + + + + + + + +Acceptance: + + + + + + + +The simulator's missing time interval is recovered after reconnection. + + + + + + + +\\--- + + + + + + + +\\# Phase 11 – OPC UA Historical Access + + + + + + + +Implement: + + + + + + + +```text + + + +HistoryRead + + + +raw values + + + +timestamps + + + +quality + + + +continuation + + + +``` + + + + + + + +Acceptance: + + + + + + + +An OPC UA HA client can retrieve both originally stored and recovered historical values. + + + + + + + +\\--- + + + + + + + +\\# Phase 12 – Multiple storage destinations + + + + + + + +Implement storage sink abstraction plus second sink implementation. + + + + + + + +Acceptance: + + + + + + + +```text + + + +one HistoricalSample + + + +\ │ + + + +\ ├── Repository A + + + +\ └── Storage B + + + +``` + + + + + + + +and failure of Storage B does not stop Repository A. + + + + + + + +\\--- + + + + + + + +\\# Phase 13 – Store-and-forward resilience + + + + + + + +Implement: + + + + + + + +```text + + + +persistent spool + + + +destination acknowledgements + + + +retry + + + +backpressure + + + +disk limits + + + +``` + + + + + + + +Acceptance: + + + + + + + +A storage destination may be offline while history accumulates and receive the backlog when restored. + + + + + + + +\\--- + + + + + + + +\\# Phase 14 – Production hardening + + + + + + + +Implement and validate: + + + + + + + +```text + + + +security + + + +resource limits + + + +performance + + + +operations documentation + + + +backup/recovery + + + +deployment + + + +certificate handling + + + +structured diagnostics + + + +long-duration tests + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 61. Codex task sizing + + + + + + + +Implementation phases shall be divided into bounded tasks rather than requesting the complete gateway in one prompt. + + + + + + + +Preferred task structure: + + + + + + + +```text + + + +Goal + + + + + + + +Relevant files + + + + + + + +Required behavior + + + + + + + +Constraints + + + + + + + +Tests + + + + + + + +Acceptance criteria + + + +``` + + + + + + + +Example: + + + + + + + +```text + + + +Implement the HistoricalSample deduplication service. + + + + + + + +Relevant: + + + +src/history + + + +docs/architecture/historical-data.md + + + + + + + +Requirements: + + + +\\- identity based on StationId + PointId + SourceTimestamp + + + +\\- conflicting value must be detected + + + +\\- default conflict policy REJECT\\\_CONFLICT + + + + + + + +Do not: + + + +\\- introduce database-specific logic + + + +\\- modify AquaCom codec + + + +\\- modify OPC UA + + + + + + + +Add unit tests covering: + + + +\\- first sample + + + +\\- exact duplicate + + + +\\- conflicting duplicate + + + +\\- different point + + + +\\- different timestamp + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 62. Codex rule for incomplete requirements + + + + + + + +When Codex encounters an implementation ambiguity, it shall classify it as: + + + + + + + +```text + + + +A. Local implementation detail + + + +B. Architectural decision + + + +C. AquaCom protocol uncertainty + + + +D. Safety/security uncertainty + + + +``` + + + + + + + +For A: + + + + + + + +Choose the simplest implementation consistent with architecture. + + + + + + + +For B: + + + + + + + +Record the decision in the current ExecPlan. + + + + + + + +For C: + + + + + + + +Do not guess. Add a protocol gap. + + + + + + + +For D: + + + + + + + +Choose the safer behavior and document the decision. + + + + + + + +\\--- + + + + + + + +\\# 63. AquaCom source traceability + + + + + + + +Every implemented protocol operation shall have traceability metadata in documentation. + + + + + + + +Example: + + + + + + + +```text + + + +Operation: HistoricalRead-X + + + + + + + +Evidence: + + + +AquaCom specification section 8.3 + + + +Capture fixture AQ-HIST-004 + + + +Validated against ControllerType-A + + + + + + + +Implemented: + + + +yes + + + + + + + +Tests: + + + +protocol/history\\\_read\\\_004 + + + +``` + + + + + + + +This traceability shall make it possible to audit why the implementation behaves as it does. + + + + + + + +\\--- + + + + + + + +\\# 64. Protocol capture handling + + + + + + + +Production captures used as test fixtures shall be: + + + + + + + +\\- sanitized; + + + +\\- stripped of unnecessary network identifiers; + + + +\\- documented; + + + +\\- immutable once used as reference fixtures. + + + + + + + +Fixture modification requires justification. + + + + + + + +Raw captures shall not automatically be committed if they contain sensitive operational information. + + + + + + + +\\--- + + + + + + + +\\# 65. Storage migration rule + + + + + + + +Storage schemas shall be versioned. + + + + + + + +Schema changes shall have explicit migrations. + + + + + + + +Application startup shall not silently destroy incompatible historical data. + + + + + + + +Destructive migration requires explicit administrative action. + + + + + + + +\\--- + + + + + + + +\\# 66. Configuration versioning + + + + + + + +The configuration model shall include a schema version. + + + + + + + +Example: + + + + + + + +```text + + + +configVersion: 1 + + + +``` + + + + + + + +Future incompatible configuration changes shall provide validation and, where reasonable, migration tooling. + + + + + + + +\\--- + + + + + + + +\\# 67. Software version exposure + + + + + + + +Gateway software version shall be available through: + + + + + + + +\\- startup logs; + + + +\\- diagnostics; + + + +\\- OPC UA diagnostics namespace. + + + + + + + +Build metadata should include where possible: + + + + + + + +```text + + + +version + + + +build identifier + + + +source revision + + + +configuration schema version + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 68. Compatibility strategy + + + + + + + +The gateway shall distinguish: + + + + + + + +```text + + + +protocol compatibility + + + +configuration compatibility + + + +storage compatibility + + + +OPC UA namespace compatibility + + + +``` + + + + + + + +Changes to any of these shall be considered independently. + + + + + + + +Stable OPC UA NodeIds are particularly important and shall not change unnecessarily between releases. + + + + + + + +\\--- + + + + + + + +\\# 69. Performance validation + + + + + + + +Before production acceptance, test: + + + + + + + +```text + + + +expected station count + + + + + + + +expected point count + + + + + + + +normal polling interval + + + + + + + +normal historical rate + + + + + + + +large backfill + + + + + + + +simultaneous OPC UA subscriptions + + + + + + + +large HistoryRead + + + + + + + +storage unavailable + + + + + + + +maximum expected spool backlog + + + +``` + + + + + + + +The purpose is to establish capacity limits rather than merely demonstrate successful execution. + + + + + + + +\\--- + + + + + + + +\\# 70. Live-priority scheduling + + + + + + + +AquaCom scheduling shall conceptually prioritize: + + + + + + + +```text + + + +1\\. connection/health-critical transactions + + + +2\\. current/live acquisition + + + +3\\. alarm/event retrieval when implemented + + + +4\\. requested configuration operations + + + +5\\. historical recovery + + + +6\\. low-priority maintenance + + + +``` + + + + + + + +Historical recovery shall be throttled if required to maintain live acquisition responsiveness. + + + + + + + +\\--- + + + + + + + +\\# 71. Memory and queue limits + + + + + + + +Every queue shall be bounded. + + + + + + + +No component may create an unbounded: + + + + + + + +```text + + + +message queue + + + +history list + + + +retry list + + + +client response + + + +log buffer + + + +``` + + + + + + + +Queue-full behavior shall be explicitly defined. + + + + + + + +\\--- + + + + + + + +\\# 72. Graceful shutdown + + + + + + + +The application shall support controlled shutdown. + + + + + + + +Order: + + + + + + + +```text + + + +stop accepting administration changes + + + +\ ↓ + + + +stop scheduling new acquisition + + + +\ ↓ + + + +complete/cancel active AquaCom transactions + + + +\ ↓ + + + +persist watermarks + + + +\ ↓ + + + +flush durable state + + + +\ ↓ + + + +stop OPC UA + + + +\ ↓ + + + +close storage + + + +\ ↓ + + + +terminate + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 73. Crash recovery + + + + + + + +Following unclean shutdown: + + + + + + + +```text + + + +load persistent state + + + +\ ↓ + + + +validate spool + + + +\ ↓ + + + +recover pending deliveries + + + +\ ↓ + + + +restore synchronization watermarks + + + +\ ↓ + + + +reconnect stations + + + +\ ↓ + + + +resume live operation + + + +\ ↓ + + + +continue required historical synchronization + + + +``` + + + + + + + +Live communication shall normally resume before large backfill jobs. + + + + + + + +\\--- + + + + + + + +\\# 74. Initial production scope + + + + + + + +The first production release shall include: + + + + + + + +```text + + + +AquaCom transport + + + +AquaCom protocol framework + + + +verified live-value acquisition + + + +verified historical acquisition + + + +multiple stations + + + +canonical data model + + + +live cache + + + +historical pipeline + + + +deduplication + + + +durable spool + + + +at least one history repository + + + +storage adapter framework + + + +at least two independently configurable storage targets + + + +OPC UA Data Access + + + +OPC UA Historical Access + + + +OPC UA security + + + +stable NodeIds + + + +diagnostics + + + +structured logging + + + +simulator + + + +automated tests + + + +restart recovery + + + +configuration validation + + + +``` + + + + + + + +\\--- + + + + + + + +\\# 75. Explicitly excluded from first production release + + + + + + + +Unless separately approved: + + + + + + + +```text + + + +AquaCom remote pump control + + + +AquaCom setpoint write + + + +OPC UA control writes + + + +OPC UA Methods for process control + + + +OPC UA HistoryUpdate + + + +automatic historian correction + + + +clustered high availability + + + +automatic protocol discovery + + + +``` + + + + + + + +Read-only process integration shall be established before remote-control functionality is introduced. + + + + + + + +\\--- + + + + + + + +\\# 76. Future process-control architecture + + + + + + + +If control is later implemented, it shall use a separate command pipeline: + + + + + + + +```text + + + +OPC UA + + + +\ │ + + + +\ ▼ + + + +authorization + + + +\ │ + + + +\ ▼ + + + +command validation + + + +\ │ + + + +\ ▼ + + + +command service + + + +\ │ + + + +\ ▼ + + + +AquaCom control operation + + + +\ │ + + + +\ ▼ + + + +confirmation/readback + + + +\ │ + + + +\ ▼ + + + +audit + + + +``` + + + + + + + +Direct mapping: + + + + + + + +```text + + + +OPC UA write → raw AquaCom telegram + + + +``` + + + + + + + +shall not be permitted. + + + + + + + +\\--- + + + + + + + +\\# 77. Definition of Done + + + + + + + +The gateway implementation is complete for production evaluation when: + + + + + + + +1\\. All mandatory Phase 0–14 features are implemented. + + + + + + + +2\\. No implemented AquaCom operation depends on undocumented guessed protocol behavior. + + + + + + + +3\\. Current data is available through OPC UA. + + + + + + + +4\\. Historical data is available through OPC UA Historical Access. + + + + + + + +5\\. AquaCom history backfill does not alter current values. + + + + + + + +6\\. Historical source timestamps are preserved. + + + + + + + +7\\. Gateway restart does not lose acknowledged history. + + + + + + + +8\\. Temporary storage outage does not immediately cause historical loss. + + + + + + + +9\\. Multiple storage destinations operate independently. + + + + + + + +10\\. OPC UA NodeIds are stable. + + + + + + + +11\\. OPC UA security is enabled by default. + + + + + + + +12\\. Simulator-based end-to-end acceptance tests pass. + + + + + + + +13\\. Tests against real AquaCom equipment or validated traffic have passed. + + + + + + + +14\\. Operational deployment and recovery documentation exists. + + + + + + + +15\\. Remaining protocol gaps are explicitly documented. + + + + + + + +\\--- + + + + + + + +\\# 78. Implementation objective + + + + + + + +The resulting software shall behave as an integration platform: + + + + + + + +```text + + + +\ AquaCom + + + +\ │ + + + +\ ▼ + + + +\ ┌───────────────────────┐ + + + +\ │ AquaCom Gateway │ + + + +\ │ │ + + + +\ │ Protocol │ + + + +\ │ Acquisition │ + + + +\ │ State │ + + + +\ │ History recovery │ + + + +\ │ Normalization │ + + + +\ │ Diagnostics │ + + + +\ └───────┬───────┬───────┘ + + + +\ │ │ + + + +\ LIVE │ │ HISTORY + + + +\ │ │ + + + +\ ▼ ▼ + + + +\ OPC UA Historical pipeline + + + +\ │ │ + + + +\ │ ├─────────► Repository + + + +\ │ ├─────────► Historian + + + +\ │ ├─────────► Database + + + +\ │ └─────────► Archive + + + +\ │ + + + +\ └───────────────► OPC UA HA + + + +``` + + + + + + + +The implementation shall remain usable even if: + + + + + + + +\\- the SCADA platform changes; + + + +\\- the historical database changes; + + + +\\- additional storage destinations are introduced; + + + +\\- AquaCom equipment is gradually replaced; + + + +\\- additional northbound interfaces are introduced. + + + + + + + +The gateway's permanent value shall therefore be the normalized information and integration boundary, not merely its OPC UA endpoint. + + + + + + + +\\--- + + + + + + + +\\# 79. First Codex execution sequence + + + + + + + +The recommended first Codex tasks are: + + + + + + + +```text + + + +Task 001 + + + +Create repository skeleton and architecture documents. + + + + + + + +Task 002 + + + +Create core domain models and stable identifier rules. + + + + + + + +Task 003 + + + +Create configuration model and schema validation. + + + + + + + +Task 004 + + + +Create AquaCom transport abstraction and mock transport. + + + + + + + +Task 005 + + + +Create AquaCom protocol codec framework without inventing protocol fields. + + + + + + + +Task 006 + + + +Create protocol fixture/test-vector framework. + + + + + + + +Task 007 + + + +Create AquaCom simulator architecture. + + + + + + + +Task 008 + + + +Implement first documented live AquaCom operation. + + + + + + + +Task 009 + + + +Implement Station Manager and live acquisition. + + + + + + + +Task 010 + + + +Implement current-state service. + + + + + + + +Task 011 + + + +Implement OPC UA live-value interface. + + + + + + + +Task 012 + + + +Implement historical repository abstraction. + + + + + + + +Task 013 + + + +Implement historical pipeline and deduplication. + + + + + + + +Task 014 + + + +Implement durable spool. + + + + + + + +Task 015 + + + +Implement first verified AquaCom historical operation. + + + + + + + +Task 016 + + + +Implement backfill state machine. + + + + + + + +Task 017 + + + +Implement OPC UA Historical Access. + + + + + + + +Task 018 + + + +Implement second storage destination. + + + + + + + +Task 019 + + + +Implement full reconnect/backfill acceptance test. + + + + + + + +Task 020 + + + +Production hardening. + + + +``` + + + + + + + +Each task shall result in a working repository state rather than leaving the main branch intentionally uncompilable or untestable. + + + + + + + +\\--- + + + + + + + +\\# 80. Primary instruction to Codex + + + + + + + +When implementing this system, prioritize correctness, traceability and recoverability over speed of implementation. + + + + + + + +In particular: + + + + + + + +> Never compensate for missing AquaCom documentation by inventing plausible protocol behavior. + + + + + + + +Build the architecture around the unknown portions first. + + + + + + + +Add real AquaCom behavior only as verified protocol knowledge becomes available. + + + + + + + +Every protocol feature shall be backed by evidence and automated tests. + + + + + + + +Every architectural component shall be replaceable behind its documented interface. + + + + + + + +Every historical sample shall retain its original process timestamp. + + + + + + + +And no recovered historical value shall ever masquerade as a new live process value. + + + + + diff --git a/docs/product/software-specification.md b/docs/product/software-specification.md new file mode 100644 index 0000000..de6eba9 --- /dev/null +++ b/docs/product/software-specification.md @@ -0,0 +1,3288 @@ +\# Software Specification – AquaCom Integration Gateway + + + +\*\*Document type:\*\* Software Requirements and Architecture Specification + +\*\*Status:\*\* Draft + +\*\*Version:\*\* 0.1 + +\*\*System name:\*\* AquaCom Integration Gateway + +\*\*Primary interfaces:\*\* AquaCom, OPC UA + +\*\*Implementation language:\*\* Not specified + +\*\*Database/storage technology:\*\* Not specified + + + +\--- + + + +\# 1. Purpose + + + +The purpose of the AquaCom Integration Gateway is to provide a modern integration layer between legacy AquaCom-compatible field equipment and higher-level OT/IT systems. + + + +The gateway shall communicate with AquaCom devices and provide: + + + +\- current/live process values; + +\- historical process values retrieved from AquaCom devices; + +\- normalized timestamps and data quality; + +\- OPC UA access to current values; + +\- OPC UA Historical Access to historical values; + +\- configurable storage of historical data in one or several independent storage systems; + +\- controlled buffering and backfill following communication interruptions; + +\- diagnostics concerning AquaCom communication, history synchronization, storage and OPC UA operation. + + + +The architecture shall separate AquaCom-specific communication from OPC UA and historical storage so that each component can evolve independently. + + + +The gateway shall not require an OPC UA client to understand AquaCom. + + + +\--- + + + +\# 2. Design objectives + + + +The system shall be designed around the following principles: + + + +1\. \*\*Protocol isolation\*\* + + AquaCom telegram handling shall be isolated from OPC UA, persistence and application logic. + + + +2\. \*\*Canonical data model\*\* + + AquaCom information shall be transformed into an internal protocol-independent representation before being exposed or stored. + + + +3\. \*\*Separation of live and historical processing\*\* + + Historical samples retrieved from an RTU shall not be replayed as current values. + + + +4\. \*\*Source timestamp preservation\*\* + + Timestamps originating from the field device shall be retained throughout the system. + + + +5\. \*\*Storage independence\*\* + + Historical information shall not be coupled to a specific database technology. + + + +6\. \*\*Multiple storage targets\*\* + + The gateway shall support simultaneous writing to zero, one or several configured historical destinations. + + + +7\. \*\*OPC UA as an interface, not the internal data model\*\* + + OPC UA shall expose information from the gateway but shall not dictate the internal architecture. + + + +8\. \*\*Recoverability\*\* + + Temporary failure of a communication channel, storage destination or OPC UA client shall not result in unnecessary loss of recoverable historical data. + + + +9\. \*\*Deterministic and testable protocol implementation\*\* + + AquaCom encoding, decoding and state handling shall be independently testable. + + + +10\. \*\*Secure-by-default operation\*\* + + OPC UA security and gateway administration shall use authenticated and protected communication by default. + + + +\--- + + + +\# 3. Scope + + + +\## 3.1 Included + + + +The initial system scope includes: + + + +\- AquaCom connection management; + +\- AquaCom telegram encoding and decoding; + +\- configuration of AquaCom stations; + +\- acquisition of live/current values; + +\- acquisition of available AquaCom historical information; + +\- detection and retrieval of historical data after communication interruptions; + +\- normalization of AquaCom values into a canonical model; + +\- live-value cache; + +\- historical-data processing; + +\- duplicate detection; + +\- local buffering; + +\- one or multiple storage adapters; + +\- OPC UA Server; + +\- OPC UA Data Access; + +\- OPC UA Historical Access; + +\- communication status; + +\- gateway diagnostics; + +\- logging; + +\- configuration management; + +\- auditability; + +\- health monitoring. + + + +\## 3.2 Not mandatory in the initial implementation + + + +The following shall be considered extensions unless separately specified: + + + +\- AquaCom machine control; + +\- AquaCom setpoint modification; + +\- OPC UA write access to control process equipment; + +\- OPC UA Alarms \& Conditions; + +\- historian aggregates; + +\- report-generation services; + +\- HTTP/REST interfaces; + +\- MQTT publishing; + +\- clustered gateway operation; + +\- active/standby gateway redundancy. + + + +The architecture shall not prevent these capabilities from being implemented later. + + + +\--- + + + +\# 4. System context + + + +The intended conceptual architecture is: + + + +```text + + AquaCom field systems + + │ + + ┌───────────┴───────────┐ + + │ │ + + Current values Stored history + + │ │ + + ▼ ▼ + + ┌────────────────────────────────────────┐ + + │ AquaCom Protocol Layer │ + + │ │ + + │ Transport │ + + │ Telegram codec │ + + │ Session/state management │ + + │ Station capability model │ + + └───────────────────┬────────────────────┘ + + │ + + ▼ + + ┌────────────────────────────────────────┐ + + │ Canonical Gateway Model │ + + └──────────┬───────────────────┬─────────┘ + + │ │ + + Current state Historical pipeline + + │ │ + + │ ┌────────┴───────────┐ + + │ │ │ + + │ History store Storage adapters + + │ │ │ + + │ │ ┌──────┼───────┐ + + │ │ │ │ │ + + │ │ DB File Historian + + │ │ + + ▼ ▼ + + ┌────────────────────┐ + + │ OPC UA Server │ + + │ │ + + │ Data Access │ + + │ Historical Access │ + + └─────────┬──────────┘ + + │ + + ▼ + + SCADA / clients + +``` + + + +The OPC UA server and storage mechanisms shall consume the canonical gateway model rather than AquaCom telegrams directly. + + + +\--- + + + +\# 5. Logical components + + + +\## 5.1 AquaCom Transport Layer + + + +The transport layer shall provide physical or network communication required by the target AquaCom implementation. + + + +It shall be responsible for: + + + +\- establishing communication; + +\- maintaining connections; + +\- reconnecting following failure; + +\- sending telegrams; + +\- receiving telegrams; + +\- detecting transport timeout; + +\- exposing transport diagnostics. + + + +Transport handling shall not interpret process values. + + + +The architecture shall allow multiple AquaCom transports to be implemented without changing higher-level application logic. + + + +\--- + + + +\# 6. AquaCom Protocol Engine + + + +The AquaCom Protocol Engine shall implement the AquaCom application protocol. + + + +Its responsibilities shall include: + + + +\- telegram framing; + +\- address handling; + +\- checksum validation; + +\- telegram validation; + +\- request generation; + +\- response decoding; + +\- error-response interpretation; + +\- mapping protocol operations to logical operations; + +\- protocol timeout handling; + +\- detection of malformed telegrams. + + + +The protocol implementation shall not directly: + + + +\- write database records; + +\- create OPC UA nodes; + +\- modify OPC UA values; + +\- make assumptions regarding graphical presentation. + + + +The complete AquaCom protocol implementation shall be developed against an authoritative protocol specification and validated using captured communication from actual AquaCom equipment where possible. + + + +\--- + + + +\# 7. Station Manager + + + +Each AquaCom station shall have a logical station instance. + + + +The Station Manager shall maintain information including: + + + +| Attribute | Description | + +|---|---| + +| Station ID | Stable gateway identifier | + +| AquaCom address | Protocol address | + +| Name | Human-readable station name | + +| Enabled | Station communication enabled/disabled | + +| Connection state | Current communication status | + +| Last successful communication | Gateway timestamp | + +| Last device response | Timestamp | + +| Consecutive errors | Communication diagnostic | + +| History synchronization state | State of historical retrieval | + +| Configuration version | Version of station definition | + + + +Station configuration shall be independent of OPC UA NodeIds. + + + +\--- + + + +\# 8. Station capability and point definition + + + +The system shall maintain a definition of the information available from each station. + + + +This definition may originate from: + + + +\- AquaCom ATF files; + +\- manually supplied configuration; + +\- imported engineering data; + +\- another machine-readable configuration source. + + + +The point definition shall contain sufficient information to map raw AquaCom information into the canonical gateway model. + + + +A point definition should support at least: + + + +| Field | Purpose | + +|---|---| + +| PointId | Stable unique identifier | + +| StationId | Parent station | + +| Name | Human-readable designation | + +| Source reference | AquaCom-specific identifier | + +| Data type | Boolean, integer, floating point, text etc. | + +| Engineering unit | Where applicable | + +| Scaling | If required | + +| Live enabled | Current value acquisition | + +| History enabled | Historical acquisition | + +| Historizing | Whether the gateway records the value | + +| OPC UA enabled | Whether exposed through OPC UA | + +| OPC UA NodeId | Stable configured/generated identifier | + +| Storage policy | Storage behavior | + +| Description | Engineering description | + + + +Changes to display names shall not automatically change stable identifiers. + + + +\--- + + + +\# 9. Canonical data model + + + +AquaCom data shall be converted into a canonical representation before further processing. + + + +\## 9.1 Current value + + + +A current process value shall conceptually contain: + + + +```text + +CurrentValue + + StationId + + PointId + + Value + + DataType + + Quality + + SourceTimestamp + + ReceivedTimestamp + + UpdatedTimestamp + + Source + +``` + + + +\### SourceTimestamp + + + +`SourceTimestamp` represents the time associated with the process value at its source when such information is available. + + + +\### ReceivedTimestamp + + + +`ReceivedTimestamp` represents the time when the gateway received the value. + + + +\### UpdatedTimestamp + + + +`UpdatedTimestamp` represents the time when the current gateway state was updated. + + + +The distinction between these timestamps shall be maintained internally. + + + +OPC UA itself distinguishes source and server timestamps in its `DataValue` model, making this mapping appropriate. + + + +\--- + + + +\# 10. Historical sample model + + + +Historical process data shall use a distinct model: + + + +```text + +HistoricalSample + + StationId + + PointId + + SourceTimestamp + + ReceivedTimestamp + + Value + + DataType + + Quality + + AcquisitionSource + + AcquisitionId + +``` + + + +`AcquisitionSource` shall identify how the value entered the gateway, for example: + + + +```text + +LIVE + +AQUACOM\_HISTORY + +AQUACOM\_REPORT + +IMPORT + +RECOVERY + +``` + + + +The exact values are implementation-defined. + + + +Historical samples shall never become current values solely because they have just been received. + + + +Example: + + + +```text + +Gateway time: 18:31 + +Sample time: 14:05 + +Value: 2.31 m + +``` + + + +The sample shall be stored as a value from 14:05 and shall not cause a normal live OPC UA subscription to report that the current process value is 2.31 m. + + + +\--- + + + +\# 11. Live-value processing + + + +The live-value subsystem shall maintain the latest known state of every configured current point. + + + +A live update shall perform the following logical sequence: + + + +```text + +AquaCom telegram + + │ + + ▼ + +Protocol decode + + │ + + ▼ + +Point mapping + + │ + + ▼ + +Type/scaling validation + + │ + + ▼ + +Canonical CurrentValue + + │ + + ├─────────► Current-state cache + + │ + + ├─────────► OPC UA + + │ + + └─────────► Historical pipeline + + if configured + +``` + + + +Acquisition of live values and historization of those values shall be separate functions. + + + +A point may therefore be: + + + +\- exposed live but not stored; + +\- stored but not exposed through OPC UA; + +\- both exposed and stored; + +\- disabled completely. + + + +\--- + + + +\# 12. Historical acquisition + + + +The gateway shall contain a History Acquisition Manager responsible for obtaining historical information available in AquaCom field equipment. + + + +The component shall support: + + + +\- normal periodic history retrieval; + +\- history retrieval following reconnect; + +\- configurable historical synchronization; + +\- tracking the last successfully synchronized time; + +\- detection of gaps where possible; + +\- recovery/backfill; + +\- duplicate suppression; + +\- partial transfer recovery; + +\- rate limitation so history retrieval does not prevent live communication. + + + +A station shall maintain a persistent synchronization watermark where applicable. + + + +Conceptually: + + + +```text + +Last complete history: + +2026-10-05 12:00 + + + +Communication lost: + +12:03 + + + +Communication restored: + +17:24 + + + +Gateway determines missing interval: + +12:00 → 17:24 + + + +Gateway requests AquaCom history. + + + +Recovered historical values + + │ + + ▼ + +Historical pipeline + + │ + + ▼ + +Historian/storage + +``` + + + +Live polling shall normally take priority over large backfill operations. + + + +\--- + + + +\# 13. Duplicate handling + + + +Historical processing shall be idempotent. + + + +Receiving the same historical sample multiple times shall not normally result in multiple logical records. + + + +A logical historical identity should be derivable from information equivalent to: + + + +```text + +StationId + +PointId + +SourceTimestamp + +``` + + + +Where AquaCom provides additional sequence or sample identifiers, these may form part of the identity. + + + +The implementation shall define behavior for the unusual situation where two different values are supplied for the same logical historical sample. + + + +Supported strategies should include: + + + +\- retain first value; + +\- retain latest value; + +\- version the sample; + +\- flag conflict for diagnostics. + + + +The selected strategy shall be configurable. + + + +\--- + + + +\# 14. History repository abstraction + + + +OPC UA Historical Access shall not directly depend on a specific database. + + + +The gateway shall define a logical History Repository interface capable of operations equivalent to: + + + +```text + +StoreSample + +StoreSamples + +ReadRaw + +ReadAtTime + +GetOldestTimestamp + +GetNewestTimestamp + +CheckAvailability + +``` + + + +The implementation technology is intentionally unspecified. + + + +An installation may use: + + + +\- an internal gateway historian; + +\- an external relational database; + +\- a time-series database; + +\- an industrial historian; + +\- another storage service capable of fulfilling the required history interface. + + + +One configured history provider shall be designated as the authoritative source for OPC UA Historical Access. + + + +\--- + + + +\# 15. Multiple historical storage destinations + + + +The gateway shall permit historical information to be delivered to one or several destinations simultaneously. + + + +Example: + + + +```text + + Historical pipeline + + │ + + ┌─────────────┼──────────────┐ + + │ │ │ + + ▼ ▼ ▼ + + Local DB Enterprise Archive + + historian file + +``` + + + +Storage destinations shall be implemented as independent adapters. + + + +Failure of one destination shall not normally prevent delivery to another destination. + + + +Each storage adapter shall independently maintain: + + + +\- enabled state; + +\- connection status; + +\- last successful write; + +\- error count; + +\- pending record count; + +\- retry state. + + + +\--- + + + +\# 16. Storage adapter interface + + + +A storage adapter shall consume canonical historical records. + + + +The adapter shall not receive raw AquaCom telegrams. + + + +A logical interface shall provide functionality equivalent to: + + + +```text + +Initialize + +Store + +StoreBatch + +CheckHealth + +Flush + +Shutdown + +``` + + + +Optional storage adapters may support queries, but writing and querying shall be considered separate capabilities. + + + +Possible adapters include, without limiting implementations to: + + + +\- relational database; + +\- time-series database; + +\- external historian; + +\- append-only file; + +\- structured CSV; + +\- JSON/NDJSON; + +\- message broker; + +\- data-lake/object storage; + +\- another application through an API. + + + +\--- + + + +\# 17. Store-and-forward + + + +The gateway shall provide a durable buffering mechanism when a configured storage destination is temporarily unavailable. + + + +Example: + + + +```text + +AquaCom + + │ + + ▼ + +History pipeline + + │ + + ▼ + +Durable spool + + │ + + ├──► Storage A + + ├──► Storage B + + └──► Storage C + +``` + + + +Each destination shall maintain its own delivery acknowledgement. + + + +A record shall therefore not be deleted from the spool merely because one of several destinations has accepted it. + + + +The implementation should use at-least-once delivery semantics combined with idempotent storage where practical. + + + +Configuration shall include: + + + +\- maximum spool size; + +\- maximum storage duration; + +\- disk-space thresholds; + +\- retry behavior; + +\- overflow policy. + + + +Loss of buffered information shall generate a diagnostic event. + + + +\--- + + + +\# 18. OPC UA Server + + + +The gateway shall contain an OPC UA server compliant with applicable OPC UA specifications. + + + +OPC UA shall expose: + + + +1\. current values through normal OPC UA Data Access; + +2\. historical values through OPC UA Historical Access; + +3\. gateway communication and synchronization diagnostics. + + + +OPC UA Historical Access defines standardized mechanisms for exposing historical information, including `HistoryRead`; it does not require the historical backend itself to be a particular database technology. + + + +\--- + + + +\# 19. OPC UA namespace + + + +A logical namespace should use a structure comparable to: + + + +```text + +AquaCom + +│ + +├── Stations + +│ │ + +│ ├── Station01 + +│ │ ├── Process + +│ │ │ ├── Level + +│ │ │ ├── Pump01Running + +│ │ │ └── Pump02Running + +│ │ │ + +│ │ └── Diagnostics + +│ │ ├── CommunicationState + +│ │ ├── LastCommunication + +│ │ ├── ProtocolErrors + +│ │ ├── HistoryState + +│ │ ├── LastHistorySync + +│ │ └── PendingHistory + +│ │ + +│ └── Station02 + +│ + +└── Gateway + + ├── Status + + ├── StartTime + + ├── Version + + ├── Storage + + └── Diagnostics + +``` + + + +The precise hierarchy shall be configurable without changing the AquaCom protocol implementation. + + + +\--- + + + +\# 20. Stable OPC UA NodeIds + + + +NodeIds used for engineering data shall remain stable across: + + + +\- gateway restart; + +\- OPC UA server restart; + +\- database restart; + +\- software upgrade; + +\- temporary station removal; + +\- changes to point display names. + + + +NodeIds shall therefore derive from stable engineering identifiers rather than runtime object allocation. + + + +Changing the human-readable name of: + + + +```text + +Level + +``` + + + +to: + + + +```text + +WetWellLevel + +``` + + + +shall not automatically create a different logical OPC UA point. + + + +\--- + + + +\# 21. Current OPC UA values + + + +Each configured point exposed as current data shall support normal OPC UA reads. + + + +Where appropriate it shall also support OPC UA subscriptions. + + + +The OPC UA value shall contain: + + + +\- process value; + +\- appropriate StatusCode; + +\- source timestamp where available; + +\- server timestamp. + + + +The gateway shall translate internal quality into appropriate OPC UA quality/status semantics. + + + +Communication loss shall not silently retain an indefinitely "Good" value. + + + +\--- + + + +\# 22. OPC UA Historical Access + + + +Points configured for historical access shall advertise historical capability according to OPC UA. + + + +OPC UA distinguishes whether history is available through the Variable's access attributes and whether the server is actively collecting history through its `Historizing` attribute. + + + +The gateway shall support, at minimum: + + + +\*\*Raw historical reads\*\* + + + +```text + +HistoryRead + +Point + +StartTime + +EndTime + +MaximumValues + +``` + + + +The implementation shall support continuation where the requested history exceeds the configured response size. + + + +Historical responses shall maintain: + + + +\- process value; + +\- source timestamp; + +\- applicable quality/status information. + + + +The gateway shall not require historical data to have originally been received while an OPC UA client was connected. + + + +\--- + + + +\# 23. HistoryRead data flow + + + +A Historical Access request shall follow the logical path: + + + +```text + +OPC UA Client + + │ + + │ HistoryRead + + ▼ + +OPC UA Server + + │ + + ▼ + +History Provider + + │ + + ▼ + +Configured authoritative repository + + │ + + ▼ + +Canonical HistoricalSample\[] + + │ + + ▼ + +OPC UA DataValue\[] + + │ + + ▼ + +OPC UA Client + +``` + + + +The OPC UA layer shall not perform AquaCom history polling synchronously in response to a client `HistoryRead`. + + + +Historical retrieval from field equipment and historical access from clients shall therefore be decoupled. + + + +This prevents a long-running AquaCom operation from blocking an OPC UA request. + + + +\--- + + + +\# 24. OPC UA HistoryUpdate + + + +Modification of historical records through OPC UA shall be disabled by default. + + + +If later enabled, separate authorization shall be required. + + + +Normal SCADA clients shall not be permitted to alter gateway history solely because they are allowed to read it. + + + +\--- + + + +\# 25. Current state versus historical state + + + +The gateway shall maintain a strict separation: + + + +```text + +Current State + + │ + + └── latest known process value + + + +Historical State + + │ + + └── timestamped sequence of previous process values + +``` + + + +Historical backfill shall never cause an old value to overwrite a newer current value unless a separately defined reconciliation rule determines that the current state itself is invalid. + + + +\--- + + + +\# 26. Time handling + + + +All internal timestamps shall have an unambiguous time basis. + + + +UTC shall be preferred internally. + + + +The system shall preserve information necessary to correctly interpret AquaCom timestamps supplied in local time. + + + +Configuration shall include: + + + +\- station timezone; + +\- daylight-saving-time handling; + +\- assumed timezone for timestamps lacking zone information; + +\- permitted clock deviation; + +\- invalid-time handling. + + + +The system shall detect or flag where practical: + + + +\- future timestamps; + +\- implausibly old timestamps; + +\- backward-moving device clocks; + +\- duplicate timestamps; + +\- ambiguous daylight-saving-time timestamps. + + + +Original source timestamps shall not silently be replaced by gateway receipt time. + + + +\--- + + + +\# 27. Quality handling + + + +The canonical data model shall contain protocol-independent data quality. + + + +At minimum the internal model shall distinguish: + + + +```text + +GOOD + +UNCERTAIN + +BAD + +UNKNOWN + +``` + + + +Additional sub-status information may identify: + + + +\- communication failure; + +\- stale value; + +\- configuration error; + +\- conversion error; + +\- invalid source value; + +\- historical gap; + +\- timestamp uncertainty. + + + +The OPC UA layer shall map internal quality to suitable OPC UA `StatusCode` values. + + + +Storage adapters shall retain quality information where the destination format supports it. + + + +\--- + + + +\# 28. Configuration + + + +Configuration shall be external to the executable software and shall be machine-readable. + + + +Configuration shall cover at least: + + + +\- gateway identity; + +\- AquaCom stations; + +\- transports; + +\- point definitions; + +\- polling; + +\- historical acquisition; + +\- OPC UA namespace; + +\- OPC UA endpoints; + +\- certificates; + +\- authorization; + +\- storage destinations; + +\- historian configuration; + +\- buffering; + +\- logging; + +\- diagnostics. + + + +Configuration shall be versionable using normal source-control mechanisms. + + + +Secrets shall not be stored as unprotected ordinary configuration values. + + + +\--- + + + +\# 29. Dynamic configuration + + + +Where technically reasonable, non-structural configuration should be reloadable without restarting the entire gateway. + + + +Structural changes that affect point identity or protocol configuration may require controlled restart. + + + +The gateway shall validate configuration before activation. + + + +Invalid configuration shall not replace the last known valid configuration. + + + +\--- + + + +\# 30. Security + + + +The OPC UA endpoint shall use OPC UA security mechanisms supporting: + + + +\- server authentication; + +\- client/application authentication; + +\- confidentiality; + +\- integrity; + +\- user authorization where required. + + + +The OPC UA security model provides application authentication using certificates as well as user authentication and authorization mechanisms. + + + +Security mode `None` shall be disabled by default. Current OPC UA guidance specifies that the None profile should be disabled by default. + + + +The gateway shall support certificate trust management. + + + +Administrative functions shall be restricted separately from normal OPC UA data access. + + + +\--- + + + +\# 31. AquaCom security boundary + + + +AquaCom communication shall be treated as communication with a legacy field protocol. + + + +Security controls around AquaCom shall therefore be provided by the surrounding OT architecture, for example: + + + +```text + +Enterprise/SCADA network + + │ + + Firewall + + │ + + AquaCom Gateway + + │ + + OT network + + │ + + VPN/router/firewall + + │ + + AquaCom RTU + +``` + + + +The gateway shall not assume that authenticity, confidentiality or authorization are inherently provided by AquaCom. + + + +\--- + + + +\# 32. Diagnostics + + + +The system shall expose diagnostic information for the gateway and every station. + + + +Station diagnostics shall include at least: + + + +```text + +Enabled + +CommunicationState + +LastSuccessfulCommunication + +LastRequest + +LastResponse + +CommunicationErrors + +ProtocolErrors + +LastValidValue + +HistorySynchronizationState + +LastHistorySynchronization + +HistoricalBacklog + +``` + + + +Gateway diagnostics shall include: + + + +```text + +GatewayState + +SoftwareVersion + +ConfigurationVersion + +StartTime + +Uptime + +ConnectedStations + +FailedStations + +HistoricalQueueDepth + +SpoolUsage + +OPCUAState + +``` + + + +Storage diagnostics shall be available for each configured destination: + + + +```text + +State + +LastSuccessfulWrite + +LastError + +PendingRecords + +RetryCount + +``` + + + +\--- + + + +\# 33. Logging + + + +Logging shall distinguish at minimum: + + + +\- operational information; + +\- communication errors; + +\- protocol errors; + +\- configuration errors; + +\- storage errors; + +\- security events; + +\- historical synchronization events; + +\- software faults. + + + +Raw AquaCom telegram logging shall be separately configurable because it may generate large volumes of information. + + + +Sensitive information shall not be unnecessarily written to normal logs. + + + +\--- + + + +\# 34. Audit logging + + + +Security-relevant and administrative changes shall be auditable. + + + +Examples include: + + + +\- configuration changed; + +\- station enabled/disabled; + +\- certificate trusted/rejected; + +\- storage adapter changed; + +\- history synchronization manually initiated; + +\- historical records administratively modified; + +\- software started/stopped. + + + +Future control functionality shall additionally audit all process commands. + + + +\--- + + + +\# 35. Failure handling + + + +The gateway shall continue providing unaffected functionality where practical. + + + +Examples: + + + +| Failure | Expected behavior | + +|---|---| + +| One AquaCom station fails | Other stations continue | + +| One storage destination fails | Other destinations continue | + +| OPC UA client disconnects | Acquisition continues | + +| OPC UA server temporarily unavailable | AquaCom acquisition continues where architecture permits | + +| External historian fails | Records buffered | + +| Gateway restarts | Persistent synchronization state recovered | + +| Invalid telegram received | Telegram rejected and diagnostic generated | + +| Historical duplicate received | Deduplication policy applied | + + + +A failure in a secondary data consumer shall not stop AquaCom communication. + + + +\--- + + + +\# 36. Startup sequence + + + +A logical startup shall perform: + + + +```text + +Load configuration + + ↓ + +Validate configuration + + ↓ + +Initialize persistent state + + ↓ + +Initialize storage adapters + + ↓ + +Initialize historical subsystem + + ↓ + +Initialize OPC UA namespace + + ↓ + +Initialize AquaCom stations + + ↓ + +Start acquisition + + ↓ + +Start history synchronization + +``` + + + +A storage destination that is temporarily unavailable during startup shall not necessarily prevent the complete gateway from entering service. + + + +\--- + + + +\# 37. Shutdown + + + +Shutdown shall be controlled. + + + +The gateway shall: + + + +1\. stop accepting new administrative work; + +2\. stop initiating new AquaCom transactions; + +3\. finish or cancel active transactions safely; + +4\. persist synchronization watermarks; + +5\. flush historical queues where possible; + +6\. close storage adapters; + +7\. close OPC UA services; + +8\. terminate. + + + +Unclean shutdown shall be detectable at the next startup. + + + +\--- + + + +\# 38. Persistence of gateway state + + + +State required for reliable recovery shall survive restart. + + + +This includes, where applicable: + + + +\- history synchronization watermarks; + +\- spool contents; + +\- delivery acknowledgements; + +\- configuration version; + +\- station state needed for recovery. + + + +Transient live values need not be permanently persisted unless required by installation policy. + + + +\--- + + + +\# 39. Historical retention + + + +Retention shall be configurable independently for each storage destination. + + + +The gateway shall not assume that all historical destinations have the same retention period. + + + +For example: + + + +```text + +Local operational cache 30 days + +Central historian 10 years + +Archive indefinite + +``` + + + +These values are examples only and are not system defaults. + + + +\--- + + + +\# 40. Data export extensibility + + + +The internal historical pipeline shall permit future exporters without modification to the AquaCom protocol implementation. + + + +Examples might later include: + + + +```text + +AquaCom + + ↓ + +Canonical data + + ├── OPC UA + + ├── SQL + + ├── time-series DB + + ├── enterprise historian + + ├── MQTT + + └── data lake + +``` + + + +This shall be achieved through explicit interfaces rather than direct dependencies between components. + + + +\--- + + + +\# 41. Performance requirements + + + +Performance targets shall be installation-specific and configurable. + + + +The gateway architecture shall support measurement of: + + + +\- AquaCom request latency; + +\- point update latency; + +\- OPC UA response latency; + +\- historical ingestion rate; + +\- history query time; + +\- pending history size; + +\- storage write throughput; + +\- spool utilization. + + + +Historical backfill shall have configurable throttling. + + + +Large history synchronization jobs shall not starve current-value acquisition. + + + +\--- + + + +\# 42. Resource limits + + + +The gateway shall protect itself against unbounded resource consumption. + + + +Configurable limits shall include: + + + +\- maximum AquaCom telegram size; + +\- maximum queued requests; + +\- maximum OPC UA HistoryRead result size; + +\- maximum number of simultaneous historical queries; + +\- maximum spool storage; + +\- maximum storage batch size; + +\- maximum diagnostic-log size. + + + +OPC UA continuation mechanisms shall be used when a historical query exceeds the configured response size. + + + +\--- + + + +\# 43. Deployment + + + +The specification shall not assume a particular operating system. + + + +The gateway should be capable of deployment as a long-running service. + + + +The implementation shall allow unattended startup following host restart. + + + +Runtime dependencies shall be documented and minimized. + + + +The gateway should support deployment in either: + + + +```text + +Physical/virtual OT server + +``` + + + +or + + + +```text + +Containerized environment + +``` + + + +provided that the selected deployment method satisfies communication and security requirements. + + + +\--- + + + +\# 44. Internal component boundaries + + + +The following logical modules shall remain separable: + + + +```text + +AquaCom Transport + + │ + +AquaCom Protocol + + │ + +Station/session handling + + │ + +Canonical Data Model + + │ + + ┌──────┴────────┐ + + │ │ + +Live State History Engine + + │ │ + + │ ┌─────┴───────┐ + + │ │ │ + +OPC UA Repository Storage adapters + +``` + + + +A change of OPC UA library shall not require reimplementation of AquaCom. + + + +A change of database shall not require reimplementation of AquaCom. + + + +A new storage adapter shall not require modification to the AquaCom parser. + + + +\--- + + + +\# 45. Testing requirements + + + +The system shall support automated testing at multiple levels. + + + +\## 45.1 Protocol unit tests + + + +Tests shall verify: + + + +\- telegram framing; + +\- checksum calculation; + +\- request encoding; + +\- response decoding; + +\- invalid telegram detection; + +\- timeout behavior; + +\- error response handling. + + + +Known production captures should be converted into reusable test vectors where legally and operationally appropriate. + + + +\--- + + + +\## 45.2 AquaCom simulator + + + +A simulator or mock endpoint shall be provided for development and testing. + + + +It shall support: + + + +\- normal responses; + +\- configurable live values; + +\- historical data; + +\- delayed responses; + +\- malformed telegrams; + +\- communication loss; + +\- duplicate historical samples; + +\- clock anomalies. + + + +Development shall not require connection to operational wastewater infrastructure. + + + +\--- + + + +\## 45.3 Historical tests + + + +Tests shall verify: + + + +```text + +Historical backfill after outage + +Duplicate handling + +Timestamp preservation + +Quality preservation + +Partial synchronization recovery + +Gateway restart during backfill + +Storage destination outage + +Spool replay + +Multi-destination delivery + +``` + + + +\--- + + + +\## 45.4 OPC UA tests + + + +Tests shall verify: + + + +\- namespace creation; + +\- stable NodeIds; + +\- current reads; + +\- subscriptions; + +\- source timestamps; + +\- quality; + +\- HistoryRead; + +\- continuation; + +\- empty historical intervals; + +\- large historical intervals; + +\- station communication loss; + +\- certificate validation; + +\- authorization. + + + +\--- + + + +\# 46. End-to-end acceptance scenario + + + +A mandatory acceptance scenario shall simulate: + + + +```text + +1\. Station communicating normally. + + + +2\. Live values available through OPC UA. + + + +3\. Values stored historically. + + + +4\. AquaCom connection interrupted. + + + +5\. OPC UA indicates communication degradation. + + + +6\. Station continues recording locally. + + + +7\. AquaCom connection restored. + + + +8\. Gateway resumes live acquisition. + + + +9\. Gateway determines missing historical interval. + + + +10\. Gateway retrieves missing samples. + + + +11\. Retrieved samples retain their original timestamps. + + + +12\. Historical samples are persisted. + + + +13\. Old historical samples do not appear as new current values. + + + +14\. OPC UA HistoryRead returns the complete time interval. + + + +15\. Configured secondary historical destinations receive the recovered data. + + + +16\. Duplicate acquisition does not produce unintended duplicate records. + +``` + + + +Successful execution of this scenario shall be a principal acceptance criterion for the gateway. + + + +\--- + + + +\# 47. Recommended initial functional baseline + + + +The first production-capable release should implement: + + + +```text + +AquaCom communication + +AquaCom live acquisition + +AquaCom historical acquisition + +Station configuration + +Point mapping + +Canonical data model + +Live-value cache + +Historical repository + +Backfill manager + +Deduplication + +Persistent synchronization watermark + +Store-and-forward queue + +At least one historical storage adapter + +Storage adapter framework + +OPC UA Data Access + +OPC UA Historical Access + +OPC UA security + +Diagnostics + +Logging + +AquaCom simulator + +Automated protocol tests + +Automated history tests + +``` + + + +This baseline deliberately excludes remote process control. + + + +\--- + + + +\# 48. Future extensions + + + +The architecture shall permit later addition of: + + + +```text + +OPC UA Alarms \& Conditions + +AquaCom alarm/event retrieval + +AquaCom machine control + +AquaCom setpoint management + +OPC UA Methods + +OPC UA writable Variables + +MQTT + +REST API + +central configuration management + +redundant gateways + +high availability + +multiple gateway federation + +external identity management + +historical aggregates + +automated station discovery + +``` + + + +OPC UA Alarms \& Conditions is defined separately in OPC UA Part 9 and can therefore be introduced later without treating alarm events as ordinary process-value history. + + + +\--- + + + +\# 49. Key architectural decision + + + +The system shall be considered an: + + + +\*\*AquaCom Integration Gateway\*\* + + + +rather than merely an: + + + +\*\*AquaCom OPC UA Server\*\*. + + + +The distinction is intentional. + + + +The internal architecture shall be: + + + +```text + + AQUACOM + + │ + + ▼ + + Protocol abstraction + + │ + + ▼ + + Canonical data + + │ + + ┌───────────┼────────────┐ + + │ │ │ + + ▼ ▼ ▼ + + Live state History Diagnostics + + │ │ + + │ ┌─────┼───────────────┐ + + │ │ │ │ + + ▼ ▼ ▼ ▼ + + OPC UA DB Historian Archive + + │ + + ├── Data Access + + └── Historical Access + +``` + + + +OPC UA is consequently one standardized northbound interface to the gateway rather than the mechanism upon which acquisition and historical storage depend. + + + +\--- + + + +\# 50. Architectural rule for historical information + + + +The following rule shall be treated as fundamental: + + + +> \*\*A historical sample represents the state of the process at its SourceTimestamp, not the state of the process at the time the gateway received the sample.\*\* + + + +Therefore: + + + +```text + +Historical recovery + + ≠ + +replay of live values + +``` + + + +and: + + + +```text + +AquaCom historical timestamp + + │ + + ▼ + +Canonical SourceTimestamp + + │ + + ├──► Historical repository + + ├──► External storage + + └──► OPC UA Historical Access + +``` + + + +This rule shall apply consistently throughout implementation, testing and validation. + + + +\--- + + + +\# 51. Architectural rule for storage + + + +Historical acquisition and historical storage shall be decoupled. + + + +The gateway shall be capable of configurations conceptually equivalent to: + + + +```text + +Configuration A + + + +AquaCom + + ↓ + +Gateway + + ↓ + +OPC UA live only + +``` + + + +```text + +Configuration B + + + +AquaCom + + ↓ + +Gateway + + ├── OPC UA live + + └── Internal history + + ↓ + + OPC UA HA + +``` + + + +```text + +Configuration C + + + +AquaCom + + ↓ + +Gateway + + ├── OPC UA + + ├── SQL + + └── Historian + +``` + + + +```text + +Configuration D + + + +AquaCom + + ↓ + +Gateway + + ├── OPC UA + + ├── Time-series DB + + ├── Enterprise historian + + ├── Archive + + └── Future integration adapter + +``` + + + +The protocol implementation shall be identical in all cases. + + + +\--- + + + +\# 52. Requirement summary + + + +| ID | Requirement | + +|---|---| + +| AQG-001 | AquaCom shall be isolated behind a protocol abstraction. | + +| AQG-002 | Current and historical data shall use a canonical internal model. | + +| AQG-003 | Current and historical processing shall be separated. | + +| AQG-004 | Original source timestamps shall be preserved. | + +| AQG-005 | Historical backfill shall not modify current state with obsolete values. | + +| AQG-006 | Historical acquisition shall recover after communication interruption where supported by the RTU. | + +| AQG-007 | Historical ingestion shall support duplicate suppression. | + +| AQG-008 | Synchronization progress shall survive gateway restart. | + +| AQG-009 | Historical storage shall use replaceable adapters. | + +| AQG-010 | Multiple historical storage destinations shall be supported. | + +| AQG-011 | Failure of one destination shall not normally block others. | + +| AQG-012 | Store-and-forward shall protect data during destination failure. | + +| AQG-013 | OPC UA shall expose current process values. | + +| AQG-014 | OPC UA shall support subscriptions for configured current values. | + +| AQG-015 | OPC UA Historical Access shall expose configured historical information. | + +| AQG-016 | OPC UA NodeIds shall be stable. | + +| AQG-017 | OPC UA history shall be retrieved through an abstract History Provider. | + +| AQG-018 | OPC UA HistoryRead shall not directly initiate synchronous AquaCom retrieval. | + +| AQG-019 | Data quality shall be maintained through acquisition, storage and OPC UA. | + +| AQG-020 | Historical SourceTimestamp and gateway ReceivedTimestamp shall remain distinguishable. | + +| AQG-021 | OPC UA security shall be enabled by default. | + +| AQG-022 | Configuration shall be machine-readable and versionable. | + +| AQG-023 | Gateway diagnostics shall be available independently of process values. | + +| AQG-024 | AquaCom communication shall be testable without operational field equipment. | + +| AQG-025 | A simulator or equivalent mock environment shall be available. | + +| AQG-026 | The software shall not depend upon a particular historical database implementation. | + +| AQG-027 | The software architecture shall not depend upon a particular programming language. | + +| AQG-028 | Live acquisition shall take precedence over bulk history recovery where necessary. | + +| AQG-029 | HistoryWrite through OPC UA shall be disabled by default. | + +| AQG-030 | Administrative and security-sensitive operations shall be auditable. | + + + +\--- + + + +\# 53. Final target architecture + + + +```text + + FIELD LAYER + + │ + + AquaCom-compatible + + RTU / PLC + + │ + + ▼ + + ┌───────────────────┐ + + │ AquaCom Transport │ + + └─────────┬─────────┘ + + │ + + ┌─────────▼─────────┐ + + │ AquaCom Protocol │ + + │ Engine │ + + └─────────┬─────────┘ + + │ + + ┌─────────▼─────────┐ + + │ Station Manager │ + + └─────────┬─────────┘ + + │ + + ┌─────────▼─────────┐ + + │ Canonical Model │ + + └────┬─────────┬────┘ + + │ │ + + LIVE │ │ HISTORY + + │ │ + + ┌──────────▼───┐ ┌───▼────────────────┐ + + │ Current State│ │ History Acquisition │ + + │ Cache │ │ / Backfill Manager │ + + └──────┬───────┘ └─────────┬──────────┘ + + │ │ + + │ ┌─────▼─────┐ + + │ │ Historical│ + + │ │ Pipeline │ + + │ └─────┬─────┘ + + │ │ + + │ ┌───────────┼───────────┐ + + │ │ │ │ + + │ ▼ ▼ ▼ + + │ Repository Storage A Storage B + + │ │ + + │ │ + + ┌──────▼───────▼──────┐ + + │ OPC UA Server │ + + │ │ + + │ Data Access │ + + │ Historical Access │ + + └──────────┬──────────┘ + + │ + + ▼ + + SCADA / historian / + + analytics clients + +``` + + + +This architecture shall be the baseline for detailed design and implementation. +