Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ All notable public changes to ARIEC61850 are recorded here. The project is still

### Added

- Added bounded SCL-assisted association resolution for incomplete ConnectedAP addressing: explicit valid selectors/application identity remain immutable constraints, genuinely unspecified fields may be resolved from engine-owned interoperability profiles, malformed/conflicting declarations fail closed, and accepted candidate provenance is retained without mutating the source SCL.
- Added zero-traffic smart-discovery KPI evidence across structural `GetNameList`, DataSet directory, hierarchy GVA, and bounded FC-root initial Read phases, including per-phase latency, duplicate semantic-request detection, peak outstanding requests, canonical completeness counters, deterministic repeat-run signatures, and explicit partial wire-accounting status for unobserved enrichment paths.
- Added live-authoritative SCL ReportControl family reconciliation for static reporting: indexed declarative controls are matched only to concrete live MMS RCB instances in the same domain/logical-node/report-FC with decimal instance suffixes, while non-indexed controls remain exact-name only and no runtime RCB name is synthesized.
- Added an SCL-aware static report planner that scopes the existing safe RCB selector to the reconciled live family, allowing a busy first instance to fall through to another proven-free instance without escaping to an unrelated control block.
Expand Down Expand Up @@ -38,6 +39,7 @@ All notable public changes to ARIEC61850 are recorded here. The project is still

### Fixed

- SCL-assisted connection no longer rejects a usable CID/SCL before TCP solely because AP-title or AE-qualifier is omitted; the runtime now performs serial fresh-transport negotiation over the bounded engine candidate set and still limits live validation to VMD Domain inventory rather than falling back to full discovery.
- Closed the persistent-monitor GI startup race in the new bootstrap path: a fast IED can no longer deliver the initial GI InformationReport before the target persistent monitor has been registered for routing.
- Hardened the SCL-assisted Step-3 runtime so the configured timeout bounds TCP/COTP/ACSE/MMS plus Domain/VMD inventory, MMS domain identifiers are reconciled case-sensitively, and malformed SCL returns typed validation evidence instead of leaking XML parser exceptions.
- Live-model discovery no longer drops DataSet members when callers request DataSet-directory reads through `MmsClientSession.DiscoverAsync`.
Expand Down
10 changes: 6 additions & 4 deletions docs/SCL_ASSISTED_MMS_CONNECT_STEP2.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The design keeps remote/called and local/calling identity separate:

- remote/called IP, TSEL, SSEL, PSEL, AP-title and AE qualifier come from the selected SCL `ConnectedAP`;
- local/calling selectors, AP-title, AE qualifier and MMS Initiate limits come from an explicit named client profile;
- missing or invalid remote SCL association values fail closed and remain visible as typed build errors;
- the **exact-plan builder** still fails closed when required remote values are missing or invalid; later runtime interoperability resolution is a separate typed layer and never rewrites the source SCL;
- no remote value is silently replaced with a local value.

## Implemented
Expand All @@ -21,7 +21,9 @@ The design keeps remote/called and local/calling identity separate:
- exact SCL selector/AP-title parsing and validation;
- `ExistingRuntimeDefault` as an explicit compatibility baseline, not an automatic fallback;
- golden test proving the parameterized encoder reproduces the existing `BalancedApTitle` association payload exactly when supplied the same identities;
- negative tests proving incomplete SCL association addressing does not silently fall back.
- negative tests proving the exact builder does not silently invent incomplete SCL association addressing.

The exact builder is intentionally preserved as the deterministic complete-SCL contract. Step 3 now layers a bounded candidate resolver above it: genuinely unspecified fields may be resolved from engine-owned association profiles, while malformed or conflicting explicit declarations still fail closed.

## Runtime boundary

Expand All @@ -34,6 +36,6 @@ Step 2 does **not**:

The existing runtime continues to use `CotpConnectRequest.BuildDefault()` and the existing association profiles.

## Next step
## Runtime handoff

Step 3 should add an opt-in SCL-assisted association entry point that consumes a validated plan, performs TCP/COTP/ACSE association, then validates only the live MMS domain inventory with `GetNameList(Domain, VMD)`. It must not repeat NamedVariable/GVAA/DataSet discovery when the trusted SCL model is being used.
Step 3 consumes either a complete exact plan or an engine-owned bounded association resolution, performs TCP/COTP/ACSE association, and then validates only the live MMS domain inventory with `GetNameList(Domain, VMD)`. It does not repeat NamedVariable/GVAA/DataSet discovery when the trusted SCL model is being used.
36 changes: 30 additions & 6 deletions docs/SCL_ASSISTED_MMS_CONNECT_STEP3.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,33 @@ Step 3 is the first opt-in runtime slice for the SCL-assisted connect path. It d
```text
trusted SCL
-> Step 1: parse MMS endpoint + ISO association identity
-> Step 2: build exact COTP + Session/Presentation/ACSE/MMS plan
-> Step 3: TCP/COTP/ACSE/MMS associate with that exact plan
-> Step 2: retain exact-plan capability for complete addressing
-> Step 3: classify association fields
explicit valid -> immutable constraint
unspecified -> bounded engine-profile resolution
invalid/conflict -> fail closed
-> serial fresh-transport candidate negotiation
-> first accepted MMS association
-> GetNameList(Domain, VMD) only
-> compare online domains with SCL logical devices
-> keep the MMS association alive for later work
```

