diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 1ee687b..ce87a30 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -53,7 +53,7 @@ Plans: 2. Running the audit returns a list of all access entries the user holds across the selected sites 3. Results distinguish between direct role assignments, SharePoint group memberships, and inherited access 4. Results can be exported to CSV or HTML in the same format established by v1.0 export patterns -**Plans:** 3/8 plans executed +**Plans:** 4/8 plans executed Plans: - [ ] 07-01-PLAN.md — UserAccessEntry model + service interfaces (Wave 1) - [ ] 07-02-PLAN.md — UserAccessAuditService implementation (Wave 2) @@ -96,6 +96,6 @@ Plans: | 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 | | 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 | | 6. Global Site Selection | 5/5 | Complete | 2026-04-07 | - | -| 7. User Access Audit | 3/8 | In Progress| | - | +| 7. User Access Audit | 4/8 | In Progress| | - | | 8. Simplified Permissions | v1.1 | 0/? | Not started | - | | 9. Storage Visualization | v1.1 | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index cdc1141..e40a3ac 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: completed -stopped_at: Completed 07-02-PLAN.md -last_updated: "2026-04-07T10:40:45.186Z" +stopped_at: Completed 07-06-PLAN.md +last_updated: "2026-04-07T10:41:47.594Z" last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped progress: total_phases: 4 completed_phases: 1 total_plans: 13 - completed_plans: 8 + completed_plans: 9 --- # Project State @@ -50,6 +50,7 @@ Phase 6 [ ] → Phase 7 [ ] → Phase 8 [ ] → Phase 9 [ ] | Phase 07-user-access-audit P01 | 5 | 2 tasks | 3 files | | Phase 07-user-access-audit P03 | 2 | 1 tasks | 1 files | | Phase 07-user-access-audit P02 | 1 | 1 tasks | 1 files | +| Phase 07-user-access-audit P06 | 2 | 2 tasks | 2 files | ## Accumulated Context @@ -79,6 +80,8 @@ Decisions are logged in PROJECT.md Key Decisions table. - [Phase 07-03]: ConsistencyLevel=eventual and Count=true both required for startsWith on Graph directory objects - [Phase 07-user-access-audit]: TenantProfile.ClientId empty in service — session pre-authenticated at ViewModel level; SessionManager returns cached context by URL key - [Phase 07-user-access-audit]: Bidirectional contains matching for user login — handles both plain email and full SharePoint claim formats +- [Phase 07-user-access-audit]: UserAccessCsvExportService has two write modes: WriteAsync (per-user files to directory) and WriteSingleFileAsync (combined for SaveFileDialog) +- [Phase 07-user-access-audit]: HTML sortTable() scoped per group so sorting in by-user view keeps each user's rows together ### Pending Todos @@ -90,6 +93,6 @@ None. ## Session Continuity -Last session: 2026-04-07T10:40:45.184Z -Stopped at: Completed 07-02-PLAN.md +Last session: 2026-04-07T10:41:47.591Z +Stopped at: Completed 07-06-PLAN.md Resume file: None diff --git a/.planning/phases/07-user-access-audit/07-06-SUMMARY.md b/.planning/phases/07-user-access-audit/07-06-SUMMARY.md new file mode 100644 index 0000000..6ffb293 --- /dev/null +++ b/.planning/phases/07-user-access-audit/07-06-SUMMARY.md @@ -0,0 +1,110 @@ +--- +phase: 07-user-access-audit +plan: 06 +subsystem: export +tags: [csv, html, export, user-access-audit, csharp] + +requires: + - phase: 07-01 + provides: [UserAccessEntry, AccessType enum] +provides: + - UserAccessCsvExportService with BuildCsv, WriteAsync (per-user files), WriteSingleFileAsync (combined) + - UserAccessHtmlExportService with BuildHtml (interactive dual-view report), WriteAsync +affects: [07-04, 07-07, 07-08] + +tech-stack: + added: [] + patterns: [RFC 4180 CSV escaping, UTF-8+BOM for CSV, UTF-8 no-BOM for HTML, inline CSS/JS self-contained HTML, dual-view toggle pattern, collapsible group rows] + +key-files: + created: + - SharepointToolbox/Services/Export/UserAccessCsvExportService.cs + - SharepointToolbox/Services/Export/UserAccessHtmlExportService.cs + modified: [] + +key-decisions: + - "UserAccessCsvExportService has two write modes: WriteAsync (per-user files to directory, audit_{email}_{date}.csv) and WriteSingleFileAsync (all users combined, for SaveFileDialog export in ViewModel)" + - "HTML BuildHtml uses group-scoped sortTable so sorting within one user/site group does not disrupt others" + - "filterTable() shows/hides group headers based on whether any of their child rows match, avoiding orphaned headers" + +patterns-established: + - "Export services follow consistent pattern: BuildX() returns string, WriteAsync() writes to path — same as CsvExportService and HtmlExportService" + - "HTML reports use data-group attributes on detail rows for JS group operations (toggle, sort, filter)" + - "High-privilege CSS applied inline via rowClass variable — keeps HTML generation declarative" + +requirements-completed: [UACC-02] + +duration: 2min +completed: 2026-04-07 +--- + +# Phase 7 Plan 06: Export Services Summary + +**Two self-contained export services for User Access Audit: per-user CSV files with summary headers and a single interactive HTML report with dual-view toggle (by-user/by-site), collapsible groups, sortable columns, risk highlighting, and color-coded access type badges.** + +## Performance + +- **Duration:** ~2 min +- **Started:** 2026-04-07T10:39:04Z +- **Completed:** 2026-04-07T10:41:05Z +- **Tasks:** 2 +- **Files modified:** 2 + +## Accomplishments + +- UserAccessCsvExportService: BuildCsv (per-user with summary block), WriteAsync (one file per user), WriteSingleFileAsync (combined for SaveFileDialog) — RFC 4180 escaping, UTF-8+BOM +- UserAccessHtmlExportService: self-contained HTML with stats cards, per-user summary cards, dual-view toggle (By User / By Site), collapsible group headers, sortable columns (per-group), text filter scoped to active view +- Risk highlighting: high-privilege rows bold + warning icon, high-privilege user cards with red left border, external user guest badge (orange pill) + +## Task Commits + +1. **Task 1: Implement UserAccessCsvExportService** - `9f891aa` (feat) +2. **Task 2: Implement UserAccessHtmlExportService** - `3146a04` (feat) + +**Plan metadata:** (docs commit pending) + +## Files Created/Modified + +- `SharepointToolbox/Services/Export/UserAccessCsvExportService.cs` — Per-user and combined CSV export with summary headers +- `SharepointToolbox/Services/Export/UserAccessHtmlExportService.cs` — Interactive HTML report with dual-view toggle, collapsible groups, inline CSS/JS + +## Decisions Made + +1. **Two CSV write modes** — WriteAsync writes one file per user to a directory (batch export); WriteSingleFileAsync writes all users to one file (for ViewModel's SaveFileDialog flow, simpler UX). + +2. **Group-scoped sort** — sortTable() collects and re-inserts rows within each group individually, so sorting by "Permission Level" in the by-user view keeps each user's rows together. + +3. **Filter hides empty group headers** — filterTable() tracks which groups have at least one visible row, then hides group headers for empty groups to avoid orphaned section labels. + +## Deviations from Plan + +None — plan executed exactly as written. + +## Issues Encountered + +None. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- Both export services ready for wiring into the UserAccessAuditViewModel export commands (07-04) +- CSV: ViewModel calls WriteSingleFileAsync(entries, filePath, ct) after SaveFileDialog +- HTML: ViewModel calls WriteAsync(entries, filePath, ct) after SaveFileDialog +- Both services are stateless and constructable without DI parameters + +## Self-Check: PASSED + +Files confirmed present: +- FOUND: SharepointToolbox/Services/Export/UserAccessCsvExportService.cs +- FOUND: SharepointToolbox/Services/Export/UserAccessHtmlExportService.cs + +Commits confirmed: +- FOUND: 9f891aa +- FOUND: 3146a04 + +--- +*Phase: 07-user-access-audit* +*Completed: 2026-04-07*