Add data-path ACL design (acl-design.md, closes corrections B1) + dev-environment inventory and setup plan (dev-environment.md), and remove consumer cutover from OtOpcUa v2 scope.
ACL design defines NodePermissions bitmask flags covering Browse / Read / Subscribe / HistoryRead / WriteOperate / WriteTune / WriteConfigure / AlarmRead / AlarmAcknowledge / AlarmConfirm / AlarmShelve / MethodCall plus common bundles (ReadOnly / Operator / Engineer / Admin); 6-level scope hierarchy (Cluster / Namespace / UnsArea / UnsLine / Equipment / Tag) with default-deny + additive grants and Browse-implication on ancestors; per-LDAP-group grants in a new generation-versioned NodeAcl table edited via the same draft → diff → publish → rollback boundary as every other content table; per-session permission-trie evaluator with O(depth × group-count) cost cached for the lifetime of the session and rebuilt on generation-apply or LDAP group cache expiry; cluster-create workflow seeds a default ACL set matching the v1 LmxOpcUa LDAP-role-to-permission map for v1 → v2 consumer migration parity; Admin UI ACL tab with two views (by LDAP group, by scope), bulk-grant flow, and permission simulator that lets operators preview "as user X" effective permissions across the cluster's UNS tree before publishing; explicit Deny deferred to v2.1 since verbose grants suffice at v2.0 fleet sizes; only denied OPC UA operations are audit-logged (not allowed ones — would dwarf the audit log). Schema doc gains the NodeAcl table with cross-cluster invariant enforcement and same-generation FK validation; admin-ui.md gains the ACLs tab; phase-1 doc gains Task E.9 wiring this through Stream E plus a NodeAcl entry in Task B.1's DbContext list. Dev-environment doc inventories every external resource the v2 build needs across two tiers per decision #99 — inner-loop (in-process simulators on developer machines: SQL Server local or container, GLAuth at C:\publish\glauth\, local dev Galaxy) and integration (one dedicated Windows host with Docker Desktop on WSL2 backend so TwinCAT XAR VM can run in Hyper-V alongside containerized oitc/modbus-server, plus WSL2-hosted Snap7 and ab_server, plus OPC Foundation reference server, plus FOCAS TestStub and FaultShim) — with concrete container images, ports, default dev credentials (clearly marked dev-only since production uses Integrated Security / gMSA per decision #46), bootstrap order for both tiers, network topology diagram, test data seed locations, and operational risks (TwinCAT trial expiry automation, Docker pricing, integration host SPOF mitigation, per-developer GLAuth config sync, Aveva license scoping that keeps Galaxy tests on developer machines and off the shared host). Removes consumer cutover (ScadaBridge / Ignition / System Platform IO) from OtOpcUa v2 scope per decision #136 — owned by a separate integration / operations team, tracked in 3-year-plan handoff §"Rollout Posture" and corrections §C5; OtOpcUa team's scope ends at Phase 5. Updates implementation/overview.md phase index to drop the "6+" row and add an explicit "OUT of v2 scope" callout; updates phase-1 and phase-2 docs to reframe cutover as integration-team-owned rather than future-phase numbered. Decisions #129–137 added: ACL model (#129), NodeAcl generation-versioned (#130), v1-compatibility seed (#131), denied-only audit logging (#132), two-tier dev environment (#133), Docker WSL2 backend for TwinCAT VM coexistence (#134), TwinCAT VM centrally managed / Galaxy on dev machines only (#135), cutover out of v2 scope (#136), dev credentials documented openly (#137). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,7 +40,7 @@ Stand up the **central configuration substrate** for the v2 fleet:
|
||||
| OPC UA wire behavior | Galaxy address space still served exactly as v1; the Configuration substrate is read but not yet driving everything |
|
||||
| Equipment-class template integration with future schemas repo | `EquipmentClassRef` is a nullable hook column; no validation yet (decisions #112, #115) |
|
||||
| Per-driver custom config editors in Admin | Generic JSON editor only in v2.0 (decision #27); driver-specific editors land in their respective phases |
|
||||
| Consumer cutover (ScadaBridge / Ignition / SystemPlatform IO) | Phases 6–8 |
|
||||
| Consumer cutover (ScadaBridge / Ignition / SystemPlatform IO) | OUT of v2 scope — separate integration-team track per `implementation/overview.md` |
|
||||
|
||||
## Entry Gate Checklist
|
||||
|
||||
@@ -139,6 +139,7 @@ Implement DbContext with entities matching `config-db-schema.md` exactly:
|
||||
- `UnsArea`, `UnsLine`
|
||||
- `ConfigGeneration`
|
||||
- `DriverInstance`, `Device`, `Equipment`, `Tag`, `PollGroup`
|
||||
- `NodeAcl` (generation-versioned per decision #130; data-path authorization grants per `acl-design.md`)
|
||||
- `ClusterNodeGenerationState`, `ConfigAuditLog`
|
||||
- `ExternalIdReservation` (NOT generation-versioned per decision #124)
|
||||
|
||||
@@ -443,6 +444,24 @@ Per `admin-ui.md` §"Release an external-ID reservation" and §"Merge or rebind
|
||||
- After release: same `(Kind, Value)` can be reserved by a different EquipmentUuid in a future publish
|
||||
- Merge equipment A → B: draft preview shows tag re-pointing + ID re-reservation; publish executes atomically; A is disabled with `EquipmentMergedAway` audit entry
|
||||
|
||||
#### Task E.9 — ACLs tab + bulk-grant + permission simulator
|
||||
|
||||
Per `admin-ui.md` Cluster Detail tab #8 ("ACLs") and `acl-design.md` §"Admin UI":
|
||||
- ACLs tab on Cluster Detail with two views ("By LDAP group" + "By scope")
|
||||
- Edit grant flow: pick scope, group, permission bundle or per-flag, save to draft
|
||||
- Bulk-grant flow: multi-select scope, group, permissions, preview rows that will be created, publish via draft
|
||||
- Permission simulator: enter username + LDAP groups → live trie of effective permissions across the cluster's UNS tree
|
||||
- Cluster-create workflow seeds the v1-compatibility default ACL set (per decision #131)
|
||||
- Banner on Cluster Detail when the cluster's ACL set diverges from the seed
|
||||
|
||||
**Acceptance**:
|
||||
- Add an ACL grant via draft → publishes → row in `NodeAcl` table; appears in both Admin views
|
||||
- Bulk grant 10 LDAP groups × 1 permission set across 5 UnsAreas → preview shows 50 rows; publish creates them atomically
|
||||
- Simulator: a user in `OtOpcUaReadOnly` group sees `ReadOnly` bundle effective at every node in the cluster
|
||||
- Simulator: a user in `OtOpcUaWriteTune` sees `Engineer` bundle effective; `WriteConfigure` is denied
|
||||
- Cluster-create workflow seeds 5 default ACL grants matching v1 LDAP roles (table in `acl-design.md` §"Default Permissions")
|
||||
- Divergence banner appears when an operator removes any of the seeded grants
|
||||
|
||||
## Compliance Checks (run at exit gate)
|
||||
|
||||
A `phase-1-compliance.ps1` script that exits non-zero on any failure:
|
||||
@@ -599,8 +618,8 @@ The exit gate signs off only when **every** item below is checked. Each item lin
|
||||
- Any Modbus / AB / S7 / TwinCAT / FOCAS driver code (Phases 3–5)
|
||||
- Per-driver custom config editors in Admin (each driver's phase)
|
||||
- Equipment-class template integration with the schemas repo
|
||||
- Consumer cutover (Phases 6–8, separate planning track)
|
||||
- ACL / namespace-level authorization for OPC UA clients (corrections doc B1 — needs scoping before Phase 6, parallel work track)
|
||||
- Consumer cutover (out of v2 scope, separate integration-team track per `implementation/overview.md`)
|
||||
- Wiring the OPC UA NodeManager to enforce ACLs at runtime (Phase 2+ in each driver phase). Phase 1 ships the `NodeAcl` table + Admin UI ACL editing + evaluator unit tests; per-driver enforcement lands in each driver's phase per `acl-design.md` §"Implementation Plan"
|
||||
- Push-from-DB notification (decision #96 — v2.1)
|
||||
- Generation pruning operator UI (decision #93 — v2.1)
|
||||
- Cluster-scoped admin grant editor in UI (admin-ui.md "Deferred / Out of Scope" — v2.1)
|
||||
|
||||
Reference in New Issue
Block a user