Commit Graph
100 Commits
Author SHA1 Message Date
Dev 5df95032ee test(07-08): add UserAccessAuditService unit tests
- 12 tests: user filtering, claim format matching, Direct/Group/Inherited
  access type classification, Full Control + SCA high-privilege detection,
  external user flagging (#EXT#), semicolon user/level splitting, multi-site scan
2026-04-07 12:57:21 +02:00
Dev 34c1776dcc docs(07-07): complete integration wiring plan summary
- Add 07-07-SUMMARY.md for MainWindow/DI/localization integration
- Update STATE.md: progress 92%, new decisions, session record
- Update ROADMAP.md: phase 7 showing 7/8 summaries
2026-04-07 12:55:02 +02:00
Dev a2531ea33f feat(07-07): add localization keys for User Access Audit tab in English and French
- Add 17 audit.* keys and tab.userAccessAudit to Strings.resx (English)
- Add matching French translations with proper Unicode accented characters to Strings.fr.resx
2026-04-07 12:53:37 +02:00
Dev df796ee956 feat(07-07): add UserAccessAuditTabItem to MainWindow and wire dialog factory
- Add UserAccessAuditTabItem to MainWindow.xaml TabControl before SettingsTabItem
- Wire UserAccessAuditView content and SitePickerDialog factory in MainWindow.xaml.cs
2026-04-07 12:53:04 +02:00
Dev 2ed8a0cb12 feat(07-07): add DI registrations for Phase 7 services and create UserAccessAuditView
- Register IUserAccessAuditService, IGraphUserSearchService, export services, ViewModel and View in App.xaml.cs
- Create UserAccessAuditView.xaml with two-panel layout: people picker, site picker, scan options, color-coded DataGrid with grouping, summary banner
- Create UserAccessAuditView.xaml.cs code-behind with ViewModel constructor injection
- [Rule 3] UserAccessAuditView was missing (07-05 not executed); created inline to unblock 07-07
2026-04-07 12:52:36 +02:00
Dev c42140db1a docs(07-05): complete UserAccessAuditView plan
- 07-05-SUMMARY.md: view with people picker, summary banner, color-coded DataGrid
- STATE.md: progress updated to 85% (11/13), decisions recorded, session updated
- ROADMAP.md: phase 7 in progress with 6/8 summaries complete
2026-04-07 12:50:53 +02:00
Dev 975762dee4 feat(07-05): create UserAccessAuditView code-behind
- UserControl with UserAccessAuditViewModel constructor injection, sets DataContext
- Wires SearchResults.CollectionChanged to show/hide autocomplete ListBox
- OnSearchResultClicked handler invokes AddUserCommand for mouse-based user selection
2026-04-07 12:49:41 +02:00
Dev bb9ba9d310 feat(07-05): create UserAccessAuditView XAML layout
- Two-panel layout (290px left + * right) following PermissionsView pattern
- Left panel: people picker with autocomplete list + removable user pills, site picker button, scan option checkboxes, run/cancel/export buttons
- Right panel: 3-card summary banner (TotalAccessCount, SitesCount, HighPrivilegeCount), filter TextBox, group-by ToggleButton, color-coded DataGrid
- DataGrid: color-coded rows by AccessType (Direct=blue, Group=green, Inherited=gray), warning icon for high privilege, Guest badge for external users, access type icons
- GroupStyle with Expander headers showing group name + item count
- Status bar with ProgressBar + StatusMessage
2026-04-07 12:49:37 +02:00
Dev 72349d8415 docs(07-04): complete UserAccessAuditViewModel plan
- Add 07-04-SUMMARY.md with task commits and decisions
- Update STATE.md: progress 77%, session record, decisions
- Update ROADMAP.md: phase 7 plan count updated to 5/8 summaries
2026-04-07 12:45:14 +02:00
Dev 3de737ac3f feat(07-04): implement UserAccessAuditViewModel
- Extends FeatureViewModelBase with RunOperationAsync calling IUserAccessAuditService.AuditUsersAsync
- People picker with 300ms debounced Graph search via IGraphUserSearchService.SearchUsersAsync
- SelectedUsers ObservableCollection<GraphUserResult> with AddUserCommand/RemoveUserCommand
- Results ObservableCollection<UserAccessEntry> with CollectionViewSource grouping (by user/site) and FilterText predicate
- Summary banner properties: TotalAccessCount, SitesCount, HighPrivilegeCount (computed from Results)
- ExportCsvCommand/ExportHtmlCommand using UserAccessCsvExportService/UserAccessHtmlExportService
- Site selection with _hasLocalSiteOverride + OnGlobalSitesChanged pattern from PermissionsViewModel
- Dual constructors (DI + internal test constructor omitting export services)
- OnTenantSwitched resets all state (results, users, search, sites)
2026-04-07 12:44:02 +02:00
DevandClaude Sonnet 4.6 5c4a285473 docs(07-06): complete export services plan
- UserAccessCsvExportService and UserAccessHtmlExportService implemented
- SUMMARY.md created with task commits, decisions, self-check
- STATE.md updated: progress 69%, session, metrics, decisions
- ROADMAP.md updated: phase 7 showing 4/8 summaries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:42:00 +02:00
Dev 85712ad3ba docs(07-02): complete UserAccessAuditService plan
- Add 07-02-SUMMARY.md with implementation details
- Update STATE.md: progress 62%, decisions, session
- Update ROADMAP.md: phase 7 now 3/8 plans complete
2026-04-07 12:40:56 +02:00
Dev 3146a04ad8 feat(07-06): implement UserAccessHtmlExportService
- BuildHtml produces self-contained HTML with inline CSS and JS
- Stats cards: Total Accesses, Users Audited, Sites Scanned, High Privilege, External Users
- Per-user summary cards with high-privilege border highlight and guest badge
- Dual-view toggle (By User / By Site) with JS toggleView()
- Collapsible group headers per user and per site via toggleGroup()
- Sortable columns via sortTable() within each group
- Text filter via filterTable() scoping to active view
- Color-coded access type badges: Direct (blue), Group (green), Inherited (gray)
- High-privilege rows with bold text and warning icon
- External user guest badge (orange pill)
- UTF-8 without BOM encoding (matching HtmlExportService pattern)
2026-04-07 12:40:51 +02:00
Dev cc513777ec docs(07-03): complete GraphUserSearchService plan
- Add 07-03-SUMMARY.md with implementation details and decisions
- Update STATE.md: progress 54%, decisions, session, metrics
- Update ROADMAP.md: phase 07 now 2/8 summaries
2026-04-07 12:40:22 +02:00
Dev 44b238e07a feat(07-02): implement UserAccessAuditService
- Scans permissions via IPermissionsService.ScanSiteAsync per site
- Filters PermissionEntry results to matching target user logins (case-insensitive contains)
- Splits semicolon-delimited users/logins/levels into per-user UserAccessEntry rows
- Classifies AccessType: Inherited (!HasUniquePermissions), Group (GrantedThrough), Direct
- Flags IsHighPrivilege (Full Control, Site Collection Administrator) and IsExternalUser (#EXT#)
2026-04-07 12:39:57 +02:00
Dev 9f891aa512 feat(07-06): implement UserAccessCsvExportService
- BuildCsv per-user CSV with summary section (user, totals, sites, high-privilege, date)
- WriteAsync groups entries by UserLogin, writes one file per user (audit_{email}_{date}.csv)
- WriteSingleFileAsync combines all users in one file for SaveFileDialog export
- RFC 4180 CSV escaping, UTF-8 with BOM for Excel compatibility
- SanitizeFileName strips invalid path chars from email addresses
2026-04-07 12:39:35 +02:00
Dev 026b8294de feat(07-03): implement GraphUserSearchService for people-picker autocomplete
- Queries Graph /users with startsWith filter on displayName, mail, UPN
- Requires minimum 2 chars to prevent overly broad queries
- Sets ConsistencyLevel=eventual + Count=true (required for advanced filter)
- Escapes single quotes to prevent OData injection
- Returns up to maxResults (default 10) GraphUserResult records
2026-04-07 12:39:22 +02:00
Dev 7e6f3e7fc0 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)
2026-04-07 12:38:19 +02:00
Dev 1a6989a9bb feat(07-01): add IUserAccessAuditService and IGraphUserSearchService interfaces
- IUserAccessAuditService.AuditUsersAsync: scan sites and filter by user logins
- IGraphUserSearchService.SearchUsersAsync: Graph API people-picker autocomplete
- GraphUserResult record: DisplayName, UserPrincipalName, Mail
2026-04-07 12:37:26 +02:00
Dev e08df0f658 feat(07-01): add UserAccessEntry model and AccessType enum
- UserAccessEntry record with 12 fields for user-centric audit results
- AccessType enum: Direct, Group, Inherited
- Pre-computed IsHighPrivilege and IsExternalUser fields for grid display
2026-04-07 12:37:00 +02:00
DevandClaude Opus 4.6 19e4c3852d docs(07): create phase plan - 8 plans across 5 waves
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:32:39 +02:00
DevandClaude Opus 4.6 91058bc2e4 docs(state): record phase 7 context session
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:22:02 +02:00
DevandClaude Opus 4.6 ab253ca80a docs(07): capture phase context for user access audit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:21:57 +02:00
DevandClaude Opus 4.6 e96ca3edfe test(06): complete UAT - 8/8 passed
All Phase 6 global site selection features verified:
- Toolbar button, site count label, single/multi-site pre-fill
- Transfer pre-fill, local override, clear-reverts, tenant switch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:01:33 +02:00
DevandClaude Opus 4.6 4846915c80 fix(site-list): fix parsing error and double-auth in SiteListService
- Replace GetSitePropertiesFromSharePoint("", true) with modern
  GetSitePropertiesFromSharePointByFilters using null StartIndex
- Use ctx.Clone(adminUrl) instead of creating new AuthenticationManager
  for admin URL, eliminating second browser auth prompt

Resolves: UAT issue "Must specify valid information for parsing in the string"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 11:00:54 +02:00
DevandClaude Opus 4.6 5666565ac1 test(06): complete UAT - 0 passed, 3 issues, 7 skipped
Fix two pre-existing blockers found during UAT:
- ProfileManagementViewModel: add NotifyCanExecuteChanged on property changes
- SessionManager: open browser in openBrowserCallback (was no-op)

Remaining blocker: SitePickerDialog parsing error from PnP Framework.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:41:39 +02:00
DevandClaude Opus 4.6 52670bd262 docs(phase-06): complete phase verification and update state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:18:14 +02:00
Dev 9add2592b3 docs(06-05): complete GlobalSiteSelectionTests plan — phase 6 done
- SUMMARY.md created with test coverage details and decision rationale
- STATE.md updated: progress 100%, decisions recorded, session logged
- ROADMAP.md phase 6 marked Complete (5/5 plans with summaries)
2026-04-07 10:14:48 +02:00
Dev 80ef092a2e test(06-05): add GlobalSiteSelectionTests with 10 passing tests
- Message broadcast: GlobalSitesChangedMessage carries site list to receivers
- Base class: FeatureViewModelBase.GlobalSites updated on message receive
- Storage tab: SiteUrl pre-filled from first global site
- Storage tab: local override prevents global from overwriting SiteUrl
- Storage tab: clearing SiteUrl reverts to global site (override reset)
- Permissions tab: SelectedSites pre-populated from global sites
- Permissions tab: local picker override blocks subsequent global updates
- Tenant switch: resets local override so new global sites apply cleanly
- Transfer tab: SourceSiteUrl pre-filled from first global site
- MainWindowViewModel: GlobalSitesSelectedLabel reflects site count
2026-04-07 10:13:31 +02:00
Dev da905b6ec0 docs(06-04): complete tab-vms global site consumption plan
- Add 06-04-SUMMARY.md with all task details and self-check
- Update STATE.md: progress bar 80%, decisions, session record
- Update ROADMAP.md: phase 6 now 4/5 plans complete (In Progress)
- Mark SITE-02 complete in REQUIREMENTS.md
2026-04-07 10:10:18 +02:00
Dev 0a91dd4ff3 feat(06-04): update TransferViewModel for global site consumption; confirm BulkMembers excluded
- TransferViewModel: add _hasLocalSourceSiteOverride field
- Override OnGlobalSitesChanged to pre-fill SourceSiteUrl from first global site
- Add OnSourceSiteUrlChanged partial to detect local user input
- Reset _hasLocalSourceSiteOverride on tenant switch
- BulkMembersViewModel confirmed excluded: no SiteUrl field, CSV-driven, no OnGlobalSitesChanged override added
2026-04-07 10:08:52 +02:00
Dev 9a4365bd32 docs(06-03): complete toolbar UI, localization, and dialog factory wiring plan
- SUMMARY.md created for plan 06-03
- STATE.md updated: progress 60%, decisions logged, session recorded
- ROADMAP.md updated: phase 6 now 3/5 summaries (In Progress)
2026-04-07 10:08:51 +02:00
Dev 6a2e4d1d89 feat(06-04): update single-site tab VMs for global site consumption
- StorageViewModel: add OnGlobalSitesChanged, OnSiteUrlChanged, _hasLocalSiteOverride
- SearchViewModel: add OnGlobalSitesChanged, OnSiteUrlChanged, _hasLocalSiteOverride
- DuplicatesViewModel: add OnGlobalSitesChanged, OnSiteUrlChanged, _hasLocalSiteOverride
- FolderStructureViewModel: add OnGlobalSitesChanged, OnSiteUrlChanged, _hasLocalSiteOverride
- All four VMs pre-fill SiteUrl from first global site; local typing sets override flag
- Tenant switch resets _hasLocalSiteOverride in all four VMs
2026-04-07 10:08:19 +02:00
Dev 45eb531128 feat(06-03): add global site picker button and count label to toolbar
- Add Separator + Select Sites button (bound to OpenGlobalSitePickerCommand) to ToolBar
- Add TextBlock bound to GlobalSitesSelectedLabel for site count display
- Wire viewModel.OpenGlobalSitePickerDialog factory in MainWindow.xaml.cs using DI
- Add using SharepointToolbox.Core.Models for TenantProfile in code-behind
2026-04-07 10:07:35 +02:00
Dev 467a940c6f feat(06-03): localize GlobalSitesSelectedLabel in MainWindowViewModel
- Replace hardcoded EN strings with TranslationSource.Instance lookups
- Uses toolbar.globalSites.count (formatted) and toolbar.globalSites.none keys
- Follows same pattern as PermissionsViewModel.SitesSelectedLabel
2026-04-07 10:06:57 +02:00
Dev 1bf47b5c4e feat(06-04): update PermissionsViewModel for multi-site global consumption
- Add _hasLocalSiteOverride field to track local user selection
- Override OnGlobalSitesChanged to pre-populate SelectedSites from global sites
- Set _hasLocalSiteOverride=true when user picks sites via site picker dialog
- Reset _hasLocalSiteOverride=false on tenant switch (OnTenantSwitched)
2026-04-07 10:06:57 +02:00
Dev 185642f4af feat(06-03): add EN/FR localization keys for global site picker toolbar
- Add toolbar.selectSites, toolbar.selectSites.tooltip, toolbar.selectSites.tooltipDisabled
- Add toolbar.globalSites.count and toolbar.globalSites.none to both Strings.resx and Strings.fr.resx
2026-04-07 10:06:40 +02:00
Dev a39c87d43e docs(06-01): complete GlobalSitesChangedMessage and FeatureViewModelBase plan
- 06-01-SUMMARY.md created with deviations and decisions documented
- STATE.md updated: progress 40%, decisions added, session recorded
- ROADMAP.md updated: phase 6 in-progress (2/5 summaries)
2026-04-07 10:05:16 +02:00
Dev 95bf9c2eed docs(06-02): complete MainWindowViewModel global site selection plan
- Add 06-02-SUMMARY.md with execution results and dependency graph
- Update STATE.md: progress 20%, decision logged, session recorded
- Update ROADMAP.md: phase 6 in progress (1/5 plans complete)
- Mark SITE-01 requirement complete in REQUIREMENTS.md
2026-04-07 10:04:36 +02:00
Dev d4fe169bd8 feat(06-01): extend FeatureViewModelBase with GlobalSites support
- Add protected GlobalSites property (IReadOnlyList<SiteInfo>) initialized to Array.Empty
- Register GlobalSitesChangedMessage in OnActivated alongside TenantSwitchedMessage
- Add private OnGlobalSitesReceived to update GlobalSites and invoke virtual hook
- Add protected virtual OnGlobalSitesChanged for derived VMs to override
- [Rule 3 - Blocking] Fix MainWindowViewModel missing ExecuteOpenGlobalSitePicker and BroadcastGlobalSites stubs referenced in constructor (pre-existing partial state from earlier TODO commit)
2026-04-07 10:03:40 +02:00
Dev a10f03edc8 feat(06-02): add global site selection state, command, and broadcast to MainWindowViewModel
- Add OpenGlobalSitePickerDialog factory property (dialog factory pattern)
- Add GlobalSelectedSites ObservableCollection<SiteInfo>
- Add GlobalSitesSelectedLabel computed property for toolbar display
- Add OpenGlobalSitePickerCommand (disabled when no profile selected)
- Broadcast GlobalSitesChangedMessage via WeakReferenceMessenger on collection change
- Clear GlobalSelectedSites on tenant switch (OnSelectedProfileChanged)
- Clear GlobalSelectedSites on session clear (ClearSessionAsync)
- Add using SharepointToolbox.Views.Dialogs for SitePickerDialog cast
2026-04-07 10:03:30 +02:00
Dev 7874fa8524 feat(06-01): create GlobalSitesChangedMessage
- New ValueChangedMessage<IReadOnlyList<SiteInfo>> following TenantSwitchedMessage pattern
- Carries snapshot of globally selected sites (IReadOnlyList — immutable by design)
2026-04-07 10:02:20 +02:00
DevandClaude Opus 4.6 6ae3629301 docs(06): create phase plan for global site selection (5 plans, 3 waves)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:57:15 +02:00
DevandClaude Opus 4.6 59efdfe3f0 docs: create milestone v1.1 roadmap (4 phases)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:41:49 +02:00
DevandClaude Opus 4.6 04a307b69c docs: define milestone v1.1 requirements (10 requirements)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:40:02 +02:00
DevandClaude Opus 4.6 81da0f6a99 docs: start milestone v1.1 Enhanced Reports
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:38:28 +02:00
DevandClaude Opus 4.6 0fb35de80f docs: capture todo - Add global multi-site selection option
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:33:05 +02:00
DevandClaude Opus 4.6 724fdc550d chore: complete v1.0 milestone
Archive 5 phases (36 plans) to milestones/v1.0-phases/.
Archive roadmap, requirements, and audit to milestones/.
Evolve PROJECT.md with shipped state and validated requirements.
Collapse ROADMAP.md to one-line milestone summary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:19:03 +02:00
DevandClaude Opus 4.6 b815c323d7 fix: resolve post-milestone tech debt items
- Add DataGrid RowStyle with red highlighting for invalid CSV rows
  in BulkMembersView, BulkSitesView, and FolderStructureView
- Fix cancel test locale mismatch by setting EN culture before assertion
- Remove dead FeatureTabBase placeholder (replaced by full tab views)
- Clean up unused xmlns:controls from MainWindow.xaml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 09:15:02 +02:00
DevandClaude Opus 4.6 c81d8959f7 docs(phase-05): complete phase execution — verification passed, human approved
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:51:50 +02:00
DevandClaude Sonnet 4.6 b3686cc24c docs(05-03): complete integration gate and human sign-off plan
- 134 tests pass, 22 skip, 0 fail across all three Phase 5 workstreams
- Single-file EXE (201 MB, 0 loose DLLs) verified
- Human smoke test approved: French locale correct, all 10 tabs render
- Phase 5 and project marked complete in STATE.md and ROADMAP.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 16:51:53 +02:00
Dev e0e3d55013 chore(05-03): verify full test suite and publish artifact
- 134 pass, 22 skip (MSAL interactive), 0 fail — all new helper + locale tests green
- dotnet publish -p:PublishSingleFile=true produces SharepointToolbox.exe (201 MB)
- 0 loose DLL files in ./publish/ — single-file self-contained confirmed
2026-04-03 16:39:00 +02:00
Dev 0758ce9593 docs(05-01): complete helper unit tests and locale completeness plan
- SUMMARY.md: 2 tasks, 5 files, 12 new tests all passing
- STATE.md: updated progress, decisions, session
- ROADMAP.md: phase 5 progress updated (2/3 summaries)
2026-04-03 16:37:34 +02:00
Dev 711f9502f2 docs(05-02): complete French locale and single-file publish plan
- 05-02-SUMMARY.md: 27 FR diacritic fixes + conditional PublishSingleFile
- STATE.md: progress 97%, session updated, decisions recorded
- ROADMAP.md: Phase 5 progress updated (2/3 summaries)
- REQUIREMENTS.md: FOUND-11 marked complete
2026-04-03 16:37:31 +02:00
Dev 8c6539440c feat(05-01): add FR locale completeness tests
- Test 1 (AllEnKeys_HaveNonEmptyFrTranslation): verifies every EN key has a non-empty, non-bracketed FR translation
- Test 2 (FrStrings_ContainExpectedDiacritics): spot-checks 5 keys for correct diacritics (é/è)
- Both tests pass — FR file already contains correct diacritics
2026-04-03 16:36:08 +02:00
Dev 39517d8956 feat(05-02): add self-contained single-file publish configuration
- Added conditional PropertyGroup for PublishSingleFile=true
- Sets SelfContained=true, RuntimeIdentifier=win-x64,
  IncludeNativeLibrariesForSelfExtract=true
- Conditional activation avoids affecting dotnet build and dotnet test
- Produces single SharepointToolbox.exe with zero loose DLL files
- PublishTrimmed remains false (required by PnP.Framework + MSAL)
2026-04-03 16:36:07 +02:00
Dev f7829f0801 fix(05-02): correct French diacritics in Strings.fr.resx
- Fixed 27 strings with missing accents across Transfer, BulkMembers,
  BulkSites, FolderStruct, Templates, and shared bulk operation keys
- Corrected: Bibliothèque, Déplacer, Écraser, Démarrer, transférer,
  Aperçu, Créer, Propriétaires, Modèles, Sélectionner, Terminé, etc.
2026-04-03 16:35:34 +02:00
Dev 4d7e9ea02a feat(05-01): make helper methods internal and add unit tests
- Changed IsThrottleException to internal static in ExecuteQueryRetryHelper
- Changed BuildPagedViewXml to internal static in SharePointPaginationHelper
- Created ExecuteQueryRetryHelperTests: 5 tests (throttle true x3, non-throttle false, nested false)
- Created SharePointPaginationHelperTests: 5 tests (null, empty, whitespace, replace, append)
2026-04-03 16:34:54 +02:00
DevandClaude Opus 4.6 0122a47c9e docs(05): create phase plan for distribution and hardening
3 plans in 2 waves: helper tests + locale completeness (W1), FR diacritics + publish config (W1), verification + human checkpoint (W2).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:40:41 +02:00
DevandClaude Opus 4.6 0dc2a2d8e4 docs(phase-5): add research and validation strategy
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 14:29:51 +02:00
DevandClaude Sonnet 4.6 af2177046f docs(phase-05): research distribution and hardening phase
Verified single-file publish works with IncludeNativeLibrariesForSelfExtract,
documented 25+ FR diacritic gaps, and mapped retry/pagination test coverage gaps.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 14:27:51 +02:00
DevandClaude Opus 4.6 1d5dde9ceb docs(phase-04): complete phase execution — verification passed, human approved
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 13:52:45 +02:00
DevandClaude Opus 4.6 3d62b2c48b fix(04): resolve null-reference crashes in CsvValidationService and TransferView
- Add null-conditional on CsvReader.Context.Parser to fix CS8602 warnings
- Guard ConflictCombo_SelectionChanged against null ViewModel during XAML init

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:06:25 +02:00
Dev a1c2a68cb5 docs(04-10): complete TemplatesViewModel + DI registration + MainWindow wiring plan — Phase 4 complete
- SUMMARY.md: 7 files created/modified, 1 auto-fix (missing converter classes), checkpoint:human-verify pending
- STATE.md: Phase 4 complete (10/10 plans), progress 100%, decisions recorded
- ROADMAP.md: Phase 4 marked Complete (10/10 summaries)
2026-04-03 10:26:44 +02:00
Dev 988bca844b feat(04-10): register Phase 4 DI + wire MainWindow tabs + TemplatesView
- App.xaml.cs: register TemplateRepository, GraphClientFactory, ICsvValidationService, BulkResultCsvExportService
- App.xaml.cs: register BulkMemberService, BulkSiteService, ITemplateService, IFolderStructureService
- App.xaml.cs: register all 5 Phase 4 ViewModels and Views (Transfer, BulkMembers, BulkSites, FolderStructure, Templates)
- MainWindow.xaml: replace 3 FeatureTabBase stub tabs with 5 named TabItems (tab.transfer through tab.templates)
- MainWindow.xaml.cs: wire all 5 new TabItem.Content from DI-resolved Views
2026-04-03 10:24:32 +02:00
Dev a49bbb9f98 feat(04-10): create TemplatesViewModel and TemplatesView
- TemplatesViewModel: list, capture with 5 options, apply, rename, delete, refresh
- TemplatesView: capture section with checkboxes, apply section, template DataGrid
- RenameInputDialog: simple WPF dialog (no Microsoft.VisualBasic dependency)
- Capture/Apply are separate async commands from RunCommand
2026-04-03 10:24:23 +02:00
Dev 87dd4bb3ef feat(04-08,04-09): create Transfer/BulkMembers/BulkSites/FolderStructure ViewModels and Views
- TransferViewModel: source/dest site selection, Copy/Move mode, conflict policy, export failed
- TransferView: SitePickerDialog and FolderBrowserDialog wiring, confirm dialog
- BulkMembersViewModel, BulkSitesViewModel: CSV import, validate, preview, execute, retry, export
- FolderStructureViewModel: CSV import, site URL + library inputs, folder creation
- All 3 bulk Views: ConfirmBulkOperationDialog wiring, DataGrid preview with validation status
- Added EnumBoolConverter, StringToVisibilityConverter, ListToStringConverter to converters file
2026-04-03 10:23:54 +02:00
Dev 93218b0953 docs(04-09): complete BulkMembers, BulkSites, and FolderStructure ViewModels + Views plan
- SUMMARY.md: 9 files created, 2 auto-fixed deviations documented
- STATE.md: position advanced to plan 09 of 10, 2 new decisions recorded
- ROADMAP.md: phase 4 progress updated to 9/10 summaries
2026-04-03 10:22:07 +02:00
DevandClaude Sonnet 4.6 57f2c1d304 docs(04-08): complete TransferViewModel + TransferView plan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:20:32 +02:00
Dev fcd5d1d938 feat(04-09): create BulkMembers, BulkSites, and FolderStructure ViewModels and Views
- BulkMembersViewModel: CSV import, validate, preview, confirm, execute, retry failed, export failed
- BulkSitesViewModel: same flow using IBulkSiteService.CreateSitesAsync
- FolderStructureViewModel: site URL + library inputs, CSV folders, FolderStructureService.BuildUniquePaths
- BulkMembersView/BulkSitesView/FolderStructureView: XAML + code-behind wiring ConfirmBulkOperationDialog
- [Rule 3] Fixed duplicate converter definitions: removed untracked standalone EnumBoolConverter/StringToVisibilityConverter/ListToStringConverter files (already defined in IndentConverter.cs)
2026-04-03 10:20:23 +02:00
Dev 7b78b19bf5 feat(04-08): create TransferViewModel and TransferView
- TransferViewModel: source/dest site selection, transfer mode, conflict policy, confirmation dialog, per-item results, failed-items CSV export
- TransferView.xaml: DockPanel layout with GroupBoxes for source/dest, mode radio buttons, conflict policy ComboBox, progress bar, cancel button, export failed items button
- TransferView.xaml.cs: code-behind wires SitePickerDialog + FolderBrowserDialog for source and dest browsing
- Added EnumBoolConverter and StringToVisibilityConverter to IndentConverter.cs
- Registered converters in App.xaml; registered TransferViewModel, TransferView, IFileTransferService, BulkResultCsvExportService in App.xaml.cs
2026-04-03 10:19:16 +02:00
Dev 509c0c6843 docs(04-07): complete Localization + Shared Dialogs + Example CSV Resources plan
- Create 04-07-SUMMARY.md with task details, decisions, and self-check results
- Update STATE.md: progress 91%, decisions recorded, session updated
- Update ROADMAP.md: phase 4 progress (7/10 summaries)
2026-04-03 10:15:06 +02:00
Dev 1a2cc13224 feat(04-07): add Phase 4 localization, shared dialogs, and example CSV resources
- Add 80+ Phase 4 EN/FR localization keys to Strings.resx and Strings.fr.resx (tabs, transfer, bulkmembers, bulksites, folderstruct, templates, bulk-shared, folderbrowser)
- Add ResourceManager property accessors for all new keys to Strings.Designer.cs
- Create ConfirmBulkOperationDialog (XAML + code-behind) with Proceed/Cancel buttons
- Create FolderBrowserDialog (XAML + code-behind) with lazy-loading TreeView of SharePoint libraries/folders
- Bundle bulk_add_members.csv, bulk_create_sites.csv, folder_structure.csv as EmbeddedResource in csproj
2026-04-03 10:13:39 +02:00
DevandClaude Sonnet 4.6 fdb1108e76 docs(04-06): complete TemplateService + FolderStructureService plan — CSOM template capture/apply and CSV folder hierarchy creation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:09:31 +02:00
Dev 84cd569fb7 feat(04-06): implement TemplateService and FolderStructureService
- FolderStructureService.CreateFoldersAsync creates folder hierarchy from CSV rows using BulkOperationRunner
- FolderStructureService.BuildUniquePaths deduplicates and sorts paths parent-first by slash depth
- TemplateService already committed; verified compilation and interface compliance
- FolderStructureServiceTests: 4 unit tests pass (BuildUniquePaths edge cases, deduplication, empty levels, BuildPath) + 1 skip
- TemplateServiceTests: 3 unit tests pass (interface impl, SiteTemplate defaults, SiteTemplateOptions defaults) + 2 skip
2026-04-03 10:07:49 +02:00
Dev 773393c4c0 docs(04-04): complete BulkMemberService plan — Graph API member addition with CSOM fallback
- Create 04-04-SUMMARY.md with full execution details and deviation docs
- Update STATE.md: plan 04 complete, new decisions, session record
- Update REQUIREMENTS.md: BULK-02 marked complete (BULK-04/05 already done in 04-01)
2026-04-03 10:06:37 +02:00
Dev c4d8124a81 docs(04-02): complete CsvValidationService + TemplateRepository plan
- 9 CsvValidationService tests passing (delimiter detection, BOM, member/site/folder validation)
- 6 TemplateRepository tests passing (round-trip, GetAll, delete, rename, empty dir, non-existent)
- All 10 previously-skipped scaffold tests now active and passing (15 total)
- Requirements TMPL-03, TMPL-04, FOLD-02 marked complete
2026-04-03 10:05:21 +02:00
DevandClaude Sonnet 4.6 0cf6f50448 docs(04-03): complete FileTransferService plan — CSOM file transfer with conflict policies
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:05:00 +02:00
DevandClaude Sonnet 4.6 98fa16a195 docs(04-05): complete BulkSiteService plan — PnP Framework Team + Communication site creation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:04:03 +02:00
Dev f3a1c352c7 feat(04-02): implement CsvValidationService and TemplateRepository with tests
- CsvValidationService: CsvHelper-based parsing with DetectDelimiter, BOM detection,
  per-row validation for BulkMemberRow/BulkSiteRow/FolderStructureRow
- TemplateRepository: atomic JSON write (tmp + File.Move) with SemaphoreSlim,
  supports GetAll/GetById/Save/Delete/Rename operations
- CsvValidationServiceTests: 9 passing tests (email validation, delimiter detection,
  BOM handling, folder/site/member validation)
- TemplateRepositoryTests: 6 passing tests (round-trip, GetAll, delete, rename,
  empty directory, non-existent id)
- All previously-skipped scaffold tests now active and passing (15 total)
2026-04-03 10:03:41 +02:00
Dev ac74d31933 feat(04-03): implement FileTransferService with MoveCopyUtil and conflict policies
- FileTransferService.cs: CSOM copy/move via MoveCopyUtil.CopyFileByPath/MoveFileByPath
- Conflict policies: Skip (catch ServerException), Overwrite (overwrite=true), Rename (KeepBoth=true)
- ResourcePath.FromDecodedUrl for special character support
- Recursive folder enumeration with system folder filtering
- EnsureFolderAsync creates intermediate destination folders
- Best-effort metadata preservation (ResetAuthorAndCreatedOnCopy=false)
- FileTransferServiceTests.cs: 4 passing tests, 3 skipped (integration)
2026-04-03 10:02:57 +02:00
Dev b0956adaa3 feat(04-05): implement BulkSiteService with PnP Framework site creation
- BulkSiteService creates Team sites via TeamSiteCollectionCreationInformation with owners/members
- BulkSiteService creates Communication sites via CommunicationSiteCollectionCreationInformation with generated URL
- Per-site error handling via BulkOperationRunner with continue-on-error semantics
- SanitizeAlias generates URL-safe aliases from site names for Communication sites
- BulkSiteServiceTests: 3 pass (interface check + model defaults + CSV parsing), 3 skip (live SP)
- Fixed pre-existing BulkMemberService.cs Group type ambiguity (MSCSC.Group vs Graph.Models.Group)
2026-04-03 10:02:09 +02:00
Dev fdcd4c8377 docs(04-01): complete Phase 4 Plan 01 — models, interfaces, BulkOperationRunner
- Create 04-01-SUMMARY.md with full execution details and deviation docs
- Update STATE.md: progress 73%, new decisions, session record
- Update ROADMAP.md: Phase 4 In Progress, 1/10 plans complete
- Mark requirements BULK-04 and BULK-05 complete in REQUIREMENTS.md
2026-04-03 09:55:26 +02:00
Dev 39deed9d8d feat(04-01): add Phase 4 models, interfaces, BulkOperationRunner, and test scaffolds
- Install CsvHelper 33.1.0 and Microsoft.Graph 5.74.0 (main + test projects)
- Add 14 core model/enum files (BulkOperationResult, BulkMemberRow, BulkSiteRow, TransferJob, FolderStructureRow, SiteTemplate, SiteTemplateOptions, TemplateLibraryInfo, TemplateFolderInfo, TemplatePermissionGroup, ConflictPolicy, TransferMode, CsvValidationRow)
- Add 6 service interfaces (IFileTransferService, IBulkMemberService, IBulkSiteService, ITemplateService, IFolderStructureService, ICsvValidationService)
- Add BulkOperationRunner with continue-on-error and cancellation support
- Add BulkResultCsvExportService stub (compile-ready)
- Add test scaffolds: BulkOperationRunnerTests (5 passing), BulkResultCsvExportServiceTests (2 passing), CsvValidationServiceTests (6 skipped), TemplateRepositoryTests (4 skipped)
2026-04-03 09:53:05 +02:00
DevandClaude Opus 4.6 d73e50948d docs(04): create Phase 4 plan — 10 plans for Bulk Operations and Provisioning
Wave 0: models, interfaces, BulkOperationRunner, test scaffolds
Wave 1: CsvValidationService, TemplateRepository, FileTransferService,
        BulkMemberService, BulkSiteService, TemplateService, FolderStructureService
Wave 2: Localization, shared dialogs, example CSV resources
Wave 3: TransferVM+View, BulkMembers/BulkSites/FolderStructure VMs+Views,
        TemplatesVM+View, DI registration, MainWindow wiring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 09:38:33 +02:00
DevandClaude Opus 4.6 97fc29c15e docs(04): research phase domain for Bulk Operations and Provisioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 09:17:41 +02:00
DevandClaude Opus 4.6 97d1e10faf docs(state): record phase 4 context session
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 09:07:43 +02:00
DevandClaude Opus 4.6 6dd5faf65d docs(04): capture phase context for Bulk Operations and Provisioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 09:07:34 +02:00
Dev 43dd6ce17f docs(03-08): complete SearchViewModel + DuplicatesViewModel + Views plan — Phase 3 complete
- 3 tasks completed, 9 files created/modified
- Visual checkpoint pending: all three Phase 3 tabs wired and ready for UI verification
2026-04-02 16:10:54 +02:00
Dev 1f2a49d7d3 feat(03-08): DI registration + MainWindow wiring for Search and Duplicates tabs
- App.xaml.cs: register ISearchService, SearchCsvExportService, SearchHtmlExportService, SearchViewModel, SearchView, IDuplicatesService, DuplicatesHtmlExportService, DuplicatesViewModel, DuplicatesView
- MainWindow.xaml: add x:Name to SearchTabItem and DuplicatesTabItem (remove FeatureTabBase stubs)
- MainWindow.xaml.cs: wire SearchTabItem.Content and DuplicatesTabItem.Content via DI
2026-04-02 15:45:29 +02:00
Dev 0984a36bc7 feat(03-08): create DuplicatesViewModel, DuplicatesView XAML and code-behind
- DuplicatesViewModel: ModeFiles/Folders, criteria checkboxes, group flattening to DuplicateRow
- Uses TenantProfile site URL override pattern (ctx.Url is read-only)
- ExportHtmlCommand exports DuplicateGroup list via DuplicatesHtmlExportService
- DuplicatesView.xaml: type selector, criteria panel + flattened DataGrid
- DuplicatesView.xaml.cs: DI constructor with DataContext wiring
2026-04-02 15:44:26 +02:00
Dev 7e6d39a3db feat(03-08): create SearchViewModel, SearchView XAML and code-behind
- SearchViewModel: full filter props, RunOperationAsync via ISearchService
- Uses TenantProfile site URL override pattern (ctx.Url is read-only)
- ExportCsvCommand + ExportHtmlCommand with CanExport guard
- SearchView.xaml: filter panel + DataGrid with all 8 columns
- SearchView.xaml.cs: DI constructor with DataContext wiring
2026-04-02 15:43:22 +02:00
Dev 50c7ab19f5 docs(03-05): complete Search and Duplicate export services plan
- 9/9 export tests pass (6 Search + 3 Duplicates)
- SearchCsvExportService, SearchHtmlExportService, DuplicatesHtmlExportService fully implemented
- Requirements SRCH-03, SRCH-04, DUPL-03 satisfied
2026-04-02 15:40:30 +02:00
Dev 82acc81e13 docs(03-07): complete StorageViewModel and StorageView plan — SUMMARY, STATE, ROADMAP updated 2026-04-02 15:40:07 +02:00
Dev fc1ba00aa8 feat(03-05): implement DuplicatesHtmlExportService with grouped cards
- Replace stub with full grouped HTML export (port of PS Export-DuplicatesToHTML)
- One collapsible card per DuplicateGroup with item count badge and path table
- Uses System.IO.File explicitly per WPF project pattern
- 3/3 DuplicatesHtmlExportServiceTests pass; 9/9 total export tests pass
2026-04-02 15:38:43 +02:00
Dev e08452d1bf feat(03-07): create StorageView XAML, DI registration, and MainWindow wiring
- StorageView.xaml: DataGrid with IndentLevel-based name indentation
- StorageView.xaml.cs: code-behind wiring DataContext to StorageViewModel
- IndentConverter.cs: IndentConverter, BytesConverter, InverseBoolConverter
- App.xaml: register converters and RightAlignStyle as Application.Resources
- App.xaml.cs: register IStorageService, StorageCsvExportService, StorageHtmlExportService, StorageViewModel, StorageView
- MainWindow.xaml: add x:Name=StorageTabItem to Storage TabItem
- MainWindow.xaml.cs: wire StorageTabItem.Content from DI
2026-04-02 15:38:20 +02:00
Dev e174a18350 feat(03-07): create StorageViewModel with IStorageService orchestration and export commands
- Rule 1: Fixed ctx.Url read-only bug — use new TenantProfile with site URL for GetOrCreateContextAsync
- Rule 3: Added missing System.IO using to SearchCsvExportService and SearchHtmlExportService
2026-04-02 15:36:27 +02:00
Dev 9a55c9e7d0 docs(03-04): complete SearchService and DuplicatesService plan — 2/2 tasks, 5 MakeKey tests pass 2026-04-02 15:33:47 +02:00
DevandClaude Sonnet 4.6 e83c4f34f1 docs(03-06): complete Phase 3 localization plan — 54 EN/FR keys added for Storage, Search, Duplicates tabs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 15:32:56 +02:00
Dev 47e6cf62d2 docs(03-03): complete Storage export services plan — CSV and HTML exporters
- Add 03-03-SUMMARY.md: StorageCsvExportService and StorageHtmlExportService
- Update STATE.md: advance to plan 03-04, record metrics and decision
- Update ROADMAP.md: phase 3 progress 3/8 plans complete
2026-04-02 15:32:03 +02:00