Skip to content

[WotCon] Add the WoT Connectivity registry client - #4142

Merged
marcschier merged 107 commits into
marcschier/wot-13-registryfrom
marcschier/wot-15-client
Aug 5, 2026
Merged

[WotCon] Add the WoT Connectivity registry client#4142
marcschier merged 107 commits into
marcschier/wot-13-registryfrom
marcschier/wot-15-client

Conversation

@marcschier

Copy link
Copy Markdown
Collaborator

PR 15 of a stacked split of integration PR #4093 into independently reviewable pieces.

This branch is stacked on #4139 (marcschier/wot-10-wotcon-model) and additionally has #4128 (marcschier/wot-01-core-types) and #4130 (marcschier/wot-09-xregistry-client) merged in so this client slice can build.

Those extra dependencies are intentional:

The extra diff from #4128 and #4130 disappears once those PRs land.

This PR adds the WoT Connectivity registry client surface for browsing and reading registry groups, resources and versions, uploading documents through FileTransfer, invoking registry methods, and registering the client through DI/builder helpers.

Adds the client-side surface for the WoT Connectivity registry: browsing and reading registry groups, resources and versions, uploading documents through FileTransfer, and invoking the registry methods.

WotRegistryClient derives from the shared XRegistryClient so the generic registry traversal is not reimplemented here, and it takes an explicit registry root so a server that hosts the registry somewhere other than the well-known location can still be used.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Reverts the temporary client-only compile exclusions so the WotCon test project keeps the existing server, provider and hosting tests from the base branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Copilot AI review requested due to automatic review settings July 31, 2026 10:05
@marcschier

Copy link
Copy Markdown
Collaborator Author

Follow-up: the initial PR 15 commit temporarily excluded the non-client WotCon tests from Opc.Ua.WotCon.Tests.csproj; that was wrong because it removed existing base coverage. I have restored the test project to match the base branch, merged the #4139 fixes for the DataTypeIds shadowing / predefined-node partitioning issues, and revalidated with the full WotCon test project intact.

Validation now passes:

  • dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m — 0 warnings / 0 errors
  • dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build — 396 passed, 0 failed, 0 skipped
  • dotnet build src\Opc.Ua.WotCon.Client\Opc.Ua.WotCon.Client.csproj -c Release -v:m — 0 warnings / 0 errors

@marcschier

Copy link
Copy Markdown
Collaborator Author

Confirmed after merging the fixed marcschier/wot-10-wotcon-model (a88b971f2): the earlier temporary WotCon test exclusions were wrong and have been reverted. tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj is byte-identical to the base branch, with no Compile Remove entries and the server project references restored.

Validation with the full test project intact:

  • dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 -v:m — 0 warnings / 0 errors
  • dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c Release -p:CustomTestTarget=net10.0 --no-build — 396 passed, 0 failed, 0 skipped
  • dotnet build src\Opc.Ua.WotCon.Client\Opc.Ua.WotCon.Client.csproj -c Release -v:m — 0 warnings / 0 errors

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds the WoT Connectivity 1.1 registry client surface (plus supporting xRegistry and core type enhancements) and wires it into DI/builder helpers, including comprehensive session-mock tests.

Changes:

  • Introduce WotRegistryClient + group/resource wrappers, plus a shared browse-path resolver and DI registration helpers.
  • Extend xRegistry client construction to accept an explicit registry root NodeId.
  • Add atomic file replacement to the IFileSystem abstraction and update built-in file system implementations + tests; enhance Variant/ExtensionObject structure decoding and related type-system tests.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tools/Opc.Ua.SourceGeneration/SourceGeneratorFileSystem.cs Implements new IFileSystem.Replace API as not supported for the source generator FS.
