Repository navigation
OPC UA Part 3 compliance: permissions, Write semantics, NodeManagement, NodeSet DataTypes, locales - #4675
Conversation
…, Browse and data changes OPC 10000-4 5.4 / OPC 10000-3 5.2.5, 8.5: the server returns the most preferred translation for the session's LocaleIds, all translations for 'mul'. - ResourceManager.TranslateValue (virtual) translates scalar and array LocalizedText values; used centrally by the service dispatcher for Read results and Browse/BrowseNext target DisplayNames, by MonitoredItem for data change notifications and event fields. Stored node values unchanged. - Locale ids compared case-insensitively (RFC 5646) in ResourceManager and LocalizedText.FilterByPreferredLocales; mul+locales falls back to another region of the requested language. - ResourceManager labels a region fallback with its real locale and no longer returns all translations for mul+locales when only the count matches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ct in the Reflection.Emit builder and support OptionSet subtypes OPC 10000-6 5.1.7: in a StructureWithSubtypedValues or UnionWithSubtypedValues only a field with IsOptional=TRUE allows subtypes and is serialized as an ExtensionObject; a field with IsOptional=FALSE is encoded directly. The Reflection.Emit builder encoded every structure field of such types as an ExtensionObject, unlike the default builder. - AttributeExtensions: use ExtensionObject only for IsOptional fields; record the declared DataType of encodeable fields (StructureFieldAttribute.DataTypeId) so fields whose runtime type does not identify it (OptionSet subtypes) are written with the right type id. - ComplexTypeFieldBuilder: an optional subtyped structure field is an IEncodeable property so it can hold a subtype (generated subtypes are unrelated classes); before, decoding a subtype value threw. - ComplexTypeBuilder.AddOptionSetType: create the Structure-backed OptionSet subtype (Encoders.OptionSet) like the default builder instead of throwing; the factory lists it in GetTypes. - ComplexTypeSystem: a type the builder cannot create as an OptionSet subtype is logged and skipped instead of aborting the whole load batch; its definition is cached only after the type was created. Parity tests run binary, XML and JSON cases through both builders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a type TypeInfo.GetXmlName(object, context) fell back to the CLR type name for instances that describe their own data type (Encoders.Structure and its Union/StructureWithOptionalFields subclasses, the dynamic OptionSet). Every dynamically built structure was therefore written as <Structure> instead of the data type's XML name required by OPC 10000-6 5.3.1.16. Prefer the instance's IEncodeableType.XmlName when it is set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…check Call on the Object (Part 3 8.55) - The IsPartOfTypeHierarchy exemption in ValidateRolePermissions and ValidateAccessRestrictions now only covers Browse, Read and ReadRolePermissions, so type nodes stay discoverable. All other permissions are enforced on type nodes: ReceiveEvents on the EventType (Anonymous/AuthenticatedUser no longer receive AuditEventType-derived events; ns0 grants ReceiveEvents on audit types only to SecurityAdmin), Call on methods declared on types, Write, WriteRolePermissions, AddReference, RemoveReference and DeleteNode. - Add a ValidateAccessRestrictions overload taking the requested permission; the dispatcher passes it through. - Call checks the Call permission (and the AccessRestrictions in the dispatcher) on the Object passed as ObjectId as well as on the Method, in NodeManagerServiceDispatcher, AsyncCustomNodeManager and CustomNodeManager. - AuditingOperationTests: audit delivery is asserted for a SecurityAdmin subscriber; new test that Anonymous and AuthenticatedUser subscribers receive RefreshStart/End events but no audit events. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AddNodes creates the Mandatory InstanceDeclarations of the TypeDefinition and its supertypes (most derived declaration wins, Optional overrides hide inherited Mandatory ones), recursively completed from each child's own TypeDefinition, rebased onto per-instance NodeIds via the NodeId factory (Part 4 5.8.2.1, Part 3 6.4.2). - AddNodes rejects abstract TypeDefinitions, BaseVariableType, BaseEventType and Interface types with Bad_TypeDefinitionInvalid (Part 3 5.5.2, 5.6.5, 4.10.2). - AddReferences/DeleteReferences record ReferenceAdded/ReferenceDeleted, which bumps the NodeVersion and raises a GeneralModelChangeEvent; DeleteNodes records ReferenceDeleted on the parent (Part 3 5.x, 9.32.2). - MethodState.Call accepts omitted trailing optional input arguments declared by HasOptionalInputArgumentDescription and passes them as null Variants (Part 3 5.7.3, Part 4 5.12.2.2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The body element name of dynamic structures now follows the data type, so the Reflection.Emit and default builders produce identical XML. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- BaseVariableState: verify DataType/ValueRank (Bad_TypeMismatch) before the synchronous OnWriteValue handler runs, as the async path already did. - Merge an IndexRange slice into the cached value after OnWriteValue accepts it instead of storing the slice as the whole value. - Enforce AccessLevel StatusWrite/TimestampWrite (Part 3 8.57): without the bits only StatusCode Good / a null SourceTimestamp may be written, else Bad_WriteNotSupported. Server-internal setters are not affected. - Reject Int32 values that are not defined values of an Enumeration DataType registered with the encodeable factory (Bad_OutOfRange, Part 4 Table 55). - OptionSet structure writes (Part 3 8.40): size and valid-bit checks (Bad_OutOfRange) and (value & validBits) | (current & ~validBits) merge in AsyncCustomNodeManager and CustomNodeManager2. - Public ReportPropertyValueChanged / ReportSemanticChange on both node managers so server-side changes of semantic Properties raise a SemanticChangeEvent and set the SemanticsChanged bit (Part 3 5.6.2). - Tests that wrote source timestamps/status codes to variables without the access bits now write null timestamps or set the bits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rt 3 5.8.3, 8.48) A NodeSet Definition lists only the fields a DataType adds (Part 6 F.12), but the DataTypeDefinition attribute must start with the fields of the baseDataType (Part 3 8.48). Runtime-loaded subtypes were served with their own fields only, so clients decoded them with the wrong layout. - UANodeSet.CompleteDataTypeDefinitions merges inherited fields after all DataTypes of an import are known: multi-level, order independent, cycle-guarded, idempotent (FirstExplicitFieldIndex records the inherited part; a definition that already lists the base fields is not extended). StructureType follows inherited optional/subtyped fields. It runs at the end of every UANodeSet.Import and again over the whole runtime/fluent import batch, where supertypes in other documents, other node managers and compiled types (encodeable factory) are resolved. - A Structure subtype without own fields (no Field list) now gets a StructureDefinition instead of none. - Enumeration vs structure is decided by the supertype (Enumeration, OptionSet flag, Structure/Union); the Value heuristic is a fallback. - DefaultEncodingId of concrete structures is set from the Default Binary HasEncoding target at import; abstract types keep null. - DataTypeState no longer mutates the stored StructureDefinition on read; the encodeable-factory DefaultEncodingId fill works on a copy and is skipped for abstract types. - Field ArrayDimensions are parsed before the "first dimension > 0" check (was comparing a character) and dropped for scalars. - NodeSet export writes only the own fields (from FirstExplicitFieldIndex). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cept them Part 14 6.2.11.1: a received timestamp is not used when the target Variable does not allow writing timestamps. Servers now reject timestamps without the TimestampWrite access level bit (Part 3 8.57), so the external-server writer retries a Bad_WriteNotSupported write without timestamps and remembers the target. The StatusCode is kept so a target that cannot take it still reports the failure to the reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… declaration OPC 10000-4 5.12.2.2 allows the methodId of a Call to be the Method declaration of the ObjectType, but the RolePermissions are always verified with the Method that is the HasComponent target of the objectId. When the Object's Method did not carry the declaration as MethodDeclarationId (for example because a subtype overrides the Method), the node managers invoked the declaration and checked its permissions instead. Resolve a declaration found in the type hierarchy to the Object's Method with the same BrowseName (child or HasComponent target) in AsyncCustomNodeManager, CustomNodeManager2 and the sample node manager; keep the declaration only when the Object has no such Method. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test variable has no TimestampWrite access level bit, so the server rejects a SourceTimestamp with Bad_WriteNotSupported (OPC 10000-3 8.57). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved critical write-access and OptionSet issues, plus moderate correctness findings, block approval.
Review effort: Balanced
Findings: 2
Open (6)
Validate and merge OptionSet array and matrix elements · New Enforce status and timestamp writes against UserAccessLevel · New Preserve and enforce all-zero ValidBits masks · New Validate undefined enum values in matrices · New Resolve trailing optional argument descriptions correctly · New Use dedicated Lock objects for synchronization · New
What changed in this PR
Addresses OPC UA Part 3 compliance across permissions, Write and Call semantics, NodeManagement, NodeSet DataTypes, localization, and client complex-type encoding.
Changes:
- Tightens authorization and write validation; extends optional arguments and model-change reporting.
- Completes inherited DataType definitions and adds session-locale selection.
- Extends complex-type support and PubSub timestamp fallback, with regression tests and migration guidance.
| File | Changes and unresolved findings |
|---|---|
tests/Opc.Ua.Types.Tests/State/MethodStateTests.cs |
Tests omitted optional Call arguments. |
tests/Opc.Ua.Types.Tests/State/DataTypeStateTests.cs |
Tests nonmutating definition reads. |
tests/Opc.Ua.Types.Tests/State/BaseVariableStateWriteSemanticsTests.cs |
Tests write validation, access bits, and enumeration values. |
tests/Opc.Ua.Types.Tests/State/BaseVariableStateAsyncHooksTests.cs |
Updates async write tests for timestamp restrictions. |
tests/Opc.Ua.Types.Tests/Encoders/CodecReviewRegressionTests.cs |
Tests dynamic XML body names. |
tests/Opc.Ua.Types.Tests/BuiltIn/LocalizedTextTranslationTests.cs |
Tests locale matching and fallback. |
tests/Opc.Ua.Server.Tests/TypeHierarchyPermissionTests.cs |
Tests type permissions, audit-event delivery, and Call authorization. |
tests/Opc.Ua.Server.Tests/RuntimeNodeSet/RuntimeNodeSetLifecycleTests.cs |
Updates inherited-definition rejection expectations. |
tests/Opc.Ua.Server.Tests/RuntimeNodeSet/RuntimeNodeSetDataTypeDefinitionTests.cs |
Tests cross-namespace structure inheritance. |
tests/Opc.Ua.Server.Tests/ResourceManagerTests.cs |
Tests translation selection and localized values. |
tests/Opc.Ua.Server.Tests/MonitoredItemTests.cs |
Tests localized notifications. |
tests/Opc.Ua.Server.Tests/LocaleSelectionServiceTests.cs |
Tests Read and Browse localization. |
tests/Opc.Ua.Server.Tests/Fluent/TypedBuilderTests.cs |
Removes unsupported write timestamps. |
tests/Opc.Ua.Server.Tests/Fluent/NodeSetImportBuilderTests.cs |
Updates import-completion invocation. |
tests/Opc.Ua.Server.Tests/CustomNodeManagerTests.cs |
Tests instance Method resolution. |
tests/Opc.Ua.Server.Tests/ComplexTypes/ServerComplexTypeSystemIntegrationTests.cs |
Tests structure-subtype round-trips. |
tests/Opc.Ua.Server.Tests/ComplexTypes/ServerComplexTypesTestServer.cs |
Initializes subtype fixture values. |
tests/Opc.Ua.Server.Tests/ComplexTypes/ServerComplexTypesTestNodeManager.cs |
Adds subtype fixture identifiers. |
tests/Opc.Ua.Server.Tests/ComplexTypes/ServerComplexTypesTestModel.NodeSet2.xml |
Defines subtype fixture nodes. |
tests/Opc.Ua.Server.Tests/AsyncCustomNodeManagerTests.cs |
Tests semantic changes, OptionSets, and Call permissions. |
tests/Opc.Ua.Server.TestFramework/ServerFixtureUtils.cs |
Supports session locale preferences. |
tests/Opc.Ua.PubSub.Adapter.Tests/ServerTargetVariableWriterTests.cs |
Tests timestamp retries and status preservation. |
tests/Opc.Ua.InformationModel.Tests/NodeManagementAddNodeTests.cs |
Tests mandatory members and abstract-type rejection. |
tests/Opc.Ua.Core.Tests/Stack/State/NodeStateAttributeConcurrencyTests.cs |
Enables status and timestamp writes in fixtures. |
tests/Opc.Ua.Core.Tests/Stack/Schema/UANodeSetDataTypeDefinitionTests.cs |
Tests definition completion and export. |
tests/Opc.Ua.Core.Security.Tests/AuditingOperationTests.cs |
Tests role-restricted audit delivery. |
tests/Opc.Ua.Client.ComplexTypes.Tests/TypeSystemClientTest.cs |
Removes an unsupported write timestamp. |
tests/Opc.Ua.Client.ComplexTypes.Tests/Types/MockResolver.cs |
Supports explicit DataType supertypes. |
src/Opc.Ua.Types/State/MethodState.cs |
Supports trailing optional arguments. Moderate, 2 votes (L907): mixed child/reference descriptions incorrectly reject omission of multiple optional arguments. |
src/Opc.Ua.Types/State/DataTypeState.cs |
Returns encoding information without mutating stored definitions. |
src/Opc.Ua.Types/State/BaseVariableState.cs |
Validates writes and merges slices. Critical, 1 vote (L1848): status/timestamp checks omit effective UserAccessLevel. Moderate, 3 votes (L1964): enumeration matrices bypass value validation. Moderate, 1 vote (L1712): callback replacements are not revalidated before caching. Moderate, 1 vote (L1848): Good-severity statuses with information bits incorrectly require StatusWrite. |
src/Opc.Ua.Types/Schema/UANodeSetHelpers.cs |
Integrates imported DataType definition completion. |
src/Opc.Ua.Types/Schema/UANodeSetDataTypeDefinitions.cs |
Completes inherited fields and encoding metadata. |
src/Opc.Ua.Types/Internal/StatusCodes.cs |
Adds internal BadOutOfRange support. |
src/Opc.Ua.Types/BuiltIn/TypeInfo.cs |
Uses dynamic DataType XML names. |
src/Opc.Ua.Types/BuiltIn/LocalizedText.cs |
Improves locale matching and fallback. |
src/Opc.Ua.Server/Subscription/MonitoredItem/MonitoredItem.cs |
Localizes published values. |
src/Opc.Ua.Server/RuntimeNodeSet/RuntimeNodeSetNodeManager.cs |
Completes runtime DataType definitions. |
src/Opc.Ua.Server/RuntimeNodeSet/NodeSetImporter.cs |
Resolves external DataType supertypes. |
src/Opc.Ua.Server/NodeManager/ResourceManager.cs |
Adds value translation and locale fixes. |
src/Opc.Ua.Server/NodeManager/OptionSetWriteMerge.cs |
Validates and merges OptionSet writes. Critical, 1 vote (L70): arrays, matrices, and addressed IndexRange elements bypass validation and merging. Moderate, 1 vote (L69): cached UserAccessLevel ignores callback-granted write access. Moderate, 2 votes (L159): populated all-zero ValidBits masks are not preserved or enforced. |
src/Opc.Ua.Server/NodeManager/NodeManagerServiceDispatcher.cs |
Localizes responses and checks Object Call permissions. |
src/Opc.Ua.Server/NodeManager/MasterNodeManager.ServiceDispatch.cs |
Narrows type-hierarchy permission exemptions. |
src/Opc.Ua.Server/NodeManager/CustomNodeManagerAsync.cs |
Checks Object Call permissions. |
src/Opc.Ua.Server/NodeManager/CustomNodeManager.cs |
Resolves instance Methods and reports semantic changes. |
src/Opc.Ua.Server/Fluent/NodeManagerBuilder.cs |
Completes imported DataType definitions. |
src/Opc.Ua.Server/Fluent/FluentNodeManagerBase.cs |
Supplies server context for import completion. |
src/Opc.Ua.PubSub.Adapter/Subscriber/ServerTargetVariableWriter.cs |
Retries rejected timestamp writes. Moderate, 1 vote (L121): ServerTimestamp rejection can permanently suppress valid future SourceTimestamps. |
src/Opc.Ua.Core.Schema/ComplexTypes/ComplexTypeSystem.cs |
Skips unsupported OptionSet types. Moderate, 1 vote (L1078): the catch also suppresses resolver service/communication failures, allowing incomplete loads. |
src/Opc.Ua.Client.ComplexTypes/Types/StructureFieldAttribute.cs |
Adds declared field DataType metadata. |
src/Opc.Ua.Client.ComplexTypes/Types/ComplexTypePropertyInfo.cs |
Resolves field DataType identifiers. Moderate, 1 vote (L692): interpreting session-local namespace indices against another NamespaceTable can fail decoding or select the wrong type. |
src/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeFieldBuilder.cs |
Supports subtype-capable fields. |
src/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeFactory.cs |
Includes runtime-created types. |
src/Opc.Ua.Client.ComplexTypes/TypeBuilder/ComplexTypeBuilder.cs |
Creates runtime OptionSet types. |
src/Opc.Ua.Client.ComplexTypes/TypeBuilder/AttributeExtensions.cs |
Emits field encoding metadata. Moderate, 1 vote (L197): session-local OptionSet DataType identifiers need URI-qualified ExpandedNodeIds for reuse across NamespaceTables. |
src/Opc.Ua.Client.ComplexTypes/TypeBuilder/AssemblyModule.cs |
Tracks runtime-created types. Nit, 3 votes (L99): both synchronization sites should use a dedicated System.Threading.Lock rather than the List. |
samples/Quickstarts.Servers/SampleNodeManager/SampleNodeManager.cs |
Resolves type declarations to instance Methods. |
docs/MigrationGuide.md |
Documents compliance-related behavior changes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Code coverage✅ Coverage gate passed.
Uncovered changed lines
Coverage is above the recorded baseline - consider ratcheting Thresholds live in |
- OptionSet writes (Part 3 8.40): validate and merge every element of an OptionSet array or matrix, including elements addressed by an IndexRange, against the stored element at the same position. A populated all-zero ValidBits of the stored value means no bit is valid and is preserved; the DataType definition is used only when the stored mask is absent. The access guard uses the effective UserAccessLevel (OnReadUserAccessLevel), so callback-granted write access no longer bypasses the validation. - StatusWrite/TimestampWrite (Part 3 8.57) are also required in the effective UserAccessLevel (Bad_UserAccessDenied otherwise). "Good" is compared by the code bits only (Part 4 7.38.1: the low 16 bits do not affect the meaning of the StatusCode), so Good with info bits needs no StatusWrite. - Enumeration range check covers matrices. - Optional input arguments: trailing arguments consume unresolved HasOptionalInputArgumentDescription references, so child and bare-reference descriptions can be mixed. - AssemblyModule locks on a dedicated Lock instead of the List. - PubSub ServerTargetVariableWriter retries first without the ServerTimestamp and remembers rejected timestamp kinds separately, so a rejected ServerTimestamp does not suppress SourceTimestamps. - ComplexTypeSystem only skips an OptionSet subtype on NotSupported / DataTypeNotSupported; other failures propagate as before. - StructureFieldAttribute.DataTypeId stores the namespace-uri qualified TypeId, independent of the namespace table of the building session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Addressed the review-overview findings that have no inline thread in 9d0a22b:
The MigrationGuide is updated: UserAccessLevel must carry StatusWrite/TimestampWrite, Good with info bits counts as Good, and the OptionSet array and all-zero ValidBits rules are described. 🤖 Addressed by Claude Code |
…e variables The reference server accepts a StatusCode and SourceTimestamp written together with the Value (CTT "Attribute Write StatusCode & Timestamp", Data Access PercentDeadband, Monitor Value Change V2). OPC 10000-3 8.57 now gates those writes on the StatusWrite / TimestampWrite AccessLevel bits, so add them to every data variable that grants CurrentWrite (AccessLevel and UserAccessLevel separately, keeping user restrictions and the AccessLevelEx bits). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bits The fluent Configure step assigned AccessLevelEx on the two non-atomic variables after StatusWrite/TimestampWrite were added, which reset the low byte of AccessLevel while UserAccessLevel kept the new bits. Add the non-atomic bits instead of replacing the value and update ReferenceNodeManagerNonatomicAccessLevelsAreConsistentAsync for the new access bits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dAuditEvents; document CTT defect C57 (#4693) ## Description CTT 1.05.513 (patched scripts) GDS Application Directory `011.js`, `018.js` and `028.js` fail on master (fa06c66) with "Step 3: Did not receive any Events after calling Publish." and passed on efad0dd. ### Root cause 7212607 (#4675, Part 3 compliance), not #4668. Since #4675 the server enforces `ReceiveEvents` on the EventType node (OPC 10000-3 §8.55: a Client only receives an Event if it has ReceiveEvents on its EventType and SourceNode). The GDS NodeSet grants it on `ApplicationRegistrationChangedAuditEventType` (`AuditEventDefaultPermissions`) only to **SecurityAdmin**. The CTT test cases subscribe on the Session of the GDS `AdministrativeUser`, a **DiscoveryAdmin**, so the server correctly withholds the events. The audit events are still raised and delivered: the RegisterApplication change to `OnCallAsync` in #4668 does not affect them. This is a CTT defect, so the server is unchanged. It is documented as **C57** in `plans/ctt-issues.md` and filed as [Mantis 11482](https://mantis.opcfoundation.org/view.php?id=11482). The fix is for the scripts to subscribe on a second Session of the CU's `SecurityAdminUser`. ### Changes - `tests/Opc.Ua.Gds.Tests/GdsApplicationRegistrationAuditEventTests.cs` (new): a DiscoveryAdmin calls RegisterApplication, UpdateApplication and UnregisterApplication. A SecurityAdmin subscriber on `Server.EventNotifier` must receive all three `ApplicationRegistrationChangedAuditEvent`s with `SourceNode` = Directory and the matching `MethodId`. A DiscoveryAdmin subscriber must receive none of them. - `plans/ctt-issues.md`: C57 (Mantis 11482). ## Verification - New test passes on net10.0 (~1 s); the test project builds on net48. - CTT p14-gds against an unchanged master server (fa06c66) with the C57 script patch (second Session as `sysadmin` for the event subscription), compared with efad0dd using the unpatched scripts: - Application Directory 011/018/028: Error → **Pass**. - AliasName Discovery 001 Pass, 002 Warning, 004 Pass. - Only other differences: two response-timestamp timing Warnings (App Directory 023 ActivateSession and Query Applications 002 CreateSession, > 100 ms). - CTT p12-auditing against fa06c66: identical to the baseline (21 Pass, 5 Skipped, 81 NotImpl, 0 errors). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>



Description
Fixes the High and Medium findings of an OPC UA Part 3 (OPC 10000-3, Address Space Model) compliance audit. Each finding was checked against the full spec text (Parts 3, 4, 5, 6, 14 and 18) before it was fixed. Every fix comes with regression tests that fail without it.
Role permissions (Part 3 §8.55, Part 4 §5.12.2.2)
MasterNodeManager.ValidateRolePermissions/ValidateAccessRestrictionsnow covers only Browse, Read and ReadRolePermissions. Type nodes stay visible to generic clients, which was the intent of fix address space issues #3705; every other permission bit is now enforced on them.ReceiveEventsis enforced on the EventType node. The standard NodeSet grants it onAuditEventTypeand its subtypes only to SecurityAdmin, so only SecurityAdmin sessions now receive audit events.Callpermission and AccessRestrictions on the Object as well as on the Method.methodIdis the Method declaration of the ObjectType, the Object's Method with the same BrowseName is permission-checked and invoked. The declaration is used only if the Object has no such Method. This applies toAsyncCustomNodeManager,CustomNodeManager2and the sample node manager.Write service (Part 3 §5.6.2, §8.40, §8.57; Part 4 §5.11.4)
OnWriteValuepath (fluentOnWrite) checks DataType and ValueRank first (Bad_TypeMismatch). After an IndexRange write it merges the slice into the cached value instead of replacing it.Bad_WriteNotSupported).Bad_OutOfRange. OptionSet writes merge only the valid bits into the stored value.ReportPropertyValueChanged/ReportSemanticChangelet server code raise SemanticChangeEvents for changes it makes itself.NodeManagement and Call arguments (Part 3 §5.5.2, §5.7.3, §6.4.2; Part 4 §5.8, §5.12.2)
Bad_TypeDefinitionInvalid).HasOptionalInputArgumentDescription).NodeSet DataTypes (Part 3 §5.8.3, §8.48; Part 6 Annex F.12)
UANodeSet.Importcompletes structure definitions with the base type's fields (base fields first). It creates definitions for structures without fields and setsDefaultEncodingId.StructureDefinition.FirstExplicitFieldIndexmarks the subtype's own fields.DataTypeStateno longer mutates the stored definition on read.Locales (Part 3 §5.2.5, §8.5; Part 4 §5.4)
mul. The selection lives in the server dispatcher and is built onResourceManager: the newTranslateValuecalls the overridableTranslate.Client complex types (Part 6 §5.1.7)
IsOptionalsubtyped fields as ExtensionObject. It also supports OptionSet subtypes: an unsupported type is skipped instead of aborting the whole load.TypeInfo.GetXmlNameuses the data type's XML name for dynamic structures and OptionSets (the XML body element was<Structure>). Both builders now produce identical XML.Behaviour changes
All are documented in
docs/MigrationGuide.md.AuditingOperationTestswas updated.Bad_WriteNotSupportedunless the Variable has StatusWrite/TimestampWrite. No variable insrc/sets these bits.BaseVariableTypeandBaseEventType), and new instances now come with child nodes.Not included
Testing
net10.0, Debug, one suite at a time on the merged branch. All suites below pass:
ActivityTraceFlags_Metrics_ShouldRecordMetricsOnly. That telemetry test passed when re-run alone, so it looks flaky.UA.slnxbuilds with 0 errors for net10.0 and net48, with no new analyzer warnings in changed files.Related Issues
Checklist
🤖 Generated with Claude Code