Files
Sharepoint-Toolbox/.planning/STATE.md
Dev df6f4949a8 docs(13-02): complete User Directory ViewModel plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:44:56 +02:00

6.2 KiB

gsd_state_version, milestone, milestone_name, status, stopped_at, last_updated, last_activity, progress
gsd_state_version milestone milestone_name status stopped_at last_updated last_activity progress
1.0 v2.2 Report Branding & User Directory completed Completed 13-02-PLAN.md 2026-04-08T14:08:49.579Z 2026-04-08 — Phase 11 planning completed
total_phases completed_phases total_plans completed_plans
5 4 12 12

Project State

Project Reference

See: .planning/PROJECT.md (updated 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. Current focus: v2.2 Report Branding & User Directory — HTML report logos (Phases 10-12), user directory browse mode (Phases 13-14)

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

v2.2 Progress: [██░░░░░░░░] 20% (1/5 phases, 3/7 plans)

Accumulated Context

Decisions

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)

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.

Blockers/Concerns

None.

Session Continuity

Last session: 2026-04-08T14:08:49.577Z Stopped at: Completed 13-02-PLAN.md Resume file: None Next step: /gsd:execute-phase 11