Phase 6.2 Stream D data layer - ValidatedNodeAclAuthoringService #87
Reference in New Issue
Block a user
Delete Branch "phase-6-2-stream-d-validated-authoring"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ships the non-UI piece of Stream D. Blazor RoleGrantsTab + AclsTab refresh + SignalR invalidation deferred as visual-compliance follow-up.
Summary
ValidatedNodeAclAuthoringServicealongside existingNodeAclService. 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).InvalidNodeAclGrantExceptionsurfaces violations.Microsoft.EntityFrameworkCore.InMemoryadded to Admin.Tests csproj for the in-memory DbContext tests.Test plan
dotnet test: 1097 passing (was 1087, +10).🤖 Generated with Claude Code
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>