docs(01-02): complete core models and helpers plan — SUMMARY, STATE, ROADMAP updated
- 01-02-SUMMARY.md created with 7 files, 2 tasks, 1 auto-fix deviation - STATE.md: progress 25% (2/8 plans), 2 new decisions added - ROADMAP.md: phase 1 updated (2/8 summaries, In Progress) - REQUIREMENTS.md: FOUND-05/06/07/08 marked complete
This commit is contained in:
@@ -13,10 +13,10 @@ Requirements for initial release. Each maps to roadmap phases.
|
|||||||
- [ ] **FOUND-02**: Multi-tenant profile registry — user can create, rename, delete, and switch between tenant profiles (tenant URL, client ID, display name)
|
- [ ] **FOUND-02**: Multi-tenant profile registry — user can create, rename, delete, and switch between tenant profiles (tenant URL, client ID, display name)
|
||||||
- [ ] **FOUND-03**: Multi-tenant session caching — user stays authenticated across tenant switches without re-logging in (MSAL token cache per tenant)
|
- [ ] **FOUND-03**: Multi-tenant session caching — user stays authenticated across tenant switches without re-logging in (MSAL token cache per tenant)
|
||||||
- [ ] **FOUND-04**: Interactive Azure AD OAuth login via browser — no client secrets or certificates stored
|
- [ ] **FOUND-04**: Interactive Azure AD OAuth login via browser — no client secrets or certificates stored
|
||||||
- [ ] **FOUND-05**: All long-running operations report progress to the UI in real-time
|
- [x] **FOUND-05**: All long-running operations report progress to the UI in real-time
|
||||||
- [ ] **FOUND-06**: User can cancel any long-running operation mid-execution
|
- [x] **FOUND-06**: User can cancel any long-running operation mid-execution
|
||||||
- [ ] **FOUND-07**: All errors surface to the user with actionable messages — no silent failures
|
- [x] **FOUND-07**: All errors surface to the user with actionable messages — no silent failures
|
||||||
- [ ] **FOUND-08**: Structured logging for diagnostics (Serilog or equivalent)
|
- [x] **FOUND-08**: Structured logging for diagnostics (Serilog or equivalent)
|
||||||
- [ ] **FOUND-09**: Localization system supporting English and French with dynamic language switching
|
- [ ] **FOUND-09**: Localization system supporting English and French with dynamic language switching
|
||||||
- [ ] **FOUND-10**: JSON-based local storage for profiles, settings, and templates (compatible with current app's format for migration)
|
- [ ] **FOUND-10**: JSON-based local storage for profiles, settings, and templates (compatible with current app's format for migration)
|
||||||
- [ ] **FOUND-11**: Self-contained single EXE distribution — no .NET runtime dependency for end users
|
- [ ] **FOUND-11**: Self-contained single EXE distribution — no .NET runtime dependency for end users
|
||||||
@@ -119,10 +119,10 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| FOUND-02 | Phase 1 | Pending |
|
| FOUND-02 | Phase 1 | Pending |
|
||||||
| FOUND-03 | Phase 1 | Pending |
|
| FOUND-03 | Phase 1 | Pending |
|
||||||
| FOUND-04 | Phase 1 | Pending |
|
| FOUND-04 | Phase 1 | Pending |
|
||||||
| FOUND-05 | Phase 1 | Pending |
|
| FOUND-05 | Phase 1 | Complete |
|
||||||
| FOUND-06 | Phase 1 | Pending |
|
| FOUND-06 | Phase 1 | Complete |
|
||||||
| FOUND-07 | Phase 1 | Pending |
|
| FOUND-07 | Phase 1 | Complete |
|
||||||
| FOUND-08 | Phase 1 | Pending |
|
| FOUND-08 | Phase 1 | Complete |
|
||||||
| FOUND-09 | Phase 1 | Pending |
|
| FOUND-09 | Phase 1 | Pending |
|
||||||
| FOUND-10 | Phase 1 | Pending |
|
| FOUND-10 | Phase 1 | Pending |
|
||||||
| FOUND-11 | Phase 5 | Pending |
|
| FOUND-11 | Phase 5 | Pending |
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5
|
|||||||
|
|
||||||
| Phase | Plans Complete | Status | Completed |
|
| Phase | Plans Complete | Status | Completed |
|
||||||
|-------|----------------|--------|-----------|
|
|-------|----------------|--------|-----------|
|
||||||
| 1. Foundation | 1/8 | In Progress| |
|
| 1. Foundation | 2/8 | In Progress| |
|
||||||
| 2. Permissions | 0/? | Not started | - |
|
| 2. Permissions | 0/? | Not started | - |
|
||||||
| 3. Storage and File Operations | 0/? | Not started | - |
|
| 3. Storage and File Operations | 0/? | Not started | - |
|
||||||
| 4. Bulk Operations and Provisioning | 0/? | Not started | - |
|
| 4. Bulk Operations and Provisioning | 0/? | Not started | - |
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: planning
|
status: planning
|
||||||
stopped_at: Completed 01-foundation-01-PLAN.md
|
stopped_at: Completed 01-foundation-02-PLAN.md
|
||||||
last_updated: "2026-04-02T10:04:03.489Z"
|
last_updated: "2026-04-02T10:07:59.501Z"
|
||||||
last_activity: 2026-04-02 — Roadmap created, requirements mapped, all 42 v1 requirements assigned to phases
|
last_activity: 2026-04-02 — Roadmap created, requirements mapped, all 42 v1 requirements assigned to phases
|
||||||
progress:
|
progress:
|
||||||
total_phases: 5
|
total_phases: 5
|
||||||
completed_phases: 0
|
completed_phases: 0
|
||||||
total_plans: 8
|
total_plans: 8
|
||||||
completed_plans: 1
|
completed_plans: 2
|
||||||
percent: 13
|
percent: 13
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -51,6 +51,7 @@ Progress: [█░░░░░░░░░] 13%
|
|||||||
|
|
||||||
*Updated after each plan completion*
|
*Updated after each plan completion*
|
||||||
| Phase 01-foundation P01 | 4 | 2 tasks | 14 files |
|
| Phase 01-foundation P01 | 4 | 2 tasks | 14 files |
|
||||||
|
| Phase 01-foundation P02 | 1 | 2 tasks | 7 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -66,6 +67,8 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 01-foundation]: Upgraded MSAL from 4.83.1 to 4.83.3 — Extensions.Msal 4.83.3 requires MSAL >= 4.83.3; minor patch with no behavioral difference
|
- [Phase 01-foundation]: Upgraded MSAL from 4.83.1 to 4.83.3 — Extensions.Msal 4.83.3 requires MSAL >= 4.83.3; minor patch with no behavioral difference
|
||||||
- [Phase 01-foundation]: Test project targets net10.0-windows with UseWPF=true — required to reference WPF main project; net10.0 is framework-incompatible
|
- [Phase 01-foundation]: Test project targets net10.0-windows with UseWPF=true — required to reference WPF main project; net10.0 is framework-incompatible
|
||||||
- [Phase 01-foundation]: Solution uses .slnx format (new .NET 10 XML solution) — dotnet new sln creates .slnx by default in .NET 10 SDK
|
- [Phase 01-foundation]: Solution uses .slnx format (new .NET 10 XML solution) — dotnet new sln creates .slnx by default in .NET 10 SDK
|
||||||
|
- [Phase 01-foundation]: TenantProfile is a plain mutable class (not record) — System.Text.Json requires settable properties; field names Name/TenantUrl/ClientId match JSON schema exactly
|
||||||
|
- [Phase 01-foundation]: SharePointPaginationHelper uses [EnumeratorCancellation] on ct — required for correct WithCancellation() forwarding in async iterators
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -79,6 +82,6 @@ None yet.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-02T10:04:03.486Z
|
Last session: 2026-04-02T10:07:59.499Z
|
||||||
Stopped at: Completed 01-foundation-01-PLAN.md
|
Stopped at: Completed 01-foundation-02-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
143
.planning/phases/01-foundation/01-02-SUMMARY.md
Normal file
143
.planning/phases/01-foundation/01-02-SUMMARY.md
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
---
|
||||||
|
phase: 01-foundation
|
||||||
|
plan: 02
|
||||||
|
subsystem: core
|
||||||
|
tags: [wpf, dotnet10, csom, pnp-framework, serilog, sharepoint, pagination, retry, messaging, csharp]
|
||||||
|
|
||||||
|
# Dependency graph
|
||||||
|
requires:
|
||||||
|
- 01-01 (solution scaffold, NuGet packages)
|
||||||
|
provides:
|
||||||
|
- TenantProfile model matching JSON schema (Name/TenantUrl/ClientId)
|
||||||
|
- OperationProgress record with Indeterminate factory for IProgress<T> pattern
|
||||||
|
- TenantSwitchedMessage and LanguageChangedMessage broadcast-ready via WeakReferenceMessenger
|
||||||
|
- SharePointPaginationHelper: async iterator bypassing 5k item limit via ListItemCollectionPosition
|
||||||
|
- ExecuteQueryRetryHelper: exponential backoff on 429/503 with IProgress<OperationProgress> surfacing
|
||||||
|
- LogPanelSink: custom Serilog ILogEventSink writing to RichTextBox via Dispatcher.InvokeAsync
|
||||||
|
affects:
|
||||||
|
- 01-03 (ProfileService uses TenantProfile)
|
||||||
|
- 01-04 (MsalClientFactory uses TenantProfile.ClientId/TenantUrl)
|
||||||
|
- 01-05 (TranslationSource sends LanguageChangedMessage; LoggingIntegration uses LogPanelSink)
|
||||||
|
- 01-06 (FeatureViewModelBase uses OperationProgress + IProgress<T> pattern)
|
||||||
|
- 02-xx (all SharePoint feature services use pagination and retry helpers)
|
||||||
|
|
||||||
|
# Tech tracking
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- IAsyncEnumerable<ListItem> with [EnumeratorCancellation] for correct WithCancellation support
|
||||||
|
- ListItemCollectionPosition loop (do/while until null) for CSOM pagination past 5k items
|
||||||
|
- Exponential backoff: delay = 2^attempt * 5s (10, 20, 40, 80, 160s) up to MaxRetries=5
|
||||||
|
- WeakReferenceMessenger messages via ValueChangedMessage<T> base class
|
||||||
|
- Dispatcher.InvokeAsync for thread-safe UI writes from Serilog background thread
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- SharepointToolbox/Core/Models/TenantProfile.cs
|
||||||
|
- SharepointToolbox/Core/Models/OperationProgress.cs
|
||||||
|
- SharepointToolbox/Core/Messages/TenantSwitchedMessage.cs
|
||||||
|
- SharepointToolbox/Core/Messages/LanguageChangedMessage.cs
|
||||||
|
- SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs
|
||||||
|
- SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs
|
||||||
|
- SharepointToolbox/Infrastructure/Logging/LogPanelSink.cs
|
||||||
|
modified: []
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "TenantProfile is a plain class (not record) — mutable for System.Text.Json deserialization; fields Name/TenantUrl/ClientId match existing JSON schema casing"
|
||||||
|
- "SharePointPaginationHelper uses [EnumeratorCancellation] on ct parameter — required for correct cancellation forwarding when callers use WithCancellation(ct)"
|
||||||
|
- "ExecuteQueryRetryHelper uses catch-when filter with IsThrottleException — matches 429/503 status codes and 'throttl' text in message, covers PnP.Framework exception surfaces"
|
||||||
|
|
||||||
|
requirements-completed:
|
||||||
|
- FOUND-05
|
||||||
|
- FOUND-06
|
||||||
|
- FOUND-07
|
||||||
|
- FOUND-08
|
||||||
|
|
||||||
|
# Metrics
|
||||||
|
duration: 1min
|
||||||
|
completed: 2026-04-02
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 1 Plan 02: Core Models, Messages, and Infrastructure Helpers Summary
|
||||||
|
|
||||||
|
**7 Core/Infrastructure files providing typed contracts (TenantProfile, OperationProgress, messages, CSOM pagination helper, throttle-aware retry helper, RichTextBox Serilog sink) — 0 errors, 0 warnings**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 1 min
|
||||||
|
- **Started:** 2026-04-02T10:04:59Z
|
||||||
|
- **Completed:** 2026-04-02T10:06:00Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 7
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- All 7 Core/Infrastructure files created and compiling with 0 errors, 0 warnings
|
||||||
|
- TenantProfile fields match JSON schema exactly (Name/TenantUrl/ClientId)
|
||||||
|
- OperationProgress record with Indeterminate factory, usable by all feature services via IProgress<T>
|
||||||
|
- TenantSwitchedMessage and LanguageChangedMessage correctly inherit ValueChangedMessage<T> for WeakReferenceMessenger broadcast
|
||||||
|
- SharePointPaginationHelper iterates past 5,000 items using ListItemCollectionPosition do/while loop; RowLimit=2000
|
||||||
|
- ExecuteQueryRetryHelper surfaces retry events via IProgress<OperationProgress> with exponential backoff (10s, 20s, 40s, 80s, 160s)
|
||||||
|
- LogPanelSink writes color-coded, timestamped entries to RichTextBox via Dispatcher.InvokeAsync for thread safety
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Core models and WeakReferenceMessenger messages** - `ddb216b` (feat)
|
||||||
|
2. **Task 2: SharePointPaginationHelper, ExecuteQueryRetryHelper, LogPanelSink** - `c297801` (feat)
|
||||||
|
|
||||||
|
**Plan metadata:** (docs commit follows)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `SharepointToolbox/Core/Models/TenantProfile.cs` - Plain class; Name/TenantUrl/ClientId match JSON schema
|
||||||
|
- `SharepointToolbox/Core/Models/OperationProgress.cs` - Record with Indeterminate factory; IProgress<T> contract
|
||||||
|
- `SharepointToolbox/Core/Messages/TenantSwitchedMessage.cs` - ValueChangedMessage<TenantProfile>; WeakReferenceMessenger broadcast
|
||||||
|
- `SharepointToolbox/Core/Messages/LanguageChangedMessage.cs` - ValueChangedMessage<string>; WeakReferenceMessenger broadcast
|
||||||
|
- `SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs` - Async iterator; ListItemCollectionPosition loop; [EnumeratorCancellation]
|
||||||
|
- `SharepointToolbox/Core/Helpers/ExecuteQueryRetryHelper.cs` - Retry on 429/503/throttle; exponential backoff; IProgress surfacing
|
||||||
|
- `SharepointToolbox/Infrastructure/Logging/LogPanelSink.cs` - ILogEventSink; Dispatcher.InvokeAsync; color-coded by level
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- TenantProfile is a plain mutable class (not a record) — System.Text.Json deserialization requires a parameterless constructor and settable properties; field names match the existing JSON schema exactly to avoid serialization mismatches.
|
||||||
|
- SharePointPaginationHelper.GetAllItemsAsync decorates `ct` with `[EnumeratorCancellation]` — without this attribute, cancellation tokens passed via `WithCancellation()` on the async enumerable are silently ignored. This is a correctness requirement for callers who use the cancellation pattern.
|
||||||
|
- ExecuteQueryRetryHelper.IsThrottleException checks for "429", "503", and "throttl" (case-insensitive) — PnP.Framework surfaces HTTP errors in the exception message rather than a dedicated exception type; this covers all known throttle surfaces.
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 2 - Missing critical functionality] Added [EnumeratorCancellation] attribute to SharePointPaginationHelper**
|
||||||
|
- **Found during:** Task 2 (dotnet build)
|
||||||
|
- **Issue:** CS8425 warning — async iterator with `CancellationToken ct` parameter missing `[EnumeratorCancellation]`; without it, cancellation via `WithCancellation(ct)` on the `IAsyncEnumerable<T>` is silently dropped, breaking cancellation for all callers
|
||||||
|
- **Fix:** Added `using System.Runtime.CompilerServices;` and `[EnumeratorCancellation]` attribute on the `ct` parameter
|
||||||
|
- **Files modified:** `SharepointToolbox/Core/Helpers/SharePointPaginationHelper.cs`
|
||||||
|
- **Verification:** Build 0 warnings, 0 errors after fix
|
||||||
|
- **Committed in:** c297801 (Task 2 commit)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total deviations:** 1 auto-fixed (Rule 2 — missing critical functionality for correct cancellation behavior)
|
||||||
|
**Impact on plan:** Fix required for correct operation. One line change, no scope creep.
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None beyond the auto-fixed deviation above.
|
||||||
|
|
||||||
|
## User Setup Required
|
||||||
|
|
||||||
|
None - no external service configuration required.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- All contracts in place for plan 01-03 (ProfileService uses TenantProfile)
|
||||||
|
- All contracts in place for plan 01-04 (MsalClientFactory uses TenantProfile.ClientId/TenantUrl)
|
||||||
|
- All contracts in place for plan 01-05 (LoggingIntegration uses LogPanelSink; LanguageChangedMessage for TranslationSource)
|
||||||
|
- All contracts in place for plan 01-06 (FeatureViewModelBase uses OperationProgress + IProgress<T>)
|
||||||
|
- All Phase 2+ SharePoint feature services can use pagination and retry helpers immediately
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 01-foundation*
|
||||||
|
*Completed: 2026-04-02*
|
||||||
Reference in New Issue
Block a user