docs(02-06): complete PermissionsViewModel and SitePickerDialog plan
- Add 02-06-SUMMARY.md with TDD results and deviation documentation - Update STATE.md: progress bar 87%, record metrics, ISessionManager decision - Update ROADMAP.md: phase 02-permissions now 6/7 summaries (In Progress)
This commit is contained in:
@@ -3,8 +3,8 @@ gsd_state_version: 1.0
|
||||
milestone: v1.0
|
||||
milestone_name: milestone
|
||||
status: planning
|
||||
stopped_at: Completed 02-04-PLAN.md
|
||||
last_updated: "2026-04-02T12:00:54.419Z"
|
||||
stopped_at: Completed 02-06-PLAN.md
|
||||
last_updated: "2026-04-02T12:08:05.688Z"
|
||||
last_activity: 2026-04-02 — Roadmap created, requirements mapped, all 42 v1 requirements assigned to phases
|
||||
progress:
|
||||
total_phases: 5
|
||||
@@ -64,6 +64,7 @@ Progress: [█░░░░░░░░░] 13%
|
||||
| Phase 02-permissions P01 | 5min | 2 tasks | 9 files |
|
||||
| Phase 02-permissions P02 | 7min | 2 tasks | 4 files |
|
||||
| Phase 02-permissions P04 | 1min | 2 tasks | 2 files |
|
||||
| Phase 02-permissions P06 | 4min | 2 tasks | 6 files |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
@@ -106,6 +107,7 @@ Recent decisions affecting current work:
|
||||
- [Phase 02-permissions]: Folder is not a SecurableObject in CSOM — ListItem used for permission extraction — Required by CSOM type system; Folder inherits from ClientObject not SecurableObject
|
||||
- [Phase 02-permissions]: Principal.Email excluded from CSOM Include — email not needed for PermissionEntry — Principal base type has no Email property; only User subtype does; avoids CS1061
|
||||
- [Phase 02-permissions]: CsvExportService uses UTF-8 with BOM for Excel compatibility; HtmlExportService uses UTF-8 without BOM
|
||||
- [Phase 02-permissions]: ISessionManager interface extracted from concrete SessionManager — required for Moq-based unit testing of PermissionsViewModel
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -119,6 +121,6 @@ None yet.
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-04-02T12:00:50.874Z
|
||||
Stopped at: Completed 02-04-PLAN.md
|
||||
Last session: 2026-04-02T12:08:01.918Z
|
||||
Stopped at: Completed 02-06-PLAN.md
|
||||
Resume file: None
|
||||
|
||||
138
.planning/phases/02-permissions/02-06-SUMMARY.md
Normal file
138
.planning/phases/02-permissions/02-06-SUMMARY.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
phase: 02-permissions
|
||||
plan: 06
|
||||
subsystem: ui
|
||||
tags: [wpf, mvvm, csharp, permissions, viewmodel, dialog, export]
|
||||
|
||||
requires:
|
||||
- phase: 02-permissions
|
||||
provides: IPermissionsService (ScanSiteAsync), ISiteListService (GetSitesAsync), CsvExportService, HtmlExportService, FeatureViewModelBase
|
||||
|
||||
provides:
|
||||
- PermissionsViewModel: full scan orchestrator extending FeatureViewModelBase
|
||||
- SitePickerDialog: multi-site selection dialog with checkboxes and filter
|
||||
- ISessionManager interface: abstraction over SessionManager for testability
|
||||
|
||||
affects:
|
||||
- 02-07 (DI wiring — must register PermissionsViewModel, SitePickerDialog, ISessionManager)
|
||||
- 03-storage (same FeatureViewModelBase + ISessionManager pattern)
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "ISessionManager interface extracted from concrete SessionManager for ViewModel testability"
|
||||
- "Flat ObservableProperty booleans (IncludeInherited, ScanFolders, FolderDepth, IncludeSubsites) assembled into ScanOptions record at scan time"
|
||||
- "Dialog factory pattern: PermissionsViewModel.OpenSitePickerDialog is Func<Window>? set by View layer"
|
||||
- "TestRunOperationAsync internal method bridges protected RunOperationAsync for xUnit tests"
|
||||
- "Dispatcher null-guard: Application.Current?.Dispatcher handles test context with no WPF message pump"
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs
|
||||
- SharepointToolbox/Views/Dialogs/SitePickerDialog.xaml
|
||||
- SharepointToolbox/Views/Dialogs/SitePickerDialog.xaml.cs
|
||||
- SharepointToolbox/Services/ISessionManager.cs
|
||||
modified:
|
||||
- SharepointToolbox/Services/SessionManager.cs
|
||||
- SharepointToolbox.Tests/ViewModels/PermissionsViewModelTests.cs
|
||||
|
||||
key-decisions:
|
||||
- "ISessionManager interface extracted — SessionManager is a concrete class; interface required for Moq-based unit testing of PermissionsViewModel"
|
||||
- "Test constructor (internal) omits CsvExportService/HtmlExportService — export services not needed for scan loop unit test, avoids null noise"
|
||||
- "Application.Current?.Dispatcher null-guard — WPF Dispatcher is null in xUnit test context; fall-through to direct assignment preserves testability"
|
||||
- "PermissionsViewModel uses ILogger<FeatureViewModelBase> — matches established pattern from SettingsViewModel"
|
||||
|
||||
patterns-established:
|
||||
- "ISessionManager: all future feature ViewModels should inject ISessionManager (not concrete SessionManager) for testability"
|
||||
- "TestRunOperationAsync internal method: expose protected scan methods via internal test hook + InternalsVisibleTo"
|
||||
|
||||
requirements-completed: [PERM-01, PERM-02, PERM-04, PERM-05, PERM-06]
|
||||
|
||||
duration: 4min
|
||||
completed: 2026-04-02
|
||||
---
|
||||
|
||||
# Phase 2 Plan 6: PermissionsViewModel and SitePickerDialog Summary
|
||||
|
||||
**PermissionsViewModel orchestrates multi-site CSOM permission scans with TDD-verified scan loop, CSV/HTML export commands, and SitePickerDialog for multi-site selection via factory pattern**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 4 min
|
||||
- **Started:** 2026-04-02T12:02:49Z
|
||||
- **Completed:** 2026-04-02T12:06:55Z
|
||||
- **Tasks:** 2
|
||||
- **Files modified:** 6
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- PermissionsViewModel fully implements FeatureViewModelBase with scan loop, export, and tenant-switch reset
|
||||
- SitePickerDialog XAML + code-behind: filterable ListView with checkboxes, loads via ISiteListService on Window.Loaded
|
||||
- ISessionManager interface extracted so ViewModels can be unit-tested without live MSAL/SharePoint
|
||||
- TDD: RED→GREEN cycle with StartScanAsync_WithMultipleSiteUrls_CallsServiceOncePerUrl passing; 60/60 tests pass
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1 RED: Failing test for PermissionsViewModel** - `c462a0b` (test)
|
||||
2. **Task 1 GREEN + Task 2: Full PermissionsViewModel and SitePickerDialog** - `f98ca60` (feat)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
- `SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs` - Feature orchestrator: scan loop, export commands, dialog factory, tenant switch
|
||||
- `SharepointToolbox/Views/Dialogs/SitePickerDialog.xaml` - Multi-site picker: filterable list with CheckBox + Title + URL columns
|
||||
- `SharepointToolbox/Views/Dialogs/SitePickerDialog.xaml.cs` - Code-behind: loads sites on Loaded, exposes SelectedUrls, filter/select-all/deselect-all
|
||||
- `SharepointToolbox/Services/ISessionManager.cs` - Interface for SessionManager (new)
|
||||
- `SharepointToolbox/Services/SessionManager.cs` - Now implements ISessionManager
|
||||
- `SharepointToolbox.Tests/ViewModels/PermissionsViewModelTests.cs` - Real test replacing the previous stub
|
||||
|
||||
## Decisions Made
|
||||
|
||||
- **ISessionManager extracted** — SessionManager is a concrete class with MSAL dependencies; interface required to mock it in unit tests. Matches "extract interface for testability" pattern from Phase 1 (IPermissionsService, ISiteListService already existed).
|
||||
- **Test constructor** — Internal constructor omits CsvExportService and HtmlExportService since export commands are not exercised in the scan loop test. Keeps tests lean.
|
||||
- **Dispatcher null-guard** — `Application.Current?.Dispatcher` is null in xUnit test context (no WPF thread). Guard ensures Results assignment succeeds in both test and production contexts.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 2 - Missing Critical] ISessionManager interface extracted for testability**
|
||||
- **Found during:** Task 1 (PermissionsViewModel TDD setup)
|
||||
- **Issue:** Plan specified injecting concrete `SessionManager`. Moq cannot mock concrete classes without virtual methods; unit test required a mockable abstraction.
|
||||
- **Fix:** Created `ISessionManager` interface with `GetOrCreateContextAsync`, `ClearSessionAsync`, `IsAuthenticated`; `SessionManager` implements it.
|
||||
- **Files modified:** SharepointToolbox/Services/ISessionManager.cs (new), SharepointToolbox/Services/SessionManager.cs
|
||||
- **Verification:** Build succeeds, existing 60 tests still pass
|
||||
- **Committed in:** c462a0b (RED phase commit)
|
||||
|
||||
---
|
||||
|
||||
**Total deviations:** 1 auto-fixed (1 missing critical)
|
||||
**Impact on plan:** Required for correct testability. SessionManager DI registration changes to `services.AddSingleton<ISessionManager, SessionManager>()` — handled in Plan 07.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
None — plan executed as written with one necessary interface extraction for testability.
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None - no external service configuration required.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
- PermissionsViewModel and SitePickerDialog complete — all business logic for Permissions tab is done
|
||||
- Plan 07 (DI wiring) must: register ISessionManager as singleton, register SitePickerDialog as Transient, set OpenSitePickerDialog factory in PermissionsView code-behind
|
||||
- 60 tests passing, 3 skipped (known interactive MSAL tests)
|
||||
|
||||
---
|
||||
*Phase: 02-permissions*
|
||||
*Completed: 2026-04-02*
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- FOUND: SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs
|
||||
- FOUND: SharepointToolbox/Views/Dialogs/SitePickerDialog.xaml
|
||||
- FOUND: SharepointToolbox/Views/Dialogs/SitePickerDialog.xaml.cs
|
||||
- FOUND: SharepointToolbox/Services/ISessionManager.cs
|
||||
- FOUND commits: c462a0b (test), f98ca60 (feat)
|
||||
- Tests: 60 passed, 3 skipped, 0 failed
|
||||
Reference in New Issue
Block a user