v0.3 (script-only): fix all actionable open issues, final PowerShell release#63
Merged
Conversation
- Fix Autopilot property typo: lastContactDateTime -> lastContactedDateTime - Fix BitLocker key retrieval array bug: access first element explicitly - Clear stale parsedDevices on bulk import cancel - Fix status string corruption from $deviceSuccess++ inside PSCustomObject - Fix permission scopes: Device.ReadWrite.All, add BitlockerKey.Read.All - Fix export functions to use actual DeviceObject class properties - Load playbooks from local Playbooks/ directory instead of remote GitHub URLs - Generate playbook result columns dynamically from actual output schema Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Invoke-GraphRequestWithRetry wrapper for 429 throttling (reads Retry-After header), 5xx transient errors (exponential backoff), and network-level failures - Add Invoke-GraphBatchRequest helper that auto-chunks up to 20 sub-requests per POST /$batch with sub-request retry logic - Update Get-GraphPagedResults to use retry wrapper and accept optional Headers parameter - Migrate all v1.0 endpoints to beta with $select across main script and Playbooks 1-5 to reduce API payload size - Rewrite dashboard statistics to use $count batch (1 API call replaces 3 full-collection fetches + client-side counting), with automatic fallback to full-fetch for tenants without $count support - Batch Entra+Intune search queries for device name lookups and Intune+Autopilot queries for serial number lookups - Hoist Autopilot full-collection fetch out of per-search-term loop - Batch per-device offboarding operations (Entra+Intune+Autopilot) into single $batch call per device - Add bulk Autopilot deletion via deleteDevices endpoint using serial numbers when 2+ devices selected, with individual deletion fallback and per-device status parsing from API response
…m filtering, grid filtering, HTML reports - Add saved authentication config (#48): Save/auto-load cert and secret configs to %LocalAppData%/DeviceOffboardingManager. Client secret is never persisted for security. - Add co-management awareness: ManagementAgent property on DeviceObject, amber warning banner in confirmation dialog for co-managed devices. - Add platform filtering on dashboard (#40): ComboBox to filter all dashboard statistics by OS platform. - Add grid filtering and shift-click range selection (#33): Filter TextBoxes above DataGrid for live column filtering, shift-click on checkboxes to toggle ranges. - Add HTML offboarding report generation: Export-OffboardingReport function with professional styled HTML, per-device service status, summary stats. Export buttons in summary and dashboard dialogs. - Update homepage to show Defender for Endpoint as supported (no longer "Soon"). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…polation - Add fallback from EntraDeviceObjectId to intuneDevice.azureADDeviceId for LAPS lookup (mirrors BitLocker fallback pattern) - Fix PowerShell string interpolation in LAPS URI using $() syntax - Add diagnostic logging for LAPS device ID resolution Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ybooks, confirmation dialog - Standardize CornerRadius to 6, fix dashboard subtitle contrast - Fix DataGrid column widths, add tooltips and hover states - Restructure sidebar: connect/tenant at top, nav center, utils bottom - Add ConnectionStatusDot indicator (red/green) - Redesign home page: slim preview banner, Get Started card, quick nav buttons - Add dashboard page header with refresh button - Fix hardcoded stale device progress bars with dynamic calculation - Add device management page header, search placeholder, result count - Fix dropdown labels (Device Name, Serial Number) - Add filter toggle, clear search, conditional offboard panel with selection count - Categorize playbook cards into Device Compliance, Inventory, Health sections - Make playbook cards responsive (MinWidth/MaxWidth) - Move confirmation warning to top, add type-to-confirm safeguard Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… sidebar, and page-by-page polish Toast notifications: - Inline toast overlay replaces ~33 blocking MessageBox popups in main window - Slide-in/out animation with generation counter to prevent stale callbacks - Auto-dismiss with configurable duration, manual dismiss via X button or Escape - Color-coded: green (success), red (error), blue (info) Keyboard shortcuts: - Ctrl+K: navigate to Device Offboarding and focus search - Ctrl+B: toggle sidebar collapse/expand - F5: refresh dashboard (when on Dashboard page) - Escape: contextual dismiss (toast > filter row > clear search) - Enter: search (in search box), connect (auth dialog), confirm (OS picker) - IsCancel on all modal Close/Cancel buttons for universal Escape-to-close Collapsible sidebar: - Toggle button with collapse to 48px rail - Connection status dot remains visible when collapsed - Synced at all connection state change points Search UX: - Search button shows "Searching..." with wait cursor during operation - Dynamic placeholder text updates when search mode dropdown changes - Empty state message shown before first search - Clear button returns focus to search input - DataGrid visibility toggled with empty state Home page: - Specific subtitle about offboarding workflow - Ellipse dot bullets replacing ASCII dashes - Feature list rewritten (offboarding, CSV import, stale reporting, key backup) - Full Microsoft service names - Card backgrounds unified to 2 tones - Get Started card updates dynamically on connection (green button, new text) - Quick nav tooltips show "(connect first)" when disabled, Ctrl+K hint - Auto-navigate to Dashboard when already connected on launch Dashboard page: - ScrollViewer wrapper for small windows - "Last refreshed" timestamp in header - All counts show "--" before data loads (not "0") - Specific subtitles: "Managed by Intune", "Registered in Autopilot", etc. - Stale cards: "Not synced in 30/90/180+ days" - Tooltips on all clickable stat cards - Refresh button loading state with F5 shortcut - "EntraID" corrected to "Entra ID" Device Management page: - Search/Clear button tooltips with keyboard hints - Filter row columns aligned to DataGrid widths - Filter boxes have tooltips - "OS" column header expanded to "Operating System" - "View" groups link gets tooltip - "Offboard device(s)" simplified to "Offboard Devices" - Empty state TextBlock before first search Playbooks page: - Specific subtitle about compliance, inventory, security audits - "Device Compliance" renamed to "Enrollment Discrepancies" - Hover effect on playbook cards - Back/Export buttons get cursor and tooltips - Results header includes device count - Results DataGrid column widths proportional Auth dialog: - Window title matches header text - Concise subtitle without "API" - "Interactive Login (Browser)" instead of "(Admin User)" - IsDefault on Connect, IsCancel on Cancel - Cursor and tooltips on Save/Import buttons - "Save Config" renamed to "Save Locally" - Auto-selects previously used auth method Bulk Import dialog: - "File Template" instead of "CSV Template" - "Save Template" instead of "Download Template" - Instructive placeholder text - IsCancel on Cancel button - Tooltips on all buttons - Full file path as tooltip on file path TextBox Confirmation dialog: - Warning text covers both delete and disable actions - Dynamic subtitle with device count - IsCancel on Cancel, Cursor on Confirm - Type-to-confirm TextBox turns green on match - Copy Key button gets tooltip Offboarding Summary dialog: - Dynamic timestamp subtitle - Clean status labels without ASCII art prefixes - "Defender" instead of "MDE" column label - IsCancel + Cursor on Close, tooltip on Export Report All remaining modals: - IsCancel="True" on every Close/Cancel button (10 total) - Cursor="Hand" on every interactive button (42 total) - MenuButtonStyle gets Cursor="Hand" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…o script The v0.3 line returns to the single-script layout; this ports the functional content of the module-only commits back into DeviceOffboardingManager.ps1: - Add ConvertTo-ODataStringValue and escape search text and device-derived names/serials in all Graph $filter interpolations (from 2d47b30). The module-era serial-search regression does not apply here: the script always used serialNumber eq and deviceName-only contains filters. - Document why Intune managedDevices filters must use serialNumber eq and must not combine contains(deviceName) with contains(serialNumber) (from 2979360). - Show a loading toast + dispatcher pump in all 8 dashboard stat-card handlers before the synchronous fetch (from 2979360). - Remove dead locals $bulkAutopilotIds and $playbookName (from 2979360). - Mark 0.3 changelog as Unreleased. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backports the functional content of module commits fe01ab9 and bdf71f4 into the script: - New settings.json in the config directory with DefenderIntegrationEnabled (default false), managed via Get/Save-DeviceOffboardingSettings and Get/Set-DefenderIntegrationEnabled. - Defender only appears as an offboarding target when the setting is enabled; offboarding and summary checks are gated the same way. - Prerequisites dialog gains a Defender integration toggle and an optional MSAL.PS module check with install button. - Get-MdeAccessToken now tries both Defender API resource endpoints and supports app-only token acquisition for client-secret and certificate auth via $script:CurrentAuthDetails (captured in Connect-ToGraph, disposed on disconnect/auth failure), with delegated silent/interactive fallback. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backports the device-code flow from module commit 2d47b30 into the script: a DeviceCodeAuth radio button in the authentication dialog, a DeviceCode branch in Connect-ToGraph using Connect-MgGraph -UseDeviceCode, and input-panel collapse handling. Avoids browser localhost redirect / WAM failures with interactive authentication. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Publish-Script only delivers DeviceOffboardingManager.ps1, so PSGallery installs had no Playbooks/ directory and every playbook failed with 'Playbook file not found'. The script now embeds all 10 playbooks plus PlaybookHelpers.ps1 as here-strings; Get-PlaybookRoot prefers the repo-local Playbooks/ directory and otherwise extracts the bundled copies to the per-user config directory. Also: - Replace 3-argument Join-Path calls at playbook call sites, which fail on Windows PowerShell 5.1. - Guard recovery-key clipboard copy against transient clipboard failures so the exception cannot escape the routed event handler and destabilize the offboarding dialogs (Issue #38). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backported from module commit 2d47b30: a 'Set Group Tag' button next to the export buttons, enabled with device selection; Show-GroupTagDialog for entering or clearing a tag; Set-AutopilotGroupTagForDevices posts updateDeviceProperties per device, resolving missing Autopilot identities by exact serial match only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Backported from module commit 2d47b30: lists imported corporate device identifiers (importedDeviceIdentities) with enrollment state and last contact staleness. Wired into the Playbooks page and included in the embedded playbook bundle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Parses the main script and all playbooks, validates every inline XAML block as well-formed XML, and checks that the embedded playbook bundle is in sync with the Playbooks/ directory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
#52, #53) - Get-Graph403Message maps per-service 403 Forbidden responses during offboarding to the likely missing directory/Intune role instead of a raw HTTP error (MAA detection unchanged) - README: final-script-release note (v0.4 WinUI plan), Required Roles table, device code login, Defender opt-in section, saved auth config, group tags, playbook bundling, updated search/usage docs - Bump .VERSION to 0.3.0, date changelog 7/7/2026 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
v0.3 stays a single PowerShell Gallery script (published with
Publish-Script, exactly like 0.2.x). This branch replaces the module-migration approach from #61: converting the PSGallery package from script to module would have required freeing the package name via PSGallery support and retraining users, for a distribution that the v0.4 WinUI app replaces anyway. v0.3 is the final PowerShell release.The branch starts from the last pre-migration commit of
feature/v0.3(so every v0.3 bug fix and feature is already in script form) and backports the functional content of the module-only commits, plus new fixes found during triage.Issues fixed in this PR / on this branch
DeviceLocalCredential.Read.All)Install-Scriptonly delivers the.ps1)BitlockerKey.Read.AllupdateDeviceProperties)DOM_*.logaudit log; recovery keys logged withSENSITIVEprefixdisplayNamefilters (client-side matching instead)ShowDialog%LocalAppData%/DeviceOffboardingManagerdeviceId)Addressed but left open for reporter confirmation: #46 (dashboard
$countbatch rework with full-fetch fallback plus rebuilt device-name search should resolve both symptoms; needs a live-tenant check).Deferred to v0.4 (WinUI app): #60, #14, #62 (AD/ConfigMgr part), #3.
Verification
[System.Management.Automation.Language.Parser]::ParseFileclean on the final script; all 11 XAML blocks validated as well-formed XMLRelease notes
.VERSIONbumped to 0.3.0, changelog dated 7/7/2026 — merging this PR ships the 0.3.0 releasetasks/todo.mdrewritten with the script-only strategy and full issue triage🤖 Generated with Claude Code