Files
Sharepoint-Toolbox/.planning/phases/11-html-export-branding/11-CONTEXT.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.8 KiB

phase, title, status, created
phase title status created
11 HTML Export Branding + ViewModel Integration ready-for-planning 2026-04-08

Phase 11 Context: HTML Export Branding + ViewModel Integration

Decided Areas (from Phase 10 context + STATE.md)

These are locked — do not re-litigate during planning or execution.

Decision Value
Logo storage format Base64 strings in JSON (not file paths)
MSP logo location BrandingSettings.MspLogobranding.json via BrandingRepository
Client logo location TenantProfile.ClientLogo (per-tenant, in profile JSON)
Logo model LogoData { string Base64, string MimeType } — shared by both MSP and client logos
SVG support Rejected (XSS risk) — PNG/JPG only
Export service signature change Optional ReportBranding? branding = null parameter on existing BuildHtml methods
No new interfaces No IHtmlExportService<T> — keep concrete classes with optional branding param
Report header layout display: flex; gap: 16px — MSP logo left, client logo right
Logo HTML format <img src="data:{MimeType};base64,{Base64}"> inline data-URI
No new NuGet packages All capabilities provided by existing stack

Phase 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.

Success Criteria

  1. Running any of the five HTML exports (Permissions, Storage, Search, Duplicates, User Access) produces an HTML file whose header contains the MSP logo <img> 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

Depends On

Phase 10 (completed) — provides LogoData, BrandingSettings, BrandingRepository, IBrandingService, TenantProfile.ClientLogo

Requirements Mapped

  • BRAND-05: Logos appear in HTML report headers
  • BRAND-04: Auto-pull client logo from Entra branding API

Code Context

Phase 10 Infrastructure (already built)

Asset Path Role
LogoData record Core/Models/LogoData.cs { string Base64, string MimeType }
BrandingSettings model Core/Models/BrandingSettings.cs { LogoData? MspLogo }
TenantProfile model Core/Models/TenantProfile.cs { LogoData? ClientLogo } (per-tenant)
IBrandingService Services/IBrandingService.cs ImportLogoAsync, SaveMspLogoAsync, ClearMspLogoAsync, GetMspLogoAsync
BrandingService Services/BrandingService.cs Validates PNG/JPG via magic bytes, auto-compresses >512KB
BrandingRepository Infrastructure/Persistence/BrandingRepository.cs JSON persistence with SemaphoreSlim + atomic write

HTML Export Services (5 targets for branding injection)

Service Path BuildHtml Signature Header Location
HtmlExportService Services/Export/HtmlExportService.cs BuildHtml(IReadOnlyList<PermissionEntry>) <h1>SharePoint Permissions Report</h1> at line 76
HtmlExportService (simplified) Same file BuildHtml(IReadOnlyList<SimplifiedPermissionEntry>) (2nd overload) Similar pattern
SearchHtmlExportService Services/Export/SearchHtmlExportService.cs BuildHtml(IReadOnlyList<SearchResult>) <h1>File Search Results</h1> at line 46
StorageHtmlExportService Services/Export/StorageHtmlExportService.cs BuildHtml(IReadOnlyList<StorageNode>) <h1>SharePoint Storage Metrics</h1> at line 51
DuplicatesHtmlExportService Services/Export/DuplicatesHtmlExportService.cs BuildHtml(IReadOnlyList<DuplicateGroup>) <h1>Duplicate Detection Report</h1> at line 55
UserAccessHtmlExportService Services/Export/UserAccessHtmlExportService.cs BuildHtml(IReadOnlyList<UserAccessEntry>) <h1>User Access Audit Report</h1> at line 91

WriteAsync Signatures (7 overloads across 5 services)

// HtmlExportService.cs
WriteAsync(IReadOnlyList<PermissionEntry>, string filePath, CancellationToken)
WriteAsync(IReadOnlyList<SimplifiedPermissionEntry>, string filePath, CancellationToken)

// SearchHtmlExportService.cs
WriteAsync(IReadOnlyList<SearchResult>, string filePath, CancellationToken)

// StorageHtmlExportService.cs
WriteAsync(IReadOnlyList<StorageNode>, string filePath, CancellationToken)
WriteAsync(IReadOnlyList<StorageNode>, IReadOnlyList<FileTypeMetric>, string filePath, CancellationToken)

// DuplicatesHtmlExportService.cs
WriteAsync(IReadOnlyList<DuplicateGroup>, string filePath, CancellationToken)

// UserAccessHtmlExportService.cs
WriteAsync(IReadOnlyList<UserAccessEntry>, string filePath, CancellationToken)

ViewModels That Trigger Exports (5 targets)

ViewModel Path Export Call Pattern
PermissionsViewModel ViewModels/Tabs/PermissionsViewModel.cs _htmlExportService.WriteAsync(Results/SimplifiedResults, ...)
SearchViewModel ViewModels/Tabs/SearchViewModel.cs _htmlExportService.WriteAsync(Results, ...)
StorageViewModel ViewModels/Tabs/StorageViewModel.cs _htmlExportService.WriteAsync(Results, FileTypeMetrics, ...)
DuplicatesViewModel ViewModels/Tabs/DuplicatesViewModel.cs _htmlExportService.WriteAsync(_lastGroups, ...)
UserAccessAuditViewModel ViewModels/Tabs/UserAccessAuditViewModel.cs _htmlExportService.WriteAsync(Results, ...)

Logo Management ViewModels (2 targets)

ViewModel Path Current State
SettingsViewModel ViewModels/Tabs/SettingsViewModel.cs Has language + data folder; needs MSP logo browse/clear commands
ProfileManagementViewModel ViewModels/ProfileManagementViewModel.cs Has CRUD profiles; needs client logo browse/clear/auto-pull commands

DI Registration

App.xaml.cs — All export services registered as Transient, branding services registered as Singleton.

HTML Generation Pattern

All 5 HTML exporters use StringBuilder with inline HTML/CSS/JS. No template files. Each builds a self-contained single-file report. The branding header must be injected between <body> and the existing <h1> tag in each exporter.

Deferred Ideas (out of scope for Phase 11)

  • Logo preview in Settings UI (Phase 12)
  • Live thumbnail preview after import (Phase 12)
  • "Pull from Entra" button in profile dialog UI (Phase 12)
  • User directory browse mode (Phase 13-14)