Commit Graph
5 Commits
Author SHA1 Message Date
Marc Schier 0f710adc8e Split MigrationGuide.md, add What's New in 2.0, rewrite Profiles.md and Landing page (#3745) (#3874)
# Description

This PR is a documentation overhaul for OPC UA .NET Standard 2.0. It
splits the monolithic `Docs/MigrationGuide.md` into per-version sub-docs
(so a coding agent can load only the relevant section), adds a new
"What's New in 2.0" landing doc, rewrites `Docs/Profiles.md` and the
repo-root `README.md` to reflect what master actually implements, and
renames the misnamed `Docs/ALiasNames.md` to `Docs/AliasNames.md`.

The branch is `docupdates` and contains **6 commits** stacked on top of
`master`. All changes are doc-only except for `HelpLinkUri` string
updates in `Opc.Ua.MigrationAnalyzer` (all 119 analyzer tests still pass
× 5 TFMs).

## What changed

### `Docs/MigrationGuide.md` is now a thin landing page

Before: a single ~144 KB / 1,549-line document covering 22 distinct
migration topics in one file. After: a small 3.8 KB / 64-line landing
page that introduces general principles, lists a per-version table, and
keeps the tiny `1.05.377 → 1.05.378` and `1.04 → 1.05` legacy sections
inline.

The 1.5.378 → 2.0 content moves to a new **`Docs/migrate/2.0.x/`**
folder with a README index plus 12 thematic sub-docs, mapped 1-to-1 to
the existing H3 sections:

| Sub-doc | Folded H3 sections |
| --- | --- |
| `telemetry.md` | Telemetry and Logging |
| `packages.md` | Package, Target Framework and Dependency Changes |
| `source-generation.md` | Source Generation |
| `types.md` | Improved Type safety |
| `encoders.md` | Encodeable Factory + Encoders/Decoders + Complex Types
|
| `node-states.md` | Node States + INodeCache changes |
| `identity.md` | User Identity Token Handlers + User Identity Providers
+ Secrets |
| `certificates.md` | Certificate Management + ICertificateProvider |
| `configuration.md` | Configuration + Session/Browser State Persistence
|
| `sessions-subscriptions.md` | GDS Client API modernisation +
ManagedSession + Subscriptions/Transports |
| `alarms-model-change.md` | Alarms and Conditions + Address-space model
change tracking |
| `timeprovider.md` | Time and Timer abstraction (TimeProvider) |

Each sub-doc starts with a **"When to read this"** lead paragraph
(analyzer rules / symptoms / API areas it covers) and ends with a
sibling-links footer. `Docs/migrate/2.0.x/README.md` has a symptom →
sub-doc index table reused as-is in the agent skill.

### `opcua-v20-migration` agent skill is now context-efficient

`.agents/skills/opcua-v20-migration/SKILL.md` gains a "Migration sub-doc
index — load only what you need" section near the top with an explicit
*"Do not load `Docs/MigrationGuide.md` into context"* instruction and a
table keyed by symptom / API area / analyzer rule ID, so an agent loads
at most one sub-doc per migration scenario. Path references in
`README.md`, `references/analyzer-rules.md`,
`references/migration-patterns.md`, and `references/source-generator.md`
are updated to point at the new sub-doc locations.

### New `Docs/WhatsNewIn2.0.md`

Developer-facing narrative tour of the 1.5.378 → 2.0 delta (~320 lines,
hybrid grouping: cross-cutting themes first — type system &
immutability, async/cancellation/TimeProvider, DI & hosting, Native AOT,
source generators, companion specs Part 9/11/13/16/17/18/20/100 + WoT +
LDS, performance, security — then by layer: Server,
Client/Sessions/Subscriptions, PubSub, GDS, Tooling, CI). Paragraph per
feature, no PR/commit references, links to the deeper per-feature docs.
Linked from `Docs/README.md` between `Profiles.md` and
`MigrationGuide.md`.

### `Docs/Profiles.md` rewritten to reflect master

Adds Functional Facets for newly-implemented features (Part 9 Alarms,
Part 11 Historical Access, Part 13 Aggregates, Part 16 State Machines,
Part 17 Alias Names, Part 18 Role Management, Part 20 FileSystem server,
Part 100 Device Integration / Software Update, OPC 10100-1 WoT, Node
Management, Local Discovery Server, Auditing, Model Change Tracking).
Expands Client Profiles (classic `Session` vs `ManagedSession`, V2
subscription engine, `FileSystemClient`, `HistoryClient`, `AlarmClient`,
NodeSet export, source-generated typed `ObjectType` proxies). Adds a
Reference Applications section listing all of `Applications/*`
(Quickstarts/Ctt/Mono configs, Reference Client, LDS, MCP, Minimal* /
Pump* samples). Security policies and transport profiles confirmed
against `Stack/Opc.Ua.Core/Security/Constants/*` — no changes needed
there.

