docs(07-01): complete data models and service interfaces plan

- UserAccessEntry, AccessType, IUserAccessAuditService, IGraphUserSearchService
- UACC-01, UACC-02 requirements marked complete
- STATE.md updated with position and decisions
- ROADMAP.md Phase 7 progress updated (1/8 plans)
This commit is contained in:
Dev
2026-04-07 12:38:19 +02:00
parent 1a6989a9bb
commit 7e6f3e7fc0
4 changed files with 96 additions and 13 deletions

View File

@@ -12,8 +12,8 @@
### User Access Audit ### User Access Audit
- [ ] **UACC-01**: User can export all SharePoint/Teams accesses a specific user has across selected sites - [x] **UACC-01**: User can export all SharePoint/Teams accesses a specific user has across selected sites
- [ ] **UACC-02**: Export includes direct assignments, group memberships, and inherited access - [x] **UACC-02**: Export includes direct assignments, group memberships, and inherited access
### Simplified Permissions ### Simplified Permissions
@@ -47,8 +47,8 @@ None deferred — all active requirements scoped to v1.1.
|-------------|-------|--------| |-------------|-------|--------|
| SITE-01 | Phase 6 | Complete | | SITE-01 | Phase 6 | Complete |
| SITE-02 | Phase 6 | Complete | | SITE-02 | Phase 6 | Complete |
| UACC-01 | Phase 7 | Pending | | UACC-01 | Phase 7 | Complete |
| UACC-02 | Phase 7 | Pending | | UACC-02 | Phase 7 | Complete |
| SIMP-01 | Phase 8 | Pending | | SIMP-01 | Phase 8 | Pending |
| SIMP-02 | Phase 8 | Pending | | SIMP-02 | Phase 8 | Pending |
| SIMP-03 | Phase 8 | Pending | | SIMP-03 | Phase 8 | Pending |

View File

@@ -53,7 +53,7 @@ Plans:
2. Running the audit returns a list of all access entries the user holds across the selected sites 2. Running the audit returns a list of all access entries the user holds across the selected sites
3. Results distinguish between direct role assignments, SharePoint group memberships, and inherited access 3. Results distinguish between direct role assignments, SharePoint group memberships, and inherited access
4. Results can be exported to CSV or HTML in the same format established by v1.0 export patterns 4. Results can be exported to CSV or HTML in the same format established by v1.0 export patterns
**Plans:** 8 plans **Plans:** 1/8 plans executed
Plans: Plans:
- [ ] 07-01-PLAN.md — UserAccessEntry model + service interfaces (Wave 1) - [ ] 07-01-PLAN.md — UserAccessEntry model + service interfaces (Wave 1)
- [ ] 07-02-PLAN.md — UserAccessAuditService implementation (Wave 2) - [ ] 07-02-PLAN.md — UserAccessAuditService implementation (Wave 2)
@@ -96,6 +96,6 @@ Plans:
| 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 | | 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 |
| 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 | | 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 |
| 6. Global Site Selection | 5/5 | Complete | 2026-04-07 | - | | 6. Global Site Selection | 5/5 | Complete | 2026-04-07 | - |
| 7. User Access Audit | v1.1 | 0/8 | Planned | - | | 7. User Access Audit | 1/8 | In Progress| | - |
| 8. Simplified Permissions | v1.1 | 0/? | Not started | - | | 8. Simplified Permissions | v1.1 | 0/? | Not started | - |
| 9. Storage Visualization | v1.1 | 0/? | Not started | - | | 9. Storage Visualization | v1.1 | 0/? | Not started | - |

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0 milestone: v1.0
milestone_name: milestone milestone_name: milestone
status: completed status: completed
stopped_at: Phase 7 context gathered stopped_at: Completed 07-01-PLAN.md
last_updated: "2026-04-07T10:22:02.651Z" last_updated: "2026-04-07T10:38:10.474Z"
last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped
progress: progress:
total_phases: 4 total_phases: 4
completed_phases: 1 completed_phases: 1
total_plans: 5 total_plans: 13
completed_plans: 5 completed_plans: 6
--- ---
# Project State # Project State
@@ -47,6 +47,7 @@ Phase 6 [ ] → Phase 7 [ ] → Phase 8 [ ] → Phase 9 [ ]
| Phase 06-global-site-selection P03 | 2 | 3 tasks | 5 files | | Phase 06-global-site-selection P03 | 2 | 3 tasks | 5 files |
| Phase 06-global-site-selection P04 | 2 | 3 tasks | 6 files | | Phase 06-global-site-selection P04 | 2 | 3 tasks | 6 files |
| Phase 06-global-site-selection P05 | 2 | 1 tasks | 1 files | | Phase 06-global-site-selection P05 | 2 | 1 tasks | 1 files |
| Phase 07-user-access-audit P01 | 5 | 2 tasks | 3 files |
## Accumulated Context ## Accumulated Context
@@ -69,6 +70,8 @@ Decisions are logged in PROJECT.md Key Decisions table.
- [Phase 06-global-site-selection]: BulkMembersViewModel confirmed excluded: no SiteUrl field, CSV-driven per-row site URLs - [Phase 06-global-site-selection]: BulkMembersViewModel confirmed excluded: no SiteUrl field, CSV-driven per-row site URLs
- [Phase 06-global-site-selection]: Test 8 asserts override-reset via next global sites message (not SiteUrl='' — OnSiteUrlChanged re-applies global immediately when cleared) - [Phase 06-global-site-selection]: Test 8 asserts override-reset via next global sites message (not SiteUrl='' — OnSiteUrlChanged re-applies global immediately when cleared)
- [Phase 06-global-site-selection]: Used reflection to set _hasLocalSiteOverride in PermissionsViewModel test — avoids needing a real SitePickerDialog - [Phase 06-global-site-selection]: Used reflection to set _hasLocalSiteOverride in PermissionsViewModel test — avoids needing a real SitePickerDialog
- [Phase 07-01]: UserAccessEntry is fully denormalized (one row = one user + one object + one permission) for direct DataGrid binding
- [Phase 07-01]: IsHighPrivilege and IsExternalUser pre-computed at scan time; GraphUserResult co-located with IGraphUserSearchService interface
### Pending Todos ### Pending Todos
@@ -80,6 +83,6 @@ None.
## Session Continuity ## Session Continuity
Last session: 2026-04-07T10:22:02.648Z Last session: 2026-04-07T10:38:10.472Z
Stopped at: Phase 7 context gathered Stopped at: Completed 07-01-PLAN.md
Resume file: .planning/phases/07-user-access-audit/07-CONTEXT.md Resume file: None

