4.6 KiB
4.6 KiB
phase, title, status, created
| phase | title | status | created |
|---|---|---|---|
| 10 | Branding Data Foundation | ready-for-planning | 2026-04-08 |
Phase 10 Context: Branding Data Foundation
Decided Areas (from prior research + 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.cs model → branding.json |
| Client logo location | On TenantProfile model (per-tenant) |
| File path after import | Discarded — only base64 persists |
| SVG support | Rejected (XSS risk) — PNG/JPG only |
| User directory service | New GraphUserDirectoryService, separate from GraphUserSearchService |
| Directory auto-load | No — explicit "Load Directory" button required |
| New NuGet packages | None — existing stack covers everything |
| Export service signature | Optional ReportBranding? branding = null parameter on existing export methods |
Discussed Areas
1. Logo Metadata Model
Decision: Store base64 + MIME type as separate fields in a shared LogoData record.
- Shared model:
LogoData { string Base64, string MimeType }— used by both MSP logo (inBrandingSettings) and client logo (onTenantProfile) MimeTypeis"image/png"or"image/jpeg", determined at import time from magic bytes- No other metadata stored — no original filename, dimensions, or import date
- Export services concatenate
data:{MimeType};base64,{Base64}for HTML<img>tags - WPF preview converts
Base64bytes toBitmapImagedirectly
2. Logo Validation & Compression
Decision: Validate format via magic bytes, auto-compress oversized files silently.
- Format detection: Read file header magic bytes only — ignore file extension entirely
- PNG signature:
89 50 4E 47(first 4 bytes) - JPEG signature:
FF D8 FF(first 3 bytes) - Anything else → reject with specific error message (e.g., "File format is BMP, only PNG and JPG are accepted")
- PNG signature:
- Size handling: If file exceeds 512 KB, auto-compress silently (no user notification)
- Strategy: resize dimensions (e.g., max 300px width/height) + reduce quality
- Keep original format — PNG stays PNG, JPEG stays JPEG (no format conversion)
- Compress until under 512 KB
- Dimension limits: None — the 512 KB cap and compression handle naturally
- Validation errors: Specific messages for format rejection (format-related only, since size is auto-handled)
3. Profile Deletion & Duplication Behavior
Decision: Warn about logo loss on deletion; do NOT copy logo on duplication.
- Deletion: When deleting a tenant profile that has a client logo, the confirmation message explicitly mentions it: "This will also remove its client logo." The logo is embedded in the profile JSON, so deletion is automatic — no orphaned files.
- Duplication: Duplicating a tenant profile copies connection fields (Name, TenantUrl, ClientId) but starts with a blank client logo. The user must re-import or auto-pull for the new profile. Rationale: duplicated profiles are typically for different tenants, so the logo shouldn't carry over.
Deferred Ideas (out of scope for Phase 10)
- Logo preview in Settings UI (Phase 12)
- Auto-pull client logo from Entra branding API (Phase 11/12)
- Report header layout with logos side-by-side (Phase 11)
- "Load Directory" button placement decision (Phase 14)
- Session-scoped directory cache (UDIR-F01, deferred)
code_context
| Asset | Path | Reuse |
|---|---|---|
| TenantProfile model | SharepointToolbox/Core/Models/TenantProfile.cs |
Extend with LogoData? ClientLogo property |
| AppSettings model | SharepointToolbox/Core/Models/AppSettings.cs |
Reference for BrandingSettings pattern |
| SettingsRepository | SharepointToolbox/Infrastructure/Persistence/SettingsRepository.cs |
Clone pattern for BrandingRepository (write-then-replace + SemaphoreSlim) |
| ProfileRepository | SharepointToolbox/Infrastructure/Persistence/ProfileRepository.cs |
Already handles TenantProfile persistence — will serialize new logo field |
| GraphUserSearchService | SharepointToolbox/Services/GraphUserSearchService.cs |
Reference for Graph SDK usage, auth, and query patterns |
| GraphClientFactory | SharepointToolbox/Infrastructure/Auth/GraphClientFactory.cs |
Provides GraphServiceClient for new directory service |
| DI registration | SharepointToolbox/App.xaml.cs (lines 73-163) |
Register new BrandingRepository, BrandingService, GraphUserDirectoryService |
| Profile deletion UI | SharepointToolbox/ViewModels/ProfileManagementViewModel.cs |
Update deletion confirmation message to mention logo |