# Codebase Concerns

**Analysis Date:** 2026-04-02

## Tech Debt

**Silent Error Handling (Widespread):**
- Issue: 38 empty `catch` blocks that suppress errors without logging
- Files: `Sharepoint_ToolBox.ps1` (lines 1018, 1020, 1067, 1068, 1144, 2028, 2030, etc.)
- Impact: Failures go unnoticed, making debugging difficult. Users don't know why operations fail. Error conditions are hidden from logs.
- Fix approach: Add logging to all `catch` blocks. Use `BgLog` for background tasks, `Write-Log` for UI threads. Example: `catch { BgLog "Folder enumeration failed: $_" "DarkGray" }` instead of `catch {}`

**Resource Cleanup Issues:**
- Issue: Runspace and PowerShell objects created in background jobs may not be properly disposed if exceptions occur
- Files: `Sharepoint_ToolBox.ps1` lines 1040-1052, 4564-4577, 5556-5577
- Impact: Memory leaks possible if UI interactions are interrupted. Zombie runspaces could accumulate over multiple operations.
- Fix approach: Wrap all runspace/PS object creation in try-finally blocks. Ensure `$rs.Dispose()` and `$ps.Dispose()` are called in finally block, not just in success path

**Overly Broad Error Suppression:**
- Issue: 27 instances of `-ErrorAction SilentlyContinue` spread throughout code
- Files: `Sharepoint_ToolBox.ps1` (e.g., lines 1142, 1188, 2070, 4436, etc.)
- Impact: Real failures indistinguishable from expected failures (e.g., list doesn't exist vs. connection failed). Masks bugs.
- Fix approach: Use selective error suppression. Only suppress when you've explicitly checked for the condition (e.g., "if list doesn't exist, create it"). Otherwise use `-ErrorAction Stop` with explicit try-catch.

**Inconsistent JSON Error Handling:**
- Issue: JSON parsing in `Load-Profiles`, `Load-Settings`, `Load-Templates` uses empty catch blocks
- Files: `Sharepoint_ToolBox.ps1` lines 61, 140, 568-570
- Impact: Corrupted JSON files silently fail and return empty defaults, losing user data silently
- Fix approach: Log actual error message. Implement validation schema. Create backup of corrupted files.

## Known Bugs

**Blank Client ID Warning Not Actionable:**
- Symptoms: "WARNING: No Client ID returned" appears but doesn't prevent further operations or clear user input
- Files: `Sharepoint_ToolBox.ps1` line 4237
- Trigger: Azure AD app registration completes but returns null ClientId (can happen with certain tenant configurations)
- Workaround: Manually register app via Azure Portal and paste Client ID
- Fix approach: Check for null ClientId before continuing, clear the warning state properly

**Group Member Addition Silent Failures:**
- Symptoms: Members appear not to be added to sites, but no error shown in UI
- Files: `Sharepoint_ToolBox.ps1` lines 1222-1225, 5914, 5922 (try-catch with SilentlyContinue)
- Trigger: User exists but cannot be added to group (permissions, licensing, or source-specific SP group issues)
- Workaround: Manual group membership assignment
- Fix approach: Replace SilentlyContinue with explicit logging of why Add-PnPGroupMember failed

**Folder Metadata Loss in Template Application:**
- Symptoms: Folder permissions captured correctly but not reapplied when permissions=true but structure already exists
- Files: `Sharepoint_ToolBox.ps1` lines 1229-1292 (folder-level permission application depends on library structure map being built first)
- Trigger: Target library created by Apply-FolderTree but permissions application logic expects library to already exist in template structure
- Workaround: Delete and recreate target library, or manually apply permissions via SharePoint UI
- Fix approach: Build library map before applying folder tree, or add validation that all referenced libraries exist

**CSV Import for Bulk Operations Not Validated:**
- Symptoms: Invalid CSV format silently fails, users see no clear error, form appears unresponsive
- Files: `Sharepoint_ToolBox.ps1` lines 5765-5800 (CSV parsing with inadequate error context)
- Trigger: CSV with missing headers, wrong delimiter, or invalid format
- Workaround: Edit CSV manually to match expected format, restart tool
- Fix approach: Add CSV schema validation before processing, show specific validation errors

## Security Considerations

**Client ID and Tenant URL Hardcoded in Temp Files:**
- Risk: Temp registration script contains unencrypted Client ID and Tenant ID in plaintext
- Files: `Sharepoint_ToolBox.ps1` lines 4210-4245 (temp file creation)
- Current mitigation: Temp file cleanup attempted but not guaranteed if process crashes
- Recommendations: Use SecureString to pass credentials, delete temp file with -Force in finally block, or use named pipes instead of files

**No Validation of Tenant URL Format:**
- Risk: Arbitrary URLs accepted, could be typos leading to authentication against wrong tenant
- Files: `Sharepoint_ToolBox.ps1` lines 4306-4317, 30-43 (Validate-Inputs)
- Current mitigation: URL used as-is, relies on PnP authentication failure to catch issues
- Recommendations: Add regex validation for SharePoint tenant URLs, warn on suspicious patterns

**Profile File Contains Credentials in Plaintext:**
- Risk: `Sharepoint_Export_profiles.json` contains Client ID and Tenant URL in plaintext on disk
- Files: `Sharepoint_ToolBox.ps1` lines 50-72 (profile persistence)
- Current mitigation: File located in user home directory (Windows ACL protection), but still plaintext
- Recommendations: Consider encrypting profile file with DPAPI, or move to Windows Credential Manager

**PnP PowerShell Module Trust Not Validated:**
- Risk: Module imported without version pinning, could load compromised version
- Files: `Sharepoint_ToolBox.ps1` lines 151, 1151, 4218, 4521, 5833 (Import-Module PnP.PowerShell)
- Current mitigation: None
- Recommendations: Pin module version in manifest, use `-MinimumVersion` parameter, check module signature

## Performance Bottlenecks

**Synchronous UI Freezes During Large Operations:**
- Problem: File search with 50,000 result limit processes all results at once, building HTML string in memory
- Files: `Sharepoint_ToolBox.ps1` lines 2112-2133 (Export-SearchResultsToHTML builds entire table in string)
- Cause: All results concatenated into single `$rows` string before sending to UI
- Improvement path: Implement pagination in HTML reports, stream results rather than buffering all in memory. For large datasets, chunk exports into multiple files.

**Folder Storage Recursion Not Depth-Limited by Default:**
- Problem: `Collect-FolderStorage` recurses unlimited depth unless explicitly capped, can take hours on deep folder structures
- Files: `Sharepoint_ToolBox.ps1` lines 2009-2032, 4432-4455
- Cause: CurrentDepth compared against FolderDepth limit, but FolderDepth defaults to 999 if not set
- Improvement path: Default to depth 3-4, show estimated scan time based on depth, implement cancellation token

**No Parallel Processing for Multiple Sites:**
- Problem: Sites processed sequentially in Permissions/Storage reports, one site blocks all others
- Files: `Sharepoint_ToolBox.ps1` lines 4379-4401 (foreach loop in permissions scan)
- Cause: Single-threaded approach with `Connect-PnPOnline` context switches
- Improvement path: Queue-based processing for multiple sites (partially done for storage scans), implement async context management

**HTML Report Generation for Large Duplicates List:**
- Problem: Export-DuplicatesToHTML builds entire HTML in memory, slow for 10,000+ duplicates
- Files: `Sharepoint_ToolBox.ps1` lines 2235-2400 (HTML string concatenation in loop)
- Cause: All groups converted to HTML before writing to file
- Improvement path: Stream HTML generation, write to file incrementally, implement lazy-loading tables in browser

## Fragile Areas

**Language System (T() function):**
- Files: `Sharepoint_ToolBox.ps1` (translation lookups throughout, ~15 hardcoded English fallbacks like "Veuillez renseigner")
- Why fragile: Language loading can fail silently, UI control updates hardcoded at multiple locations, no fallback chain for missing translations
- Safe modification: Add validation that all UI strings have corresponding translation keys before form creation. Create helper function that returns English default if key missing.
- Test coverage: No tests for translation system. Gaps: Missing translations for error messages, hardcoded "Veuillez renseigner" strings that bypass T() function

**Profile Management:**
- Files: `Sharepoint_ToolBox.ps1` lines 50-127
- Why fragile: Profile list is in-memory array that syncs with JSON file. If Save-Profiles fails, changes are lost. No transaction semantics.
- Safe modification: Implement write-lock pattern. Create backup before write. Validate JSON before replacing file.
- Test coverage: No validation that profile save actually persists. Race condition if opened in multiple instances.

**Runspace State Machine:**
- Files: `Sharepoint_ToolBox.ps1` lines 1034-1095, 4580-4650 (runspace creation, async timer polling)
- Why fragile: UI state (`btnGenPerms.Enabled = false`) set before runspace begins, but no explicit state reset if runspace crashes or hangs
- Safe modification: Implement state enum (Idle, Running, Done, Error). Always reset state in finally block. Set timeout on runspace execution.
- Test coverage: No timeout tests. Gaps: What happens if runspace hangs indefinitely? Button remains disabled forever.

**Site Picker List View:**
- Files: `Sharepoint_ToolBox.ps1` lines 157-250 (_Pkl-* functions)
- Why fragile: AllSites list updates while UI may be reading it (SuppressCheck flag used but incomplete synchronization)
- Safe modification: Use proper locking or rebuild entire list atomically. Current approach relies on flag which may miss updates.
- Test coverage: No concurrent access tests. Gaps: What if site is checked while sort is happening?

## Scaling Limits

**Permissions Report HTML with Large Item Counts:**
- Current capacity: Tested up to ~5,000 items, performance degrades significantly
- Limit: HTML table becomes unusable in browser above 10,000 rows (sorting, filtering slow)
- Scaling path: Implement client-side virtual scrolling in HTML template, paginate into multiple reports, add server-side filtering before export

**File Search Result Limit:**
- Current capacity: 50,000 result maximum hardcoded
- Limit: Beyond 50,000 files, results truncated without warning
- Scaling path: Implement pagination in SharePoint Search API, show "more results available" warning, allow user to refine search

**Runspace Queue Processing:**
- Current capacity: Single queue per scan, sequential processing
- Limit: If background job produces messages faster than timer dequeues, queue could grow unbounded
- Scaling path: Implement back-pressure (slow producer if queue > 1000 items), implement priority queue

**Profile JSON File Size:**
- Current capacity: Profiles loaded entirely into memory, no limit on file size
- Limit: If user creates 1,000+ profiles, JSON file becomes slow to load/save
- Scaling path: Implement profile paging, index file by profile name, lazy-load profile details

## Dependencies at Risk

**PnP.PowerShell Module Version Mismatch:**
- Risk: Module API changes between major versions, cmdlet parameter changes
- Impact: Features relying on specific cmdlet parameters break silently
- Migration plan: Pin to stable version range in script header. Create version compatibility matrix. Test against 2-3 stable versions.

**System.Windows.Forms Dependency:**
- Risk: WinForms support in PowerShell 7 is deprecated, future versions may not ship it
- Impact: GUI completely broken on future PowerShell versions
- Migration plan: Consider migrating to WPF or cross-platform GUI framework (Avalonia). Current WinForms code is tied to Assembly loading.

## Missing Critical Features

**No Operation Cancellation:**
- Problem: Running operations (permissions scan, storage metrics, file search) cannot be stopped mid-execution
- Blocks: User stuck waiting for slow operations to complete, no way to abort except kill process

**No Audit Log:**
- Problem: No record of who ran what operation, what results were exported, when last backup occurred
- Blocks: Compliance, troubleshooting

**No Dry-Run for Most Operations:**
- Problem: Only version cleanup has dry-run. Permission changes, site creation applied immediately without preview
- Blocks: Prevents risk assessment before making changes

## Test Coverage Gaps

**PnP Connection Failures:**
- What's not tested: Connection timeouts, intermittent network issues, authentication failures mid-operation
- Files: `Sharepoint_ToolBox.ps1` lines 36, 157, 170, 2036, 4458, etc. (Connect-PnPOnline calls)
- Risk: Tool may hang indefinitely if connection drops. No retry logic.
- Priority: High

**Malformed JSON Resilience:**
- What's not tested: Templates.json, Profiles.json, Settings.json with invalid JSON, missing fields, type mismatches
- Files: `Sharepoint_ToolBox.ps1` lines 61, 140, 568 (ConvertFrom-Json)
- Risk: Tool fails to start or loses user data
- Priority: High

**Large-Scale Operations:**
- What's not tested: Permissions scan on site with 50,000+ items, storage metrics on 10,000+ folders, file search returning 40,000+ results
- Files: Bulk scanning functions throughout
- Risk: Memory exhaustion, timeout, UI freeze
- Priority: Medium

**Runspace Cleanup on Error:**
- What's not tested: Runspace exception handling, cleanup if UI window closes during background operation
- Files: `Sharepoint_ToolBox.ps1` lines 1040-1052, 4564-4577, 5556-5577
- Risk: Zombie processes, resource leaks
- Priority: Medium

**CSV Format Validation:**
- What's not tested: Invalid column headers, wrong delimiter, missing required columns in bulk operations
- Files: `Sharepoint_ToolBox.ps1` lines 5765-5800
- Risk: Silent failures, partial data import
- Priority: Medium

---

*Concerns audit: 2026-04-02*