tests/Opc.Ua.XRegistry.Tests/XRegistryClientTests.cs Adds tests for explicit registry root NodeId behavior in XRegistryClient.
tests/Opc.Ua.WotCon.Tests/Hosting/OpcUaWotRegistryClientBuilderExtensionsTests.cs Adds DI/builder tests for AddWotRegistryClient registration and behavior.
tests/Opc.Ua.WotCon.Tests/Client/WotRegistrySessionMock.cs Adds an in-memory scripted ISession mock to test WoT registry behavior end-to-end.
tests/Opc.Ua.WotCon.Tests/Client/WotRegistryClientTests.cs Adds WoT registry client tests (browse resolution, uploads, refresh, lifecycle).
tests/Opc.Ua.WotCon.Tests/Client/WotRegistryBulkLoadTests.cs Adds tests for bulk document load ordering and failure propagation.
tests/Opc.Ua.WotCon.Tests/Client/WotConnectivityClientTests.cs Updates/extends tests for connectivity client behavior (browse-path helper usage).
tests/Opc.Ua.Types.Tests/Utils/FileSystem/AtomicFileReplaceTests.cs Adds tests validating atomic replace semantics across file systems.
tests/Opc.Ua.Types.Tests/Nodes/TypeTableTests.cs Adds coverage for type/encoding equivalence handling.
tests/Opc.Ua.Types.Tests/BuiltIn/VariantCoverageTests.cs Adds coverage for new Variant.TryGetStructure(context, ...) overloads.
tests/Opc.Ua.Types.Tests/BuiltIn/ExtensionObjectTests.cs Adds coverage for context-based decoding of binary/xml/json extension bodies.
src/Opc.Ua.XRegistry.Client/XRegistryClient.cs Adds explicit-root constructor and stores RegistryNodeId as an instance property.
src/Opc.Ua.XRegistry.Client/GenericXRegistryClient.cs Adds explicit-root constructor for generic registry client.
src/Opc.Ua.WotCon.Client/WotRegistryResourceClient.cs Adds resource wrapper with validate/enable/default/delete and upload/download helpers.
src/Opc.Ua.WotCon.Client/WotRegistryGroupClient.cs Adds group wrapper for create/get-or-create/open resource and delete operations.
src/Opc.Ua.WotCon.Client/WotRegistryClient.cs Adds primary WoT registry client (group ops, refresh, bulk load workflow).
src/Opc.Ua.WotCon.Client/WotConnectivityClient.cs Refactors browse-path resolution to shared resolver; minor doc formatting.
src/Opc.Ua.WotCon.Client/WotConBrowsePathResolver.cs Adds centralized TranslateBrowsePaths helper for resolving single children.
src/Opc.Ua.WotCon.Client/Opc.Ua.WotCon.Client.csproj Adds dependency on Opc.Ua.XRegistry.Client for shared base lifecycle.
src/Opc.Ua.WotCon.Client/NugetREADME.md Updates package README to document registry client surface.
src/Opc.Ua.WotCon.Client/Hosting/WotRegistryClientOptions.cs Adds registry-client DI options (LazyConnect).
src/Opc.Ua.WotCon.Client/Hosting/OpcUaWotConClientBuilderExtensions.cs Adds AddWotRegistryClient extension methods and lazy accessor implementation.
src/Opc.Ua.Types/Utils/FileSystem/VirtualFileSystem.cs Implements atomic Replace for in-memory virtual file system.
src/Opc.Ua.Types/Utils/FileSystem/ResourceFileSystem.cs Implements Replace as not writeable for resource FS.
src/Opc.Ua.Types/Utils/FileSystem/NullFileSystem.cs Implements Replace as not available for null FS.
src/Opc.Ua.Types/Utils/FileSystem/LocalFileSystem.cs Implements Replace using File.Move(overwrite) or File.Replace fallback.
src/Opc.Ua.Types/Utils/FileSystem/IFileSystem.cs Adds Replace(source, destination) API with atomic publish semantics.
src/Opc.Ua.Types/Utils/FileSystem/CombinedFileSystem.cs Delegates Replace to the configured writeable side.
src/Opc.Ua.Types/Nodes/TypeTable.cs Adjusts type/encoding equivalence logic and fixes doc indentation.
src/Opc.Ua.Types/BuiltIn/Variant.cs Adds TryGetStructure(context, ...) overloads; adds docs for internal Union.
src/Opc.Ua.Types/BuiltIn/TypeInfo.cs Improves data type id resolution for known extension object type ids.
src/Opc.Ua.Types/BuiltIn/ExtensionObject.cs Adds context-based decoding for binary/xml/json bodies in TryGetValue.
Suppressed comments (1)

src/Opc.Ua.Types/Utils/FileSystem/IFileSystem.cs:1

  • The XML doc contains a duplicated <param name="destinationPath"> entry, which can break doc generation and IntelliSense. Remove the duplicate param line. Also, since some platform implementations (e.g., File.Replace on older TFMs) can fail across volumes/filesystems, it would be helpful to document any such constraints explicitly in this contract comment.
