Files
Sharepoint-Toolbox/.planning/phases/02-permissions/02-03-SUMMARY.md
Dev d17689cc46 docs(02-03): complete SiteListService plan
- 02-03-SUMMARY.md created
- STATE.md: progress updated 67%, decisions added, session recorded
- ROADMAP.md: phase 2 progress updated (2/7 summaries)
2026-04-02 13:52:17 +02:00

5.6 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
02-permissions 03 api
sharepoint
pnp-framework
tenant-admin
site-listing
csharp
phase provides
01-foundation SessionManager.GetOrCreateContextAsync, TenantProfile, OperationProgress
ISiteListService interface for ViewModel mocking
SiteListService tenant admin API wrapper enumerating all sites
SiteInfo record model (Url, Title)
02-06-site-picker-dialog
02-permissions-viewmodel
added patterns
Admin URL derivation: Regex transform contoso.sharepoint.com → contoso-admin.sharepoint.com
ServerException wrapping: Access denied → InvalidOperationException with actionable message
InternalsVisibleTo pattern for testing internal static helpers without making them public
created modified
SharepointToolbox/Core/Models/SiteInfo.cs
SharepointToolbox/Services/ISiteListService.cs
SharepointToolbox/Services/SiteListService.cs
SharepointToolbox/AssemblyInfo.cs
SharepointToolbox.Tests/Services/SiteListServiceTests.cs
DeriveAdminUrl is internal static (not private) so tests can call it directly without a live tenant
InternalsVisibleTo added to AssemblyInfo.cs — plan specified internal visibility but omitted the assembly attribute needed to test it
OneDrive personal sites filtered by -my.sharepoint.com URL pattern in addition to Active status check
Admin URL derivation: use Regex.Replace with (https://[^.]+)(.sharepoint.com) pattern
Tenant admin access: pass synthetic TenantProfile with admin URL to SessionManager.GetOrCreateContextAsync
PERM-02
1min 2026-04-02

Phase 2 Plan 3: SiteListService Summary

ISiteListService + SiteListService wrapper for SharePoint tenant admin API using PnP.Framework Tenant.GetSitePropertiesFromSharePoint, with admin URL regex derivation and ServerException-to-InvalidOperationException wrapping

Performance

  • Duration: 1 min
  • Started: 2026-04-02T11:48:57Z
  • Completed: 2026-04-02T11:50:40Z
  • Tasks: 1 (TDD: RED + GREEN)
  • Files modified: 5

Accomplishments

  • SiteInfo record model created in Core/Models
  • ISiteListService interface defined — enables ViewModel mocking in Plan 06 (SitePickerDialog)
  • SiteListService derives admin URL via Regex, connects via SessionManager to tenant admin endpoint
  • Active-only filtering with OneDrive personal site exclusion (-my.sharepoint.com)
  • DeriveAdminUrl tested with 2 unit tests (standard URL, trailing-slash URL)

Task Commits

Each task was committed atomically:

  1. Task 1 RED: SiteListServiceTests (failing) - 5c10840 (test)
  2. Task 1 GREEN: ISiteListService, SiteListService, SiteInfo - 78b3d4f (feat)

Plan metadata: (pending)

Note: TDD task has two commits (test RED → feat GREEN); no REFACTOR step needed — code is clean as written

Files Created/Modified

  • SharepointToolbox/Core/Models/SiteInfo.cs - Simple record with Url and Title properties
  • SharepointToolbox/Services/ISiteListService.cs - Interface contract for GetSitesAsync
  • SharepointToolbox/Services/SiteListService.cs - Implementation: admin URL derivation, tenant query, filtering, error wrapping
  • SharepointToolbox/AssemblyInfo.cs - Added InternalsVisibleTo("SharepointToolbox.Tests")
  • SharepointToolbox.Tests/Services/SiteListServiceTests.cs - Two unit tests for DeriveAdminUrl

Decisions Made

  • DeriveAdminUrl marked internal static rather than private static to allow direct unit testing without mocking a full SessionManager
  • InternalsVisibleTo("SharepointToolbox.Tests") added to AssemblyInfo.cs — this is the standard .NET approach for testing internal members (Rule 3 deviation, see below)
  • OneDrive sites excluded by URL pattern (-my.sharepoint.com) in addition to Status == "Active" to avoid returning personal storage sites in the picker

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] Added InternalsVisibleTo to expose internal DeriveAdminUrl to test project

  • Found during: Task 1 GREEN (test compilation failed with CS0117)
  • Issue: Plan specified internal static for DeriveAdminUrl for testability, but did not include the InternalsVisibleTo assembly attribute required for the test project to access it
  • Fix: Added [assembly: InternalsVisibleTo("SharepointToolbox.Tests")] to AssemblyInfo.cs
  • Files modified: SharepointToolbox/AssemblyInfo.cs
  • Verification: Tests compile and both DeriveAdminUrl tests pass (2/2)
  • Committed in: 78b3d4f (GREEN commit)

Total deviations: 1 auto-fixed (1 blocking) Impact on plan: Necessary for test infrastructure — plan's intent was clearly to test internal method; InternalsVisibleTo is the standard mechanism. No scope creep.

Issues Encountered

None

User Setup Required

None - no external service configuration required.

Next Phase Readiness

  • ISiteListService ready for injection into SitePickerDialog (Plan 06)
  • SiteListService compiles and DeriveAdminUrl verified; live tenant testing requires admin credentials (handled at runtime via SessionManager interactive login)
  • Full test suite: 53 pass, 4 skip, 0 fail

Self-Check: PASSED

  • FOUND: SharepointToolbox/Core/Models/SiteInfo.cs
  • FOUND: SharepointToolbox/Services/ISiteListService.cs
  • FOUND: SharepointToolbox/Services/SiteListService.cs
  • FOUND: .planning/phases/02-permissions/02-03-SUMMARY.md
  • FOUND: commit 5c10840 (test RED)
  • FOUND: commit 78b3d4f (feat GREEN)

Phase: 02-permissions Completed: 2026-04-02