3753 lines
48 KiB
Markdown
3753 lines
48 KiB
Markdown
# Implementation Specification
|
||
|
||
## AquaCom Integration Gateway
|
||
|
||
**Document type:** Implementation specification
|
||
|
||
**Target implementation agent:** any AI coding agent (Codex, Copilot, or equivalent)
|
||
|
||
**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 the implementation agent 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;
|
||
|
||
- implementation-agent 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. Implementation agent principles
|
||
|
||
The implementation agent shall follow these principles throughout development.
|
||
|
||
## 3.1 Do not invent AquaCom protocol details
|
||
|
||
The implementation agent 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 the implementation agent to the authoritative project documentation rather than attempt to contain the complete project specification.
|
||
|
||
This follows current agent guidance favoring concise repository instructions with deeper documentation maintained separately.
|
||
|
||
Complex implementation work shall use an execution plan maintained in the repository. Current agent guidance 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` implements this strategy: it is the short entry point that directs the implementation agent to the authoritative documents, lists the non-negotiable architecture and evidence rules, and never restates full specifications. The current root `AGENTS.md` in this repository is the reference implementation of that form and takes precedence over any example restated here.
|
||
|
||
Nested `AGENTS.md` files may later be added where a specific module requires additional constraints. Current coding agents support 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. Such a record shall be **quarantined with diagnostics**: rejected from normal history, recorded distinctly for investigation, and never stored with a fabricated or gateway-generated timestamp (see `software-specification.md` §10).
|
||
|
||
---
|
||
|
||
# 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.
|
||
|
||
```
|
||
|
||
The implementation agent shall not close a protocol gap without evidence.
|
||
|
||
### Evidence acquisition plan
|
||
|
||
Protocol evidence does not currently exist in this repository. The evidence rule above is therefore not executable until evidence is acquired. Until then, Phase 3 (codec framework) may proceed with the framework, fixture and simulation scaffolding, but no telegram behavior may be implemented.
|
||
|
||
Evidence shall be acquired through at least one of:
|
||
|
||
1. obtaining the authoritative AquaCom protocol specification from the equipment vendor or system owner;
|
||
2. capturing traffic from a known-good AquaCom deployment (sanitized per §64 before committing);
|
||
3. deriving behavior from an existing known-good integration.
|
||
|
||
The responsible party for obtaining the authoritative documentation shall be identified before Phase 3 starts, and the acquisition status shall be tracked in `docs/protocol/protocol-gaps.md` until resolved. Implementation milestones that depend on specific operations (live polling, history retrieval) are blocked by missing evidence for those operations and shall be sequenced after the evidence exists.
|
||
|
||
---
|
||
|
||
# 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. The precise advancement condition — durably spooled, not finally delivered — is defined in `ARCHITECTURE.md` §21; final delivery is tracked independently through per-destination spool acknowledgements.
|
||
|
||
---
|
||
|
||
# 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
|
||
|
||
```
|
||
|
||
The configuration reference (`docs/configuration/configuration-reference.md` §24.2) names these policies `keep-first`, `keep-last`, `reject`, and `version`; the semantic mapping between the two namings shall be kept in the configuration model so the same policy cannot drift apart between documents.
|
||
|
||
Recommended default:
|
||
|
||
```text
|
||
|
||
REJECT_CONFLICT
|
||
|
||
```
|
||
|
||
where conflicting values are stored diagnostically rather than silently overwritten.
|
||
|
||
Deduplication state shall remain correct across restart (see `ARCHITECTURE.md` §23): a restart during synchronization shall not introduce duplicate records, either through persisted deduplication state or through idempotent storage.
|
||
|
||
The deduplication window shall be bounded.
|
||
|
||
---
|
||
|
||
# 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=<gateway namespace>;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
|
||
|
||
opcua.historicalAccess.maxValuesPerRead
|
||
|
||
```
|
||
|
||
(This is the field defined in `docs/configuration/configuration-reference.md` §19.3. Earlier revisions of this document called it `maximumValuesPerHistoryRead`; the configuration-reference name is authoritative.)
|
||
|
||
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
|
||
|
||
The implementation agent 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
|
||
|
||
```
|
||
|
||
Implementation-agent task prompts work best when scoped similarly to concrete issues or PRs with explicit files and expected outcomes.
|
||
|
||
---
|
||
|
||
# 59. ExecPlan requirement
|
||
|
||
The implementation agent 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. Implementation agent 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. Rule for incomplete requirements
|
||
|
||
When the implementation agent 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 implementation execution sequence
|
||
|
||
The recommended first implementation 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 the implementation agent
|
||
|
||
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.
|
||
|