View File

@@ -0,0 +1,80 @@
---
phase: 07-user-access-audit
plan: 01
subsystem: core-models-interfaces
tags: [models, interfaces, contracts, user-access-audit]
dependency_graph:
requires: []
provides: [UserAccessEntry, AccessType, IUserAccessAuditService, IGraphUserSearchService, GraphUserResult]
affects: [07-02, 07-03, 07-04, 07-05, 07-06, 07-07, 07-08]
tech_stack:
added: []
patterns: [record types, interface contracts, C# nullable annotations]
key_files:
created:
- SharepointToolbox/Core/Models/UserAccessEntry.cs
- SharepointToolbox/Services/IUserAccessAuditService.cs
- SharepointToolbox/Services/IGraphUserSearchService.cs
modified: []
decisions:
- "UserAccessEntry is fully denormalized (one row = one user + one object + one permission) for direct DataGrid binding without post-processing"
- "IsHighPrivilege and IsExternalUser are pre-computed at scan time so the grid can show icons without re-evaluating strings"
- "GraphUserResult is defined in IGraphUserSearchService.cs (same file as interface) since it is only used by that interface"
metrics:
duration_minutes: 5
completed_date: "2026-04-07"
tasks_completed: 2
files_created: 3
files_modified: 0
---
# Phase 7 Plan 01: Data Models and Service Interfaces Summary
**One-liner:** Contract layer with UserAccessEntry record (12-field denormalized model), AccessType enum, IUserAccessAuditService, IGraphUserSearchService, and GraphUserResult — zero-error foundation for all downstream Phase 7 plans.
## What Was Built
Three files establishing the Wave 1 contract layer for the User Access Audit feature:
1. **UserAccessEntry.cs** — C# record with 12 positional properties representing one row in the audit results grid. Includes AccessType enum (Direct/Group/Inherited), pre-computed IsHighPrivilege and IsExternalUser flags, and SiteUrl/SiteTitle for multi-site grouping.
2. **IUserAccessAuditService.cs** — Service interface with single method `AuditUsersAsync` that accepts a session manager, list of target user login names, list of sites, scan options, progress reporter, and cancellation token. Returns `IReadOnlyList<UserAccessEntry>`.
3. **IGraphUserSearchService.cs** — Service interface with `SearchUsersAsync` for Graph API people-picker autocomplete, plus the `GraphUserResult` record (DisplayName, UserPrincipalName, nullable Mail).
## Tasks
| # | Task | Status | Commit |
|---|------|--------|--------|
| 1 | Create UserAccessEntry model and AccessType enum | Done | e08df0f |
| 2 | Create IUserAccessAuditService and IGraphUserSearchService interfaces | Done | 1a6989a |
## Decisions Made
1. **Denormalized record design** — Each UserAccessEntry row represents one user + one object + one permission level. This avoids nested object graphs and allows direct DataGrid binding and CSV export without flattening logic.
2. **Pre-computed flags** — IsHighPrivilege (Full Control, Site Collection Administrator) and IsExternalUser (#EXT# in login) are computed during the scan pass, not at display time. This keeps the ViewModel simple and the grid row data self-contained.
3. **GraphUserResult co-located with interface** — Defined in the same file as IGraphUserSearchService since it is exclusively used as the return type of that interface. No separate file needed.
## Deviations from Plan
None — plan executed exactly as written.
## Verification
- `dotnet build SharepointToolbox/SharepointToolbox.csproj` — 0 errors, 0 warnings
- UserAccessEntry.cs: record with 12 fields + AccessType enum confirmed
- IUserAccessAuditService.cs: AuditUsersAsync with correct 6-parameter signature confirmed
- IGraphUserSearchService.cs: SearchUsersAsync with 4 parameters + GraphUserResult record confirmed
## Self-Check: PASSED
Files confirmed present:
- FOUND: SharepointToolbox/Core/Models/UserAccessEntry.cs
- FOUND: SharepointToolbox/Services/IUserAccessAuditService.cs
- FOUND: SharepointToolbox/Services/IGraphUserSearchService.cs
Commits confirmed:
- FOUND: e08df0f
- FOUND: 1a6989a