For new facets whose canonical URI could not be confidently verified
against `profiles.opcfoundation.org` (the registry is fully
SPA-rendered), the doc describes the facet by name and points readers at
the OPC Foundation registry rather than fabricating URIs. The
`ServerProfileArray` in the reference-server configs is intentionally
left unchanged to avoid CTT-compliance regressions from advertising an
unverified URI.

### Repo-root `README.md` cleaned up

Front page now makes the 2.0 / `master378` context explicit. New
5-section structure with one emoji per heading: 🆕 version callout → 📦
What it is → 🚀 Getting started (grouped sample list linking to each
sample's own README) → 🔧 Migrating from 1.5.378 → 🤝 Contributing &
license → 📚 Further reading. Removes the "New in 1.04.368 / 1.05.373 /
.374 / .375 / .376 / .378 / 2.0" laundry list, the dated "Key Features
and Updates in OPC UA 1.05" section, inline VS / `dotnet run` build
instructions, the "Start the server" walkthrough, the "Remarks"
(self-signed certs + LDS) notes, and the inaccurate `.NET Standard 2.1`
overview claim. Trims the 11 status badges down to 5 essentials
(release, NuGet downloads, build, tests, codecov).

### File rename — `Docs/ALiasNames.md` → `Docs/AliasNames.md`

The on-disk filename had a stray capital `L` while every link in
`Docs/README.md`, `Docs/Profiles.md`, etc. used the lowercase spelling.
Renamed via case-only `git mv` (Windows two-step). Existing links across
the docs now resolve on GitHub's case-sensitive filesystem.

### `Opc.Ua.MigrationAnalyzer` `HelpLinkUri` updates

- `Tools/Opc.Ua.MigrationAnalyzer/Diagnostics/DiagnosticIds.cs` —
`HelpLinkUriBase` repointed from `Docs/MigrationGuide.md#` to
`Docs/migrate/2.0.x/README.md#` so the rule-ID help links land on the
symptom → sub-doc index instead of a generic landing page.
- `Tools/Opc.Ua.MigrationAnalyzer/Diagnostics/DiagnosticDescriptors.cs`
— UA0021 / UA0022 message strings reference the new
`Docs/migrate/2.0.x/certificates.md`.
-
`Tools/Opc.Ua.MigrationAnalyzer/Analyzers/UA0021CertificateValidatorRenameAnalyzer.cs`
— XML-doc path updated.
- `Tools/Opc.Ua.MigrationAnalyzer/NugetREADME.md` and
`AnalyzerReleases.Unshipped.md` — references repointed.

## Verification

- `Opc.Ua.MigrationAnalyzer` builds with **0 Warning(s), 0 Error(s)** in
Release.
- `Opc.Ua.MigrationAnalyzer.Tests`: **119/119 tests pass × 5 TFMs**
(net48, net472, net8.0, net9.0, net10.0).
- `ConsoleReferenceServer` builds with **0 Warning(s), 0 Error(s)** in
Release on net10.0 (verifies the reference-server config XML still
parses cleanly after our doc-touching).
- **Every relative markdown link** in the new / changed docs (the new
`Docs/migrate/2.0.x/*`, `Docs/MigrationGuide.md`,
`Docs/WhatsNewIn2.0.md`, `Docs/Profiles.md`, `Docs/Sessions.md`,
`Docs/IdentityProviders.md`, the agent skill files, and the new
`README.md`) was walked programmatically — **0 broken links**.
- Deep heading anchors verified to match GitHub-generated slugs
(`MigrationGuide.md#encoders-and-decoders`,
`Sessions.md#1-session--the-opc-ua-session-primitive`,
`Sessions.md#3-managedsession--the-connection-state-machine-facade`,
`migrate/2.0.x/identity.md#user-identity-providers`,
`migrate/2.0.x/identity.md#user-identity-token-handlers`,
`migrate/2.0.x/encoders.md#encoders-and-decoders`,
`migrate/2.0.x/node-states.md#inodecache-changes`,
`migrate/2.0.x/certificates.md#certificatemanager-and-segregated-interfaces`,
`migrate/2.0.x/sessions-subscriptions.md#managedsession-and-automatic-reconnection`).
- No `ALiasNames` (capital L) references remain anywhere in the repo
(case-sensitive search).

## Commit history (6 commits)

1. `548d0b5ed` — Docs: rename `ALiasNames.md` to `AliasNames.md`
2. `8a8db8c30` — Docs: add `WhatsNewIn2.0.md` (1.5.378 → 2.0 highlights)
3. `e69b2169e` — Docs: rewrite `Profiles.md` to reflect master
implementation
4. `5fb8a282b` — Merge remote-tracking branch `origin/master` into
`docupdates` (resolves overlap with #3854's `Docs/Subscriptions.md`
rename of `StreamingSubscription.md`)
5. `d853fbc74` — Docs: split `MigrationGuide.md` into per-version
sub-docs (#3745)
6. `65d6e6851` — Docs: rewrite repo-root `README.md` for 2.0

## Related Issues

- Fixes #3745 (MigrationGuide.md document structure)

## Checklist

- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage. *(N/A — documentation change;
existing `Opc.Ua.MigrationAnalyzer.Tests` (119 tests × 5 TFMs) still
pass after the `DiagnosticDescriptors` / `DiagnosticIds` text updates.)*
- [x] I have added all necessary documentation. *(this PR is the
documentation; all internal links verified)*
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings. *(both `Opc.Ua.MigrationAnalyzer` and
`ConsoleReferenceServer` build with 0 warnings / 0 errors)*
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed. *(only the
migration-analyzer test suite was rerun, since this PR is doc + a few
`HelpLinkUri` strings; full UA.slnx run pending CI)*
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings. *(pending CI)*
- [ ] I have addressed **all** PR feedback received.
2026-06-14 17:48:27 +02:00
Marc Schier 4e6c3303dd Add V2 subscription triggering (SetTriggering) with N:M support and recreate replay (#3854)
# Description

Adds **triggered-item (SetTriggering) support to the V2 (modern)
subscription engine** with a hybrid API, batched apply pipeline, and
automatic replay on recreate/reconnect — closing the gap from #3834 and
adding store/load round-trip for triggering relationships.

## Public API

| Concern | Surface |
|---|---|
| Declarative | `MonitoredItemOptions.TriggeredByNames`
(`IReadOnlyList<string>`) — set at item-add time |
| Imperative | `ISubscription.SetTriggeringAsync(IMonitoredItem
triggeringItem, IReadOnlyCollection<IMonitoredItem>? linksToAdd,
IReadOnlyCollection<IMonitoredItem>? linksToRemove, CancellationToken
ct)` returning `SetTriggeringResult` with per-link statuses |
| Fluent helpers | name-based overloads `SetTriggeringAsync(this
ISubscription, string triggeringItemName, params string[]
triggeredItemNames)` (and `add`/`remove`/`ct` variant) |
| N:M navigation | `IMonitoredItem.TriggeringItems` (items that trigger
this) and `IMonitoredItem.TriggeredItems` (items I trigger), both
on-demand projections |
| Result type | `public sealed record SetTriggeringResult(IMonitoredItem
TriggeringItem, IReadOnlyList<(IMonitoredItem Item, StatusCode Status)>
AddResults, IReadOnlyList<(IMonitoredItem Item, StatusCode Status)>
RemoveResults, StatusCode ServiceResult)` |

No client handles surface on the public API. Validation in the
imperative path is by **reference identity** under the manager lock —
items from a different subscription with a matching name cannot sneak
through, and a removed-then-re-added item with the same name does not
silently re-target.

## Engine — batched apply

A new manager-level operations queue + a batched apply step in
`MonitoredItemManager.ApplyMonitoredItemChangesAsync`:

1. After Create / Modify / SetMonitoringMode, drain the operations
queue.
2. Group by triggering item (reference identity).
3. Re-queue ops whose triggering item is not yet `Created` (bounded by
`MaxTriggeringRetryCount`; permanently failed items propagate the
create-failure status to the operation TCS).
4. Fold per-edge across operations targeting the same triggering item —
last-intent wins; same-edge add+remove resolves to one net operation.
5. Pre-resolve: triggered items with `Created=false` resolve to
`Bad_MonitoredItemIdInvalid` (adds) or `Good` no-op (removes, per Part 4
§5.13.1.6 server auto-cleanup).
6. Issue **one `SetTriggering` RPC per triggering item** carrying both
`linksToAdd` and `linksToRemove` (the server processes remove before add
per §5.13.5.2 — atomic swap semantics).
7. Map per-link results back to contributing operations; complete each
TCS with its own `SetTriggeringResult` subset.

Imperative writes mutate the per-item runtime `DesiredTriggeredByNames`
synchronously so navigation (`TriggeringItems`/`TriggeredItems`) and
`Snapshot()` reflect intent before the RPC fires. Per-link failures roll
back the optimistic mutation so the client view matches server reality.

## State ownership

`MonitoredItemOptions.TriggeredByNames` is the **initial declarative
input**. The canonical runtime source of truth is a per-item
`DesiredTriggeredByNames` field, initialized from options and mutated by
both the imperative API and subsequent options changes. The field is
preserved across `Reset` (recreate path), which is what enables
automatic SetTriggering replay after recreate.

## Save / load (closes #3834)

- `MonitoredItemStateSnapshot.TriggeredByNames` (`ArrayOf<string>`)
replaces the old `TriggeringItemClientHandle` field (V2-only — not yet
shipped, so a clean break; classic snapshot format unchanged).
- `Snapshot()` reads from runtime `DesiredTriggeredByNames`;
`ApplyLoadState` writes loaded names into both options and runtime state
without leaking through the OnChange tracker.
- **TransferSubscriptions** success path: only the local view is
restored — trusting the spec (`§5.13.5`) that servers preserve
triggering links across subscription transfer. No SetTriggering RPC is
issued.
- **Recreate-fallback** (transfer rejected), **in-session
`RecreateAsync`**, and **Reconnect** paths: `Reset` preserves
`DesiredTriggeredByNames` and enqueues an add-delta per preserved
triggering name; the batched apply pass replays SetTriggering after
items finish (re)creating.

## Error handling

Per OPC UA Part 4 §5.13.5.3/§5.13.5.4 (Tables 73/74):

| Condition | Engine response |
|---|---|
| Per-link `Bad_MonitoredItemIdInvalid` | Surfaced in
`SetTriggeringResult.AddResults`/`RemoveResults`; optimistic
`DesiredTriggeredByNames` mutation rolled back |
| Service-level `Bad_SubscriptionIdInvalid` | Operations re-queued, not
terminal — replays after the subscription state machine recreates |
| Service-level `Bad_TooManyOperations` | Surfaced as
`ServiceResultException` to all contributing TCSs (no auto-chunking in
this version) |
| Triggering item never reaches `Created` | After
`MaxTriggeringRetryCount` re-queues, op completes with the triggering
item's propagated error (no infinite loop) |
| Communication errors | Routed through the existing retry policy with
bounded retry count |

## Spec consultation

Cross-checked against **OPC UA Part 4 v1.05.07 §5.13.5** (verified Table
73 / Table 74 directly via the OPC Foundation spec site) and §5.13.1.6
(deletion side-effects, monitoring-mode interactions). The only per-link
spec-specific status code is `Bad_MonitoredItemIdInvalid`;
`linksToRemove` is processed server-side before `linksToAdd` (driving
the single-RPC-per-trigger batch shape).

## Tests

- **9 new unit tests** in `MonitoredItemManagerTriggeringTests.cs`
(single op, multi-op merge into one RPC, per-trig grouping,
requeue-when-not-Created, per-link rollback, `Bad_SubscriptionIdInvalid`
recovery, deletion races, last-intent same-edge conflict resolution).
- **Updated** integration tests `SetTriggeringTrackingV2Async` and
`SnapshotCapturesTriggeringForReplayAsync` to use the new API.
- **2 new integration tests** in `SubscriptionTests.cs`:
`DeclarativeTriggeredByNamesV2Async` (options-driven path end-to-end)
and `NToMTriggeringV2Async` (one triggered item linked to two trigger
items, per-link removal).
- **AOT smoke test** in `SubscriptionAotTests.cs` for the
`MonitoredItemStateSnapshot.TriggeredByNames` binary encoder/decoder
round-trip.
- All **344 V2 subscription/monitored-item unit tests** and **71 V2
subscription integration tests** pass locally (net10).

## Documentation

- New: `Docs/Subscriptions.md` — *Subscriptions and Monitored Items
Service Set*. Merges the previous `StreamingSubscription.md` and
`SubscriptionTriggering.md` into a single guide; leads with a
Classic-vs-V2 engine overview (recommending V2 for new code) and links
to `Sessions.md` §4 for the full engine comparison. Covers the V2
callback API, declarative + imperative SetTriggering with N:M,
save/load/restore behavior, error handling, and the
`IStreamingSubscription` async-enumerable surface.
- Updated: `Docs/README.md`, `Docs/AlarmsAndConditions.md`,
`Docs/StateMachines.md`, `Docs/Profiles.md` — all point to the new
merged doc.
- Updated: `plans/26-v2-subscription-parity.md` — rows 49
(`SetTriggeringAsync`) and 111 (`TriggeringItems` plural /
`TriggeredItems`).

## Related Issues

- Fixes #3834 — `TransferSubscription does not automatically
restore/retain links between trigger and monitored items`. The fix is
two-pronged: (a) transfer preserves links server-side per spec and the
client snapshot captures `TriggeredByNames` so the local view restores
automatically; (b) when transfer fails and the engine falls back to
recreate (or when `RecreateAsync` is invoked explicitly), `Reset`
enqueues per-triggering-name add-deltas from the preserved runtime state
and the batched apply pass replays `SetTriggering` after re-creation.

## Checklist

- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
2026-06-12 10:38:41 +02:00
Copilot 43a8358eac Update Profiles.md to document v2 improvements and new security profiles (#3832)
The Profiles.md documentation was outdated and did not accurately
reflect the significant improvements and new features added in v2, as
well as containing an inaccuracy regarding server-side aggregate
support. This PR updates the document to provide an accurate and
comprehensive profile of current functionality.

## Changes Made

- **Overview**: Updated to highlight v2 improvements and clarified OPC
UA specification version to 1.05.07
- **Server Features**: Added three new Additional Features sections
documenting:
  - Alias Names (OPC UA Part 17) with wildcard search
  - WoT Connectivity (OPC 10100-1) for IoT asset integration
  - Model Change Tracking for address space change notifications
- Added reference to fluent API and dependency injection patterns for
feature configuration
- **Client Enhancements**: Expanded Client Profiles section with new
capabilities:
- Streaming Subscriptions integrated into subscription management
(IAsyncEnumerable-based API)
  - Model Change Tracking (address space invalidation)
  - File System Operations (System.IO-style async client)
  - Alarms and Conditions (full subscription support)
- **Security Profiles**: Significantly expanded security policy
documentation to include v2.0 additions:
  - Modern ECC Curves: Curve25519 and Curve448 with AEAD ciphers
  - AES-GCM and ChaCha20-Poly1305 variants for traditional ECC curves
  - RSA Diffie-Hellman key agreement policies
  - Updated platform requirements to reflect modern cipher support needs
- **GDS Expansion**: Added Authorization Service and Key Credential
Service to GDS section for token and credential issuance
- **Restructuring**: Removed "Currently Not Supported (Server)" section
to provide clearer distinction between fully implemented features and
those with limited coverage, and integrated streaming subscriptions as a
subscription management capability rather than a separate profile
- **Documentation**: Added 8 new entries to Related Documentation
linking to comprehensive guides for all v2 features
- **Aggregate Correction**: Corrected the inaccurate claim that
server-side aggregates are not implemented. Server-side aggregates
(Average, Total, Minimum, Maximum, and more) are fully implemented via
streaming fallback and provider push-down. Removed "Aggregates Server
Facet" from the "Currently Not Supported" section.

## Related Issues

## Checklist

- [ ] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [ ] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [ ] I have added all necessary documentation.
- [ ] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-03 12:43:28 +02:00
Marc Schier 03777ecb09 New Json decoder/encoders, array/matrix abstractions, ByteString, and more. (#3619)
- **Collections overhaul** — new/rewritten collection types (`ArrayOf`, `Collections` commits)
- **`Variant` builder/accessor** — new APIs for constructing and accessing Variants
- **`NodeId` operators made explicit** — breaking change for implicit conversions
- **Version bumped to 1.6** with preview build support
- **NumericRange** uses Variant
- **object** type accessors and general usage removed.

### 🏗️ Infrastructure
- Build config updated; `.NET 10` targeting
- InternalsVisibleTo moved to `.csproj`
- Pipeline/CI adjustments
2026-03-18 12:23:30 +01:00
Copilotandromanett c9b211e61e Add comprehensive OPC UA Profiles and Facets documentation (#3397)
* Initial plan

* Add comprehensive OPC UA Profiles and Facets documentation

Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>

* Fix URL in Profiles documentation to use current OPC Foundation site

Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
2025-12-09 17:49:09 +01:00