Closes task #123 (partial — builder semantics unit-tested; production wiring is the new task #133). ScopePathIndexBuilder + NodeScopeResolver indexed mode already exist — they produce a full Cluster → Namespace → UnsArea → UnsLine → Equipment → Tag scope from the published generation's config rows. What was missing: unit coverage of the Build semantics (the only consumers were compile-time references) + explicit acknowledgement in the readiness doc that the gate/resolver aren't yet wired into Program.cs. Tests — 6 cases in ScopePathIndexBuilderTests.cs: - Well-formed content emits full hierarchy. - Tags with null EquipmentId skipped (SystemPlatform-namespace fallback). - Tags with broken Equipment FK skipped (publish-time validation should have caught; builder is defensive). - Equipment with broken Line FK skipped. - Duplicate TagConfig throws InvalidOperationException. - Resolver with index returns full-path scope; un-indexed ref falls through to cluster-only scope (pre-ADR-001 behaviour preserved). Server.Tests 277 → 283. Critical follow-up (task #133): Program.cs still constructs OpcUaApplicationHost WITHOUT authzGate or scopeResolver, so all six dispatch-layer gates (Read, Write, HistoryRead, Browse, CreateMonitoredItems, Call) are currently inert in production. Wiring them up — load NodeAcl + EquipmentNamespaceContent at bootstrap, construct gate + resolver, pass into OpcUaApplicationHost, rebind on generation refresh — is the last Phase 6.2 GA blocker. Docs: v2-release-readiness.md Phase 6.2 Stream C hardening list marks the scope-resolution bullet struck-through with a close-out note that calls out the gate-inert-in-production gap + task #133. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5.2 KiB
5.2 KiB