New project src/ZB.MOM.WW.OtOpcUa.Core.Abstractions (.NET 10, BCL-only dependencies, GenerateDocumentationFile=true, TreatWarningsAsErrors=true) defining the contract surface every driver implements. Per docs/v2/plan.md decisions #4 (composable capability interfaces), #52 (streaming IAddressSpaceBuilder), #53 (capability discovery via `is` checks no flag enum), #54 (optional IRediscoverable sub-interface), #59 (Core.Abstractions internal-only for now design as if public). Eleven capability interfaces: - IDriver — required lifecycle / health / config-apply / memory-footprint accounting (per driver-stability.md Tier A/B allocation tracking) - ITagDiscovery — discovers tags streaming to IAddressSpaceBuilder - IReadable — on-demand reads idempotent for Polly retry - IWritable — writes NOT auto-retried by default per decisions #44 + #45 - ISubscribable — data-change subscriptions covering both native (Galaxy MXAccess advisory, OPC UA monitored items, TwinCAT ADS) and driver-internal polled (Modbus, AB CIP, S7, FOCAS) mechanisms; OnDataChange callback regardless of source - IAlarmSource — alarm events + acknowledge + AlarmSeverity enum mirroring acl-design.md NodePermissions alarm-severity values - IHistoryProvider — HistoryReadRaw + HistoryReadProcessed with continuation points - IRediscoverable — opt-in change-detection signal; static drivers don't implement - IHostConnectivityProbe — generalized from Galaxy's GalaxyRuntimeProbeManager per plan §5a - IDriverConfigEditor — Admin UI plug-point for per-driver custom config editors deferred to each driver's phase per decision #27 - IAddressSpaceBuilder — streaming builder API for driver-driven address-space construction Plus DTOs: DriverDataType, SecurityClassification (mirroring v1 Galaxy model), DriverAttributeInfo (replaces Galaxy-specific GalaxyAttributeInfo per plan §5a), DriverHealth + DriverState, DataValueSnapshot (universal OPC UA quality + timestamp carrier per decision #13), HostConnectivityStatus + HostState + HostStatusChangedEventArgs, RediscoveryEventArgs, DataChangeEventArgs, AlarmEventArgs + AlarmAcknowledgeRequest + AlarmSeverity, WriteRequest + WriteResult, HistoryReadResult + HistoryAggregateType, ISubscriptionHandle + IAlarmSubscriptionHandle + IVariableHandle. DriverTypeRegistry singleton with Register / Get / TryGet / All; thread-safe via Interlocked.Exchange snapshot replacement on registration; case-insensitive lookups; rejects duplicate registrations; rejects empty type names. DriverTypeMetadata record carries TypeName + AllowedNamespaceKinds (NamespaceKindCompatibility flags enum per decision #111) + per-config-tier JSON Schemas the validator checks at draft-publish time (decision #91). Tests project tests/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests (xUnit v3 1.1.0 matching existing test projects). 24 tests covering: 1) interface independence reflection check (no references outside BCL/System; all public types in root namespace; every capability interface is public); 2) DriverTypeRegistry round-trip, case-insensitive lookups, KeyNotFoundException on unknown, null on TryGet of unknown, InvalidOperationException on duplicate registration (case-insensitive too), All() enumeration, NamespaceKindCompatibility bitmask combinations, ArgumentException on empty type names. Build: 0 errors, 4 warnings (only pre-existing transitive package vulnerability + analyzer hints). Full test suite: 845 passing / 1 failing — strict improvement over Phase 0 baseline (821/1) by the 24 new Core.Abstractions tests; no regressions in any other test project. Phase 1 entry-gate record (docs/v2/implementation/entry-gate-phase-1.md) documents the deviation: only Stream A executed in this continuation since Streams B-E need SQL Server / GLAuth / Galaxy infrastructure standup per dev-environment.md Step 1, which is currently TODO. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
57 lines
3.5 KiB
Markdown
57 lines
3.5 KiB
Markdown
# Phase 1 — Entry Gate Record
|
||
|
||
**Phase**: 1 — Configuration project + Core.Abstractions + Admin scaffold
|
||
**Branch**: `phase-1-configuration`
|
||
**Date**: 2026-04-17
|
||
**Implementation lead**: Claude (executing on behalf of dohertj2)
|
||
|
||
## Entry conditions
|
||
|
||
| Check | Required | Actual | Pass |
|
||
|-------|----------|--------|------|
|
||
| Phase 0 exit gate cleared | Rename complete, all v1 tests pass under OtOpcUa names | Phase 0 merged to `v2` at commit `45ffa3e` | ✅ |
|
||
| `v2` branch is clean | Clean | Clean post-merge | ✅ |
|
||
| Phase 0 PR merged | — | Merged via `--no-ff` to v2 | ✅ |
|
||
| SQL Server 2019+ instance available | For development | NOT YET AVAILABLE — see deviation below | ⚠️ |
|
||
| LDAP/GLAuth dev instance available | For Admin auth integration testing | Existing v1 GLAuth at `C:\publish\glauth\` | ✅ |
|
||
| ScadaLink CentralUI source accessible | For parity reference | `C:\Users\dohertj2\Desktop\scadalink-design\` per memory | ✅ |
|
||
| Phase 1-relevant design docs reviewed | All read by impl lead | ✅ Read in preceding sessions | ✅ |
|
||
| Decisions read | #1–142 covered cumulatively | ✅ | ✅ |
|
||
|
||
## Deviation: SQL Server dev instance not yet stood up
|
||
|
||
The Phase 1 entry gate requires a SQL Server 2019+ dev instance for the `Configuration` project's EF Core migrations + tests. This is per `dev-environment.md` Step 1, which is currently TODO.
|
||
|
||
**Decision**: proceed with **Stream A only** (Core.Abstractions) in this continuation. Stream A has zero infrastructure dependencies — it's a `.NET 10` project with BCL-only references defining capability interfaces and DTOs. Streams B (Configuration), C (Core), D (Server), and E (Admin) all have infrastructure dependencies (SQL Server, GLAuth, Galaxy) and require the dev environment standup to be productive.
|
||
|
||
The SQL Server standup is a one-line `docker run` per `dev-environment.md` §"Bootstrap Order — Inner-loop Developer Machine" step 5. It can happen in parallel with subsequent Stream A work but is not a blocker for Stream A itself.
|
||
|
||
**This continuation will execute only Stream A.** Streams B–E require their own continuations after the dev environment is stood up.
|
||
|
||
## Phase 1 work scope (for reference)
|
||
|
||
Per `phase-1-configuration-and-admin-scaffold.md`:
|
||
|
||
| Stream | Scope | Status this continuation |
|
||
|--------|-------|--------------------------|
|
||
| **A. Core.Abstractions** | 11 capability interfaces + DTOs + DriverTypeRegistry | ▶ EXECUTING |
|
||
| B. Configuration | EF Core schema, stored procs, LiteDB cache, generation-diff applier | DEFERRED — needs SQL Server |
|
||
| C. Core | `LmxNodeManager → GenericDriverNodeManager` rename, `IAddressSpaceBuilder`, driver hosting | DEFERRED — depends on Stream A + needs Galaxy |
|
||
| D. Server | `Microsoft.Extensions.Hosting` host, credential-bound bootstrap | DEFERRED — depends on Stream B |
|
||
| E. Admin | Blazor Server scaffold mirroring ScadaLink | DEFERRED — depends on Stream B |
|
||
|
||
## Baseline metrics (carried from Phase 0 exit)
|
||
|
||
- **Total tests**: 822 (pass + fail)
|
||
- **Pass count**: 821 (improved from baseline 820 — one flaky test happened to pass at Phase 0 exit)
|
||
- **Fail count**: 1 (the second pre-existing failure may flap; either 1 or 2 failures is consistent with baseline)
|
||
- **Build warnings**: 30 (lower than original baseline 167)
|
||
- **Build errors**: 0
|
||
|
||
Phase 1 must not introduce new failures or new errors against this baseline.
|
||
|
||
## Signoff
|
||
|
||
Implementation lead: Claude (Opus 4.7) — 2026-04-17
|
||
Reviewer: pending — Stream A PR will require a second reviewer per overview.md exit-gate rules
|