diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md
index c6a8565..0b96dd9 100644
--- a/.planning/PROJECT.md
+++ b/.planning/PROJECT.md
@@ -8,28 +8,35 @@ A C#/WPF desktop application for IT administrators and MSPs to audit and manage
Administrators can audit and manage SharePoint/Teams permissions and storage across multiple client tenants from a single, reliable desktop application.
-## Current Milestone: v2.2 Report Branding & User Directory
-
-**Goal:** Add customizable logos to HTML reports and a full user directory browse mode in the user access audit tab.
-
-**Target features:**
-- HTML report branding with MSP logo (global) and client logo (per tenant — pull from tenant or import)
-- User directory browse mode as alternative to search in user access audit tab
-
## Current State
-**Shipped:** v1.1 Enhanced Reports (2026-04-08)
-**Status:** Active milestone v2.2
+**Shipped:** v2.2 Report Branding & User Directory (2026-04-09)
+**Status:** Between milestones — ready for `/gsd:new-milestone`
+
+
+v2.2 shipped features
+
+- HTML report branding with MSP logo (global) and client logo (per tenant)
+- Auto-pull client logo from Entra branding API
+- Logo validation (PNG/JPG, 512 KB limit) with auto-compression
+- User directory browse mode in user access audit tab with paginated load
+- Member/guest filter and department/job title columns
+- Directory user selection triggers existing audit pipeline
+
+
+
+v1.1 shipped features
-**v1.1 shipped features:**
- Global multi-site selection in toolbar (pick sites once, all tabs use them)
- User access audit tab with Graph API people-picker, direct/group/inherited access distinction
- Simplified permissions with plain-language labels, color-coded risk levels, detail-level toggle
- Storage visualization with LiveCharts2 pie/donut and bar charts by file type
+
Tech stack: C# / WPF / .NET 10 / PnP Framework / Microsoft Graph SDK / MSAL / Serilog / CommunityToolkit.Mvvm / LiveCharts2
-Tests: 205 automated (xUnit), 22 skipped (require live SharePoint tenant)
+Tests: 285 automated (xUnit), 26 skipped (require live SharePoint tenant)
Distribution: 200 MB self-contained EXE (win-x64)
+LOC: ~16,900 C#
## Requirements
@@ -48,10 +55,10 @@ Distribution: 200 MB self-contained EXE (win-x64)
- [x] Simplified permissions reports (plain language, summary views) (SIMP-01/02/03) — v1.1
- [x] Storage metrics graph by file type (pie/donut and bar chart, toggleable) (VIZZ-01/02/03) — v1.1
-### Active
+### Shipped in v2.2
-- [ ] HTML report branding with MSP logo (global) and client logo (per tenant)
-- [ ] User directory browse mode in user access audit tab
+- [x] HTML report branding with MSP and client logos (BRAND-01/02/03/04/05/06) — v2.2
+- [x] User directory browse mode in user access audit tab (UDIR-01/02/03/04/05) — v2.2
### Out of Scope
@@ -68,8 +75,9 @@ Distribution: 200 MB self-contained EXE (win-x64)
- **v1.0 shipped** with full feature parity: permissions, storage, search, duplicates, bulk operations, templates, folder provisioning
- **v1.1 shipped** with enhanced reports: user access audit, simplified permissions, storage charts, global site selection
-- **Localization:** 220+ EN/FR keys, full parity verified
-- **Architecture:** 120+ C# files + 17 XAML files across Core/Infrastructure/Services/ViewModels/Views layers
+- **v2.2 shipped** with report branding (logos in HTML exports) and user directory browse mode
+- **Localization:** 230+ EN/FR keys, full parity verified
+- **Architecture:** 140+ C# files + 17 XAML files across Core/Infrastructure/Services/ViewModels/Views layers
## Constraints
@@ -93,4 +101,4 @@ Distribution: 200 MB self-contained EXE (win-x64)
| Wave 0 scaffold pattern | Models + interfaces + test stubs before implementation | ✓ Good — all phases had test targets from day 1 |
---
-*Last updated: 2026-04-08 after v2.2 milestone started*
+*Last updated: 2026-04-09 after v2.2 milestone shipped*
diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 076b775..2db97c8 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -4,7 +4,7 @@
- ✅ **v1.0 MVP** — Phases 1-5 (shipped 2026-04-07) — [archive](milestones/v1.0-ROADMAP.md)
- ✅ **v1.1 Enhanced Reports** — Phases 6-9 (shipped 2026-04-08) — [archive](milestones/v1.1-ROADMAP.md)
-- 🔄 **v2.2 Report Branding & User Directory** — Phases 10-14 (active)
+- ✅ **v2.2 Report Branding & User Directory** — Phases 10-14 (shipped 2026-04-09) — [archive](milestones/v2.2-ROADMAP.md)
## Phases
@@ -29,90 +29,16 @@
-### v2.2 Report Branding & User Directory (Phases 10-14)
+
+✅ v2.2 Report Branding & User Directory (Phases 10-14) — SHIPPED 2026-04-09
-- [x] **Phase 10: Branding Data Foundation** — Models, repository, and services for logo storage and user directory enumeration (completed 2026-04-08)
-- [x] **Phase 11: HTML Export Branding + ViewModel Integration** — Inject logos into all 5 HTML report types; wire branding into export-triggering ViewModels and logo management commands (completed 2026-04-08)
-- [x] **Phase 12: Branding UI Views** — Settings and profile dialog logo sections with live preview; auto-pull client logo from Entra branding API (completed 2026-04-08)
-- [x] **Phase 13: User Directory ViewModel** — Browse mode state, paginated directory load, member/guest filter, and department/job title columns (completed 2026-04-08)
-- [x] **Phase 14: User Directory View** — Toggle panel in UserAccessAuditView, user selection to trigger existing audit pipeline (completed 2026-04-09)
+- [x] Phase 10: Branding Data Foundation (3/3 plans) — completed 2026-04-08
+- [x] Phase 11: HTML Export Branding + ViewModel Integration (4/4 plans) — completed 2026-04-08
+- [x] Phase 12: Branding UI Views (3/3 plans) — completed 2026-04-08
+- [x] Phase 13: User Directory ViewModel (2/2 plans) — completed 2026-04-08
+- [x] Phase 14: User Directory View (2/2 plans) — completed 2026-04-09
-## Phase Details
-
-### Phase 10: Branding Data Foundation
-**Goal**: The application can store, validate, and retrieve MSP and client logos as portable base64 strings in JSON, and can enumerate a full tenant user list with pagination.
-**Depends on**: Nothing (additive to existing infrastructure)
-**Requirements**: BRAND-01, BRAND-03, BRAND-06
-**Success Criteria** (what must be TRUE):
- 1. An MSP logo imported as a PNG or JPG file is persisted as a base64 string in `branding.json` and survives an application restart
- 2. A client logo imported per tenant profile is persisted as a base64 string inside the tenant's profile JSON and is not affected by other tenants' profiles
- 3. A file larger than 512 KB or not a valid PNG/JPG is rejected at import time with an error; no invalid data reaches the JSON store
- 4. `GraphUserDirectoryService.GetUsersAsync` returns all enabled member users for a tenant, following `@odata.nextLink` until exhausted, without truncating at 999
-**Plans**: 3 plans
-Plans:
-- [x] 10-01-PLAN.md — Logo models, BrandingRepository, BrandingService with validation/compression
-- [x] 10-02-PLAN.md — GraphUserDirectoryService with PageIterator pagination
-- [x] 10-03-PLAN.md — DI registration in App.xaml.cs and full test suite gate
-
-### Phase 11: HTML Export Branding + ViewModel Integration
-**Goal**: All five HTML reports display MSP and client logos in a consistent header, and administrators can manage logos from Settings and the profile dialog without touching the View layer.
-**Depends on**: Phase 10
-**Requirements**: BRAND-05, BRAND-04
-**Success Criteria** (what must be TRUE):
- 1. Running any of the five HTML exports (Permissions, Storage, Search, Duplicates, User Access) produces an HTML file whose header contains the MSP logo `
` tag when an MSP logo is configured
- 2. When a client logo is configured for the active tenant, the same HTML export header contains both the MSP logo and the client logo side by side
- 3. When no logo is configured, the HTML export header contains no broken image placeholder and the report renders identically to the pre-branding output
- 4. SettingsViewModel exposes browse/clear commands for MSP logo; ProfileManagementViewModel exposes browse/clear commands for client logo — both commands are exercisable without opening any View
- 5. Auto-pulling the client logo from the tenant's Entra branding API stores the logo in the tenant profile and falls back silently when no Entra branding is configured
-**Plans**: 4 plans
-Plans:
-- [ ] 11-01-PLAN.md — ReportBranding model + BrandingHtmlHelper static class with unit tests
-- [ ] 11-02-PLAN.md — Add optional branding param to all 5 HTML export services
-- [ ] 11-03-PLAN.md — Wire IBrandingService into all 5 export ViewModels
-- [ ] 11-04-PLAN.md — Logo management commands (Settings + Profile) and Entra auto-pull
-
-### Phase 12: Branding UI Views
-**Goal**: Administrators can see, import, preview, and clear logos directly in the Settings and profile management dialogs.
-**Depends on**: Phase 11
-**Requirements**: BRAND-02, BRAND-04 (view layer for Entra pull)
-**Success Criteria** (what must be TRUE):
- 1. Opening Settings shows the MSP logo section: an import button, a live thumbnail preview of the current logo, and a clear button that removes the logo immediately
- 2. Opening a tenant profile dialog shows the client logo section with the same import/preview/clear controls
- 3. Importing a logo via the UI shows the thumbnail preview without requiring an application restart
- 4. Clicking "Pull from Entra" in the profile dialog fetches and displays the tenant's banner logo if one exists, and shows a clear user-facing message if none is configured
-**Plans**: 3 plans
-Plans:
-- [x] 12-01-PLAN.md — Base64ToImageSourceConverter, localization keys, App.xaml registration, ClientLogoPreview property
-- [x] 12-02-PLAN.md — SettingsView MSP logo section (preview, import, clear)
-- [x] 12-03-PLAN.md — ProfileManagementDialog client logo section (preview, import, clear, Entra pull)
-
-### Phase 13: User Directory ViewModel
-**Goal**: The UserAccessAuditViewModel supports a full directory browse mode with paginated load, member/guest filtering, and department/job title display, fully testable without the View.
-**Depends on**: Phase 10
-**Requirements**: UDIR-01, UDIR-02, UDIR-03, UDIR-04
-**Success Criteria** (what must be TRUE):
- 1. `UserAccessAuditViewModel` exposes a toggle property that switches between Search mode (existing people-picker behavior) and Browse mode (directory list behavior), with no regression to Search mode behavior
- 2. Invoking the load-directory command fetches all enabled member users via `PageIterator`, updates a progress observable with the running user count, and supports cancellation mid-load
- 3. A "Members only / Include guests" toggle filters the displayed list in-memory without issuing a new Graph request
- 4. Each user row in the observable collection exposes DisplayName, UPN, Department, and JobTitle; Department and JobTitle columns are visible and sortable in the ViewModel's `ICollectionView`
-**Plans**: 2 plans
-Plans:
-- [x] 13-01-PLAN.md — Extend GraphDirectoryUser with UserType + service includeGuests parameter
-- [x] 13-02-PLAN.md — UserAccessAuditViewModel directory browse mode (toggle, load, filter, sort, tests)
-
-### Phase 14: User Directory View
-**Goal**: Administrators can toggle into directory browse mode from the user access audit tab, see the paginated user list with filters, and launch an access audit for a selected user.
-**Depends on**: Phase 13
-**Requirements**: UDIR-05, UDIR-01 (view layer)
-**Success Criteria** (what must be TRUE):
- 1. The user access audit tab shows a mode toggle control (e.g., radio buttons or segmented control) that visibly switches the left panel between the existing people-picker and the directory browse panel
- 2. In browse mode, selecting a user from the directory list and clicking Run Audit (or equivalent) launches the existing audit pipeline for that user, producing the same results as if the user had been found via search
- 3. While the directory is loading, the panel shows a "Loading... X users" counter and an active cancel button; the load button is disabled to prevent concurrent requests
- 4. When the directory load is cancelled or fails, the panel returns to a ready state with a clear status message and no broken UI
-**Plans**: 2 plans
-Plans:
-- [x] 14-01-PLAN.md — Localization keys (EN+FR), SelectDirectoryUserCommand, code-behind double-click handler
-- [x] 14-02-PLAN.md — XAML: mode toggle (Search/Browse RadioButtons), directory DataGrid, loading UX, shared SelectedUsers panel
+
## Progress
@@ -120,8 +46,4 @@ Plans:
|-------|-----------|-------|--------|-----------|
| 1-5 | v1.0 | 36/36 | Shipped | 2026-04-07 |
| 6-9 | v1.1 | 25/25 | Shipped | 2026-04-08 |
-| 10. Branding Data Foundation | v2.2 | 3/3 | Complete | 2026-04-08 |
-| 11. HTML Export Branding + ViewModel Integration | 4/4 | Complete | 2026-04-08 | — |
-| 12. Branding UI Views | 3/3 | Complete | 2026-04-08 | — |
-| 13. User Directory ViewModel | 2/2 | Complete | 2026-04-08 | — |
-| 14. User Directory View | 2/2 | Complete | 2026-04-09 | — |
+| 10-14 | v2.2 | 14/14 | Shipped | 2026-04-09 |
diff --git a/.planning/STATE.md b/.planning/STATE.md
index f1f3c74..b187d71 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -1,37 +1,38 @@
---
gsd_state_version: 1.0
-milestone: v2.2
-milestone_name: Report Branding & User Directory
-status: completed
-stopped_at: Completed 14-02-PLAN.md
-last_updated: "2026-04-09T07:30:58.818Z"
-last_activity: 2026-04-08 — Phase 11 planning completed
+milestone: none
+milestone_name: Between milestones
+status: idle
+stopped_at: v2.2 milestone archived
+last_updated: "2026-04-09"
+last_activity: 2026-04-09 — v2.2 milestone completed and archived
progress:
- total_phases: 5
- completed_phases: 5
- total_plans: 14
- completed_plans: 14
+ total_phases: 0
+ completed_phases: 0
+ total_plans: 0
+ completed_plans: 0
---
# Project State
## Project Reference
-See: .planning/PROJECT.md (updated 2026-04-08)
+See: .planning/PROJECT.md (updated 2026-04-09)
**Core value:** Administrators can audit and manage SharePoint/Teams permissions and storage across multiple client tenants from a single, reliable desktop application.
-**Current focus:** v2.2 Report Branding & User Directory — HTML report logos (Phases 10-12), user directory browse mode (Phases 13-14)
+**Current focus:** Between milestones — v2.2 shipped, ready for `/gsd:new-milestone`
## Current Position
-Phase: 11 (planned, ready to execute)
-Plan: 4 plans (11-01 through 11-04) in 3 waves
-Status: Phase 10 complete, Phase 11 planned — ready to execute
-Last activity: 2026-04-08 — Phase 11 planning completed
+Phase: None (between milestones)
+Status: v2.2 Report Branding & User Directory shipped 2026-04-09
+Next step: `/gsd:new-milestone` to start next milestone
-```
-v2.2 Progress: [██░░░░░░░░] 20% (1/5 phases, 3/7 plans)
-```
+## Shipped Milestones
+
+- v1.0 MVP — Phases 1-5 (shipped 2026-04-07)
+- v1.1 Enhanced Reports — Phases 6-9 (shipped 2026-04-08)
+- v2.2 Report Branding & User Directory — Phases 10-14 (shipped 2026-04-09)
## Accumulated Context
@@ -39,48 +40,9 @@ v2.2 Progress: [██░░░░░░░░] 20% (1/5 phases, 3/7 plans)
Decisions are logged in PROJECT.md Key Decisions table.
-**v2.2 architectural decisions (locked at roadmap):**
-- Logos stored as base64 strings in JSON (not file paths). `BrandingSettings.cs` holds MSP logo; `TenantProfile` holds client logo. File path is discarded after import. This decision is locked — all downstream phases depend on it.
-- Client logo lives on `TenantProfile`, NOT in `BrandingSettings`. Per-tenant ownership; prevents serialization and deletion awkwardness.
-- Export services use optional `ReportBranding? branding = null` parameter. All existing call sites compile unchanged. No new `IHtmlExportService` interface needed.
-- `GraphUserDirectoryService` is a new service, separate from `GraphUserSearchService`. Different pagination model (`PageIterator`), different cancellation needs.
-- Directory does NOT load automatically on tab open. Explicit "Load Directory" button required to avoid blocking UI on large tenants.
-- SVG logo support: rejected. XSS risk in data-URIs. PNG/JPG only.
-- No new NuGet packages for v2.2. All capabilities provided by existing stack (BCL, Microsoft.Graph 5.74.0, WPF PresentationCore).
-
-**v1.1 architectural notes (carried forward):**
-- Global site selection (Phase 6) changes the toolbar; all tabs bind to shared `GlobalSiteSelectionViewModel`. `WeakReferenceMessenger` for cross-tab site-changed notifications.
-- Per-tab override (SITE-02): each `FeatureViewModelBase` subclass stores a nullable local site override; null means "use global".
-- Storage Visualization (Phase 9): LiveCharts2, WPF-native, self-contained friendly.
-- [Phase 10-branding-data-foundation]: No ConsistencyLevel header on equality filter for GetUsersAsync (unlike GraphUserSearchService startsWith which requires it)
-- [Phase 10-branding-data-foundation]: MapUser extracted as internal static in GraphUserDirectoryService for direct unit testability without live Graph endpoint
-- [Phase 10-branding-data-foundation]: Type alias AppGraphClientFactory used in GraphUserDirectoryService to disambiguate from Microsoft.Graph.GraphClientFactory
-- [Phase 10-branding-data-foundation]: Used WPF PresentationCore (BitmapDecoder/TransformedBitmap/JpegBitmapEncoder) for image compression instead of System.Drawing.Bitmap — System.Drawing.Common is not available without a new NuGet package on .NET 10, and WPF PresentationCore is already in the stack
-- [Phase 10-branding-data-foundation]: LogoData is a non-positional record with init properties (not positional constructor) to avoid System.Text.Json deserialization failure
-- [Phase 10-branding-data-foundation]: No new using statements required for Phase 10 DI registrations — SharepointToolbox.Infrastructure.Persistence and SharepointToolbox.Services were already imported
-- [Phase 11-html-export-branding]: BrandingHtmlHelper is internal — only used within Services.Export namespace, tests access via InternalsVisibleTo
-- [Phase 11-html-export-branding]: InternalsVisibleTo added via MSBuild AssemblyAttribute ItemGroup in csproj
-- [Phase 11-html-export-branding]: branding parameter placed AFTER CancellationToken ct in WriteAsync — existing positional callers unaffected
-- [Phase 11-html-export-branding]: MakeBranding helper added locally to each test class — test files stay self-contained
-- [Phase 11]: Test constructors on 3 ViewModels received optional IBrandingService? brandingService = null as last parameter to preserve all existing test call sites
-- [Phase 11]: Guard clause (if _brandingService is not null) used for graceful degradation — branding = null fallback preserves backward compat
-- [Phase 11]: No App.xaml.cs changes needed for ViewModel branding injection — IBrandingService already registered as singleton, ViewModel registrations auto-resolve
-- [Phase 12]: Skipped BitmapImage creation test due to missing Xunit.StaFact; STA thread required for WPF BitmapImage
-- [Phase 12]: Used Grid overlay with DataTrigger for logo/placeholder visibility toggle in SettingsView
-- [Phase 12]: Label+StackPanel layout for logo section in ProfileManagementDialog, consistent with SettingsView pattern
-- [Phase 13]: UserType added as last positional param for backward compat; includeGuests defaults false; userType always in Select
-- [Phase 13]: Directory always fetches with includeGuests=true from Graph; member/guest filtering is in-memory via ICollectionView
-- [Phase 13]: Separate _directoryCts for directory load cancellation (independent from base class _cts)
-- [Phase 14]: SelectDirectoryUserCommand does not clear SearchQuery/SearchResults since it operates in browse mode context
-- [Phase 14]: Used DataTrigger inverse visibility for search panel instead of ConverterParameter=Inverse
-- [Phase 14]: Used plain English DataGrid column headers -- DataGridTextColumn.Header binding is unreliable in WPF
-
### Pending Todos
-- Confirm `$filter=accountEnabled eq true and userType eq 'Member'` behavior without `ConsistencyLevel: eventual` against a real tenant before Phase 13 planning.
-- Verify Entra `bannerLogo` stream endpoint returns empty body (not HTTP 404) when no tenant branding is configured — determines error handling branch for BRAND-04 auto-pull.
-- Decide report header layout before Phase 11: logos side-by-side (current spec: `display: flex; gap: 16px`, MSP left + client right).
-- Decide "Load Directory" button placement before Phase 14: inside browse panel (recommended) or tab-level toolbar.
+None — milestone complete.
### Blockers/Concerns
@@ -88,7 +50,7 @@ None.
## Session Continuity
-Last session: 2026-04-09T07:30:58.816Z
-Stopped at: Completed 14-02-PLAN.md
+Last session: 2026-04-09
+Stopped at: v2.2 milestone archived
Resume file: None
-Next step: `/gsd:execute-phase 11`
+Next step: `/gsd:new-milestone`
diff --git a/.planning/REQUIREMENTS.md b/.planning/milestones/v2.2-REQUIREMENTS.md
similarity index 59%
rename from .planning/REQUIREMENTS.md
rename to .planning/milestones/v2.2-REQUIREMENTS.md
index 0941575..8e2db8a 100644
--- a/.planning/REQUIREMENTS.md
+++ b/.planning/milestones/v2.2-REQUIREMENTS.md
@@ -1,11 +1,10 @@
-# Requirements: SharePoint Toolbox v2.2
+# Requirements Archive: SharePoint Toolbox v2.2 Report Branding & User Directory
**Defined:** 2026-04-08
-**Core Value:** Administrators can audit and manage SharePoint/Teams permissions and storage across multiple client tenants from a single, reliable desktop application.
+**Completed:** 2026-04-09
+**Coverage:** 11/11 requirements complete
-## v2.2 Requirements
-
-Requirements for v2.2 Report Branding & User Directory. Each maps to roadmap phases.
+## Requirements
### Report Branding
@@ -24,15 +23,26 @@ Requirements for v2.2 Report Branding & User Directory. Each maps to roadmap pha
- [x] **UDIR-04**: User can see department and job title columns in directory list
- [x] **UDIR-05**: User can select one or more users from directory to run the access audit
-## Future Requirements
+## Traceability
-### Report Branding (Deferred)
+| Requirement | Phase | Status | Notes |
+|-------------|-------|--------|-------|
+| BRAND-01 | Phase 10 | Complete | Base64 JSON persistence via BrandingRepository |
+| BRAND-02 | Phase 12 | Complete | Base64ToImageSourceConverter + live preview |
+| BRAND-03 | Phase 10 | Complete | Per-tenant logo on TenantProfile |
+| BRAND-04 | Phase 11 | Complete | Entra bannerLogo stream endpoint |
+| BRAND-05 | Phase 11 | Complete | BrandingHtmlHelper + optional param on all 5 services |
+| BRAND-06 | Phase 10 | Complete | Magic-byte validation, 512 KB limit, auto-compression |
+| UDIR-01 | Phase 13 | Complete | IsDirectoryBrowseMode toggle property |
+| UDIR-02 | Phase 13 | Complete | PageIterator pagination via GraphUserDirectoryService |
+| UDIR-03 | Phase 13 | Complete | In-memory ICollectionView filter |
+| UDIR-04 | Phase 13 | Complete | Sortable Department/JobTitle columns |
+| UDIR-05 | Phase 14 | Complete | SelectDirectoryUserCommand + double-click handler |
+
+## Deferred to Future Milestones
- **BRAND-F01**: PDF export with embedded logos
- **BRAND-F02**: Custom report title/footer text per tenant
-
-### User Directory (Deferred)
-
- **UDIR-F01**: Session-scoped directory cache (avoid re-fetching on tab switch)
- **UDIR-F02**: Export user directory list to CSV
@@ -45,29 +55,5 @@ Requirements for v2.2 Report Branding & User Directory. Each maps to roadmap pha
| User directory as standalone tab | Directory browse is a mode within existing user access audit tab |
| Real-time directory sync | One-time load with manual refresh is sufficient for audit workflows |
-## Traceability
-
-Which phases cover which requirements. Updated during roadmap creation.
-
-| Requirement | Phase | Status |
-|-------------|-------|--------|
-| BRAND-01 | Phase 10 | Complete |
-| BRAND-03 | Phase 10 | Complete |
-| BRAND-06 | Phase 10 | Complete |
-| BRAND-05 | Phase 11 | Complete |
-| BRAND-04 | Phase 11 | Complete |
-| BRAND-02 | Phase 12 | Complete |
-| UDIR-01 | Phase 13 | Complete |
-| UDIR-02 | Phase 13 | Complete |
-| UDIR-03 | Phase 13 | Complete |
-| UDIR-04 | Phase 13 | Complete |
-| UDIR-05 | Phase 14 | Complete |
-
-**Coverage:**
-- v2.2 requirements: 11 total
-- Mapped to phases: 11
-- Unmapped: 0
-
---
-*Requirements defined: 2026-04-08*
-*Last updated: 2026-04-08 after roadmap creation — all 11 requirements mapped to Phases 10-14*
+*Archived: 2026-04-09*
diff --git a/.planning/milestones/v2.2-ROADMAP.md b/.planning/milestones/v2.2-ROADMAP.md
new file mode 100644
index 0000000..aef7ef0
--- /dev/null
+++ b/.planning/milestones/v2.2-ROADMAP.md
@@ -0,0 +1,73 @@
+# v2.2 Report Branding & User Directory — Milestone Archive
+
+**Goal:** Add customizable logos to HTML reports and a full user directory browse mode in the user access audit tab
+**Status:** Shipped 2026-04-09
+**Timeline:** 2026-04-08 to 2026-04-09
+
+## Stats
+
+| Metric | Value |
+|--------|-------|
+| Phases | 5 (Phases 10-14) |
+| Plans | 14 |
+| Commits | 47 |
+| C# LOC (total) | 16,916 |
+| Tests | 285 pass / 26 skip |
+| Requirements | 11/11 complete |
+
+## Key Accomplishments
+
+1. **Branding Data Foundation (Phase 10)** — Logo models with base64 JSON persistence, BrandingRepository, BrandingService with magic-byte validation (PNG/JPG) and auto-compression via WPF PresentationCore, GraphUserDirectoryService with PageIterator pagination for full tenant user enumeration.
+
+2. **HTML Export Branding (Phase 11)** — BrandingHtmlHelper static class for consistent header generation, optional `ReportBranding` parameter added to all 5 HTML export services (Permissions, Storage, Search, Duplicates, User Access), ViewModel injection via IBrandingService, logo management commands (browse/clear) on Settings and Profile ViewModels, Entra branding API auto-pull for client logos.
+
+3. **Branding UI Views (Phase 12)** — Base64ToImageSourceConverter for live logo preview, MSP logo section in SettingsView (import/preview/clear), client logo section in ProfileManagementDialog (import/preview/clear/Entra pull), Grid overlay with DataTrigger for placeholder visibility toggle.
+
+4. **User Directory ViewModel (Phase 13)** — Browse mode toggle on UserAccessAuditViewModel, paginated directory load with cancellation via separate CancellationTokenSource, in-memory member/guest filter (fetches all users once, filters via ICollectionView), sortable columns for DisplayName, UPN, Department, JobTitle.
+
+5. **User Directory View (Phase 14)** — Search/Browse RadioButton mode toggle, directory DataGrid with loading counter and cancel button, SelectDirectoryUserCommand bridging directory selection to existing audit pipeline, double-click code-behind handler, 14 localization keys (EN + FR).
+
+## Phases
+
+### Phase 10: Branding Data Foundation (3 plans)
+- Logo models, BrandingRepository, BrandingService with validation/compression
+- GraphUserDirectoryService with PageIterator pagination
+- DI registration in App.xaml.cs and full test suite gate
+
+### Phase 11: HTML Export Branding + ViewModel Integration (4 plans)
+- ReportBranding model + BrandingHtmlHelper static class with unit tests
+- Add optional branding param to all 5 HTML export services
+- Wire IBrandingService into all 5 export ViewModels
+- Logo management commands (Settings + Profile) and Entra auto-pull
+
+### Phase 12: Branding UI Views (3 plans)
+- Base64ToImageSourceConverter, localization keys, App.xaml registration, ClientLogoPreview property
+- SettingsView MSP logo section (preview, import, clear)
+- ProfileManagementDialog client logo section (preview, import, clear, Entra pull)
+
+### Phase 13: User Directory ViewModel (2 plans)
+- Extend GraphDirectoryUser with UserType + service includeGuests parameter
+- UserAccessAuditViewModel directory browse mode (toggle, load, filter, sort, tests)
+
+### Phase 14: User Directory View (2 plans)
+- Localization keys (EN+FR), SelectDirectoryUserCommand, code-behind double-click handler
+- XAML: mode toggle (Search/Browse RadioButtons), directory DataGrid, loading UX, shared SelectedUsers panel
+
+## Requirements Covered
+
+| Requirement | Description | Status |
+|-------------|-------------|--------|
+| BRAND-01 | Import MSP logo in application settings | Complete |
+| BRAND-02 | Preview imported MSP logo in settings UI | Complete |
+| BRAND-03 | Import client logo per tenant profile | Complete |
+| BRAND-04 | Auto-pull client logo from Entra branding API | Complete |
+| BRAND-05 | All 5 HTML reports display logos in consistent header | Complete |
+| BRAND-06 | Logo validation (PNG/JPG, 512 KB limit) | Complete |
+| UDIR-01 | Toggle between search and directory browse mode | Complete |
+| UDIR-02 | Browse full tenant user directory with pagination | Complete |
+| UDIR-03 | Filter directory by user type (member vs guest) | Complete |
+| UDIR-04 | Department and job title columns in directory list | Complete |
+| UDIR-05 | Select users from directory to run access audit | Complete |
+
+---
+*Archived: 2026-04-09*