The ordinary `MmsClientSession.ConnectAsync()` and full `DiscoverAsync()` paths remain unchanged. Step 3 is reached only through `ConnectSclAssistedAsync(...)`.

## Incomplete association addressing

A ConnectedAP that omits an association parameter is not equivalent to one that declares malformed or conflicting data.

`SclAssistedMmsAssociationCandidateResolver` classifies each critical field as:

- `PresentValid` — explicit SCL evidence; candidates must match it exactly;
- `Unspecified` — no source value; the engine may resolve it from one of its bounded interoperability profiles;
- `Invalid` — explicit malformed value; fail closed before network I/O;
- `Ambiguous` — conflicting duplicate critical declarations; fail closed before network I/O.

Candidate generation is deterministic and bounded. It does not form a Cartesian product of guessed selector/AP-title/AE values. Complete SCL keeps the exact plan first. For incomplete SCL, engine-owned profiles may supply only the unspecified fields, and accepted resolution is returned as provenance rather than written back into the source SCL.

## Domain design inventory

`SclMmsDomainInventoryReader` scopes the design model to one exact `IED/AccessPoint/Server` and projects each direct `LDevice` into its expected MMS domain:
Expand Down Expand Up @@ -50,11 +68,13 @@ all expected present and no extra -> exact match

A mismatch does not rewrite the trusted SCL model and does not automatically launch full discovery. If the transport remains healthy, the association stays open so the application can show diagnostics and choose an explicit next action.

## Exact-plan guard
## Plan/candidate guards

The legacy exact-plan overload remains byte-stable: before opening a socket it rebuilds the Step-2 COTP and ACSE/MMS bytes and rejects an internally inconsistent plan as `InvalidPlan`.

Before opening a socket, Step 3 rebuilds the Step-2 COTP and ACSE/MMS bytes from the typed plan and verifies that they still match the prebuilt bytes. A mutated or internally inconsistent plan is rejected as `InvalidPlan` without network side effects.
The smart overload accepts only a successful bounded resolution. Every candidate is validated as a legal COTP request plus client ACSE/MMS associate payload before network I/O. Candidates are attempted strictly serially, each from a fresh transport. Per-attempt timeout and caller cancellation are explicit, and attempt evidence is association-scoped.

The existing no-argument `CotpClient.ConnectAsync(...)` path still builds the historical default COTP CR bytes. The new overload accepts `CotpConnectParameters` only for explicitly parameterized callers.
The existing no-argument `CotpClient.ConnectAsync(...)` path still builds the historical default COTP CR bytes. Parameterized SCL candidates use the explicit `CotpConnectParameters` overload.

## Explicit non-goals

Expand All @@ -79,7 +99,11 @@ Deterministic tests cover:
2. fail-closed missing Server handling;
3. missing expected domain => incompatible;
4. extra online domain => evidence-only and still compatible;
5. invalid design/plan input returns a typed `InvalidPlan` result without TCP side effects.
5. invalid design/plan input returns a typed `InvalidPlan` result without TCP side effects;
6. missing AP-title/AE qualifier produces bounded compatibility candidates instead of a pre-socket error;
7. explicit non-default selectors remain unchanged in typed candidates;
8. malformed and conflicting explicit association values fail closed;
9. complete-SCL exact candidate remains first and byte-stable.

Repository validation remains:

Expand Down
4 changes: 2 additions & 2 deletions src/AR.Iec61850/Discovery/Iec61850StandardModelRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ public static class Iec61850StandardModelRegistry
[Key("MMXU", "PF")] = Def("MMXU", "PF", "WYE", 0.84, "power factor"),

// Harmonic measurements use phase-group CDCs. Physical AA1E1F06R4
// plus IEDScout SCL prove that MHAI ThdA / ThdPhV are WYE objects whose
// plus field-reference SCL evidence prove that MHAI ThdA / ThdPhV are WYE objects whose
// phase children are CMV SDOs, not ACD indication structures.
[Key("MHAI", "ThdA")] = Def("MHAI", "ThdA", "WYE", 0.98, "three-phase current THD"),
[Key("MHAI", "ThdPhV")] = Def("MHAI", "ThdPhV", "WYE", 0.98, "three-phase voltage THD"),

// Instrument-transformer semantics are standardized and were also observed in
// the AA1E1F06R4 IEDScout engineering model. Exact registry entries prevent
// the field-reference engineering model. Exact registry entries prevent
// live discovery from dropping these configuration DOs when attribute-name
// heuristics alone cannot infer their CDC safely.
[Key("TCTR", "Mod")] = Def("TCTR", "Mod", "ENC", 0.98, "mode control"),
Expand Down
Loading