docs: start milestone v2.2 Report Branding & User Directory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,192 +1,211 @@
|
||||
# Feature Research
|
||||
# Feature Landscape
|
||||
|
||||
**Domain:** SharePoint Online administration and auditing desktop tool (MSP / IT admin)
|
||||
**Researched:** 2026-04-02
|
||||
**Confidence:** MEDIUM (competitive landscape from web sources; no Context7 for SaaS tools; Microsoft docs HIGH confidence)
|
||||
**Domain:** MSP IT admin desktop tool — SharePoint audit report branding + user directory browse
|
||||
**Milestone:** v2.2 — Report Branding & User Directory
|
||||
**Researched:** 2026-04-08
|
||||
**Overall confidence:** HIGH (verified via official Graph API docs + direct codebase inspection)
|
||||
|
||||
## Feature Landscape
|
||||
---
|
||||
|
||||
### Table Stakes (Users Expect These)
|
||||
## Scope Boundary
|
||||
|
||||
Features that IT admins and MSPs assume exist in any SharePoint admin tool. Missing these makes the product feel broken or incomplete.
|
||||
This file covers only the two net-new features in v2.2:
|
||||
1. HTML report branding (MSP logo + client logo per tenant)
|
||||
2. User directory browse mode in the user access audit tab
|
||||
|
||||
Everything else is already shipped. Dependencies on existing code are called out explicitly.
|
||||
|
||||
---
|
||||
|
||||
## Feature 1: HTML Report Branding
|
||||
|
||||
### Table Stakes
|
||||
|
||||
Features an MSP admin expects without being asked. If missing, the reports feel unfinished and
|
||||
unprofessional to hand to a client.
|
||||
|
||||
| Feature | Why Expected | Complexity | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| Permissions report (site-level) | Every audit tool has this; admins must prove who has access where | MEDIUM | Must show owners, members, guests, external users, and broken inheritance |
|
||||
| Export to CSV | Standard workflow — admins paste into tickets, compliance reports, Excel | LOW | Already in current app; keep for all reports |
|
||||
| Multi-site permissions scan | Admins manage dozens of sites; per-site-only scan is unusable at scale | HIGH | Requires batching Graph API calls; throttling management needed |
|
||||
| Storage metrics per site | Native M365 admin center only shows tenant-level; per-site is expected | MEDIUM | Already in current app; retain and improve |
|
||||
| Interactive login / Azure AD OAuth | No client secret storage expected; browser-based auth is the norm | MEDIUM | Already implemented; new version adds session caching |
|
||||
| Site template management | Re-using structure across client sites is a core MSP workflow | MEDIUM | Already in current app; port to C# |
|
||||
| File search across sites | Finding content across a tenant is a day-1 admin task | MEDIUM | Already in current app; Graph driveItem search |
|
||||
| Bulk operations (user add/remove, site creation) | Manual one-by-one is unacceptable at MSP scale | HIGH | Already in current app; async required to avoid UI freeze |
|
||||
| Error reporting (not silent failures) | Admins need to know when scans fail partially | LOW | Current app has 38 silent catch blocks — critical fix |
|
||||
| Localization (EN + FR) | Already exists; removing it would break existing users | LOW | Key-based translation system already in place |
|
||||
| Export to interactive HTML | Shareable reports without requiring recipients to have the tool | MEDIUM | Already in current app; retain embedded JS for sorting/filtering |
|
||||
| MSP global logo in report header | Every white-label MSP tool shows the MSP's own brand on deliverables | Low | Single image stored in AppSettings or a dedicated branding settings section |
|
||||
| Client (per-tenant) logo in report header | MSP reports are client-facing; client should see their own logo next to the MSP's | Medium | Stored in TenantProfile; 2 sources: import from file or pull from tenant |
|
||||
| Logo renders in self-contained HTML (no external URL) | Reports are often emailed or archived; external URLs break offline | Low | Base64-encode and embed as `data:image/...;base64,...` inline in `<img src=` |
|
||||
| Logo graceful absence (no logo configured = no broken image) | Admins will run the tool before configuring logos | Trivial | Conditional render — omit the `<img>` block entirely when no logo is set |
|
||||
| Consistent placement across all HTML export types | App already ships 5+ HTML exporters; logos must appear in all of them | Medium | Extract a shared header-builder method or inject a branding context into each export service |
|
||||
|
||||
### Differentiators (Competitive Advantage)
|
||||
### Differentiators
|
||||
|
||||
Features that are not universally provided, or are done poorly by competitors, where this tool can create genuine advantage.
|
||||
Features not expected by default, but add meaningful value once table stakes are covered.
|
||||
|
||||
| Feature | Value Proposition | Complexity | Notes |
|
||||
|---------|-------------------|------------|-------|
|
||||
| Multi-tenant session caching | MSPs switch between 10-30 client tenants daily; re-auth per client wastes 2-3 min each | HIGH | Token cache per tenant profile; MSAL token cache serialization; core MSP differentiator |
|
||||
| User access export across selected sites | "Show me everything User X can access across these 15 sites" — native M365 can't do this for arbitrary site subsets | HIGH | Requires enumerating group memberships, direct assignments, and inherited access across n sites; high Graph API volume |
|
||||
| Simplified permissions view (plain language) | Compliance reports today require admins to translate "Contribute" to "can edit files" — untrained staff can't read them | MEDIUM | Jargon-free labels, summary counts, color coding; configurable detail level |
|
||||
| Storage graph by file type (pie + bar toggle) | Native admin center shows totals only; file-type breakdown identifies what's consuming quota (videos, backups, etc.) | MEDIUM | Requires Graph driveItem enumeration with file extension grouping; recharts-style WPF chart control |
|
||||
| Duplicate file detection | Reduces storage waste; no native Microsoft tool provides this simply | HIGH | Hash-based (SHA256/MD5) or name+size matching; large tenant = Graph throttling challenge |
|
||||
| Folder structure provisioning | Create standardized folder trees on new sites from a template — critical for MSPs onboarding clients | MEDIUM | Already in current app; differentiating because competitors (ShareGate) don't focus on this |
|
||||
| Offline profile / tenant registry | Store tenant URLs, display names, notes locally — instant context switching without re-entering URLs | LOW | JSON-backed, local only — simple but missing from all SaaS tools by design |
|
||||
| Operation progress and cancellation | SaaS tools run jobs server-side; desktop tool must show real-time progress and allow cancel mid-scan | MEDIUM | CancellationToken throughout async operations; progress reporting via IProgress<T> |
|
||||
| Auto-pull client logo from Microsoft Entra tenant branding | Zero-config for tenants that already have a banner logo set in Entra ID | Medium | Graph API: `GET /organization/{id}/branding/localizations/default/bannerLogo` returns raw image bytes. Least-privileged scope is `User.Read` (delegated, already in use). Returns empty body or 404 when not configured — must handle gracefully. |
|
||||
| Report timestamp and tenant display name in header | Contextualizes archived reports without needing to inspect the filename | Low | TenantProfile.TenantUrl already available; display name derivable from domain |
|
||||
|
||||
### Anti-Features (Commonly Requested, Often Problematic)
|
||||
### Anti-Features
|
||||
|
||||
Features that seem valuable but create disproportionate complexity, maintenance burden, or scope creep for this tool's purpose.
|
||||
Do not build these. They add scope without proportionate MSP value.
|
||||
|
||||
| Feature | Why Requested | Why Problematic | Alternative |
|
||||
|---------|---------------|-----------------|-------------|
|
||||
| Permission change alerts / real-time monitoring | Admins want to know when permissions change | Requires persistent background service, webhook registration in Azure, certificate lifecycle management — turns a desktop tool into a service | Run scheduled audit scans manually or via Windows Task Scheduler; export diffs between runs |
|
||||
| Automated remediation (auto-revoke permissions) | "Fix it for me" saves time | One wrong rule destroys access for a client's entire org; liability risk; requires undo capability and audit trail that equals a full compliance system | Surface recommendations, let admin click to apply one at a time |
|
||||
| SQLite or database storage | Faster queries on large datasets | Adds install dependency, schema migration complexity, and breaks the "single EXE" distribution model | JSON with chunked loading; lazy evaluation; paginated display |
|
||||
| Cloud sync / shared tenant registry | Team of admins sharing tenant configs | Requires auth system, conflict resolution, server infrastructure — out of scope for local tool | Export/import JSON profiles; share config files manually |
|
||||
| AI-powered governance recommendations | Microsoft is adding this to native admin center (SharePoint Admin Agent, Copilot-licensed) | Requires Copilot license, Graph calls with high latency, and competes directly with Microsoft's own roadmap | Focus on raw data accuracy and export quality; let Microsoft handle AI summaries |
|
||||
| Cross-platform (Mac/Linux) support | Some admins use Macs | WPF is Windows-only; rewrite to MAUI/Avalonia is a full project — not justified for current user base | Confirmed out of scope in PROJECT.md |
|
||||
| Version history management / rollback | Admins sometimes need to see version bloat | Version management is a deep separate problem; Graph API pagination for versions is complex and slow at scale | Surface version storage totals in storage metrics; flag libraries with high version counts |
|
||||
| SharePoint content migration | Admins ask to move content between tenants or sites | Migration is a fully separate product category (ShareGate, AvePoint); competing here is a multi-year investment | Refer to ShareGate or native SharePoint migration for content moves |
|
||||
| Anti-Feature | Why Avoid | What to Do Instead |
|
||||
|--------------|-----------|-------------------|
|
||||
| Color theme / CSS customization per tenant | Complexity explodes — per-tenant CSS is a design system problem, not an admin tool feature | Stick to a single professional neutral theme; logo is sufficient branding |
|
||||
| PDF export with embedded logo | PDF generation requires a third-party library (iTextSharp, QuestPDF, etc.) adding binary size to the 200 MB EXE | Document in release notes that users can print-to-PDF from browser |
|
||||
| Animated or SVG logo support | MIME handling complexity; SVG in data-URIs introduces XSS risk | Support PNG/JPG/GIF only; reject SVG at import time |
|
||||
| Logo URL field (hotlinked) | Reports break when URL becomes unavailable; creates external dependency for a local-first tool | Force file import with base64 embedding |
|
||||
|
||||
## Feature Dependencies
|
||||
### Feature Dependencies
|
||||
|
||||
```
|
||||
Multi-tenant session caching
|
||||
└──requires──> Tenant profile registry (JSON-backed)
|
||||
└──required by──> All features (auth gate)
|
||||
|
||||
User access export across selected sites
|
||||
└──requires──> Multi-site permissions scan
|
||||
└──requires──> Multi-tenant session caching
|
||||
|
||||
Simplified permissions view
|
||||
└──enhances──> Permissions report (site-level)
|
||||
└──enhances──> User access export across selected sites
|
||||
|
||||
Storage graph by file type
|
||||
└──requires──> Storage metrics per site
|
||||
└──requires──> Graph driveItem enumeration (file extension data)
|
||||
|
||||
Duplicate file detection
|
||||
└──requires──> File search across sites (file enumeration infrastructure)
|
||||
└──conflicts──> Automated remediation (deletion without undo = data loss risk)
|
||||
|
||||
Bulk operations
|
||||
└──requires──> Operation progress and cancellation
|
||||
└──requires──> Error reporting (not silent failures)
|
||||
|
||||
Export (CSV / HTML)
|
||||
└──enhances──> All report features
|
||||
└──required by──> Compliance audit workflows
|
||||
|
||||
Folder structure provisioning
|
||||
└──requires──> Site template management
|
||||
AppSettings + MspLogoBase64 (string?, nullable)
|
||||
TenantProfile + ClientLogoBase64 (string?, nullable)
|
||||
+ ClientLogoSource (enum: None | Imported | AutoPulled)
|
||||
Shared branding helper → called by HtmlExportService, UserAccessHtmlExportService,
|
||||
StorageHtmlExportService, DuplicatesHtmlExportService,
|
||||
SearchHtmlExportService
|
||||
Auto-pull code path → Graph API call via existing GraphClientFactory
|
||||
Logo import UI → WPF OpenFileDialog -> File.ReadAllBytes -> Convert.ToBase64String
|
||||
-> stored in profile JSON via existing ProfileRepository
|
||||
```
|
||||
|
||||
### Dependency Notes
|
||||
**Key existing code note:** All 5+ HTML export services currently build their `<body>` independently
|
||||
with no shared header. Branding requires one of:
|
||||
- (a) a `ReportBrandingContext` record passed into each exporter's `BuildHtml` method, or
|
||||
- (b) a `HtmlReportHeaderBuilder` static/injectable helper all exporters call.
|
||||
|
||||
- **Multi-tenant session caching requires Tenant profile registry:** Without a registry of tenant URLs and display names, the session cache has nothing to key against. The tenant profile JSON must exist before any feature can authenticate.
|
||||
- **User access export requires multi-site permissions scan:** The "all accesses for user X" feature is essentially a filtered multi-site permissions scan. The scanning infrastructure must exist first.
|
||||
- **Simplified permissions view enhances reports:** This is a presentation layer on top of raw permissions data — it cannot exist without the underlying data model.
|
||||
- **Storage graph by file type requires Graph driveItem enumeration:** The native Graph storage reports do not include file type breakdown. This requires enumerating files with their extensions, which is a heavier Graph operation than summary-only calls.
|
||||
- **Duplicate detection requires file enumeration infrastructure:** The file search feature already enumerates files; duplicate detection reuses that path but adds hash computation or name+size matching on top.
|
||||
- **Bulk operations require cancellation support:** Long-running bulk operations that cannot be cancelled will freeze or force-kill the app. CancellationToken must be threaded through before bulk ops are exposed to users.
|
||||
- **Duplicate detection conflicts with automated remediation:** Surfacing duplicates is safe; auto-deleting them without undo is not. Keep these concerns separate.
|
||||
Option (b) is lower risk — it does not change method signatures that existing unit tests already call.
|
||||
|
||||
## MVP Definition
|
||||
### Complexity Assessment
|
||||
|
||||
### Launch With (v1)
|
||||
| Sub-task | Complexity | Reason |
|
||||
|----------|------------|--------|
|
||||
| AppSettings + TenantProfile model field additions | Low | Trivial nullable-string fields; JSON serialization already in place |
|
||||
| Settings UI: MSP logo upload + preview | Low | WPF OpenFileDialog + BitmapImage from base64, standard pattern |
|
||||
| ProfileManagementDialog: client logo upload per tenant | Low | Same pattern as MSP logo |
|
||||
| Shared HTML header builder with logo injection | Low-Medium | One helper; replaces duplicated header HTML in 5 exporters |
|
||||
| Auto-pull from Entra `bannerLogo` endpoint | Medium | Async Graph call; must handle 404, empty stream, no branding configured |
|
||||
| Localization keys EN/FR for new labels | Low | ~6-10 new keys; 220+ already managed |
|
||||
|
||||
Minimum viable product — sufficient to replace the existing PowerShell tool completely.
|
||||
---
|
||||
|
||||
- [ ] Tenant profile registry with multi-tenant session caching — without this, no feature works
|
||||
- [ ] Permissions report (site-level) with CSV + HTML export — core audit use case
|
||||
- [ ] Storage metrics per site — currently used daily
|
||||
- [ ] File search across sites — currently used daily
|
||||
- [ ] Bulk operations (member add, site creation, transfer) with progress + cancel — currently used; async required
|
||||
- [ ] Site template management — core MSP provisioning workflow
|
||||
- [ ] Folder structure provisioning — paired with templates
|
||||
- [ ] Duplicate file detection — currently used for storage cleanup
|
||||
- [ ] Error reporting (no silent failures) — current app's biggest reliability issue
|
||||
- [ ] Localization (EN/FR) — existing users depend on this
|
||||
## Feature 2: User Directory Browse Mode
|
||||
|
||||
### Add After Validation (v1.x)
|
||||
### Table Stakes
|
||||
|
||||
Features to add once core parity is confirmed working.
|
||||
Features an admin expects when a "browse all users" mode is offered alongside the existing search.
|
||||
|
||||
- [ ] User access export across selected sites — new feature; high value for MSP audits; add once multi-site scan is stable
|
||||
- [ ] Simplified permissions view (plain language) — presentation enhancement; add after raw data model is solid
|
||||
- [ ] Storage graph by file type (pie + bar toggle) — visualization enhancement on top of existing storage metrics
|
||||
| Feature | Why Expected | Complexity | Notes |
|
||||
|---------|--------------|------------|-------|
|
||||
| Full directory listing (all member users, paginated) | Browse implies seeing everyone, not just name-search hits | Medium | Graph `GET /users` with `$top=100`, follow `@odata.nextLink` until null. Max page size is 999 but 100 pages give better progress feedback |
|
||||
| Searchable/filterable within the loaded list | Once loaded, admins filter locally without re-querying | Low | In-memory filter on DisplayName, UPN, Mail — same pattern used in PermissionsView DataGrid |
|
||||
| Sortable columns (Name, UPN) | Standard expectation for any directory table | Low | WPF DataGrid column sorting, already used in other tabs |
|
||||
| Select user from list to run access audit | The whole point — browse replaces the people-picker for users the admin cannot spell | Low | Bind selected item; reuse the existing IUserAccessAuditService pipeline unchanged |
|
||||
| Loading indicator with progress count | Large tenants (5k+ users) take several seconds to page through | Low | Existing OperationProgress pattern; show "Loaded X users..." counter |
|
||||
| Toggle between Browse mode and Search (people-picker) mode | Search is faster for known users; browse is for discovery | Low | RadioButton or ToggleButton in the tab toolbar; visibility-toggle two panels |
|
||||
|
||||
### Future Consideration (v2+)
|
||||
### Differentiators
|
||||
|
||||
Features to defer until product-market fit is established.
|
||||
| Feature | Value Proposition | Complexity | Notes |
|
||||
|---------|-------------------|------------|-------|
|
||||
| Filter by account type (member vs guest) | MSPs care about guest proliferation; helps scope audit targets | Low | Graph returns `userType` field; add a toggle filter. Include in `$select` |
|
||||
| Department / Job Title columns | Helps identify the right user in large tenants with common names | Low-Medium | Include `department`, `jobTitle` in `$select`; optional columns in DataGrid |
|
||||
| Session-scoped directory cache | Avoids re-fetching full tenant list on every tab visit | Medium | Store list in ViewModel or session-scoped service; invalidate on TenantSwitchedMessage |
|
||||
|
||||
- [ ] Scheduled scan runs via Windows Task Scheduler integration — requires stable CLI/headless mode first
|
||||
- [ ] Permission comparison between two points in time (diff report) — useful for compliance but requires snapshot storage
|
||||
- [ ] Export to XLSX (full Excel format, not just CSV) — requested but not critical; CSV opens in Excel adequately
|
||||
### Anti-Features
|
||||
|
||||
## Feature Prioritization Matrix
|
||||
| Anti-Feature | Why Avoid | What to Do Instead |
|
||||
|--------------|-----------|-------------------|
|
||||
| Eager load on tab open | Large tenants (10k+ users) block UI and risk Graph throttling on every tab navigation | Lazy-load on explicit "Load Directory" button click; show a clear affordance |
|
||||
| Delta query / incremental sync | Delta queries are for maintaining a local replica over time; wrong pattern for a one-time audit session | Single paginated GET per session; add a Refresh button |
|
||||
| Multi-user bulk select for simultaneous audit | The audit pipeline is per-user by design; multi-user requires a fundamentally different results model | Out of scope; single-user selection only |
|
||||
| Export the user directory to CSV | That is an identity reporting feature (AdminDroid et al.), not an access audit feature | Out of scope for this milestone |
|
||||
| Show disabled accounts by default | Disabled users do not have active SharePoint access; pollutes the list for audit purposes | Default `$filter=accountEnabled eq true`; optionally expose a toggle |
|
||||
|
||||
| Feature | User Value | Implementation Cost | Priority |
|
||||
|---------|------------|---------------------|----------|
|
||||
| Tenant profile registry + session caching | HIGH | MEDIUM | P1 |
|
||||
| Permissions report (site-level) | HIGH | MEDIUM | P1 |
|
||||
| Storage metrics per site | HIGH | MEDIUM | P1 |
|
||||
| File search across sites | HIGH | MEDIUM | P1 |
|
||||
| Bulk operations with progress/cancel | HIGH | HIGH | P1 |
|
||||
| Error reporting (no silent failures) | HIGH | LOW | P1 |
|
||||
| Site template management | HIGH | MEDIUM | P1 |
|
||||
| Folder structure provisioning | MEDIUM | MEDIUM | P1 |
|
||||
| Duplicate file detection | MEDIUM | HIGH | P1 |
|
||||
| Localization (EN/FR) | MEDIUM | LOW | P1 |
|
||||
| User access export across selected sites | HIGH | HIGH | P2 |
|
||||
| Simplified permissions view | HIGH | MEDIUM | P2 |
|
||||
| Storage graph by file type | MEDIUM | MEDIUM | P2 |
|
||||
| Permission diff / snapshot comparison | MEDIUM | HIGH | P3 |
|
||||
| XLSX export | LOW | LOW | P3 |
|
||||
| Scheduled scans (headless/CLI) | LOW | HIGH | P3 |
|
||||
### Feature Dependencies
|
||||
|
||||
**Priority key:**
|
||||
- P1: Must have for v1 launch (parity with existing PowerShell tool)
|
||||
- P2: Should have — add after v1 validated; new features from PROJECT.md active requirements
|
||||
- P3: Nice to have, future consideration
|
||||
```
|
||||
New IGraphDirectoryService + GraphDirectoryService
|
||||
→ GET /users?$select=displayName,userPrincipalName,mail,jobTitle,department,userType
|
||||
&$filter=accountEnabled eq true
|
||||
&$top=100
|
||||
→ Follow @odata.nextLink in a loop until null
|
||||
→ Uses existing GraphClientFactory (DI, unchanged)
|
||||
|
||||
## Competitor Feature Analysis
|
||||
UserAccessAuditViewModel additions:
|
||||
+ IsBrowseMode (bool property, toggle)
|
||||
+ DirectoryUsers (ObservableCollection<GraphUserResult> or new DirectoryUserEntry model)
|
||||
+ DirectoryFilterText (string, filters in-memory)
|
||||
+ LoadDirectoryCommand (async, cancellable)
|
||||
+ IsDirectoryLoading (bool)
|
||||
+ SelectedDirectoryUser → feeds into existing audit execution path
|
||||
|
||||
| Feature | ShareGate | ManageEngine SharePoint Manager Plus | AdminDroid | Our Approach |
|
||||
|---------|-----------|---------------------------------------|------------|--------------|
|
||||
| Permissions matrix report | Yes — visual matrix, CSV export | Yes — granular permission level reports | Yes — site users/groups report | Yes — with plain-language layer on top |
|
||||
| Multi-tenant management | Yes — SaaS, per-tenant login | Yes — web-based | Yes — cloud SaaS | Yes — local session cache, instant switch, offline profiles |
|
||||
| Storage reporting | Basic | Basic tenant-level | Basic | Enhanced — file-type breakdown, pie/bar toggle |
|
||||
| Duplicate detection | No | No | No | Yes — differentiator |
|
||||
| Folder structure provisioning | No | No | No | Yes — differentiator |
|
||||
| Site templates | Migration focus | No | No | Yes — admin provisioning focus |
|
||||
| Bulk operations | Yes — migration-focused | Limited | No | Yes — admin-operations focus (not migration) |
|
||||
| User access export (cross-site) | Partial — site-by-site | Partial | Partial | Yes — arbitrary site subset, single export |
|
||||
| Plain language permissions | No | No | No | Yes — differentiator for untrained users |
|
||||
| Local desktop app (no SaaS) | No — cloud | No — cloud | No — cloud | Yes — core constraint and privacy advantage |
|
||||
| Offline / no internet needed | No | No | No | Yes (after auth token cached) |
|
||||
| Price | ~$6K/year | Subscription | Subscription | Tool cost (one-time dev, distributed free or licensed) |
|
||||
TenantSwitchedMessage handler in ViewModel: clear DirectoryUsers, reset IsBrowseMode
|
||||
|
||||
UserAccessAuditView.xaml:
|
||||
+ Toolbar toggle (Search | Browse)
|
||||
+ Visibility-collapsed people-picker panel when in browse mode
|
||||
+ New DataGrid panel for browse mode
|
||||
```
|
||||
|
||||
**Key existing code note:** `GraphUserSearchService` does filtered search only (`startsWith` filter +
|
||||
`ConsistencyLevel: eventual`). Directory listing is a different call pattern — no filter, plain
|
||||
pagination without `ConsistencyLevel`. A separate `GraphDirectoryService` is cleaner than extending
|
||||
the existing service; search and browse have different cancellation and retry needs.
|
||||
|
||||
### Complexity Assessment
|
||||
|
||||
| Sub-task | Complexity | Reason |
|
||||
|----------|------------|--------|
|
||||
| IGraphDirectoryService + GraphDirectoryService (pagination loop) | Low-Medium | Standard Graph paging; same GraphClientFactory in DI |
|
||||
| ViewModel additions (browse toggle, load command, filter, loading state) | Medium | New async command with progress, cancellation on tenant switch |
|
||||
| View XAML: toggle + browse DataGrid panel | Medium | Visibility-toggle two panels; DataGrid column definitions |
|
||||
| In-memory filter + column sort | Low | DataGrid pattern already used in PermissionsView |
|
||||
| Loading indicator integration | Low | OperationProgress + IsLoading used by every tab |
|
||||
| Localization keys EN/FR | Low | ~8-12 new keys |
|
||||
| Unit tests for GraphDirectoryService | Low | Same mock pattern as GraphUserSearchService tests |
|
||||
| Unit tests for ViewModel browse mode | Medium | Async load command, pagination mock, filter behavior |
|
||||
|
||||
---
|
||||
|
||||
## Cross-Feature Dependencies
|
||||
|
||||
Both features touch the same data models. Changes must be coordinated:
|
||||
|
||||
```
|
||||
TenantProfile model — gains fields for branding (ClientLogoBase64, ClientLogoSource)
|
||||
AppSettings model — gains MspLogoBase64
|
||||
ProfileRepository — serializes/deserializes new TenantProfile fields (JSON, backward-compat)
|
||||
SettingsRepository — serializes/deserializes new AppSettings field
|
||||
GraphClientFactory — used by both features (no changes needed)
|
||||
TenantSwitchedMessage — consumed by UserAccessAuditViewModel to clear directory cache
|
||||
```
|
||||
|
||||
Neither feature requires new NuGet packages. The Graph SDK, MSAL, and System.Text.Json are
|
||||
already present. No new binary dependencies means no EXE size increase.
|
||||
|
||||
---
|
||||
|
||||
## MVP Recommendation
|
||||
|
||||
Build in this order, each independently releasable:
|
||||
|
||||
1. **MSP logo in HTML reports** — highest visible impact, lowest complexity. AppSettings field + Settings UI upload + shared header builder.
|
||||
2. **Client logo in HTML reports (import from file)** — completes the co-branding pattern. TenantProfile field + ProfileManagementDialog upload UI.
|
||||
3. **User directory browse (load + select + filter)** — core browse UX. Toggle, paginated load, in-memory filter, pipe into existing audit.
|
||||
4. **Auto-pull client logo from Entra branding** — differentiator, zero-config polish. Build after manual import works so the fallback path is proven.
|
||||
5. **Directory: guest filter + department/jobTitle columns** — low-effort differentiators; add after core browse is stable.
|
||||
|
||||
Defer to a later milestone:
|
||||
- Directory session caching across tab switches — a Refresh button is sufficient for v2.2.
|
||||
- Logo on CSV exports — CSV has no image support; not applicable.
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
|
||||
- [ShareGate SharePoint audit tool feature page](https://sharegate.com/sharepoint-audit-tool) — MEDIUM confidence (marketing page)
|
||||
- [ManageEngine SharePoint Manager Plus permissions auditing](https://www.manageengine.com/sharepoint-management-reporting/sharepoint-permission-auditing-tool.html) — MEDIUM confidence
|
||||
- [Microsoft Data access governance reports — site permissions for users](https://learn.microsoft.com/en-us/sharepoint/data-access-governance-site-permissions-users-report) — HIGH confidence
|
||||
- [Microsoft SharePoint Advanced Management overview](https://learn.microsoft.com/en-us/sharepoint/advanced-management) — HIGH confidence
|
||||
- [sprobot.io: 9 must-have features for SharePoint storage reporting](https://www.sprobot.io/blog/how-to-choose-the-right-sharepoint-storage-reporting-tool-9-must-have-features) — MEDIUM confidence
|
||||
- [AdminDroid SharePoint Online auditing](https://admindroid.com/microsoft-365-sharepoint-online-auditing) — MEDIUM confidence
|
||||
- [CIAOPS: Best ways to monitor and audit permissions across SharePoint M365](https://blog.ciaops.com/2025/04/27/best-ways-to-monitor-and-audit-permissions-across-a-sharepoint-environment-in-microsoft-365/) — MEDIUM confidence
|
||||
- [ShareGate: How to generate a SharePoint user permissions report](https://sharegate.com/blog/build-the-perfect-sharepoint-permissions-report) — MEDIUM confidence
|
||||
- [Microsoft SharePoint storage reports admin center](https://learn.microsoft.com/en-us/microsoft-365/admin/activity-reports/sharepoint-storage-reports?view=o365-worldwide) — HIGH confidence
|
||||
|
||||
---
|
||||
*Feature research for: SharePoint Online administration/auditing desktop tool (C#/WPF, MSP/IT admin)*
|
||||
*Researched: 2026-04-02*
|
||||
- Graph API List Users (v1.0 official): https://learn.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0 — HIGH confidence
|
||||
- Graph API Get organizationalBranding (v1.0 official): https://learn.microsoft.com/en-us/graph/api/organizationalbranding-get?view=graph-rest-1.0 — HIGH confidence
|
||||
- Graph API bannerLogo stream: `GET /organization/{id}/branding/localizations/default/bannerLogo` — HIGH confidence (verified in official docs)
|
||||
- Graph pagination concepts: https://learn.microsoft.com/en-us/graph/paging — HIGH confidence
|
||||
- ControlMap co-branding (MSP + client logo pattern): https://help.controlmap.io/hc/en-us/articles/24174398424347 — MEDIUM confidence
|
||||
- ManageEngine ServiceDesk Plus MSP per-account branding: https://www.manageengine.com/products/service-desk-msp/rebrand.html — MEDIUM confidence
|
||||
- SolarWinds MSP report customization: http://allthings.solarwindsmsp.com/2013/06/customize-your-branding-on-client.html — MEDIUM confidence
|
||||
- Direct codebase inspection: HtmlExportService.cs, GraphUserSearchService.cs, AppSettings.cs, TenantProfile.cs — HIGH confidence
|
||||
|
||||
Reference in New Issue
Block a user