Audit (three parallel agent passes) found 43 markdown files carrying stale references to the deleted Galaxy.Host/Proxy/Shared projects after the v2-mxgw merge. This commit lands the prioritized fixes. Track 1 — high-traffic in-place rewrites (3 files, ~454 lines deleted) - README.md (202 → 91 lines): drops .NET 4.8 / x86 / TopShelf install text; leads with the multi-driver .NET 10 server identity and points at scripts/install/Install-Services.ps1 and the parity rig. - docs/v2/driver-specs.md §1 Galaxy (~289 → ~66 lines): replaces the Tier-C out-of-process spec with a Tier-A in-process description matching the current GalaxyDriver code, with the four-section GalaxyDriverOptions JSON shape pulled verbatim from Config/GalaxyDriverOptions.cs. - docs/drivers/Galaxy.md (211 → 92 lines): full rewrite around the current Browse/Runtime/Health/Config sub-folders. Track 2 — historical banners (5 files) - lmx_mxgw.md, lmx_mxgw_impl.md, lmx_backend.md, docs/v2/Galaxy.ParityMatrix.md, docs/v2/implementation/phase-2-galaxy-out-of-process.md each get a "✅ Completed 2026-04-30 — historical record" banner block. lmx_mxgw.md also fixes two dead links (`docs/Galaxy.Driver.md` and `docs/v2/Galaxy.Driver.md`) → `docs/drivers/Galaxy.md`. Track 3 — v1 archive sweep (10 git mv + 1 new index + 2 in-place scrubs) - Moved 10 v1 docs under docs/v1/ preserving subpath structure: AlarmTracking, Configuration, DataTypeMapping, HistoricalDataAccess, Subscriptions (top-level); drivers/Galaxy-Repository, drivers/Galaxy-Test-Fixture; reqs/GalaxyRepositoryReqs, reqs/MxAccessClientReqs, reqs/ServiceHostReqs. - New docs/v1/README.md is the shared archive banner + per-file table. - docs/README.md repointed to the v1 paths and updated to reflect the v2 two-process deploy shape (Server + Admin + optional OtOpcUaWonderwareHistorian). - docs/v2/Galaxy.ParityRig.md got a historical banner + four inline scrubs marking the OtOpcUaGalaxyHost service / Driver.Galaxy.Host EXE / Driver.Galaxy.ParityTests project as deleted-in-PR-7.2. The repo's live-reading surface (README + CLAUDE.md + docs/v2/) now describes only the post-PR-7.2 architecture. v1 docs are preserved as a labelled archive under docs/v1/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.8 KiB
Galaxy Driver — Galaxy Repository Requirements
Revision — Refreshed 2026-04-19 for the OtOpcUa v2 multi-driver platform (task #205). Scope clarified: this document is Galaxy-driver-specific. Galaxy is one of seven drivers in the OtOpcUa platform; the requirements below describe the SQL-side of the Galaxy driver (hierarchy/attribute/change-detection queries against the ZB database) that backs the Galaxy driver's
ITagDiscovery.DiscoverAsyncandIRediscoverableimplementations. All Galaxy-specific SQL runs insideOtOpcUa.Galaxy.Host(.NET 4.8 x86 Windows service); the in-serverDriver.Galaxy.Proxycalls it over a named pipe. For platform-wide tag discovery requirements seeOpcUaServerReqs.mdOPC-002. For deeper spec seedocs/GalaxyRepository.mdanddocs/v2/driver-specs.md.
Parent: HLR-002, HLR-003, HLR-006
Driver scope: Galaxy only. Namespace kind: SystemPlatform.
GR-001: Hierarchy Extraction
The Galaxy driver's ITagDiscovery.DiscoverAsync implementation shall query the ZB Galaxy Repository database to extract all deployed objects with their parent-child containment relationships, contained names, and tag names.
Acceptance Criteria
- Executes
queries/hierarchy.sqlagainst the ZB database from withinOtOpcUa.Galaxy.Host. - Returns a list of objects with:
gobject_id,tag_name,contained_name,browse_name,parent_gobject_id,is_area. - Objects with
parent_gobject_id = 0become children of the root ZB node inside theSystemPlatformnamespace. - Only deployed, non-template objects matching the category filter (areas, engines, user-defined objects, etc.) are returned.
- Query completes within 10 seconds on a typical Galaxy (hundreds of objects). Log Warning if it takes longer.
Details
- Results are ordered by
parent_gobject_id, tag_namefor deterministic tree building. - Empty result → Warning logged (Galaxy may have no deployed objects, or the DB connection may be misconfigured).
- Orphan detection: a row referencing a non-existent
parent_gobject_id(and not 0) is skipped with a Warning. - Streamed to the core via
IAddressSpaceBuilder.AddFolder/AddObjectcalls over the Galaxy named pipe; no in-memory full-tree buffering on the Host side.
GR-002: Attribute Extraction
The Galaxy driver shall query user-defined (dynamic) attributes for deployed objects, including data type, array flag, and array dimensions.
Acceptance Criteria
- Executes
queries/attributes.sqlusing the template chain CTE to resolve inherited attributes. - Returns:
gobject_id,tag_name,attribute_name,full_tag_reference,mx_data_type,is_array,array_dimension,security_classification. - Attributes starting with
_are filtered out by the query. array_dimensionis extracted from themx_valuehex bytes (positions 13-16, little-endian uint16).
Details
- CTE recursion depth is limited to 10 levels.
mx_data_typenot in the known set (1-8, 13-16) defaults to String.gobject_idthat doesn't match a hierarchy object is skipped (object may not be deployed).- Each emitted attribute is reported via
DriverAttributeInfoto the core throughIAddressSpaceBuilder.AddVariable.
GR-003: Change Detection and IRediscoverable
The Galaxy driver shall implement IRediscoverable by polling galaxy.time_of_last_deploy on a configurable interval to detect when a new deployment has occurred.
Acceptance Criteria
- Polls
SELECT time_of_last_deploy FROM galaxyat a configurable interval (Galaxy:ChangeDetectionIntervalSeconds, default 30 seconds). - Compares the returned timestamp to the last known value stored in memory.
- If different, raises the
IRediscoverable.RediscoveryNeededsignal so the core re-runsITagDiscovery.DiscoverAsyncand surgically rebuilds the Galaxy namespace subtree (per OPC-017). - First poll after startup always triggers an initial discovery.
- Query failure → Warning logged; no rediscovery triggered; retry at next interval.
Details
- Polling runs on a background
TaskinsideOtOpcUa.Galaxy.Host, not on the STA message-pump thread. time_of_last_deployis adatetimecolumn; compared using exact equality (not a range).- Signal delivery to the Proxy happens via a server-push message on the Galaxy named pipe.
GR-004: Rediscovery Data Flow
On a deployment change, the Galaxy driver shall re-query hierarchy + attributes and stream the updated structure to the core for surgical namespace rebuild.
Acceptance Criteria
- On change signal, re-run
GR-001(hierarchy) andGR-002(attributes) queries. - Stream the new tree to the core via
IAddressSpaceBuilderover the named pipe. - Log at Information level:
"Galaxy deployment change detected. Rebuilding. ({ObjectCount} objects, {AttributeCount} attributes)". - Log total rediscovery duration at Information level.
- On re-query failure: Error logged; existing Galaxy subtree is retained.
Details
- Rediscovery is not atomic from the DB perspective — hierarchy and attributes are two separate queries. Acceptable; Galaxy deployment is an infrequent operation.
- The core owns the diff/surgical apply per OPC-017; the Galaxy driver only streams the new authoritative tree.
GR-005: Connection Configuration
Galaxy DB connection parameters shall be configurable via environment variables passed from the OtOpcUa.Galaxy.Host supervisor at spawn time.
Acceptance Criteria
- Connection string via
OTOPCUA_GALAXY_ZB_CONNenvironment variable. - Default:
Server=localhost;Database=ZB;Integrated Security=True;TrustServerCertificate=True;Encrypt=False;(Windows Auth). - ADO.NET
SqlConnectionused for queries (.NET Framework 4.8). - Connection is opened per-query (not kept open). Connection pooling handles efficiency.
- If the initial connection test at startup fails, log Error with the connection string sanitized and continue attempting (change-detection polls keep retrying).
Details
- Command timeout:
Galaxy:CommandTimeoutSecondsin Config DB driver JSON (default 30 seconds). - No ORM. Raw ADO.NET with
SqlCommandandSqlDataReader. SQL text embedded as constants.
GR-006: Query Safety
All Galaxy SQL queries shall be static read-only SELECT statements. No writes to the Galaxy Repository database.
Acceptance Criteria
- All queries are hardcoded SQL strings with no string concatenation or user-supplied parameters.
- No INSERT, UPDATE, DELETE, or DDL statements are ever executed against the Galaxy database.
- Queries use only SELECT with read-only intent.
GR-007: Startup Validation
On startup, the Galaxy driver's DB component inside OtOpcUa.Galaxy.Host shall validate database connectivity.
Acceptance Criteria
- Execute a simple test query (
SELECT 1) against the configured Galaxy DB. - If the database is unreachable, log Error but do not prevent Host startup.
- The Galaxy driver runs in degraded mode (empty SystemPlatform namespace) until the database becomes available and the next change-detection poll succeeds.
- In degraded mode the Galaxy driver instance reports
DriverHealth.Unavailable, causing its Polly circuit state to be open until the first successful discovery.
GR-008: Capability Wrapping
All calls into the Galaxy DB component from the Proxy side shall route through CapabilityInvoker.InvokeAsync(DriverCapability.Discover, …).
Acceptance Criteria
Driver.Galaxy.Proxy.DiscoverAsyncis a thin capability-invoker call that sends a MessagePack request over the named pipe to the Host's DB component.- Roslyn analyzer OTOPCUA0001 validates there are no direct discovery calls bypassing the invoker.
- Polly pipeline for
DriverCapability.Discoveron the Galaxy driver instance carries Timeout + Retry + CircuitBreaker.