fix(galaxyrepository): scoped browse surfaces ancestors as navigation-only nodes (scadaproj#42)

A browse-subtree scope such as Plant/LineA/* filtered out Plant and
Plant/LineA, so scoped lazy browse from the root was empty and
DiscoverHierarchy returned orphans. Out-of-scope ancestors of an allowed
object are now returned as navigation-only containers: attributes stripped,
child_has_children = true, and only their children on the path to an allowed
object are listed (siblings stay hidden). DiscoverHierarchy reports them in
GalaxyHierarchyQueryResult.NavigationAncestorCount; WatchDeployEvents
subtracts it so its scoped counts stay allowed-objects-only.

- tests: ScopedAncestorBrowseTests; deploy-event scope test updated
- IGalaxyBrowseScopeProvider documents the semantics; CLAUDE.md 0.2.1 notes
- code-reviews: GalaxyRepository-002 Resolved; README regenerated

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 14:48:02 -05:00
parent 20cf3bfec7
commit 414050935e
10 changed files with 275 additions and 30 deletions
+3 -3
View File
@@ -10,7 +10,7 @@
| Last reviewed | 2026-11-09 |
| Reviewer | Claude |
| Commit reviewed | `91fb2b4` |
| Open findings | 7 |
| Open findings | 6 |
## Summary
@@ -117,7 +117,7 @@ Resolved 2026-11-09 in the commit tagged `(scadaproj#41)` (GalaxyRepository `0.2
| Severity | Medium |
| Priority | P2 |
| Category | Correctness & logic bugs |
| Status | Open |
| Status | Resolved |
| Location | `ZB.MOM.WW.GalaxyRepository/src/ZB.MOM.WW.GalaxyRepository/GalaxyBrowseProjector.cs:134` (also `ZB.MOM.WW.GalaxyRepository/src/ZB.MOM.WW.GalaxyRepository/GalaxyHierarchyProjector.cs:233`) |
**Description**
@@ -162,7 +162,7 @@ a deep scope glob.
**Resolution**
_Unresolved._
Resolved 2026-11-09 in the commit tagged `(scadaproj#42)` (GalaxyRepository `0.2.1`, unpublished) — an out-of-scope child that has an allowed descendant (also passing the request filters, via the existing `HasMatchingDescendant`) is now returned by `BrowseChildren` as a navigation-only container: `child_has_children = true`, attributes stripped; its other children stay hidden because the same rule applies when it is expanded. `DiscoverHierarchy` likewise returns the out-of-scope ancestors of allowed objects (cycle-safe parent walk; only when inside root/depth and passing the request filters), attribute-stripped, and reports them in the new `GalaxyHierarchyQueryResult.NavigationAncestorCount` init property, which `WatchDeployEvents` subtracts so its scoped counts remain allowed-objects-only. Semantics documented on `IGalaxyBrowseScopeProvider`. Regression tests in `ScopedAncestorBrowseTests` (root browse, ancestor browse, allowed subtree, sibling `LineB` does not leak, filter-gated ancestor, scoped and unscoped `DiscoverHierarchy`); root/ancestor/`DiscoverHierarchy` tests fail without the fix. `GalaxyRepositoryGrpcServiceScopeTests.WatchDeployEvents_ScopedProvider_EmitsFilteredCounts` updated (projection 4 objects incl. 2 ancestors; event still 2). Behaviour change for consumers: a scoped `DiscoverHierarchy` now includes the ancestor objects.
### GalaxyRepository-003 — Objects in a parent cycle disappear from `BrowseChildren`