# Description Fix the four blockers that prevented the OPC 10000-21 onboarding registrar and client from working end to end: - generate every `ModelDesign` target independently, including multiple models in one directory, while preserving stable identifier CSV matching and cross-model dependencies; - ship the generated `Opc.Ua.Onboarding` constants, node states, encodeables, and typed clients from `Opc.Ua.Gds.Common`; - correct the standard `EncodedTicket` datatype to derive from `ByteString`; - align the new 2.0 `OnboardingClient` API with the generated `ArrayOf<ByteString>` / `ArrayOf<StatusCode>` contract; - make `BindToTicketStore` fully asynchronous, cancellation-aware, and assign the declared output slot instead of appending a second output; - add generated-model, client fallback, server binding, and in-process end-to-end regressions. The change also adds `samples/Gds/OnboardingRegistrar`, `samples/Gds/OnboardingClient`, and `run-onboarding-demo.ps1`. The demo loads the generated GDS and Onboarding models, restricts ticket administration to an ephemeral `RegistrarAdmin` user, proves anonymous access is denied, and completes a secure register/unregister round trip. The History CI follow-up rejects negative and non-finite processed-history intervals before provider dispatch and enforces the buffered aggregate output cap while calculator results are flushed. This prevents malformed requests from running until the client timeout, exhausting memory, delaying server teardown, and causing later alarm-event tests to fail. ## Related Issues - Fixes #4378 - Unblocks OPCFoundation/UA-.NETStandard-Samples#819 - Tracks the canonical model correction in OPCFoundation/UA-Nodeset#122 ## Validation - Full `net10.0` test projects: - `Opc.Ua.SourceGeneration.Core.Tests`: 3803 passed, 8 skipped - `Opc.Ua.SourceGeneration.Tests`: 143 passed - `Opc.Ua.Gds.Tests`: 1114 passed, 42 skipped - `Opc.Ua.History.Tests` with the CI coverage settings: 506 passed, 27 skipped - `HistorianDispatcher` tests: 88 passed on `net10.0`. - Invalid processed-history interval regressions passed on `net10.0` and `net48`. - Focused onboarding/source-generation regressions passed on `net48`. - `dotnet build UA.slnx -p:CustomTestTarget=net10.0 --no-restore` succeeded; the reported analyzer warnings are pre-existing in unchanged XRegistry/WoT files. - Packed all three GDS packages and verified the packaged `Opc.Ua.Gds.Common` assembly contains the generated Onboarding model surface. - `pwsh samples/Gds/run-onboarding-demo.ps1` verified anonymous denial and the authenticated secure ticket lifecycle. ## 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. - [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. - [x] I have addressed **all** PR feedback received. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 2d2c52c7-7040-4bd6-98de-aaf82ba7846b
3.4 KiB
OPC 10000-21 Onboarding Demo
This sample demonstrates the registrar-administration part of OPC 10000-21 end to end over a real OPC UA connection. It uses only the model and runtime APIs shipped by this repository:
OnboardingRegistrarloads the generatedOpc.Ua.Onboardingmodel, exposes the standardDeviceRegistrar_Administrationobject, and bindsRegisterTickets/UnregisterTicketsto an injectedMemoryTicketStore.OnboardingClientconnects with a managed session, resolves the well-known registrar NodeId, and uses the DI-providedOpc.Ua.Gds.Client.OnboardingClient.run-onboarding-demo.ps1builds both applications, waits until the OPC UA server reaches its running state, proves an anonymous caller is denied, runs the authenticated client, and stops the exact registrar process in afinallyblock.
The demo covers ticket administration. It does not implement the
device-facing ProvideIdentities flow or a complete production GDS.
Run the complete demo
From the repository root:
pwsh samples/Gds/run-onboarding-demo.ps1
The script uses
opc.tcp://localhost:62560/OnboardingRegistrar by default. Select a
different port with:
pwsh samples/Gds/run-onboarding-demo.ps1 -Port 62660
Successful output ends with:
REGISTER Good Good
UNREGISTER Good
UNREGISTER_AGAIN BadNotFound
ONBOARDING_DEMO_OK
Pass -Keep to retain the temporary PKI stores and registrar logs for
diagnostics.
Run the applications manually
Start the registrar:
dotnet run --project samples/Gds/OnboardingRegistrar -f net10.0 -- `
--port 62560 `
--pkiRoot "$env:TEMP\opcua-onboarding-registrar"
After ONBOARDING_REGISTRAR_READY is printed, run the client:
dotnet run --project samples/Gds/OnboardingClient -f net10.0 -- `
--endpoint "opc.tcp://localhost:62560/OnboardingRegistrar" `
--pkiRoot "$env:TEMP\opcua-onboarding-client"
Wire contract
The client API uses the Part 21 types directly:
ArrayOf<StatusCode> results = await onboarding.RegisterTicketsAsync(
[
new ByteString(firstTicket),
new ByteString(secondTicket)
]);
EncodedTicket is a subtype of ByteString. The server returns one
StatusCode for every supplied ticket.
Security
The demo selects SignAndEncrypt with Basic256Sha256. For a
self-contained local run, both applications automatically accept the
other application's newly created certificate and store it under an
isolated temporary PKI root. The script also generates a one-run random
username and password, grants that user the generated RegistrarAdmin
role, and restricts the two ticket methods to that role. The endpoint
also permits an anonymous bootstrap session because ManagedSession
activates its configured identity provider after creating the session;
anonymous users have no permission to call the registrar methods.
Automatic certificate acceptance is a sample-only convenience. A production registrar must use managed trust lists, authenticate and authorize registrar administrators, persist tickets in a protected store, and apply the audit/redaction requirements described in the GDS developer guide.
For a manual run, set ONBOARDING_DEMO_USER and
ONBOARDING_DEMO_PASSWORD to the same non-empty values in both
terminals before starting either application. Do not reuse demo
credentials in a production deployment.