mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-19 07:02:16 +08:00
ecc-testing-fixes
58 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0000513cde |
Pluggable user-identity provider model (#3807)
# Description Introduces a pluggable user-identity provider model covering all OPC UA Part 6 §6.5 mechanisms (Anonymous, UserName, X509, IssuedToken/JWT) on both client and server, with full `Microsoft.Extensions.DependencyInjection` integration, plus the Part 12 §9 `AuthorizationService` two-phase token-request flow **including refresh-token rotation**, the Part 12 §8 KeyCredential Push model, and a clean provider model for OPC 10000-12 §7.2 `ApplicationSelfAdmin`. The work is split across phase-by-phase commits so it can be reviewed independently; nothing here changes wire-level behaviour or forces existing applications to migrate. ### Documentation All under `Docs/`: - `IdentityProviders.md` — full developer guide: three-layer model, recipes, configuration reference, "what gets auto-wired" matrix, JWS algorithm table, identity-augmenters section, **"Implementing your own provider"** how-to subsections for Entra / OIDC / Windows / AspNetCore (sibling files merged in per review feedback). - `DependencyInjection.md` — `Identity` sections with `appsettings.json` examples, identity-extension matrix, `WithAuthorizationService` + `WithKeyCredentialPush` + `AddIdentityAugmenter` extensions documented. - `RoleBasedUserManagement.md` — claim-criteria callout describing `IIdentityClaims` probe surface. - `AuthorizationService.md` — Architecture diagram + `IAccessTokenProvider` conceptual narrative restored from master; modern `StartRequestToken` / `FinishRequestToken` flow leads; refresh-token recipe added. - `KeyCredentialService.md` — Push model + Pull vs Push vs Bridge decision matrix + Hybrid (Push + Pull) section; explicit experimental warning for the bridge. - `GDS.md` — KeyCredential Push, `StartRequestToken`, `GdsApplicationSelfAdminProvider`, **shipped Refresh-token support with rotation policy and audit semantics** all documented. - `MigrationGuide.md` — User Identity Providers section listing `[Obsolete]` markers + mechanical recipes; SelfAdmin migration via `IIdentityAugmenter`; `EnableRefreshTokens` default note. - `README.md` index entries. ## 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. - [x] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [x] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [x] I have addressed **all** PR feedback received. |
||
|
|
5ff968fcfb |
Test project reorganization follow up (#3810)
### Test project reorganization
Splits the integration- vs unit-test boundary along **project
boundaries**
and introduces a runtime-tier split for subscription tests so the
mainline
CI no longer drags in stress / durable suites.
**New projects:**
- `Opc.Ua.Stress.Tests` ΓÇö cross-area stress tier (designed to
absorb
session / channel / pub-sub stress in future). Seeded with the 6
subscription stress classes (`SubscriptionDepthTests`,
`SubscriptionBasicDepthTests`, `MonitoredItemDepthTests`,
`SubscriptionTransferDepthTests`, `SubscriptionPublishTooManyTests`,
`SubscriptionMultipleTests`). **Excluded from mainline CI; runs
nightly.**
- `Opc.Ua.Subscriptions.Durable.Tests` ΓÇö durable-subscription tier
(needs `DurableSubscriptionsEnabled` + storage-backed lifetime).
Receives `SubscriptionDurableTests` plus the migrated
`DurableSubscriptionTest` and `DurableSubscriptionTestDebug`.
**Excluded from mainline CI; runs nightly.**
- `Opc.Ua.Features.Tests` ΓÇö cross-feature integration tier.
Receives the
`[OneTimeSetUp]`-bootstraps-its-own-server integrations for AliasNames
(Part 17), Roles (Part 18), FileSystem (Part 5 §C / Part 20), and
NodeCache. Also absorbs the misplaced
`Tests/Opc.Ua.History.Tests/FileSystemTests.cs`.
**Client.Tests cleanup (~28 files moved):**
- `Opc.Ua.Sessions.Tests` (existing) gains 10 session integration files
plus the 4 session benchmark files inline (`LoadTest`,
`RequestHeaderTest`, `TraceableRequestHeaderTest`,
`SecurityPolicyBenchmarks`).
- `Opc.Ua.Subscriptions.Tests` (existing) gains 4 subscription
integration files plus `PooledNotificationBenchmarks` inline.
- `Opc.Ua.Client.ComplexTypes.Tests` (existing) gains all
`ComplexTypes/*` integration files. The Client.Tests copy of
`TypeSystemClientTest.cs` (a stale near-duplicate) is removed.
- Benchmarks **stay inline** as `[Test]` + BenchmarkDotNet dual-use; no
new benchmark project (per the approved plan).
**CI pipeline:**
- `.azurepipelines/test.yml` now filters
`TestCategory!=LongRunning&TestCategory!=Stress` on the mainline run.
- `-ExcludeFileName` now accepts a comma-separated list. The mainline
matrix excludes the 3 nightly-tier project files alongside the
existing `Opc.Ua.Aot.Tests.csproj`.
- `get-matrix.ps1` enhanced to support multi-pattern excludes.
`InternalsVisibleTo` extended on `Opc.Ua.Client` and `Opc.Ua.Server` to
grant the new test projects access. All affected projects build clean
(`0 Error`) for `net10.0`.
### Fix 8 skipped tests flagged as suspected bugs
Triage of every `[Ignore]` / `[Explicit]` test in `Tests/**` surfaced 8
entries labelled as suspected production bugs. After inspection:
- **1 real production bug** ΓÇö the
`CancellationTokenSource.CancelAsync`
polyfill for netstandard2.0 / netfx was running cancellation callbacks
inline on the caller's thread, deadlocking dispose paths
(`SubscriptionManager.DisposeAsync`, etc.) when a callback awaits on
the caller's `SynchronizationContext`. Fixed at the polyfill root by
hoisting `Cancel()` onto the ThreadPool via `Task.Run`, matching real
.NET 8+ semantics. Caveat (deferred `IsCancellationRequested`
transition) documented inline; all in-repo callers use
`await cts.CancelAsync()` so the deviation is invisible. Test
`DrainAsyncWaitsForInFlightPublishToCompleteAsync` un-ignored ΓÇö
verified passes on net48 (943 ms) and net10.0 (1 s).
- **2 flaky tests stabilized** ΓÇö both
`ValidateMetaDataUpdateTimeNonZeroIsSentPeriodically` (MQTT JSON &
UADP) now use `Stopwatch.GetTimestamp()` instead of `DateTime.Now`,
compute deviation against the **median** interval (not the configured
cadence, so a startup hiccup doesn't skew the run), and use a
proportional `max(interval / 4, 50 ms)` tolerance. `[Ignore]` removed,
`[Category("LongRunning")]` retained.
- **1 mis-labelled "bug"** ΓÇö
`UnorderedMessagesWouldBeLostForSequentialPublishingAsync` asserts the
*documented* lossy trade-off of strict sequential publishing.
`[Explicit]`
removed and renamed to
`OldMessagesAbandonedAfterRepublishTimeoutInSequentialModeAsync`; it's
now a CI-verified regression test for the WAI behavior.
- **4 false positives** ΓÇö `JsonEncoderTestsOld.cs` (16 kLOC) was
excluded from compilation via `<Compile Remove>` and never reached the
runner. The 4 `[Ignore("ProductionBugSuspected")]` markers inside were
orphaned source from a previous JsonEncoder API. Active coverage lives
in `JsonEncoderTests.cs` and `JsonValidationData` fixtures. Deleted
the orphan file and the now-redundant `<Compile Remove>` line.
|
||
|
|
e49d17d706 |
[Server] Make MonitoredNode aware of IAsyncNodeManager and introduce channel-based queueing under load (#3804)
## Proposed changes This PR updates the server monitored-item pipeline to be `IAsyncNodeManager`-aware and introduces channel-based FIFO queueing in the monitored-node path to improve behavior under load. It also includes follow-up fixes from review/CI feedback: - Adjusted `AsyncCustomNodeManagerTests.WriteAsync_PublishesValueToMonitoredItemQueueAsync` to account for channel-based delivery timing/coalescing while still asserting the written value is observed. - Merged latest `master` into this branch and resolved merge conflicts (notably in `ConfigurationNodeManager`), keeping async address-space lookup behavior intact. - Applied small compile-safety corrections needed for successful validation. |
||
|
|
6db9a67a0a |
Fix TypeInfo.Construct for generic encodeable (#3802)
Prioritize the encodeable check over the enumerable check in `TypeInfo.Construct(Type type)` to prevent representing a generic type that implements `IEncodeable` as `TypeInfo.Unknown`. Fixes #3800 Somewhat related to #3597 --------- Co-authored-by: Marc Schier <marcschier@users.noreply.github.com> Co-authored-by: Marc Schier <marcschier@hotmail.com> |
||
|
|
eb40a59566 |
More format and diagnostic fixes (#3780)
Drive the solution to zero warnings / zero errors with analyzers on, promote the consistently-fixed rules to error, and lock in coverage on the only line of new logic. |
||
|
|
889572472f |
Convert DataValue from class to readonly struct for further GC relief (#3796)
Convert `DataValue` from a mutable reference type (`class`) to a `readonly struct` to eliminate per-allocation GC pressure on every attribute read, subscription publish, and history sample. ### Key API changes (user-visible) | Before | After | Pattern | |---|---|---| | `class DataValue` | `readonly struct DataValue : INullable` | Foundation | | `Equals(DataValue?)` / `operator ==(DataValue?, DataValue?)` | `Equals(DataValue)` / `operator ==(DataValue, DataValue)` | Value semantics | | `IEncoder.WriteDataValue(string?, DataValue?)` | `IEncoder.WriteDataValue(string?, DataValue)` | Non-nullable wire API | | `IDecoder.ReadDataValue(...) -> DataValue?` | `IDecoder.ReadDataValue(...) -> DataValue` | Same | | `IDataChangeMonitoredItemQueue.PeekLast/Oldest()` | `TryPeekLastValue/Oldest(out DataValue)` | TryGet pattern | | `IAggregateCalculator.GetProcessedValue(bool)` | `TryGetProcessedValue(bool, out DataValue)` | Same | | `IUaPubSubDataStore.ReadPublishedDataItem(...)` | `TryReadPublishedDataItem(NodeId, uint, out DataValue)` | Same | | `Dictionary<uint, DataValue?>` (NodeCacheContext) | `Dictionary<uint, DataValue>` | Default + IsNull | | `IHistoryDataSource.FirstRaw/NextRaw` | `TryFirstRaw/TryNextRaw(out DataValue)` | TryGet pattern | | `NodeState.ReadAttribute(... DataValue)` | `NodeState.ReadAttribute(... ref DataValue)` | Sync mutation via ref | | `NodeState.ReadAttributeAsync(... DataValue)` | `NodeState.ReadAttributeAsync(...) -> ValueTask<(ServiceResult, DataValue)>` | Async return tuple | | `obj as DataValue` (heterogeneous Dictionary<string, object>) | `obj is DataValue dv ? dv : default(DataValue)` | Safe struct cast | | `Assert.That(dv, Is.Not.Null)` (tests) | `Assert.That(dv.IsNull, Is.False)` | Struct test pattern | | `[Obsolete] Value` setter, all property setters | Removed; use ctor or `With*()` | Immutability | | `[DataContract]` + `[DataMember]` | Removed; surrogate via `SerializableDataValue` + `DataValueSurrogateProvider` | Serialization | ### Wire format Wire format is **byte-identical** to the previous class-based implementation across binary / JSON / XML encoders. Default DataValue (`.IsNull == true`) is treated as the equivalent of the old null reference (writes JSON `null`, binary `byte 0`, XML omitted element). ### Why TryGet pattern (instead of leaving `DataValue?`) For methods that previously returned `DataValue?` to signal "no value available" (queue peek, aggregate result, data store lookup, history navigation), the conversion to `bool TryGet(out DataValue)` matches BCL conventions (`Dictionary.TryGetValue`, `Queue.TryPeek`, `Int32.TryParse`) and gives the caller an explicit "may be absent" affordance without `Nullable<DataValue>` overhead. ### Breaking changes summary - `DataValue` is now a `readonly struct` - boxing/unboxing semantics change for callers using `object`-typed APIs. - `IEncoder.WriteDataValue` / `IDecoder.ReadDataValue` / `ReadDataValueArray` interface signatures lose the `Nullable` wrapper. - `IDataChangeMonitoredItemQueue.PeekLastValue` / `PeekOldestValue` -> `TryPeekLastValue` / `TryPeekOldestValue` (out parameter). - `IAggregateCalculator.GetProcessedValue` -> `TryGetProcessedValue` (out parameter). - `IUaPubSubDataStore.ReadPublishedDataItem` -> `TryReadPublishedDataItem` (out parameter). - `NodeState.ReadAttribute` takes `ref DataValue`; `ReadAttributeAsync` returns `ValueTask<(ServiceResult, DataValue)>`. - `DataValue` property setters removed (use constructor + `With*` mutators). |
||
|
|
239a40b183 |
GC reduction via IPooledEncodeable activator pooling (#3793)
* GC reduction via IPooledEncodeable activator pooling
Add opt-in activator-level pooling for IEncodeable instances decoded
during V2 subscription publish dispatch. The design replaces the
earlier IAllocator-on-IServiceMessageContext approach (which had a
cross-contamination hazard for non-publish decodes) with a clean
factory-based model where pooling lives on the encodeable activator.
New public API:
- IPooledEncodeable : IEncodeable - opt-in marker with Reuse() method
- PooledEncodeableType<T> : EncodeableType<T> - activator base with
BoundedObjectPool<T> (lock-free, no new package dependency)
- ISubscriptionManager.PoolNotifications { get; set; }
- ManagedSessionOptions.PoolNotifications { get; init; }
- ManagedSessionBuilder.WithPoolNotifications(bool)
Source-gen:
- All concrete non-abstract structure types (including service
request/response types) are generated with PooledEncodeableType<T>
activators and IPooledEncodeable.Reuse() bodies by default
- Derived types use 'new' to hide inherited Reuse/ClearPooledSentinel
so each concrete type routes through its own activator's pool
- No changes to external design XML files (UA Core Services.xml etc.)
- poolable selection is hardcoded in the generator
Benchmarks (MonitoredItemNotification, 1000 ops):
- Allocations: 128 KB -> 408 B (~315x reduction)
- Gen0 collections: 29.75 -> 0.09 per 1000 ops
No interface changes to IEncodeable, IDecoder, IServiceMessageContext,
or ISubscriptionNotificationHandler. Handlers retain by copy when
pooling is enabled.
Call IPooledEncodeable.Reuse() on decoded IServiceRequest and
IServiceResponse after the server is done with them:
- TcpTransportListener.OnRequestReceivedAsync: reuse both request
and response in a finally block after ProcessRequestAsync +
SendResponse complete
- EndpointBase.InvokeServiceAsync (HTTPS path): same pattern after
ProcessRequestAsync + BinaryEncoder.EncodeMessage
Walk acknowledged, overflow-evicted, and disposed NotificationMessage
objects and call IPooledEncodeable.Reuse() on their notification
payloads (MonitoredItemNotification, DataChangeNotification,
EventFieldList, EventNotificationList).
Insertion points in Subscription.cs:
- Acknowledge(): after RemoveAt from m_sentMessages
- InnerPublish() overflow: before RemoveRange/Clear on m_sentMessages
- Dispose(): before m_sentMessages.Clear()
- InnerPublish() unsent-message overflow: before RemoveRange on
the messages list
Replace new T() with XxxActivator.Instance.CreateInstance() for all
server-side notification payload types so instances are rented from
the activator pool instead of heap-allocated:
New static helper ReuseNotificationPayloads() walks the
NotificationMessage.NotificationData, extracts DataChangeNotification
and EventNotificationList via TryGetValue, iterates their items, and
calls Reuse() on each pooled payload.
|
||
|
|
df2425540d |
Fix/extension object preserve encoding typeid (#3761)
* fix: preserve wire encoding TypeId in ExtensionObject on decode BinaryDecoder, JsonDecoder, and XmlDecoder were overwriting ExtensionObject.TypeId with the DataType NodeId (e.g., i=887) instead of preserving the encoding NodeId from the wire (e.g., i=889). Use ExtensionObject(typeId, encodeable) to retain the original encoding NodeId per OPC 10000-6 §5.2.2.15. * fix: preserve encoding TypeId for XML-in-binary body path * Preserve TypeId in ExtensionObject decoding tests. Exisitng tet used in XmlDecoderTests. Introduced a test encodeable with distinct TypeId and BinaryEncodingId for validation. * ExpandedNodeId used in CreateExtensionObject for tests * copy parameter comment added * fix: JsonEncoder must write DataType NodeId per OPC UA Part 6 §5.4.2.16 Per §5.4.2.16, the UaTypeId field in JSON encoding must be the NodeId of a DataType Node, not a DataTypeEncoding Node. Previously, the JsonEncoder used ExtensionObject.TypeId directly, which after the decoder fix to preserve encoding TypeIds could contain a Binary or XML encoding NodeId when re-encoding from another format. Changed WriteExtensionObject to use encodeable.TypeId (the DataType NodeId) when the body is IEncodeable, falling back to value.TypeId only for raw bodies (ByteString, string) where no IEncodeable is available. This ensures correct cross-encoding behavior (e.g., XML→JSON or Binary→JSON) where the ExtensionObject carries an encoding-specific TypeId from the source format but must emit the DataType NodeId in JSON. * Fix nullable encodeable handling in JsonEncoder --------- Co-authored-by: Marc Schier <marcschier@users.noreply.github.com> Co-authored-by: romanett <romanett98@gmail.com> |
||
|
|
10c67fcccd |
Relax ExtensionObject equality to match across encoding ids (#3777)
An IEncodeable exposes three distinct node ids (TypeId, BinaryEncodingId, XmlEncodingId) that all identify the same logical data type. Depending on the encoder that produced an ExtensionObject (binary, XML, JSON, or direct construction), the wrapper TypeId may carry any one of those three ids, so two ExtensionObjects wrapping the same encodeable value can compare as unequal under the strict TypeId check. Relax Equals(ExtensionObject) so the incoming TypeId on either side may match any of the inner IEncodeable's three node ids; strict TypeId equality is still required when neither side has an IEncodeable body. Update GetHashCode to use the encodeable's canonical TypeId so equal values continue to share a hash. Add unit tests covering matches against each of the three ids, cross-encoding-id match (Binary <-> Xml), body inequality, unrelated TypeId+body, strict equality for ByteString / string bodies, hash stability, == / != operators, and symmetry. |
||
|
|
f3d3fd87d3 |
Reorganize Stack/ folder layout (#3775)
Two refactors that together reshape how the stack tier is laid out:
1. Rename `Opc.Ua` project to `Opc.Ua.Core.Types`
* Stack/Opc.Ua/ -> Stack/Opc.Ua.Core.Types/ (git mv preserves history)
* Opc.Ua.csproj -> Opc.Ua.Core.Types.csproj
* AssemblyName : `Opc.Ua` -> `Opc.Ua.Core.Types`
* PackageId : `OPCFoundation.NetStandard.Opc.Ua` ->
`OPCFoundation.NetStandard.Opc.Ua.Core.Types`
* RootNamespace : kept as `Opc.Ua`
* StackGeneration.cs assembly-name switch updated; the renamed
assembly still produces `StackGenerationType.Models`.
* The `OPCFoundation.NetStandard.Opc.Ua` name now belongs solely to
the roll-up meta-package (nuget/Opc.Ua.nuspec); the meta-package's
former self-dependency is replaced with the new
`.Core.Types` package, and `.Symbols.nuspec` gains the
matching `.Core.Types.Debug` debug-symbol dependency.
2. Move `Opc.Ua.Security.Certificates` from Libraries/ to Stack/
It is a stack-tier dependency consumed by Opc.Ua.Core, not a
higher-level library extension, so it now sits alongside the other
stack projects.
Both refactors update the same set of cross-cutting infrastructure:
- UA.slnx, UA Core Library.slnx, Applications/ConsoleReferenceServer/Dockerfile
- .azurepipelines/signlist{Debug,Release}.txt
- ProjectReferences across Stack/, Libraries/, Tests/, Fuzzing/
- Tests/Opc.Ua.SourceGeneration.Stack.Tests/StackGenerationAssemblyTests.cs
- Docs/PlatformBuild.md and .github/copilot-instructions.md (new
Core.Types package listed)
Verification
* dotnet build UA.slnx -c Debug -- succeeded, 0 errors
* StackGenerationAssemblyTests : 5 passed
* Opc.Ua.SourceGeneration.Tests : 40 passed
* Opc.Ua.SourceGeneration.Core.Tests : 3514 passed, 8 skipped
* Opc.Ua.Core.Tests (Stack filter) : 1982 passed, 80 skipped
* Opc.Ua.Security.Certificates.Tests : 239 passed
|
||
|
|
5edb512ab7 |
Stricter validation and error handling in GDS server & Server Method Call validation (#3746)
* Stricter validation and error handling in GDS server - Allow empty DatabaseStorePath for in-memory operation - Select database type dynamically in GdsNodeManagerFactory - Enforce required fields and argument validation in ApplicationsDatabaseBase - Prevent duplicate application URIs in LinqApplicationsDatabase - Propagate argument errors as OPC UA service exceptions in ApplicationsNodeManager - Remove obsolete attribute from ParsedNodeId - Refactor MasterNodeManager write/call validation to async with improved permission checks and attribute caching - Update UAReferenceServer.ctt.xml test data with non-empty credentials - Improves robustness, security, error reporting, and test coverage * Add method-state resolver API for call validation and tests Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/0caf8699-f0e0-4dd5-8dcf-368b08912205 Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Refine call validation comments and test coverage naming Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/0caf8699-f0e0-4dd5-8dcf-368b08912205 Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Move method resolver onto core NodeManager interfaces Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/0bb87dfd-f432-431f-a0fe-dd4d1ba3197f Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Align NodeManager interfaces and call paths for method resolver Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/0bb87dfd-f432-431f-a0fe-dd4d1ba3197f Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * fixes * fix * Fix GDS ClientTest expectations for stricter app validation Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/47d99514-94f9-4051-9e6d-8cb2b44555d0 Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * fix tests * Fix AOT GDS fixture for RSA secured endpoint Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/f6c8fba1-3dbf-41f0-b920-5e1766b9d6e1 Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Update app registration logic and audit event sources Refactor application registration to separate update and create logic, introducing UpdateApplication in database interfaces and implementations. Improve error handling and validation, ensure unique ApplicationUris, and enhance certificate revocation logging. Standardize audit event source names and add ToString override to BaseVariableState. Update server queries for correct pagination. * fixes * Add wildcard match coverage for ApplicationsDatabaseBase Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/a2c1a6b0-e867-4610-bead-7e621e3764ff Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Expand wildcard spec coverage in ApplicationsDatabaseBase tests Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/a2c1a6b0-e867-4610-bead-7e621e3764ff Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Align UA wildcard matching and add spec coverage tests Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/a2c1a6b0-e867-4610-bead-7e621e3764ff Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Fix GDS QueryServers test expectations for pagination semantics Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/efa1c64d-05c8-47ee-b308-c77e7d5a34c9 Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Add focused tests for LinqApplicationsDatabase behaviors Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/7e4ec1ce-722f-43fb-99db-06b854c3fa7a Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Refine LinqApplicationsDatabase test method naming Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/7e4ec1ce-722f-43fb-99db-06b854c3fa7a Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Merge origin/master and resolve PR merge conflicts Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/69970cd4-4196-4fb4-9e4c-6ad86104bb5f Co-authored-by: marcschier <11168470+marcschier@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> Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> |
||
|
|
3e5f129c6f | Enable nullable in Stack, Libraries (9), and Applications projects (#3732) | ||
|
|
5795e50b58 |
Source-generated, NativeAOT-clean fluent server API with event-source publish (#3765)
* Add async read/write hooks to BaseVariableState and AsyncCustomNodeManager
Introduces an end-to-end async path for variable Value-attribute reads
and writes that does not require holding lock(this) while the user
callback executes:
* New AttributeReadResult, AttributeSimpleReadResult and AttributeWriteResult
readonly record structs in NodeState carry the typed result of an async
Value-attribute hook (no ref/out params across await).
* Four new async delegates (NodeValueEventHandlerAsync,
NodeValueSimpleEventHandlerAsync, NodeValueWriteEventHandlerAsync,
NodeValueSimpleWriteEventHandlerAsync) sit alongside the existing sync
hooks.
* NodeState gains virtual ReadAttributeAsync / WriteAttributeAsync methods.
The default implementation wraps the synchronous call in lock(this) so
callers that have not opted into async hooks see bit-identical behaviour.
* BaseVariableState exposes OnReadValueAsync, OnSimpleReadValueAsync,
OnWriteValueAsync and OnSimpleWriteValueAsync slots and overrides the new
virtuals to dispatch to them WITHOUT holding the lock during the await.
On simple-read the framework still applies index range, data encoding and
copy policy; on simple-write the cached value/status/timestamp are
updated under lock after the hook completes.
* AsyncCustomNodeManager.ReadAsync and WriteAsync now await the new
ReadAttributeAsync / WriteAttributeAsync entry points instead of taking
lock(source) around the synchronous call. Existing per-source locking
semantics are preserved by the default async wrappers.
* The fluent INodeBuilder surface gains four new async OnRead/OnWrite
overloads that wire to the new BaseVariableState slots, with the same
ThrowIfSlotOccupied + null-check pattern as the sync overloads.
* Add typed IVariableBuilder<T> fluent surface
Adds typed sub-interfaces and impls so the existing fluent surface
can expose simple Func<T> / Action<T> / Func<CancellationToken,
ValueTask<T>> overloads for variables — without losing the lower-level
Variant-based overloads on INodeBuilder.
* IVariableBuilder<TValue> + VariableBuilder<TValue> derive from
INodeBuilder<BaseVariableState> / NodeBuilder<BaseVariableState>
(NodeBuilder<TState> unsealed).
* Marshalling uses Variant.AsBoxedObject(BoxingBehavior.Legacy) for
reads and Variant(object) for writes; the AOT-unsafe write path is
scoped-suppressed with a TODO pointing at the planned per-type
generated walker.
* INodeManagerBuilder gains Variable<T>(string),
Variable<T>(NodeId), VariableFromTypeId<T>(NodeId),
VariableFromTypeId<T>(NodeId, QualifiedName).
Server library builds clean across all 6 TFMs.
* Add relative-child traversal API on INodeBuilder
Adds INodeBuilder.Child(QualifiedName), Child<TState>(QualifiedName)
and Variable<TValue>(QualifiedName) so source-generated typed
wrappers can walk one segment at a time without re-resolving from
the manager root. Resolution uses NodeState.FindChild and reuses
NodeManagerBuilder.ToVariableBuilder to keep the typed-variable
marshalling story consistent.
Adds 7 NUnit cases (Fluent category) covering the happy path,
type-mismatch, null/missing browse-name, and non-variable
rejection. All 66 fluent tests pass.
* Mix old + new fluent APIs in MinimalBoilerServer demo
BoilerNodeManager.Configure now exercises five wiring styles:
(1) browse-path with the legacy ref-Variant callback
(2) absolute NodeId with the legacy ref-Variant callback
(3) typed Variable<double>(NodeId) + simple Func<double> sync getter
(4) typed Variable<double>(NodeId) + Func<CancellationToken, ValueTask<double>>
async getter — exercises the BaseVariableState.OnReadValueAsync
slot end-to-end through AsyncCustomNodeManager.ReadAsync
(5) NodeFromTypeId with OnNodeAdded lifecycle hook
All five styles compose against the same INodeManagerBuilder, with
the typed and async callbacks pulling in the new IVariableBuilder<T>
surface (committed at
|
||
|
|
46db94467a | Fix string Contains polyfills to honor StringComparison parameter (#3751) | ||
|
|
70b4498db8 |
Certificate manager and ref counted certificate type (#3688)
* New certificate and secrete abstraction with certificate infrastructure and certificate/secret stores. * leak testing for certificate resources to validate new ref counting in every test assembly * Migration guide updated and documentation added for all * Remove IDisposable from Nodestate and UserIdentity. * UserCertificateTokenHandler now just points into certificate registry/stores, no dispose required * Fix CA2000 warnings and cleanup of other diagnostics, increase warning levels in .editorconfig |
||
|
|
bd4543e961 |
ManagedSession, Pluggable Subscription engine, and fluent builder + DI (#3730)
- Add new managed session, wrapping session and providing connection management and failover handling - Add new Subscription engine that can act as alternative to current engine, but is based on channels with worker tasks - Add a fluent builder for managed session clients - Replace NodeCache with LruNodeCache, rename ILruNodeCache and LruNodeCache to INodeCache and NodeCache - Update migration guide and document new functionality. |
||
|
|
54cc3d88b1 | Prepare for C# 15 union types: UnionAttribute polyfill, TryGetValue rename, HasValue (#3727) | ||
|
|
b2cbf6b03b |
Fix DataValue(int) overload resolution bug (#3721)
new DataValue(42) silently resolved to DataValue(StatusCode) instead of DataValue(Variant) due to C# 'better conversion target' rule — StatusCode wins because it implicitly converts to Variant, making it 'more specific'. This caused m_value = Variant.Null and downstream BadTypeMismatch failures. Changes: - Add [OverloadResolutionPriority(1)] on DataValue(Variant) constructor - Obsolete DataValue(StatusCode) and DataValue(StatusCode, DateTimeUtc) - Add DataValue.FromStatusCode() static factory methods (2 overloads) - Delete DataValue(DataValue) copy constructor - Add DataValue.Copy() instance method using base.MemberwiseClone() - Rewrite Clone()/MemberwiseClone() to delegate to Copy() - Migrate all call sites across 14 files - Add tests verifying new DataValue(42) wraps value correctly - Update MigrationGuide.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
70abb05841 |
Remove Default JSON encoding infrastructure (#3713)
* Remove Default JSON encoding infrastructure Remove IJsonEncodeable interface, JsonEncodingId properties, DefaultJson constants, and all source generator JSON encoding output. The actual JsonEncoder/JsonDecoder and PubSub JSON encoding are not affected. - Delete IJsonEncodeable interface from IEncodable.cs - Remove DataTypeAttribute.JsonEncodingId and simplify TryGetTypeIdsFromType - Remove JSON encoding from 9 source generator files - Remove IJsonEncodeable from 13 built-in types and 12 node types - Remove JSON registration from EncodeableFactory and unboundTypeIds infra - Remove jsonEncodingId from OptionSet, ComplexTypeSystem, IComplexTypeFactory - Remove BrowseNames.DefaultJson and 25 *_Encoding_DefaultJson constants - Update ~14 test files and 2 documentation files Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add IJsonEncodeable removal to migration guide Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * minor --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
f23fac928a |
fix status code equals (#3711)
* fix status code equals * add tests verifying StatusCode equality fix: full code comparison including flags Agent-Logs-Url: https://github.com/OPCFoundation/UA-.NETStandard/sessions/8159cd97-f318-4a35-9dfe-663b2f6f4c0e 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> |
||
|
|
94bc03b9f6 |
fix address space issues (#3705)
* fix missing mandatory children * Source generator: fix encoding nodes, EventNotifier, and type RBAC - Emit DataType encoding nodes (Default Binary/XML/JSON) into the generated address space. CollectEncodingNodes() discovers DataTypeEncodingType instances and builds synthetic hierarchies with their HasEncoding/HasDescription references. - Auto-set EventNotifier=SubscribeToEvents on Object nodes that have forward HasEventSource or HasNotifier references. The fix works at two levels: ModelDesignValidator infers SupportsEvents on types with event references in design XML, and NodeStateGenerator checks the resolved reference set for merged instances that inherit references from their type definitions. - Wrap AccessRestrictions/RolePermissions in if(forInstance) guards for ObjectType, VariableType, DataType, and ReferenceType templates so type definition nodes remain accessible to all users. - Allow ModellingRule=None Object children on type definitions to be emitted (e.g. state machine states/transitions). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update missing nodes analysis after source generator fixes Retest with admin credentials against ConsoleReferenceServer v1.05.07. Categorize 794 truly missing nodes (after filtering optional/placeholder): - 384 encoding nodes (NodeSet2.xml-only, not in design XML) - 172 role instance children - 84 other nodes - Remaining: trust list, PubSub, diagnostics, etc. RBAC and EventNotifier fixes confirmed working. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update * plans: detailed analysis of 292 remaining missing nodes Replaced the two previous analysis files with a single consolidated validation report. Each of the 292 nodes is classified with a reason: - 212 type-level children (ObjectType definitions not instantiated) - 48 instance-level children (diagnostics, HA, FileSystem, PubSub) - 32 orphan property templates (design-time canonical definitions) Only 1 fix recommended: Server.Auditing (i=2994) should be exposed as false per Part 5 section 6.3.3. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: add GDS node manager to ConsoleReferenceServer Add Global Discovery Server functionality to the reference server: - Add Opc.Ua.Gds.Server.Common project reference - Add GdsNodeManagerFactory that creates ApplicationsNodeManager with JsonApplicationsDatabase and CertificateGroup (auto-approve) - Add GlobalDiscoveryServerConfiguration extension to config XML - Add GDS to ServerCapabilities - Registration is opt-in: only when config extension is present Also fix pre-existing source generator test failures: - Add missing CreateOrReplaceTransitionNumber stub method to StateMachineTransitionState in CompilerUtils.cs (8 tests fixed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: update missing nodes report with GDS retest results Retested after adding GDS node manager to ConsoleReferenceServer. Total missing reduced from 1325 to 1243 (82 fewer). 335 remaining 'other' nodes fully classified with per-node reasons. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: Server.Auditing is present (access-restricted, not missing) Live validation confirmed i=2994 exists with value=true, visible to admin users. Returns BadUserAccessDenied for anonymous. No fixes needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CttTestRunner build errors for v1.6 API and Jint 4.8.0 - Update System.CommandLine 2.0.7 API: SetHandler->SetAction, InvokeAsync->Parse().InvokeAsync() - Remove ObjectInstance inheritance from CttAssert, CttServiceRegister, CttIdentifierConstants, CttMonitoredItemHelper; use ToJsObject() factory methods instead - Replace Jint.Native.JsValueType with .IsObject()/.IsNumber()/.IsString() etc. - Add missing using directives (Jint.Runtime, Microsoft.Extensions.Logging, etc.) - Fix NodeId.Identifier obsolete -> TryGetIdentifier<uint> - Fix DataValue.Value obsolete -> WrappedValue.AsBoxedObject() - Fix ApplicationInstance() obsolete -> ApplicationInstance(ITelemetryContext) - Fix LoadApplicationConfiguration -> LoadApplicationConfigurationAsync - Fix CheckApplicationInstanceCertificate -> CheckApplicationInstanceCertificatesAsync - Fix CoreClientUtils.SelectEndpointAsync signature (requires telemetry param) - Fix DefaultSessionFactory() obsolete -> DefaultSessionFactory(ITelemetryContext) - Fix DiscoveryClient.Create -> DiscoveryClient.CreateAsync - Fix FindServers/GetEndpoints -> FindServersAsync/GetEndpointsAsync - Fix StatusCode to uint conversions - Fix ArrayOf<T> iteration (use foreach instead of LINQ on IConvertableToArray) - Fix XmlNodeList null coalescing in CttProjectSettings - Fix JsValue.False -> JsValue.FromObject(engine, false) - Add --json option to Program.cs for machine-readable output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: emit type-level children with ModellingRule=None for all node classes The source generator's GetChildren method only included ModellingRule=None children when they were ObjectDesign instances (state machine states/transitions). This excluded Variables and Methods that are explicitly defined on types without a modelling rule, such as: - ConditionType.ConditionRefresh (Method) - ConditionType.ConditionRefresh2 (Method) - ConditionType.SupportsFilteredRetain (Variable) - ProgramStateMachineType.Creatable (Variable) - Various TrueState/FalseState display-hint properties Remove the ObjectDesign restriction so all explicitly defined type-level children with ModellingRule=None are included in the generated address space. This adds ~52 previously missing nodes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: update report after ModellingRule=None generator fix Type-level children dropped from 261 to 203 (-58) after fixing the source generator to emit Variables and Methods with ModellingRule=None. Total 'other' reduced from 335 to 283. No fixes needed for any remaining nodes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: all 203 type-level children confirmed present via Read Verified all 203 'type-level children' exist in the server (none return BadNodeIdUnknown). They return Good, BadUserAccessDenied, or BadSecurityModeInsufficient -- all confirming the node exists but is access-restricted for anonymous users. All 1,316 export-missing nodes are now accounted for. Zero nodes are actually missing from the server address space. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CttTestRunner session service methods for CTT JS script compatibility - Implement ServiceCreateSession with real Session.CreateAsync connection - Implement ServiceActivateSession with proper response fields - Implement ServiceCloseSession with session cleanup - Fix UaSession constructor to provide service methods via CreateServiceObject - Convert all type constructors from ClrFunction to JS functions for 'new' support (Jint 4.x ClrFunction does not support [[Construct]]) - Add UaChannel.connect/disconnect stubs for OpenSecureChannel flow - Add UaDiscovery with getEndpoints/findServers from discovery session - Add missing types: UaSubscriptionDiagnosticsDataType, UaHistoryUpdateResult, etc. - Add missing enums: IdentifierType, Constants (DateTime/numeric limits) - Add UaPkiCertificate.fromDER, UaByteString.fromStringData, PkiType, UaPkiUtility - Add UaDateTime.Now constructor, equals/msecsTo methods - Add UaStatusCode with isGood/isBad/isUncertain as JS constructor - Fix response headers with Timestamp (UaDateTime), ServiceDiagnostics, StringTable - Fix endpoint descriptions with Server, UserIdentityTokens, ServerCertificate - Add CreateResponseHeader helper for consistent response header construction - Override warnOnce.js loggers to avoid Function.caller incompatibility - Add stopTest, checkResourceError (lowercase) global functions - Add UaOpcServer constructor with all method stubs - Handle JS parse errors in include() for malformed CTT files - Test.Connect() now calls InstanciateHelpers with DiscoverySession Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add CttTestRunner: .NET replacement for CTT JavaScript host environment Implements a Jint-based JavaScript engine that can execute the OPC Foundation's Compliance Test Tool .js test scripts using the OPC UA .NET Standard stack. Features: - Parses CTT .ctt.xml project files (Qt AbstractItemModelData format) - Loads and resolves CTT include() dependency chains (~100 library files) - Registers ~250 Ua* type constructors for JavaScript - Implements session.read/write/browse/getEndpoints/findServers - Provides all OPC UA enumerations, NodeId constants, Assert methods - CLI with --list, --file, --conformance-unit, --result, --json flags - Headless operation for agent/CI integration Current status: Framework connects to OPC UA server and loads CTT test infrastructure. Session establishment flow needs additional property compatibility for CreateSession/ActivateSession request objects. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: do not apply DefaultAccessRestrictions/DefaultRolePermissions to type definitions ObjectType and VariableType nodes should never have access restrictions or role permissions from DefaultAccessRestrictions/ DefaultRolePermissions. These defaults are meant to apply to instances of the type, not to the type definition node itself. Previously, CertificateGroupType, TrustListType, SecurityGroupType and other types were incorrectly emitted with AccessRestrictions inherited from their DefaultAccessRestrictions, making them unreadable without encryption even though the spec defines no restrictions on these type definitions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * CttTestRunner: fix session establishment flow - Fix constructor patterns (new/no-new dual call support) - Fix ResponseHeader with ServiceDiagnostics/StringTable - Populate ServerNonce, ServerCertificate, ServerEndpoints in CreateSession response - Add UaVariant setter methods (setNodeId/setString/setBoolean/etc.) - Add UaCreateSessionRequest/ActivateSessionRequest with proper nested structures - Fix UaPkiUtility/UaPkiCertificate with Thumbprint/toDERFile/loadCertificateFromFile - Add missing enums: PerformUpdateType, SecurityPolicy, StructureType, etc. - Add HostInfo, Bit helper, KeyPairCollection, ExpectedAndAcceptedResults - Add _error.store(), MessageSecurityMode.toString() Status: Session creates successfully, CreateSession validation runs, hits validateCertificate in PKI chain (next to implement). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: update report after DefaultAccessRestrictions type definition fix ObjectTypes no longer have incorrect access restrictions. Type children reduced from 203 to 164 (39 now visible). Total export- missing reduced from 1316 to 1146. Remaining 164 type children are individual methods/variables with spec-correct access restrictions. Two source generator fixes applied: - ModellingRule=None children for Variables/Methods - DefaultAccessRestrictions not applied to ObjectType/VariableType Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * CttTestRunner: fix PKI, cert validation, warnOnce, session response - Intercept warnOnce.js with Jint-compatible replacement (no Function.caller) - Add _log.store() global helper - Add HOSTNAMES/HostnameFromUrl helpers for cert hostname validation - Add UaPkiCertificate properties: PublicKey, Issuer, Subject, KeyUsage, Hostnames - Add UaPkiUtility.validateCertificate stub - Add UaByteString static helpers: FromByteArray, ToByteArray, fromHexString - Use JS UaNodeId constructor for proper equals() support - Fill AuthenticationToken and 32-byte ServerNonce in CreateSession response - Add clone/append to ByteString objects Session flow: CreateSession validates, ActivateSession reached, hits Channel.ServerCertificate.clone() (IsSecure check — next to fix). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * CttTestRunner: complete session establishment, crypto stubs, ByteString helpers - Add _makeByteString() helper for consistent ByteString objects with clone/append/isEmpty - Add UaCryptoProvider with asymmetricSign/Verify stubs - Add UaExtensionObject setter methods (setAnonymousIdentityToken, etc.) - Fix UaChannel with full properties (RequestedSecurityPolicyUri, IsSecure, etc.) - Fix duplicate type registrations overriding custom constructors - Fix ActivateSession response header with ServiceDiagnostics - Remove UaCreateSessionResponse/ActivateSessionRequest/CloseSessionRequest duplicates Status: Full session lifecycle works (GetEndpoints → OpenSecureChannel → CreateSession → ActivateSession). Test scripts execute and hit server capabilities initialization (MonitoredItem NodeId settings configuration). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update * plans: add spec references for access restriction reasoning Added links to Part 3 sections 5.2.9, 5.2.11, and 6.3.3 explaining why DefaultRolePermissions are applied to instance children but not to type definitions. The NodeSet2.xml has no explicit RolePermissions on these 164 nodes -- restrictions come from model design defaults. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: add GDS project references to ConsoleReferenceServer Dockerfile Add Opc.Ua.Gds.Common and Opc.Ua.Gds.Server.Common csproj COPY lines to the Docker restore layer, required since the GDS node manager was added to the ConsoleReferenceServer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update * feat: add IsPartOfTypeHierarchy flag to bypass access restrictions on types Type hierarchy nodes (ObjectType/VariableType definitions and their children) should be universally accessible regardless of AccessRestrictions and RolePermissions. Changes: - Add IsPartOfTypeHierarchy property to NodeState - Set flag on ObjectType/VariableType in generated code (!forInstance) - Propagate flag from parent to children in AddPredefinedNode - Add flag to NodeMetadata, propagate in GetPermissionMetadata - Bypass ValidateRolePermissions and ValidateAccessRestrictions when IsPartOfTypeHierarchy is true - Revert isTypeDefinition guard: AccessRestrictions and RolePermissions are now emitted on all nodes as metadata, but enforcement is skipped for type hierarchy nodes - Fix forInstance propagation in type factories: use forInstance: forInstance for type children so deep children (TrueState/FalseState etc.) are included when !forInstance Type-level missing nodes reduced from 201 to 99. Remaining 99 are in the server but not reachable by the export tool's browse path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: update report with final IsPartOfTypeHierarchy results Missing from export reduced to 998 (from 1325 original). Type children: 201 -> 99 (forInstance propagation fix). All nodes verified present via OPC UA Read. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: propagate IsPartOfTypeHierarchy in GetNodeMetadataAsync The Browse service's per-reference ValidateRolePermissionsAsync calls GetNodeMetadataAsync (not GetPermissionMetadataAsync). The IsPartOfTypeHierarchy flag was only set in GetPermissionMetadataAsync, causing type hierarchy nodes to be filtered out of Browse results. This fixes 99 ObjectType children that were previously invisible in Browse from their parent types. Type-level missing: 99 -> 0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plans: final report -- 0 type-level children missing (694 total) Type-level missing: 99 -> 0 after fixing IsPartOfTypeHierarchy propagation in GetNodeMetadataAsync. Total export-missing: 694 (384 encoding + 236 access-restricted + 74 instance/orphan). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
39fa3030fa |
Add a fluent api for server, a sample and generate node managers to use with it. (#3684)
* Add source-generated NodeManagers and fluent wiring API Adds a fluent INodeManagerBuilder API for wiring per-node callbacks and a model-aware source generator that emits a partial CustomNodeManager2 plus an INodeManagerFactory for each design file. Opt-in is per class via [Opc.Ua.Server.Fluent.NodeManager] on a partial class (recommended) or project-wide via the ModelSourceGeneratorGenerateNodeManager MSBuild property (legacy). The attribute supports NamespaceUri / Design selectors for multi-design projects and a GenerateFactory toggle. Diagnostics MODELGEN010 / MODELGEN011 surface unmatched bindings and non-partial classes. Adds the ConsoleBoilerServer NativeAOT sample driving the new pipeline end-to-end with Microsoft.Extensions.Logging.Console and updated docs in Docs/SourceGeneratedNodeManagers.md. * Add BoilerServer AOT smoke test Verifies the source-generated Boiler.BoilerNodeManagerFactory loads the boiler address space, registers its namespace, and dispatches the fluent OnRead callbacks wired in BoilerNodeManager.Configure.cs. All 3 new tests pass in JIT mode and against the NativeAOT-published binary; total Aot.Tests suite: 71/71 pass. |
||
|
|
d14cd10a86 |
Model dependency annotations using source generator + flaky test fixes (#3687)
* Fix publish/dispose race that hangs Client tests
Subscription.Dispose pre-disposed m_publishTimer and m_messageWorkerCts
before calling ResetPublishTimerAndWorkerState, causing Cancel() to throw
ObjectDisposedException and leaving the publish worker stuck. Removed the
duplicate disposal so the reset method is the single owner of those resources,
and guarded Cancel/Dispose with try/catch ObjectDisposedException for defense
in depth.
Session.OnPublishComplete could run after Session.Dispose disposed
m_reconnectLock, throwing ObjectDisposedException from SemaphoreSlim.Wait()
and re-arming via the throttle path indefinitely. Added an early Disposed
guard, wrapped Wait/Release in try/catch ObjectDisposedException, and added
a Disposed guard in QueueBeginPublish so the throttle cannot reschedule
publishes after disposal.
Fixes the macOS net10.0 hang seen in Azure pipeline build 13257
(TransferSubscriptionAsync, ReconnectWithSavedSessionSecretsAsync).
* fix lockout test and use UserName token for SuccessfulAuthenticationClearsFailedAttempts test
After
|
||
|
|
36c936a361 | Update SourceGenerator dependencies resolution mechanism. (#3680) | ||
|
|
cacf03fffc |
XmlDecoder/XmlParser: throw BadDecodingError for empty/non-element enumerated arrays (#3677)
* Fix XmlDecoder empty enumerated array handling * Fix XmlParser empty enumerated array handling |
||
|
|
6c8c1a6d29 | Enable dispose analyzers CA2000 and CA2213 and fix all issues (#3670) | ||
|
|
d1883832e1 |
Secure channel enhancements 2025 11 (Take 3) (#3665)
* merged security changes
* Tailor SecurityPolicyUri for format expected in s_securityPolicyUriToInfo
* Enhance security policy handling and key computation logic
* Merge SecurityEnhancements.
* Add support for SessionTransferToken. Removed obsolete SoftwareCertificate code.
* Fix NonceLength for None.
* Add support for RSA_DH, more fixes from IOP testings.
* Finish implementation of SecureChannelEnhancements.
* Rename EccUtils.cs to CryptoUtils.cs
* Address feedback from reviewers.
* Fix CoPilot flagged spelling errors.
* Rename EccUtils to CryptoUtils
* Update version from 1.5.378-preview to 1.5.378
* Fix unit tests.
* Allow SignatureData.Algorithm to be NULL or Empty.
* Fix issue with BrainPool_p256r1_ChaChaPoly
* Fix RSA_DH_AesGcm
* Fix OSC/padding by deriving HMAC keys, tightening symmetric size math, and correcting ECC_brainpoolP384r1/Basic128Rsa15 IV, signature, padding, and nonce parameters.
* Policies without asymmetric encryption (ECC) return the plaintext when encrypting user tokens; this prevents null payloads from causing BadIdentityTokenInvalid.
* Reserve outer CBC padding for avoiding SymetricEncryptAndSign->AddPadding to overwrite next fields (signature)
* Nonce stored as byte array in SessionConfiguration; Sesion snapshot restores ServerNonce and reconstructs ECC ephemeral key Nonce from bytes and policy
* Added _AesGcm and _ChaChaPoly variants to BuildSupportedSecurityPolicies() for all six ECC certificate types (nistP256, nistP384, brainpoolP256r1, brainpoolP384r1, curve25519, curve448) to SecurityConfiguration. Added Sign and SignAndEncrypt endpoints for the four ECC AesGcm/ChaChaPoly policy pairs (nistP256, nistP384, brainpoolP256r1, brainpoolP384r1) to ServerFixture.
* make ephemeralKeyPolicyUri nullable
* GenerateSecret also for NET7 and NET8
* Adjust Basic128Rsa15 policy properties for backword compatibility
* Exclude unsuported AEAD policies from .NET Framework client tests
* Addapt to new changes (still build fail)
* Addapt code to make it compile
* Fixed failing build on net48 (by ignoring potential null ref which is not reported on other newer targets)
* Preserve the certificate reference in Clone() so copied handlers can still sign
* Remove extra code and addapt to existing master configuration settings
* Filter *_AesGcm and *_ChaChaPoly security policies based on actual runtime support, so unsupported AEAD policies are not advertised or selected on older frameworks
* Expand ECC/RSA policy test coverage and keep Basic128Rsa15 nonce length backward-compatible
* Fix ReconnectSessionOnAlternateChannel _AES and _ChaCha policies
* Fixed IgnoreIfPolicyNotAdvertised so it now fetches endpoints on-demand (instead of relying on Endpoints being preloaded by earlier tests), which avoids false ignores when running tests directlyy
* Merge with commit
|
||
|
|
fc21f2df8c |
Fixed timer leaks in ChannelAsyncOperation.EndAsync (#3669)
* Fixed timer leaks in ChannelAsyncOperation.EndAsync (added delay task cancellation) * Added WaitAsync with timeout PolyFill extension for versions <= .NET 6.0 * The ChannelAsyncOperation.EndAsync has been unified across all .NET versions using polyfills for older versions (< .NET 6.0) * Fixed missing "using" operator |
||
|
|
abc813f56c | Support UANodeset export / import under AOT (#3667) | ||
|
|
64ca85fce3 |
Increase code coverage across solution (#3662)
Add additional tests to increase code coverage across the solution |
||
|
|
fd41681f4b |
Add support to publish OPC UA applications as Native AOT (#3633)
* make most ptojects aot compatible * Remove newtonsoft * Migrate all projects from Mono.Options to System.CommandLine 2.0.5 * Fix array clone * Replace serializers for storage using new attribute driven type geberator * Add new AOT integration tests covering all functional areas * Documentation updates |
||
|
|
23f10d89ee |
[Server] Introduce RequestLifetime for request handling and cancellation (#3643)
Use RequestLifetime throughout the server stack for unified request lifetime and cancellation management. Update all service method signatures, OperationContext, and request processing logic to use RequestLifetime, enabling precise tracking of cancellation reasons with UA StatusCodes. Remove obsolete synchronous request handling and legacy delegates. Update code generation, tests, and interfaces to support the new model. This change improves cancellation, timeout, and abort handling, and prepares the server for advanced request management features. |
||
|
|
5a1e547250 | Code cleanup and modernization of test assertions to comply with project standards. (#3631) | ||
|
|
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
|
||
|
|
56486efcdb |
Fix numeric range equality (#3600)
* test(numeric-range): add failing test * fix(numeric-range): include sub ranges in equality check * test(numeric-range): add tests for coverage |
||
|
|
25a4882145 |
Fix non enumerable generic type info construction (#3597)
* test(type-info): add failing test * fix(type-info): require IEnumerable implementation before treating generic type as array * test(type-info): add test for coverage |
||
|
|
588b7e9237 |
[Server] Implement event-driven RolePermissionsValidation caching in MonitoredNode2 (#3583)
* Initial plan * Implement event-driven RolePermissionsValidation with permission caching in MonitoredNode2 Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Add DefaultPermissionsChanged event to IConfigurationNodeManager to handle namespace-level default permission changes Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Add test & make validation functional * cover case when DefaultRolePermissions are aded after the node exists * cleanup --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> Co-authored-by: Roman Ettlinger <romanett98@gmail.com> |
||
|
|
0a4c87cef8 |
[Server] Implement smaller Performance improvements found when profiling (#3584)
* Add namespace index lookup for NamespaceMetadataState Added GetNamespaceMetadataState(ushort) to ConfigurationNodeManager and interface for efficient lookup by namespace index. Switched to ConcurrentDictionary for thread safety. Updated AsyncCustomNodeManager to use index-based lookup. Cleared index cache in Clear method. * Refactor Variant and ServiceResult handling for speed - Use WrappedValue assignment for DataValue in MonitoredNode and NodeState to align with updated Variant usage. - Return ServiceResult objects instead of raw StatusCodes for bad attribute IDs. - Update ServiceResult exception handling: include stack trace only in DEBUG, message only in release. - Optimize StatusCode to ServiceResult conversion by returning static Good/Bad instances. * Add Read Limited load test * Optimize MonitoredItem.IsReadToPublish * Add Subscription unit tests and improve triggering logic Added SubscriptionTests to verify PublishTimerExpired behavior, including timer expiry, monitored item readiness, keep-alive, and triggering scenarios. Updated Subscription.cs only process triggering if triggered items are configured, improving correctness and efficiency. * CR feedback |
||
|
|
a0e1e9f42e |
[Server] Optimize NodeState.ReadAttributes & base ReferenceNodeManager on AsyncCustomNodeManager (#3574)
* Use Interfaces Introduced with 1.5.378 Refactor to use interfaces for node managers and server Replaced concrete types with interfaces (e.g., IMasterNodeManager, ICoreNodeManager, IDiagnosticsNodeManager, IConfigurationNodeManager, IServerBase) across method signatures, properties, and internal structures to improve abstraction and flexibility. * Refactor CoreNodeManager to be Based on CustomNodeManager2 * Add Test * Add INodeManager3 with role permission validation Introduce INodeManager3 interface extending INodeManager2, adding synchronous role permission validation methods. Update all node manager interfaces and classes to use INodeManager3. Extend IAsyncNodeManager with async permission validation methods and update adapters for sync/async bridging. Deprecate FindNodeInAddressSpace in favor of new async FindNodeInAddressSpaceAsync. Refactor MonitoredNode2 to use thread-safe collections and locking for monitored items. Enhance event reporting with security and permission checks. Update constructors and documentation to reflect new interfaces and best practices. * Implement AsyncCustomNodeManager * fix comment * fix * Add tests * fix * Implement better locking strategy * fix * Add more tests * Add tests * Add tests * Add Tests * cleanup * cleanup * Add tests that verifies for AnalogItemState the instrument range is checked brefore writing * only assign new NodeID in default factory if NodeId isNull * Run all tests also with sampling groups * Add Docs * cleanup * Add chaos test * fix test * Use AsyncCustomNodeManager for ReferenceNodeManger & imrpove ReadAttributes method of NodeState * fixes * fixes and code review comments |
||
|
|
601cabf86f | Replace all use of object in code and API with Variant (#3550) | ||
|
|
f66ceffd75 |
Immutable built in types and code generation (#3534)
Generate stack and application code using source generators Change built in types to readonly structs Update localized text implementation to use JSON text serializer Status code with symbolic names Immutable node ids No boxing for all built in types <= 8 bytes in Variant. Split user identity token and token handling via token handler Add migration guide for breaking changes |
||
|
|
39ac3f665a | add throwing serviceresultexception with stacktrace (#3539) | ||
|
|
43ce7ed229 |
Code clean up and improvements (#3532)
This pull request modernizes the OPC UA .NET codebase and tests, removes .NET Standard 2.0 support from certificate/security code, and updates test code to use C# 12 and .NET 8+ features for clarity and maintainability. - Certificate and BouncyCastle interop files (e.g., CertificateBuilder.cs, X509Extensions.cs, X509SignatureFactory.cs) are refactored to drop NETSTANDARD2_0 support and use modern .NET APIs and conditional compilation. - Test code across the codebase is updated to use default, strongly-typed Parse methods, collection expressions, and improved async/await patterns. - Exception handling and assertions in tests are modernized, and test method naming is made consistent with Async suffixes. - The project and build files are updated to clarify Roslynator analyzer usage and remove obsolete netstandard tags. - General code and test cleanup includes improved null safety, type safety, and removal of deprecated or unused code. |
||
|
|
bafd63db5a |
Hook lookup of symbol in types project and set hook in opc ua core on assembly loading (#3520)
* Hook lookup of symbol in types project and set hook in opc ua core on assembly loading * Use module initializer instead of static constructor |
||
|
|
9f335c39d8 |
Change DebugCheck conditional compilation from DEBUG to CHECKED (#3496)
* Initial plan
* Change [Conditional("DEBUG")] to [Conditional("CHECKED")] in DebugCheck methods
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
|
||
|
|
e314cf53f7 |
Fix SourceTimestamp for variables without explicit timestamps in BaseVariableState (#3451)
* Initial plan * Add OnReadValue callback to update timestamps on variable reads Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Add test to verify timestamp updates on variable reads Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * fix timestamp for scalar values set loglevel in session publish when no subscriptions ignore more keepalive errors in Client Fixture * Fix timestamp updates for all variables (scalars and arrays) Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * create a proper fix * Add Order parameter to test to check the timestamp before an explicit write was done --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> Co-authored-by: Roman Ettlinger <romanett98@gmail.com> |
||
|
|
288f02f20a |
Allow status code variant creation from uint (#3472)
* Allow status code variant creation from uint * Initial plan * Add comprehensive tests for StatusCode variant creation from uint Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> * Remove redundant assertions in StatusCode variant tests Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> |
||
|
|
ae03267fbd |
Add optional parent-child linking when importing NodeSet2.xml (#3396)
* Initial plan * Fix parent-child references when importing NodeSet2.xml - Added LinkParentChildRelationships method to establish parent-child links after import - Sets Parent property and adds child to parent's children collection - Added test to verify parent-child references work correctly after import - All existing tests continue to pass Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Make parent-child linking optional with default false - Added linkParentChild parameter to Import method (defaults to false) - Maintains backward compatibility by not establishing parent-child relationships by default - Added test to verify backward compatibility (default behavior) - Updated ParentChildReferencesTest to explicitly enable the feature - All 7 tests pass Co-authored-by: marcschier <11168470+marcschier@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> Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com> |
||
|
|
dc85d522a6 |
Add support for private encodeable factory in server initialization (#3366)
* Initial plan * Add support for private encodeable factory in server initialization - Add new ServiceMessageContext constructor that accepts a custom IEncodeableFactory - Add CreateMessageContext(IEncodeableFactory) overload to ApplicationConfiguration - Mark CreateMessageContext(bool) as obsolete since the clonedFactory parameter was never used - Add PrivateEncodeableFactory property to ServerBase for specifying a private factory - Update all internal calls to use the new parameterless CreateMessageContext() Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Add unit tests for ServiceMessageContext private factory support Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Improve documentation for ServiceMessageContext constructors 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> |
||
|
|
7cd5ae34ec |
Fix ExtractValueFromVariant method call condition (#3382)
* Initial plan * Changes before error encountered Co-authored-by: romanett <7413710+romanett@users.noreply.github.com> * Fix ExtractValueFromVariant condition and add comprehensive tests 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> |