/* ========================================================================

Comment thread src/Opc.Ua.WotCon.Client/WotRegistryResourceClient.cs Outdated
Comment thread src/Opc.Ua.WotCon.Client/WotRegistryClient.cs Outdated
Comment thread src/Opc.Ua.WotCon.Client/WotRegistryClient.cs Outdated
Comment thread src/Opc.Ua.Types/Utils/FileSystem/VirtualFileSystem.cs Outdated
Comment thread tests/Opc.Ua.WotCon.Tests/Client/WotRegistrySessionMock.cs Outdated
The fluent builder generator emits calls to INodeManagerBuilder.VariableFromDataTypeId
and to a NodeManagerBuilder constructor overload that carries the data-type lookup, but
the runtime side of that API was missing, so every generated node manager failed to
compile with CS1729 and CS1061.

Adds the VariableFromDataTypeId resolution to the builder interface and implementation,
along with NodeStateLookupExtensions.FindByDataType, which is the lookup the builder
delegates to and has no other consumer.

Resolution reports BadNodeIdInvalid for a null data type, BadNodeIdUnknown when nothing
matches, BadBrowseNameDuplicated when the match is ambiguous, and BadTypeMismatch when
the resolved node is not a variable. An optional browse name disambiguates a data type
that is carried by more than one variable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
@marcschier

Copy link
Copy Markdown
Collaborator Author

Fixed the net10.0 solution build failure on this PR.

This branch carries the FluentBuilderGenerator change, which emits calls to
INodeManagerBuilder.VariableFromDataTypeId and to a NodeManagerBuilder constructor
overload carrying the data-type lookup. The runtime side of that API was not present on
any branch in the stack - it had been grouped into a later server PR that does not exist
yet - so every generated node manager failed to compile:

BoilerNodeManager.NodeManager.g.cs(97,31): CS1729: 'NodeManagerBuilder' does not
  contain a constructor that takes 7 arguments
BoilerNodeManager.FluentBuilders.g.cs(140,24): CS1061: 'INodeManagerBuilder' does not
  contain a definition for 'VariableFromDataTypeId'

The fix lands in #4132 (where the generator change belongs) and is cherry-picked here so
this branch builds standalone. It adds VariableFromDataTypeId to the builder interface
and implementation, NodeStateLookupExtensions.FindByDataType, and eight tests covering
the resolution rules.

Verified locally: MinimalBoilerServer - one of the two projects failing in CI - builds
clean on this branch.

DiNodeManager constructed NodeManagerBuilder without the data-type resolver, so
VariableFromDataTypeId reported BadNodeIdUnknown ("no predefined variable has DataType")
for every DI node manager - a misleading error, since the lookup had simply never
been supplied rather than the variable being absent.

Delegates to NodeStateLookupExtensions.FindByDataType rather than hand-rolling the
scan a fourth time in this file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
@marcschier marcschier closed this Jul 31, 2026
@marcschier marcschier reopened this Jul 31, 2026
…client

# Conflicts:
#	src/Opc.Ua.Di.Server/DiNodeManager.cs
Allow lazy client connection retries after failed attempts while keeping concurrent callers on the same in-flight task. Validate malformed method-call responses before indexing result arrays, avoid redundant resource lookups during bulk load, and add bounded spinning to virtual file replacement contention paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 69.25566% with 190 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.13%. Comparing base (66ccab9) to head (ed86073).

Files with missing lines Patch % Lines
src/Opc.Ua.WotCon.Client/WotRegistryClient.cs 65.99% 62 Missing and 22 partials ⚠️
...ient/Hosting/OpcUaWotConClientBuilderExtensions.cs 59.13% 30 Missing and 8 partials ⚠️
.../Opc.Ua.WotCon.Client/WotRegistryResourceClient.cs 54.71% 19 Missing and 5 partials ⚠️
src/Opc.Ua.Types/BuiltIn/ExtensionObject.cs 74.02% 12 Missing and 8 partials ⚠️
src/Opc.Ua.WotCon.Client/WotRegistryGroupClient.cs 62.85% 11 Missing and 2 partials ⚠️
...Opc.Ua.Types/Utils/FileSystem/VirtualFileSystem.cs 60.00% 4 Missing and 2 partials ⚠️
...c/Opc.Ua.Types/Utils/FileSystem/LocalFileSystem.cs 60.00% 1 Missing and 1 partial ⚠️
src/Opc.Ua.Types/BuiltIn/TypeInfo.cs 80.00% 0 Missing and 1 partial ⚠️
src/Opc.Ua.Types/BuiltIn/Variant.cs 95.83% 0 Missing and 1 partial ⚠️
...c.Ua.SourceGeneration/SourceGeneratorFileSystem.cs 0.00% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (69.25%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@                        Coverage Diff                         @@
##           marcschier/wot-10-wotcon-model    #4142      +/-   ##
==================================================================
+ Coverage                           79.88%   80.13%   +0.24%     
==================================================================
  Files                                1540     1544       +4     
  Lines                              214958   215517     +559     
  Branches                            37133    37236     +103     
==================================================================
+ Hits                               171723   172701     +978     
+ Misses                              30301    29886     -415     
+ Partials                            12934    12930       -4     
Files with missing lines Coverage Δ
src/Opc.Ua.Types/Nodes/TypeTable.cs 98.57% <100.00%> (+0.02%) ⬆️
...pc.Ua.Types/Utils/FileSystem/CombinedFileSystem.cs 55.55% <100.00%> (+4.04%) ⬆️
...rc/Opc.Ua.Types/Utils/FileSystem/NullFileSystem.cs 100.00% <100.00%> (ø)
...pc.Ua.Types/Utils/FileSystem/ResourceFileSystem.cs 40.00% <100.00%> (+1.76%) ⬆️
...c/Opc.Ua.WotCon.Client/WotConBrowsePathResolver.cs 100.00% <100.00%> (ø)
src/Opc.Ua.WotCon.Client/WotConnectivityClient.cs 76.40% <100.00%> (+76.40%) ⬆️
.../Opc.Ua.XRegistry.Client/GenericXRegistryClient.cs 100.00% <100.00%> (ø)
src/Opc.Ua.XRegistry.Client/XRegistryClient.cs 97.67% <100.00%> (+0.11%) ⬆️
src/Opc.Ua.Types/BuiltIn/TypeInfo.cs 83.35% <80.00%> (+0.10%) ⬆️
src/Opc.Ua.Types/BuiltIn/Variant.cs 80.84% <95.83%> (+0.57%) ⬆️
... and 8 more

... and 40 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

marcschier and others added 9 commits August 1, 2026 08:08
…to marcschier/wot-14-materialization

# Conflicts:
#	src/Opc.Ua.Types/Utils/FileSystem/LocalFileSystem.cs
#	src/Opc.Ua.Types/Utils/FileSystem/VirtualFileSystem.cs
Adds the materialization runtime that turns registered WoT Thing Descriptions into
live OPC UA nodes: a dependency graph over the registered documents, a coordinator
that drives resolution and projection, and a binding runtime that attaches protocol
channels to the projected variables.

Projection runs through the NodeManager lifecycle rather than mutating a running
address space in place, so a refresh either commits a complete new generation or
leaves the previous one untouched. The resolver, converter, contributor and target
variable seams are interfaces so a host can substitute its own document sources.

Also adds the registry NodeManager that exposes the registry itself in the address
space, and the hosting extensions that register the whole runtime with dependency
injection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Bring the PR14 materialization, dependency graph, binding runtime, registry projection lifecycle, and NodeManager coverage across from the stacked integration branch.

Keep the tests compiling for both net10.0 and net48 by naming ImmutableDictionary.Empty on the binding plan models and updating the memory binding test seam to the current codec resolver contract.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
…arcschier/wot-16-samples

# Conflicts:
#	src/Opc.Ua.Types/Utils/FileSystem/VirtualFileSystem.cs
Adds three runnable samples: two flat OPC UA tag servers and an aggregation server
that materializes them into a DI/Machinery/Pumps model through the WoT registry,
plus an aggregation client that drives the result. The AggregationServer also ships
a memory protocol binding, which doubles as the worked example for the binding
contributor guide.

Documents the WoT Connectivity surface end to end: a new protocol bindings guide,
the expanded WoT Connectivity overview covering the registry, materialization and
runtime projection, and the shadow-reload and shared byte-store sections for the
runtime NodeSet and xRegistry guides. Registers the sample and test projects in the
solution so they are built and run by CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
marcschier and others added 19 commits August 4, 2026 12:05
The WoT registry node manager can be asked to delete its address space after the externally-owned materialization coordinator has been disposed. That disposed the coordinator semaphore before DeleteAddressSpaceAsync called RemoveAllAsync, so shutdown reported ObjectDisposedException from the node manager cleanup path.

Keep coordinator cleanup available after Dispose when live projections remain, block new refreshes, and release the semaphore once the deferred cleanup has drained. Also order the direct integration-test teardown through the server fixture so the node manager cleanup runs before test-owned services are released, and add a regression test for shutting down with a live materialized projection after coordinator disposal.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
During ordered server disposal, the NodeManager lifecycle has already entered shutdown before WotRegistryNodeManager deletes its address space. Removing materialized WoT projections by routing back through the lifecycle is therefore the wrong operation: the lifecycle will tear down every remaining dynamic NodeManager as part of its shutdown completion.

Expose the lifecycle shutdown state and make the WoT projection host treat removal as a no-op once that state is active. Normal refresh/removal paths still unregister projections through the lifecycle, while full server teardown avoids re-entering a component that is already shutting down. The shutdown regression now exercises synchronous server disposal with active projections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
…arcschier/wot-14-materialization

# Conflicts:
#	src/Opc.Ua.Server/NodeManager/Lifecycle/NodeManagerLifecycle.cs
Master replaced the ambient AsyncLocal re-entrancy guard with an explicit IOperationContext parameter on the lifecycle add, reload and remove operations, so the WoT projection host no longer compiled: its cancellation token was binding to the new caller-context parameter.

The host passes null, which states that these calls are not made on behalf of an executing OPC UA request. The shadow and immediate reload paths are unchanged because those overloads deliberately take no caller context; they are the reload modes that are safe to invoke from a request callback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Merging master added an IOperationContext parameter to the NodeManager lifecycle add operation, so these tests no longer bound their argument to the intended overload. They pass null because the registration is created by the test fixture rather than on behalf of an executing request.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
## Summary
- add optional WoT Connectivity asset TD mirroring into the WoT
xRegistry
- add DI opt-in via AddWotRegistryBridge and direct
WotConnectivityServerOptions.RegistryBridge fallback
- document default-off, best-effort failure policy and usage
- add NUnit/Moq coverage for create, update, delete, disabled and
failure paths

## Validation
- dotnet build src\\Opc.Ua.WotCon.Server\\Opc.Ua.WotCon.Server.csproj -c
Release -v:m (all TFMs, 0 warnings/errors)
- dotnet test tests\\Opc.Ua.WotCon.Tests\\Opc.Ua.WotCon.Tests.csproj -c
Release -p:CustomTestTarget=net10.0 (0 failed / 983 passed)

---------

Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
@marcschier marcschier added the ready Ready to merge once CI Passes label Aug 5, 2026
…ion (#4156)

Adds the runnable WoT Connectivity samples and completes the
documentation. This is **PR 16 of a
stack** splitting #4093, and the last one.

## Samples

Three projects under `samples/WotCon/`:

* **FlatTagServer** — a plain OPC UA server exposing flat tags, used as
an aggregation source.
* **AggregationServer** — registers Thing Descriptions with the WoT
registry and materializes two
flat sources into a runtime-loaded DI/Machinery/Pumps Pump model. It
also ships a small in-memory
protocol binding, which is the worked example the binding contributor
guide walks through.
* **AggregationClient** — drives the aggregated model: commands,
`Refresh`, monitoring, and
  generation replacement.

## Documentation

* New `docs/WotBindings.md` — the bindings that ship today
(planner/executor architecture, bundled
vs separate packages, operation coverage, target mapping, lazy channels,
generation lifetime) plus
the contributor guide for adding your own, with diagnostics, tests,
packaging, TFM, trimming and
  NativeAOT guidance.
* Expanded `docs/WoTConnectivity.md` covering the registry,
dependency-closure materialization and
  runtime NodeSet projection.
* `docs/RuntimeNodeSets.md` gains the shadow-reload section and
`docs/XRegistry.md` the shared
byte-store section. Both document APIs introduced earlier in the stack;
they are collected here
  because this is the documentation PR.
* `docs/README.md` links the new pages.

## Solution registration

Registers the three samples and `Opc.Ua.WotCon.Samples.Tests` in
`UA.slnx` so CI actually builds
and runs them.

## Stack position

Sits on top of **#4154** (materialization) and additionally merges
**#4142** (registry client) and
**#4144** (protocol executors), because the samples exercise the whole
stack — `AggregationServer`
needs the OPC UA executor and the client sample needs the registry
client. Its diff therefore shows
their content until they land.

It also carries `WotRegistryProjectionLiveTests.cs`, which #4154
deliberately left out: those tests
need both the materialization runtime *and* the registry client, so this
is the first branch where
they compile.

## Validation

* All three samples build clean on every target framework.
* `Opc.Ua.WotCon.Tests`: **830 passed**, 0 failed (769 from #4154 plus
61 from the live projection
  tests).
* `Opc.Ua.WotCon.Samples.Tests`: 6 of 7 pass locally; the remaining one
fails with
`CryptographicException: The system cannot find the path specified`, a
known certificate-store
problem on this machine that was previously reproduced against a clean
baseline worktree and is
  not related to this change. CI will confirm.
* 0 warnings, 0 errors.

One fix was needed while bringing the sample across: its memory binding
called `ResolveCodec` with
the pre-`out WotPayloadDescriptor` signature. The API gained the payload
out-parameter and a
`bool` result during review of the binding PRs, so the sample now
follows the same
`if (!ResolveCodec(...)) return Unsupported(...)` pattern as the shipped
planners.

Integration PR: #4093.
…pace (#4154)

PR 14 of the stacked series splitting the large WoT Connectivity
integration PR #4093.

This PR adds the server-side materialization runtime that turns WoT
Thing Description resources from the xRegistry snapshot into OPC UA
address-space projections. The coordinator builds the dependency closure
for each resource, plans binding metadata, activates binding channels,
and publishes the resulting projection through the registry NodeManager
so refresh, retire, and reload operations remain observable and
deterministic.

Projection intentionally goes through the NodeManager lifecycle reload
API instead of mutating live nodes directly. That keeps complex type
reload, runtime NodeSet publication, shadow reload, immediate reload,
and retirement on the same lifecycle path as other dynamic server
address-space changes.

This branch has a triple dependency. It is based on #4146 (registry),
and additionally needs #4147 (lifecycle reload API) and #4128
(2-argument TryGetStructure). Both #4147 and #4128 are merged into this
branch, so this PR's diff will show their content until those
dependencies land.

Validation performed:
- dotnet build src\Opc.Ua.WotCon.Server\Opc.Ua.WotCon.Server.csproj -c
Release -f net10.0 -v:m
- dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c
Release -p:CustomTestTarget=net10.0 -v:m
- dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c
Release -p:CustomTestTarget=net10.0 --no-build
- dotnet build tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c
Release -p:CustomTestTarget=net48 -v:m
- dotnet test tests\Opc.Ua.WotCon.Tests\Opc.Ua.WotCon.Tests.csproj -c
Release -p:CustomTestTarget=net48 --no-build
- dotnet build tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c
Release -p:CustomTestTarget=net10.0 -v:m
- dotnet test tests\Opc.Ua.Server.Tests\Opc.Ua.Server.Tests.csproj -c
Release -p:CustomTestTarget=net10.0 --no-build (one known inherited
failure: LiveNodeManagerAddRefreshesTheClientNamespaceTable)
@marcschier
marcschier merged commit 3388cf5 into marcschier/wot-13-registry Aug 5, 2026
marcschier added a commit that referenced this pull request Aug 5, 2026
…ation, Server and xRegistry work it builds on (#4128)

## Summary

Adds OPC UA WoT Connectivity 1.1 to the stack, together with the Types,
source generation, Server and xRegistry work it is built on. This branch
is the merge point for the fourteen-PR stack that replaced integration
PR #4093; every constituent PR was reviewed and approved separately and
is listed below.

414 files changed, +108,936 / -3,199. Roughly 46k added lines of product
code, 57k of tests, plus samples, tools and documentation.

## Types

- Complete `ExtensionObject` raw-body decoding for binary, XML and JSON
bodies by resolving the concrete type through the message context's
encodeable factory, and simplify the `Variant` structure helpers by
delegating to it (#4128).
- Add `IAtomicFileReplace` as an optional `IFileSystem` capability so
existing external implementations keep working, with atomic publish for
`LocalFileSystem` via `File.Replace`/`File.Move` and for
`VirtualFileSystem` by re-keying the in-memory entry (#4128).
- Add lossless conversion between WoT documents and NodeSet2
(`Opc.Ua.Wot.WotNodeSetConverter`). A byte-exact `uav:nodeSet` envelope
is preserved when requested, the structured `uav:nodes` projection is
used when the readable vocabulary is incomplete, and NodeSet2 is
otherwise synthesized from readable WoT terms. Unmapped JSON members
survive a round trip as pointer-addressed residue (#4131).

## Source generation

- Improve the NodeSet to ModelDesign conversion and the generated node
state (#4132).
- Generate OPC UA models directly from WoT Thing Description files
(#4134).

## Server

- Add live NodeManager shadow and immediate reload. A reload
materializes a new generation beside the active one and switches
atomically; the superseded generation is retired gracefully so existing
MonitoredItems keep being served until they drain, or immediately when
the caller asks for it. Includes the request admission and drain
machinery that lets an orderly shutdown wait for admitted requests
instead of tearing down underneath them (#4147).
- Make subscription transfer between sessions transactional, so a failed
transfer leaves neither session holding a partially moved subscription
(#4150).

## xRegistry

- Allow clients to use explicit registry roots rather than assuming a
well-known location (#4130).

## WoT Connectivity

- Add the WoT Connectivity 1.1 information model: a registry-first
revision layered on the abstract xRegistry base model, incorporating the
complete published OPC 10100-1 v1.02 surface as deprecated nodes in the
same namespace so existing 1.02 clients keep working (#4139).
- Add the protocol binding abstractions and planners that compile WoT
forms into executable plans (#4140).
- Add the HTTP, Modbus, OPC UA and MQTT binding executors (#4144).
- Add the registry and its stores, including document versioning,
validation, dependency resolution and refresh (#4146).
- Add the registry client (#4142).
- Materialize WoT Thing Descriptions into the server address space,
deriving types from Thing Models and instances from Thing Descriptions
(#4154).
- Restore the WoT asset registry bridge so the deprecated 1.02 asset
surface is backed by the registry (#4171).
- Add the WoT Connectivity samples and complete the documentation
(#4156), and restore the remaining coverage and docs (#4172).

## New projects

`src/Opc.Ua.WotCon.Bindings`, `src/Opc.Ua.WotCon.Bindings.Mqtt`,
`tests/Opc.Ua.WotCon.Bindings.Tests`,
`tests/Opc.Ua.WotCon.Samples.Tests`, and the `samples/WotCon`
AggregationServer, AggregationClient and FlatTagServer samples.

## Constituent pull requests

Merged into this branch top-down, each independently approved:

| PR | Title |
| --- | --- |
| #4128 | [Types] Complete ExtensionObject decoding and add an atomic
file replace capability |
| #4131 | [Types] Add lossless conversion between WoT documents and
NodeSet2 |
| #4132 | [SourceGeneration] Improve NodeSet to ModelDesign conversion
and generated node state |
| #4134 | [SourceGeneration] Generate OPC UA models from WoT Thing
Description files |
| #4147 | [Server] Add live NodeManager shadow and immediate reload |
| #4150 | [Server] Make subscription transfer between sessions
transactional |
| #4130 | [XRegistry] Allow clients to use explicit registry roots |
| #4139 | [WotCon] Add the WoT Connectivity 1.1 information model |
| #4140 | [WotCon] Add the WoT protocol binding abstractions and
planners |
| #4144 | [WotCon] Add the HTTP, Modbus, OPC UA and MQTT binding
executors |
| #4146 | [WotCon] Add the WoT Connectivity registry and its stores |
| #4142 | [WotCon] Add the WoT Connectivity registry client |
| #4154 | [WotCon] Materialize WoT Thing Descriptions into the server
address space |
| #4156 | [WotCon] Add the WoT Connectivity samples and complete the
documentation |
| #4171 | Restore WoT asset registry bridge |
| #4172 | Restore WoT coverage and docs |

Supersedes #4093.

## Follow-up

The WoT Connectivity and WoT Binding drafts have moved to 1.1-draft2
since this work was authored. Aligning with that revision - the removed
group vocabulary, the new projection/View construct, the remaining model
vocabulary terms and the two new portable-identity validation rules - is
tracked separately and will follow in its own pull request.

## Validation

Built for every target framework with zero warnings and zero errors, and
validated at the tip of the stack with `Opc.Ua.WotCon.Tests` at 999
passed / 0 failed and `Opc.Ua.Server.Tests` at 4024 passed / 0 failed.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready Ready to merge once CI Passes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants