\# 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.