Phase 6.2 Stream D data layer - ValidatedNodeAclAuthoringService #87

Merged
dohertj2 merged 1 commits from phase-6-2-stream-d-validated-authoring into v2 2026-04-19 09:41:03 -04:00
Owner

Ships the non-UI piece of Stream D. Blazor RoleGrantsTab + AclsTab refresh + SignalR invalidation deferred as visual-compliance follow-up.

Summary

  • ValidatedNodeAclAuthoringService alongside existing NodeAclService. Enforces write-time invariants: Permissions != None (decision #129 additive-only); Cluster-scope null ScopeId; sub-cluster requires ScopeId; no duplicate (generation, cluster, group, scope). UpdatePermissions rejects None (operators revoke via NodeAclService).
  • InvalidNodeAclGrantException surfaces violations.
  • Microsoft.EntityFrameworkCore.InMemory added to Admin.Tests csproj for the in-memory DbContext tests.

Test plan

  • 10 new tests cover every validation branch + duplicate detection across (same-draft-same-scope / different-scope / different-draft).
  • Full solution dotnet test: 1097 passing (was 1087, +10).

🤖 Generated with Claude Code

Ships the non-UI piece of Stream D. Blazor RoleGrantsTab + AclsTab refresh + SignalR invalidation deferred as visual-compliance follow-up. ## Summary - `ValidatedNodeAclAuthoringService` alongside existing `NodeAclService`. Enforces write-time invariants: Permissions != None (decision #129 additive-only); Cluster-scope null ScopeId; sub-cluster requires ScopeId; no duplicate (generation, cluster, group, scope). UpdatePermissions rejects None (operators revoke via NodeAclService). - `InvalidNodeAclGrantException` surfaces violations. - `Microsoft.EntityFrameworkCore.InMemory` added to Admin.Tests csproj for the in-memory DbContext tests. ## Test plan - [x] 10 new tests cover every validation branch + duplicate detection across (same-draft-same-scope / different-scope / different-draft). - [x] Full solution `dotnet test`: 1097 passing (was 1087, +10). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
dohertj2 added 1 commit 2026-04-19 09:40:54 -04:00
Ships the non-UI piece of Stream D: a draft-aware write surface over NodeAcl
that enforces the Phase 6.2 plan's scope-uniqueness + grant-shape invariants.
Blazor UI pieces (RoleGrantsTab + AclsTab refresh + SignalR invalidation +
visual-compliance reviewer signoff) are deferred to the Phase 6.1-style
follow-up task.

Admin.Services:
- ValidatedNodeAclAuthoringService — alongside existing NodeAclService (raw
  CRUD, kept for read + revoke paths). GrantAsync enforces:
    * Permissions != None (decision #129 — additive only, no empty grants).
    * Cluster scope has null ScopeId.
    * Sub-cluster scope requires a populated ScopeId.
    * No duplicate (GenerationId, ClusterId, LdapGroup, ScopeKind, ScopeId)
      tuple — operator updates the row instead of inserting a duplicate.
  UpdatePermissionsAsync also rejects None (operator revokes via NodeAclService).
  Violations throw InvalidNodeAclGrantException.

Tests (10 new in Admin.Tests/ValidatedNodeAclAuthoringServiceTests):
- Grant rejects None permissions.
- Grant rejects Cluster-scope with ScopeId / sub-cluster without ScopeId.
- Grant succeeds on well-formed row.
- Grant rejects duplicate (group, scope) in same draft.
- Grant allows same group at different scope.
- Grant allows same (group, scope) in different draft.
- UpdatePermissions rejects None.
- UpdatePermissions round-trips new flags + notes.
- UpdatePermissions on unknown rowid throws.

Microsoft.EntityFrameworkCore.InMemory 10.0.0 added to Admin.Tests csproj.

Full solution dotnet test: 1097 passing (was 1087, +10). Phase 6.2 total is
now 1087+10 = 1097; baseline 906 → +191 net across Phase 6.1 (all streams) +
Phase 6.2 (Streams A, B, C foundation, D data layer).

Stream D follow-up task tracks: RoleGrantsTab CRUD over LdapGroupRoleMapping,
AclsTab write-through + Probe-this-permission diagnostic, draft-diff ACL
section, SignalR PermissionTrieCache invalidation push.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit 565032cf71 into v2 2026-04-19 09:41:03 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#87