Files
lmxopcua/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session.csproj
T
Joseph Doherty fcdc44f9f7 feat(opcuaclient-browser): real AttributesAsync + certificate-auth browse (R06:O-5)
- AttributesAsync was a stub returning nothing; it now reads NodeClass /
  DisplayName / DataType / ValueRank / UserAccessLevel in one request and maps them
  through UpstreamAttributeMapping, the same mapping discovery registers with (moved
  into the shared .Session leaf; the driver forwards to it). Objects have no value
  attributes.
- Certificate auth was refused "in v1". The browse now builds its identity through
  OpcUaUserIdentityFactory (shared .Session leaf, the driver forwards to it),
  including the secret: resolution of Password / UserCertificatePassword through the
  host's ISecretResolver (optional ctor param, DI-injected). Fail-closed: a secret:
  ref with no store throws instead of being sent as the literal (the browse used to
  send a secret: Password verbatim). The identity is built before any network I/O.

Refs #743

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
2026-10-22 15:33:08 -04:00

52 lines
3.6 KiB
XML

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Namespace stays ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient (no .Session suffix) so moving
NamespaceMap here changed no consumer's `using`. -->
<RootNamespace>ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient</RootNamespace>
<AssemblyName>ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Session</AssemblyName>
</PropertyGroup>
<!--
The live-OPC-UA-session layer of the OpcUaClient driver: everything the driver AND the AdminUI's
browser both need that is typed in ISession / NodeId / NamespaceTable / UserIdentity: NamespaceMap,
UpstreamAttributeMapping (DataType/AccessLevel/ValueRank -> driver shape) and OpcUaUserIdentityFactory
(credential secret: resolution + the SDK UserIdentity, incl. certificate auth).
WHY IT IS NOT IN .Contracts. It used to be, and .Contracts therefore carried
OPCFoundation.NetStandard.Opc.Ua.Client. When G-7 wired OpcUaClientTagDefinitionFactory.Inspect into
the deploy-time TagConfig gate, ControlPlane gained a ProjectReference to .Contracts — and with it
the whole OPC UA client stack, transitively, into every host that loads the control plane. A
Contracts project is meant to be the dependency-light parse/shape layer (see Calculation.Contracts:
Core.Abstractions and nothing else), so the SDK-typed half moved out rather than the gate doing
without.
WHY NOT JUST PUT IT IN THE .Driver PROJECT (the Mqtt.Browser-style deliberate exception). The
AdminUI project-references .Browser and NOT the runtime .Driver. Having .Browser reference .Driver
to reach NamespaceMap would pull the whole driver runtime — plus Core, Opc.Ua.Configuration and
Secrets.Abstractions — into the AdminUI's build/deploy graph. That is precisely the violation Gitea
#512 spent two extractions removing from Driver.Mqtt.Browser; re-introducing the same shape here to
save one csproj would be trading a measured regression for a little less churn.
KEEP THIS LEAF THIN. Anything addable here that is NOT session-typed belongs in .Contracts, or the
dependency-light property this split exists to buy erodes one file at a time. The pin is
ContractsIsDependencyLightTests in Driver.OpcUaClient.Tests.
-->
<ItemGroup>
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.Client" />
<!-- OpcUaUserIdentityFactory: the secret: resolution of the credential fields feeding the SDK UserIdentity is
shared by the driver and the AdminUI browse (review 2026-10-21 O-5), so the browse presents exactly the
credentials the deployed driver will. Abstractions only (one interface + a name type). -->
<PackageReference Include="ZB.MOM.WW.Secrets.Abstractions" />
</ItemGroup>
<ItemGroup>
<!-- RawTagEntry (the v3 authored-tag identity NamespaceMap indexes) lives in the Core.Abstractions
leaf; OpcUaClientTagDefinitionFactory is the ONE authority for reading a TagConfig blob's
nodeId, shared with the deploy gate — NamespaceMap calls it rather than re-parsing. -->
<ProjectReference Include="..\..\Core\ZB.MOM.WW.OtOpcUa.Core.Abstractions\ZB.MOM.WW.OtOpcUa.Core.Abstractions.csproj"/>
<ProjectReference Include="..\ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts\ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts.csproj"/>
</ItemGroup>
</Project>