diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index da30844..f5ca69f 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -9,11 +9,11 @@ Requirements for v2.3 Tenant Management & Report Enhancements. Each maps to road ### App Registration -- [ ] **APPREG-01**: User can register the app on a target tenant from the profile create/edit dialog +- [x] **APPREG-01**: User can register the app on a target tenant from the profile create/edit dialog - [x] **APPREG-02**: App auto-detects if user has Global Admin permissions before attempting registration - [x] **APPREG-03**: App creates Azure AD application + service principal + grants required permissions atomically (with rollback on failure) -- [ ] **APPREG-04**: User sees guided fallback instructions when auto-registration is not possible (insufficient permissions) -- [ ] **APPREG-05**: User can remove the app registration from a target tenant +- [x] **APPREG-04**: User sees guided fallback instructions when auto-registration is not possible (insufficient permissions) +- [x] **APPREG-05**: User can remove the app registration from a target tenant - [x] **APPREG-06**: App clears cached tokens and sessions when app registration is removed ### Site Ownership @@ -48,11 +48,11 @@ Requirements for v2.3 Tenant Management & Report Enhancements. Each maps to road | Requirement | Phase | Status | |-------------|-------|--------| -| APPREG-01 | Phase 19 | Pending | +| APPREG-01 | Phase 19 | Complete | | APPREG-02 | Phase 19 | Complete | | APPREG-03 | Phase 19 | Complete | -| APPREG-04 | Phase 19 | Pending | -| APPREG-05 | Phase 19 | Pending | +| APPREG-04 | Phase 19 | Complete | +| APPREG-05 | Phase 19 | Complete | | APPREG-06 | Phase 19 | Complete | | OWN-01 | Phase 18 | Complete | | OWN-02 | Phase 18 | Complete | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index d645837..ab23c75 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -47,7 +47,7 @@ - [x] **Phase 16: Report Consolidation Toggle** (2 plans) — Export settings toggle wired to PermissionConsolidator; first user-visible consolidation behavior (completed 2026-04-09) - [x] **Phase 17: Group Expansion in HTML Reports** (2 plans) — Clickable group expansion in HTML exports with transitive membership resolution (completed 2026-04-09) - [x] **Phase 18: Auto-Take Ownership** (2 plans) — Global toggle and automatic site collection admin elevation on access denied (completed 2026-04-09) -- [ ] **Phase 19: App Registration & Removal** (2 plans) — Automated Entra app registration with guided fallback and clean removal +- [x] **Phase 19: App Registration & Removal** (2 plans) — Automated Entra app registration with guided fallback and clean removal (completed 2026-04-09) ## Phase Details @@ -117,7 +117,7 @@ Plans: 3. Registration creates the Azure AD application, service principal, and grants all required API permissions in a single atomic operation — if any step fails, all partial changes are rolled back and the user sees a specific error explaining what failed and why 4. A "Remove App" action in the profile dialog removes the Azure AD application registration from the target tenant 5. After removal, all cached MSAL tokens and session state for that tenant are cleared, and subsequent operations require re-authentication -**Plans:** 1/2 plans executed +**Plans:** 2/2 plans complete Plans: - [ ] 19-01-PLAN.md — IAppRegistrationService + AppRegistrationResult model + TenantProfile.AppId + service implementation + unit tests - [ ] 19-02-PLAN.md — ViewModel RegisterApp/RemoveApp commands + XAML dialog UI + fallback panel + localization + VM tests @@ -133,4 +133,4 @@ Plans: | 16. Report Consolidation Toggle | v2.3 | 2/2 | Complete | 2026-04-09 | | 17. Group Expansion in HTML Reports | 2/2 | Complete | 2026-04-09 | — | | 18. Auto-Take Ownership | 2/2 | Complete | 2026-04-09 | — | -| 19. App Registration & Removal | 1/2 | In Progress| | — | +| 19. App Registration & Removal | 2/2 | Complete | 2026-04-09 | — | diff --git a/.planning/STATE.md b/.planning/STATE.md index 42d89ca..025d92f 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v2.3 milestone_name: Tenant Management & Report Enhancements status: planning -stopped_at: Completed 19-01-PLAN.md -last_updated: "2026-04-09T13:15:04.040Z" +stopped_at: Completed 19-02-PLAN.md +last_updated: "2026-04-09T13:20:41.127Z" last_activity: 2026-04-09 — Roadmap created for v2.3 (phases 15-19) progress: total_phases: 5 - completed_phases: 4 + completed_phases: 5 total_plans: 10 - completed_plans: 9 + completed_plans: 10 --- # Project State @@ -79,6 +79,9 @@ Decisions are logged in PROJECT.md Key Decisions table. - [Phase 19-app-registration-removal]: AppRegistrationService uses AppGraphClientFactory alias to disambiguate from Microsoft.Graph.GraphClientFactory - [Phase 19-app-registration-removal]: BuildRequiredResourceAccess declared internal to enable direct unit testing without live Graph calls - [Phase 19-app-registration-removal]: SharePoint AllSites.FullControl GUID marked LOW confidence — must be verified against live tenant +- [Phase 19-app-registration-removal]: ProfileManagementViewModel constructor gains IAppRegistrationService as last param — existing logo tests updated to 5-param +- [Phase 19-app-registration-removal]: TranslationSource.Instance used directly in ViewModel for status strings (consistent with runtime locale switching) +- [Phase 19-app-registration-removal]: BooleanToVisibilityConverter declared in Window.Resources (WPF built-in, no custom converter needed) ### Pending Todos @@ -90,7 +93,7 @@ None. ## Session Continuity -Last session: 2026-04-09T13:15:04.038Z -Stopped at: Completed 19-01-PLAN.md +Last session: 2026-04-09T13:20:36.865Z +Stopped at: Completed 19-02-PLAN.md Resume file: None Next step: `/gsd:plan-phase 15` diff --git a/.planning/phases/19-app-registration-removal/19-02-SUMMARY.md b/.planning/phases/19-app-registration-removal/19-02-SUMMARY.md new file mode 100644 index 0000000..8e12d50 --- /dev/null +++ b/.planning/phases/19-app-registration-removal/19-02-SUMMARY.md @@ -0,0 +1,83 @@ +--- +phase: 19-app-registration-removal +plan: "02" +subsystem: ViewModels/UI +tags: [app-registration, viewmodel, xaml, localization, unit-tests] +dependency_graph: + requires: [19-01] + provides: [register-app-ui, remove-app-ui, fallback-instructions-panel] + affects: [ProfileManagementViewModel, ProfileManagementDialog, App.xaml.cs] +tech_stack: + added: [] + patterns: [IAsyncRelayCommand, ObservableProperty, BooleanToVisibilityConverter, TranslationSource] +key_files: + created: + - SharepointToolbox.Tests/ViewModels/ProfileManagementViewModelRegistrationTests.cs + modified: + - SharepointToolbox/ViewModels/ProfileManagementViewModel.cs + - SharepointToolbox/Views/Dialogs/ProfileManagementDialog.xaml + - SharepointToolbox/Localization/Strings.resx + - SharepointToolbox/Localization/Strings.fr.resx + - SharepointToolbox/App.xaml.cs + - SharepointToolbox.Tests/ViewModels/ProfileManagementViewModelLogoTests.cs +decisions: + - ProfileManagementViewModel constructor gains IAppRegistrationService as last param — existing logo tests updated to 5-param + - RegisterAppAsync/RemoveAppAsync use CancellationToken from IAsyncRelayCommand overload + - TranslationSource.Instance used directly in ViewModel for status strings (consistent with runtime locale switching) + - BooleanToVisibilityConverter declared in Window.Resources (WPF built-in, no custom converter needed) +metrics: + duration: ~5 minutes + completed_date: "2026-04-09" + tasks_completed: 2 + files_modified: 7 +--- + +# Phase 19 Plan 02: Register/Remove App UI Summary + +Register and Remove app commands wired into ProfileManagementViewModel with fallback instructions panel, DI registration, EN/FR localization, and 7 passing unit tests. + +## Tasks Completed + +| # | Task | Commit | Status | +|---|------|--------|--------| +| 1 | ViewModel commands + DI + Localization | 42b5eda | Done | +| 2 | Profile dialog XAML + ViewModel tests | 809ac86 | Done | + +## What Was Built + +**ProfileManagementViewModel** gained: +- `IAppRegistrationService` constructor injection +- `RegisterAppCommand` / `RemoveAppCommand` (IAsyncRelayCommand) +- `IsRegistering`, `ShowFallbackInstructions`, `RegistrationStatus` observable properties +- `HasRegisteredApp` computed property +- `CanRegisterApp` / `CanRemoveApp` guards (profile selected, AppId null/non-null, not busy) +- `RegisterAppAsync`: admin check → fallback panel or full registration → AppId persistence +- `RemoveAppAsync`: app removal + MSAL clear + AppId null + persistence +- `OnIsRegisteringChanged` partial: notifies both commands on busy state change + +**ProfileManagementDialog.xaml**: +- Height 750 (was 620) +- New Row 4: Register/Remove buttons, RegistrationStatus TextBlock, fallback instructions Border (6 steps) +- `BooleanToVisibilityConverter` added to `Window.Resources` +- Buttons row shifted from Row 4 to Row 5 + +**Localization**: 16 new keys in both Strings.resx and Strings.fr.resx (register/remove/fallback flow, all accented FR characters). + +**App.xaml.cs**: `IAppRegistrationService` registered as singleton. + +**Tests**: 7 unit tests, all passing — CanExecute guards, fallback on non-admin, AppId set on success, AppId cleared on remove. + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 2 - Missing critical update] Updated ProfileManagementViewModelLogoTests to 5-param constructor** +- **Found during:** Task 2 +- **Issue:** Existing logo tests used the 4-param constructor which no longer exists after adding IAppRegistrationService +- **Fix:** Added `Mock` field and passed `_mockAppReg.Object` as 5th param in all 3 constructor calls +- **Files modified:** SharepointToolbox.Tests/ViewModels/ProfileManagementViewModelLogoTests.cs +- **Commit:** 809ac86 + +## Self-Check: PASSED + +All key files found. Both task commits verified (42b5eda, 809ac86). Full solution builds clean. 7/7 tests pass.