diff --git a/.mhs.json b/.mhs.json
new file mode 100644
index 00000000..37e91dd0
--- /dev/null
+++ b/.mhs.json
@@ -0,0 +1 @@
+{"@odata.context":"https://graph.microsoft.com/beta/$metadata#deviceManagement/deviceConfigurations/$entity","@odata.type":"#microsoft.graph.androidDeviceOwnerGeneralDeviceConfiguration","id":"070a76c2-a8c3-4f7f-9ba7-1f4ac5084184","lastModifiedDateTime":"2026-05-11T17:34:14.1395368Z","roleScopeTagIds":["0"],"supportsScopeTags":true,"deviceManagementApplicabilityRuleOsEdition":null,"deviceManagementApplicabilityRuleOsVersion":null,"deviceManagementApplicabilityRuleDeviceMode":null,"createdDateTime":"2026-04-20T16:47:42.6101923Z","description":"Device restrictions + password complexity for Cascades shared caregiver phones. HIPAA baseline: 6-digit numeric complex PIN, 1-minute inactivity lock, factory reset blocked, screen capture blocked, modify accounts blocked, Wi-Fi edit blocked.","displayName":"CSC - Android Shared Phones Restrictions","version":15,"accountsBlockModification":true,"appsAllowInstallFromUnknownSources":false,"appsAutoUpdatePolicy":"wiFiOnly","appsDefaultPermissionPolicy":"autoGrant","appsRecommendSkippingFirstUseHints":null,"bluetoothBlockConfiguration":true,"bluetoothBlockContactSharing":true,"cameraBlocked":true,"cellularBlockWiFiTethering":null,"certificateCredentialConfigurationDisabled":null,"crossProfilePoliciesAllowCopyPaste":null,"crossProfilePoliciesAllowDataSharing":null,"crossProfilePoliciesShowWorkContactsInPersonalProfile":null,"microsoftLauncherConfigurationEnabled":null,"microsoftLauncherCustomWallpaperEnabled":null,"microsoftLauncherCustomWallpaperImageUrl":null,"microsoftLauncherCustomWallpaperAllowUserModification":null,"microsoftLauncherFeedEnabled":null,"microsoftLauncherFeedAllowUserModification":null,"microsoftLauncherDockPresenceConfiguration":null,"microsoftLauncherDockPresenceAllowUserModification":null,"microsoftLauncherSearchBarPlacementConfiguration":null,"enrollmentProfile":"notConfigured","dataRoamingBlocked":true,"dateTimeConfigurationBlocked":true,"detailedHelpText":null,"deviceOwnerLockScreenMessage":null,"securityCommonCriteriaModeEnabled":null,"factoryResetDeviceAdministratorEmails":[],"factoryResetBlocked":true,"globalProxy":null,"googleAccountsBlocked":true,"kioskCustomizationDeviceSettingsBlocked":false,"kioskCustomizationPowerButtonActionsBlocked":false,"kioskCustomizationStatusBar":"notificationsAndSystemInfoEnabled","kioskCustomizationSystemErrorWarnings":true,"kioskCustomizationSystemNavigation":"navigationEnabled","kioskModeScreenSaverConfigurationEnabled":null,"kioskModeScreenSaverImageUrl":null,"kioskModeScreenSaverDisplayTimeInSeconds":null,"kioskModeScreenSaverStartDelayInSeconds":null,"kioskModeScreenSaverDetectMediaDisabled":null,"kioskModeWallpaperUrl":"https://cascadestucson.com/wp-content/uploads/2023/06/CascadesOfTucson-logo.png","kioskModeExitCode":null,"isKioskModeExitCodeSet":false,"kioskModeVirtualHomeButtonEnabled":false,"kioskModeVirtualHomeButtonType":"swipeUp","kioskModeBluetoothConfigurationEnabled":true,"kioskModeWiFiConfigurationEnabled":true,"kioskModeFlashlightConfigurationEnabled":true,"kioskModeMediaVolumeConfigurationEnabled":true,"kioskModeShowDeviceInfo":null,"kioskModeManagedSettingsEntryDisabled":null,"kioskModeDebugMenuEasyAccessEnabled":null,"kioskModeShowAppNotificationBadge":true,"kioskModeScreenOrientation":null,"kioskModeIconSize":null,"kioskModeFolderIcon":null,"kioskModeWifiAllowedSsids":[],"kioskModeAppOrderEnabled":null,"kioskModeAppsInFolderOrderedByName":null,"kioskModeGridHeight":null,"kioskModeGridWidth":null,"kioskModeLockHomeScreen":null,"kioskModeManagedHomeScreenAutoSignout":true,"kioskModeManagedHomeScreenInactiveSignOutDelayInSeconds":43200,"kioskModeManagedHomeScreenInactiveSignOutNoticeInSeconds":300,"kioskModeManagedHomeScreenPinComplexity":null,"kioskModeManagedHomeScreenPinRequired":false,"kioskModeManagedHomeScreenPinRequiredToResume":null,"kioskModeManagedHomeScreenSignInBackground":null,"kioskModeManagedHomeScreenSignInBrandingLogo":null,"kioskModeManagedHomeScreenSignInEnabled":null,"kioskModeUseManagedHomeScreenApp":"multiAppMode","microphoneForceMute":null,"networkEscapeHatchAllowed":null,"nfcBlockOutgoingBeam":null,"passwordBlockKeyguard":null,"passwordBlockKeyguardFeatures":[],"passwordExpirationDays":null,"passwordMinimumLength":6,"passwordMinimumLetterCharacters":null,"passwordMinimumLowerCaseCharacters":null,"passwordMinimumNonLetterCharacters":null,"passwordMinimumNumericCharacters":null,"passwordMinimumSymbolCharacters":null,"passwordMinimumUpperCaseCharacters":null,"passwordMinutesOfInactivityBeforeScreenTimeout":1,"passwordPreviousPasswordCountToBlock":5,"passwordRequiredType":"numericComplex","passwordRequireUnlock":null,"passwordSignInFailureCountBeforeFactoryReset":10,"playStoreMode":"notConfigured","screenCaptureBlocked":true,"securityDeveloperSettingsEnabled":false,"securityRequireVerifyApps":true,"shortHelpText":null,"statusBarBlocked":false,"stayOnModes":[],"storageAllowUsb":false,"storageBlockExternalMedia":true,"storageBlockUsbFileTransfer":true,"systemUpdateWindowStartMinutesAfterMidnight":120,"systemUpdateWindowEndMinutesAfterMidnight":360,"systemUpdateInstallType":"windowed","systemWindowsBlocked":null,"usersBlockAdd":true,"usersBlockRemove":true,"volumeBlockAdjustment":null,"vpnAlwaysOnLockdownMode":null,"vpnAlwaysOnPackageIdentifier":null,"wifiBlockEditConfigurations":true,"wifiBlockEditPolicyDefinedConfigurations":null,"personalProfileAppsAllowInstallFromUnknownSources":null,"personalProfileCameraBlocked":null,"personalProfileScreenCaptureBlocked":null,"personalProfilePlayStoreMode":null,"workProfilePasswordExpirationDays":null,"workProfilePasswordMinimumLength":null,"workProfilePasswordMinimumNumericCharacters":null,"workProfilePasswordMinimumNonLetterCharacters":null,"workProfilePasswordMinimumLetterCharacters":null,"workProfilePasswordMinimumLowerCaseCharacters":null,"workProfilePasswordMinimumUpperCaseCharacters":null,"workProfilePasswordMinimumSymbolCharacters":null,"workProfilePasswordPreviousPasswordCountToBlock":null,"workProfilePasswordSignInFailureCountBeforeFactoryReset":null,"workProfilePasswordRequiredType":null,"workProfilePasswordRequireUnlock":null,"locateDeviceUserlessDisabled":null,"locateDeviceLostModeEnabled":null,"shareDeviceLocationDisabled":null,"deviceLocationMode":null,"azureAdSharedDeviceDataClearApps":[],"kioskModeApps":[{"name":"Alis","publisher":"Cascades of Tucson","appStoreUrl":"https://play.google.com/work/apps/details?id=com.google.enterprise.webapp.x830557c4d8441444","appId":"com.google.enterprise.webapp.x830557c4d8441444"},{"name":"HelpAny","publisher":"Cascades of Tucson","appStoreUrl":"https://play.google.com/work/apps/details?id=com.google.enterprise.webapp.x6c759d4796c8526c","appId":"com.google.enterprise.webapp.x6c759d4796c8526c"},{"name":"LinkRx","publisher":"Cascades of Tucson","appStoreUrl":"https://play.google.com/work/apps/details?id=com.google.enterprise.webapp.x5fc56faf2fae1246","appId":"com.google.enterprise.webapp.x5fc56faf2fae1246"},{"name":"Microsoft Outlook","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.office.outlook","appId":"com.microsoft.office.outlook"},{"name":"Microsoft Teams","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.teams","appId":"com.microsoft.teams"},{"name":"Microsoft Authenticator","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.azure.authenticator","appId":"com.azure.authenticator"},{"name":"Microsoft Edge","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.emmx","appId":"com.microsoft.emmx"},{"name":"Managed Home Screen","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.launcher.enterprise","appId":"com.microsoft.launcher.enterprise"},{"name":"Intune Company Portal","publisher":"Microsoft","appStoreUrl":"https://play.google.com/store/apps/details?id=com.microsoft.windowsintune.companyportal","appId":"com.microsoft.windowsintune.companyportal"}],"kioskModeManagedFolders":[],"kioskModeAppPositions":[],"kioskModeManagedHomeScreenAppSettings":[],"systemUpdateFreezePeriods":[],"personalProfilePersonalApplications":[],"androidDeviceOwnerDelegatedScopeAppSettings":[]}
\ No newline at end of file
diff --git a/clients/cascades-tucson/scripts/add-nurse-printer.ps1 b/clients/cascades-tucson/scripts/add-nurse-printer.ps1
new file mode 100644
index 00000000..75b25366
--- /dev/null
+++ b/clients/cascades-tucson/scripts/add-nurse-printer.ps1
@@ -0,0 +1,21 @@
+# Add the nurse printer as a machine-level connection via Point and Print
+# This makes it available to ALL users who log in
+$printer = '\\CS-SERVER\Nurses - Brother MFC-L8900CDW'
+# Check if already installed as local/machine printer
+$existing = Get-Printer -Name $printer -ErrorAction SilentlyContinue
+if ($existing -and $existing.Type -eq 'Local') {
+ Write-Output "Already installed as machine printer: $printer"
+} else {
+ # Use rundll32 to install as machine-level
+ & rundll32 printui.dll,PrintUIEntry /ga /n $printer 2>&1
+ Write-Output "Added machine-level printer connection: $printer"
+}
+# Set as default for the machine
+# Also add the Health Services printer the same way
+$printer2 = '\\CS-SERVER\Health Services - Konica Minolta C368'
+& rundll32 printui.dll,PrintUIEntry /ga /n $printer2 2>&1
+Write-Output "Added machine-level printer connection: $printer2"
+Write-Output ""
+Write-Output "Both printers will be available to all users on next login."
+Write-Output "Current printers:"
+Get-Printer | Select-Object Name, Type | Format-Table -AutoSize
diff --git a/clients/cascades-tucson/scripts/align-test-pilot-upn.ps1 b/clients/cascades-tucson/scripts/align-test-pilot-upn.ps1
new file mode 100644
index 00000000..b24dc901
--- /dev/null
+++ b/clients/cascades-tucson/scripts/align-test-pilot-upn.ps1
@@ -0,0 +1,9 @@
+Import-Module ActiveDirectory
+$u = Get-ADUser 'test.caregiver' -Properties mail
+Set-ADUser $u -UserPrincipalName 'pilot.test@cascadestucson.com' -EmailAddress 'pilot.test@cascadestucson.com' -SamAccountName 'pilot.test'
+Rename-ADObject -Identity $u.DistinguishedName -NewName 'Pilot Test (Caregiver)'
+$v = Get-ADUser 'pilot.test' -Properties mail, MemberOf
+Write-Output "sAM: $($v.SamAccountName) UPN: $($v.UserPrincipalName) mail: $($v.mail)"
+Write-Output "DN: $($v.DistinguishedName)"
+Write-Output "Groups: $($v.MemberOf -join '; ')"
+try { Import-Module ADSync -ErrorAction Stop; Start-ADSyncSyncCycle -PolicyType Delta | Out-Null; Write-Output 'Delta sync started' } catch { Write-Output "Delta sync skipped: $_" }
diff --git a/clients/cascades-tucson/scripts/app-restrict-1.ps1 b/clients/cascades-tucson/scripts/app-restrict-1.ps1
new file mode 100644
index 00000000..ce1b8c98
--- /dev/null
+++ b/clients/cascades-tucson/scripts/app-restrict-1.ps1
@@ -0,0 +1,11 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Nurse Station Kiosk'
+$hkcu = 'HKCU\Software\Policies\Microsoft\Windows'
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRun' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSetFolders' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSMHelp' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRecentDocsHistory' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'ClearRecentDocsOnExit' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoControlPanel' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoNetHood' -Type DWord -Value 1 | Out-Null
+Write-Output "Part 1 done: Start menu + Explorer restrictions"
diff --git a/clients/cascades-tucson/scripts/app-restrict-2.ps1 b/clients/cascades-tucson/scripts/app-restrict-2.ps1
new file mode 100644
index 00000000..c5cc8999
--- /dev/null
+++ b/clients/cascades-tucson/scripts/app-restrict-2.ps1
@@ -0,0 +1,7 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Nurse Station Kiosk'
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\System' -ValueName 'DisableCMD' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableRegistryTools' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableTaskMgr' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\Installer' -ValueName 'DisableUserInstalls' -Type DWord -Value 1 | Out-Null
+Write-Output "Part 2 done: CMD/regedit/taskmgr/installer blocked"
diff --git a/clients/cascades-tucson/scripts/audit-test-accounts.ps1 b/clients/cascades-tucson/scripts/audit-test-accounts.ps1
new file mode 100644
index 00000000..bf1de0a8
--- /dev/null
+++ b/clients/cascades-tucson/scripts/audit-test-accounts.ps1
@@ -0,0 +1,13 @@
+Import-Module ActiveDirectory
+foreach ($sam in 'test.caregiver','pilot.test') {
+ $u = Get-ADUser -Filter "SamAccountName -eq '$sam'" -Properties mail, MemberOf, Enabled, whenCreated, Description
+ if ($u) {
+ Write-Output "=== $sam ==="
+ Write-Output "DN: $($u.DistinguishedName)"
+ Write-Output "UPN: $($u.UserPrincipalName) mail: $($u.mail) enabled: $($u.Enabled) created: $($u.whenCreated)"
+ Write-Output "Desc: $($u.Description)"
+ Write-Output "Groups: $($u.MemberOf -join '; ')"
+ } else { Write-Output "=== $sam : NOT FOUND ===" }
+}
+$dup = Get-ADUser -Filter "UserPrincipalName -eq 'pilot.test@cascadestucson.com'" | Measure-Object
+Write-Output "Users with UPN pilot.test@cascadestucson.com: $($dup.Count)"
diff --git a/clients/cascades-tucson/scripts/caregiver-app-restrictions.ps1 b/clients/cascades-tucson/scripts/caregiver-app-restrictions.ps1
new file mode 100644
index 00000000..e9e3b214
--- /dev/null
+++ b/clients/cascades-tucson/scripts/caregiver-app-restrictions.ps1
@@ -0,0 +1,49 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Nurse Station Kiosk'
+$hkcu = 'HKCU\Software\Policies\Microsoft\Windows'
+
+# --- Start Menu / Taskbar restrictions ---
+# Remove Run from Start Menu
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRun' -Type DWord -Value 1 | Out-Null
+# Remove Search from taskbar
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'DisableSearchBoxSuggestions' -Type DWord -Value 1 | Out-Null
+# Remove Settings from Start
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSetFolders' -Type DWord -Value 1 | Out-Null
+# Remove Help
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoSMHelp' -Type DWord -Value 1 | Out-Null
+# Don't keep history of recently opened documents
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoRecentDocsHistory' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'ClearRecentDocsOnExit' -Type DWord -Value 1 | Out-Null
+
+Write-Output "Start Menu restrictions set"
+
+# --- Block command prompt and PowerShell ---
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\System' -ValueName 'DisableCMD' -Type DWord -Value 1 | Out-Null
+# Block access to registry editor
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableRegistryTools' -Type DWord -Value 1 | Out-Null
+# Block Task Manager
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DisableTaskMgr' -Type DWord -Value 1 | Out-Null
+
+Write-Output "CMD/regedit/taskmgr blocked"
+
+# --- Restrict Control Panel ---
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoControlPanel' -Type DWord -Value 1 | Out-Null
+
+Write-Output "Control Panel blocked"
+
+# --- File Explorer restrictions ---
+# Hide drives in My Computer (don't block access, just hide)
+# Remove File Explorer from taskbar pinning isn't needed - just restrict what they see
+# Prevent access to drives from My Computer - but allow printing and Office file access
+# Remove Network from navigation pane
+Set-GPRegistryValue -Name $gpo -Key "$hkcu\Explorer" -ValueName 'NoNetHood' -Type DWord -Value 1 | Out-Null
+
+Write-Output "Explorer restrictions set"
+
+# --- Prevent installing apps ---
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Windows\Installer' -ValueName 'DisableUserInstalls' -Type DWord -Value 1 | Out-Null
+
+Write-Output "App install blocked"
+Write-Output ""
+Write-Output "Done. Caregivers can use: Edge, Office apps, Teams, printers."
+Write-Output "Blocked: CMD, PowerShell, regedit, Task Manager, Control Panel, Run, Settings, app installs."
diff --git a/clients/cascades-tucson/scripts/check-avallejo.ps1 b/clients/cascades-tucson/scripts/check-avallejo.ps1
new file mode 100644
index 00000000..4adea394
--- /dev/null
+++ b/clients/cascades-tucson/scripts/check-avallejo.ps1
@@ -0,0 +1,15 @@
+Import-Module ActiveDirectory
+$u = Get-ADUser 'a.vallejo' -Properties MemberOf, Enabled, PasswordLastSet, LockedOut, PasswordExpired
+Write-Output "Enabled: $($u.Enabled) LockedOut: $($u.LockedOut) PwExpired: $($u.PasswordExpired)"
+Write-Output "PwLastSet: $($u.PasswordLastSet)"
+Write-Output "UPN: $($u.UserPrincipalName)"
+Write-Output "Groups:"
+$u.MemberOf | ForEach-Object { Write-Output " $_" }
+# Check if ChangePasswordAtLogon is set (would block login)
+$raw = Get-ADUser 'a.vallejo' -Properties pwdLastSet
+if ($raw.pwdLastSet -eq 0) { Write-Output "WARNING: ChangePasswordAtLogon=TRUE (pwdLastSet=0)" }
+# Validate credential against DC
+Add-Type -AssemblyName System.DirectoryServices.AccountManagement
+$ctx = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Domain, "cascades.local")
+$valid = $ctx.ValidateCredentials("a.vallejo", "Sunrise4827")
+Write-Output "Password validates: $valid"
diff --git a/clients/cascades-tucson/scripts/check-cse-client.ps1 b/clients/cascades-tucson/scripts/check-cse-client.ps1
new file mode 100644
index 00000000..34a589a6
--- /dev/null
+++ b/clients/cascades-tucson/scripts/check-cse-client.ps1
@@ -0,0 +1,23 @@
+# Check what GP CSEs are registered on this machine
+Write-Output "=== Shortcuts CSE registered? ==="
+$shortcutCSE = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions\{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}" -ErrorAction SilentlyContinue
+if ($shortcutCSE) {
+ Write-Output "YES: $($shortcutCSE.'(default)') DLL: $($shortcutCSE.DllName)"
+} else { Write-Output "NOT REGISTERED" }
+
+Write-Output ""
+Write-Output "=== All GP Preference CSEs ==="
+Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions" | ForEach-Object {
+ $p = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
+ $name = $p.'(default)'
+ if ($name -match 'Preference|Shortcut|File|Folder') {
+ Write-Output " $($_.PSChildName): $name"
+ }
+}
+
+Write-Output ""
+Write-Output "=== Full GP event log (last 30, user policy) ==="
+Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 30 -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'user|User|loopback|Kiosk|Nurse|failed|error|Extension' -and $_.Level -le 3 } | ForEach-Object {
+ Write-Output "$($_.TimeCreated) [id=$($_.Id) lvl=$($_.Level)]"
+ Write-Output " $($_.Message.Substring(0,[Math]::Min(250,$_.Message.Length)))"
+}
diff --git a/clients/cascades-tucson/scripts/check-gpp-apply.ps1 b/clients/cascades-tucson/scripts/check-gpp-apply.ps1
new file mode 100644
index 00000000..3947b2c7
--- /dev/null
+++ b/clients/cascades-tucson/scripts/check-gpp-apply.ps1
@@ -0,0 +1,12 @@
+# Check if GPP shortcuts applied
+Write-Output "=== Public Desktop ==="
+Get-ChildItem "C:\Users\Public\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output "=== a.vallejo Desktop ==="
+Get-ChildItem "C:\Users\a.vallejo\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output ""
+Write-Output "=== GPResult for a.vallejo - applied GPOs ==="
+gpresult /scope user /r 2>&1 | Select-String "CSC|Caregiver|Kiosk|Nurse|Shortcut|DENIED|filtering"
+Write-Output ""
+Write-Output "=== CSE Extensions registered ==="
+$gptIni = Get-Content "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\GPT.INI" -Raw
+Write-Output $gptIni
diff --git a/clients/cascades-tucson/scripts/check-hybrid-join.ps1 b/clients/cascades-tucson/scripts/check-hybrid-join.ps1
new file mode 100644
index 00000000..16ce9489
--- /dev/null
+++ b/clients/cascades-tucson/scripts/check-hybrid-join.ps1
@@ -0,0 +1,6 @@
+gpupdate /force /wait:60 | Out-Null
+Write-Output '--- dsregcmd device state ---'
+$d = dsregcmd /status
+$d | Select-String 'AzureAdJoined|DomainJoined|DeviceId|TenantName|EnterpriseJoined' | ForEach-Object { $_.Line.Trim() }
+Write-Output '--- SSO state ---'
+$d | Select-String 'AzureAdPrt\s|OnPremTgt|CloudTgt' | ForEach-Object { $_.Line.Trim() }
diff --git a/clients/cascades-tucson/scripts/check-printers.ps1 b/clients/cascades-tucson/scripts/check-printers.ps1
new file mode 100644
index 00000000..ca00f220
--- /dev/null
+++ b/clients/cascades-tucson/scripts/check-printers.ps1
@@ -0,0 +1,9 @@
+Write-Output "=== Printers on NURSESTATION-PC ==="
+Get-Printer | Select-Object Name, PortName, Shared, Type | Format-Table -AutoSize
+Write-Output ""
+Write-Output "=== Print shares on CS-SERVER ==="
+Get-ChildItem "\\CS-SERVER\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output ""
+Write-Output "=== Shared printers on CS-SERVER ==="
+$printers = Get-WmiObject Win32_Printer -ComputerName CS-SERVER -ErrorAction SilentlyContinue | Where-Object { $_.Shared -eq $true }
+$printers | ForEach-Object { Write-Output " $($_.Name) -> $($_.ShareName) [Port: $($_.PortName)] Location: $($_.Location)" }
diff --git a/clients/cascades-tucson/scripts/cleanup-and-gpupdate.ps1 b/clients/cascades-tucson/scripts/cleanup-and-gpupdate.ps1
new file mode 100644
index 00000000..8531049c
--- /dev/null
+++ b/clients/cascades-tucson/scripts/cleanup-and-gpupdate.ps1
@@ -0,0 +1,15 @@
+# Remove manually placed shortcuts (GPO replaces them)
+foreach ($f in 'ALIS.url','Helpany.url','PharmCare.url','LinkRx.url') {
+ Remove-Item "C:\Users\Public\Desktop\$f" -Force -ErrorAction SilentlyContinue
+ Get-ChildItem "C:\Users" -Directory | Where-Object { $_.Name -notin 'Public','Default','Default User','All Users' } | ForEach-Object {
+ Remove-Item (Join-Path $_.FullName "Desktop\$f") -Force -ErrorAction SilentlyContinue
+ }
+}
+Write-Output "Cleaned all manual shortcuts"
+gpupdate /force /wait:60 2>&1 | Out-Null
+Write-Output "gpupdate done"
+# Check result
+Write-Output "=== Public Desktop ==="
+Get-ChildItem "C:\Users\Public\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output "=== pilot.test Desktop ==="
+Get-ChildItem "C:\Users\pilot.test\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
diff --git a/clients/cascades-tucson/scripts/clear-edge-profiles-gpupdate.ps1 b/clients/cascades-tucson/scripts/clear-edge-profiles-gpupdate.ps1
new file mode 100644
index 00000000..600e8296
--- /dev/null
+++ b/clients/cascades-tucson/scripts/clear-edge-profiles-gpupdate.ps1
@@ -0,0 +1,13 @@
+# Remove stale Edge profile data for the current pilot.test user
+$edgePath = "C:\Users\pilot.test\AppData\Local\Microsoft\Edge\User Data"
+if (Test-Path $edgePath) {
+ # Kill Edge first
+ Get-Process msedge -ErrorAction SilentlyContinue | Stop-Process -Force
+ Start-Sleep -Seconds 2
+ Remove-Item $edgePath -Recurse -Force -ErrorAction SilentlyContinue
+ Write-Output "Cleared Edge profile data for pilot.test"
+} else {
+ Write-Output "No Edge profile data for pilot.test"
+}
+gpupdate /force /wait:60 2>&1 | Out-Null
+Write-Output "gpupdate done"
diff --git a/clients/cascades-tucson/scripts/clear-prt-cache.ps1 b/clients/cascades-tucson/scripts/clear-prt-cache.ps1
new file mode 100644
index 00000000..f5de909b
--- /dev/null
+++ b/clients/cascades-tucson/scripts/clear-prt-cache.ps1
@@ -0,0 +1,20 @@
+Write-Output "=== Clearing stale token broker cache ==="
+$aadBroker = Get-ChildItem "C:\Users\*\AppData\Local\Packages\Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy" -Directory -ErrorAction SilentlyContinue
+foreach ($p in $aadBroker) {
+ $ac = Join-Path $p.FullName "AC\TokenBroker"
+ if (Test-Path $ac) {
+ Remove-Item "$ac\*" -Recurse -Force -ErrorAction SilentlyContinue
+ Write-Output "Cleared: $ac"
+ }
+}
+$msAccount = Get-ChildItem "C:\Users\*\AppData\Local\Packages\Microsoft.Windows.CloudExperienceHost_cw5n1h2txyewy" -Directory -ErrorAction SilentlyContinue
+foreach ($p in $msAccount) {
+ $ac = Join-Path $p.FullName "AC\TokenBroker"
+ if (Test-Path $ac) {
+ Remove-Item "$ac\*" -Recurse -Force -ErrorAction SilentlyContinue
+ Write-Output "Cleared: $ac"
+ }
+}
+Write-Output ""
+Write-Output "Cache cleared. Reboot the machine, then log in as cascades\pilot.test."
+Write-Output "The fresh login should acquire a PRT and Edge will SSO into ALIS automatically."
diff --git a/clients/cascades-tucson/scripts/create-test-caregiver.ps1 b/clients/cascades-tucson/scripts/create-test-caregiver.ps1
new file mode 100644
index 00000000..aec0dd1f
--- /dev/null
+++ b/clients/cascades-tucson/scripts/create-test-caregiver.ps1
@@ -0,0 +1,20 @@
+Import-Module ActiveDirectory
+$sam = 'test.caregiver'
+$existing = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue
+if ($existing) { Write-Output "EXISTS: $($existing.DistinguishedName)"; exit 0 }
+# Place it in the same OU as an existing caregiver
+$member = Get-ADGroupMember 'SG-Caregivers' | Where-Object objectClass -eq 'user' | Select-Object -First 1
+$refUser = Get-ADUser $member.SamAccountName
+$ou = ($refUser.DistinguishedName -split ',',2)[1]
+Write-Output "Target OU: $ou"
+$pw = ConvertTo-SecureString 'KioskTest-7492!' -AsPlainText -Force
+New-ADUser -Name 'Test Caregiver' -GivenName 'Test' -Surname 'Caregiver' `
+ -SamAccountName $sam -UserPrincipalName 'test.caregiver@cascadestucson.com' `
+ -Path $ou -AccountPassword $pw -Enabled $true -ChangePasswordAtLogon $false `
+ -Description 'ACG kiosk pilot test account - remove after WS3 go-live'
+Add-ADGroupMember -Identity 'SG-Caregivers' -Members $sam
+Start-Sleep -Seconds 3
+$u = Get-ADUser $sam -Properties MemberOf
+Write-Output "CREATED: $($u.DistinguishedName)"
+Write-Output "Groups: $($u.MemberOf -join '; ')"
+try { Import-Module ADSync -ErrorAction Stop; Start-ADSyncSyncCycle -PolicyType Delta | Out-Null; Write-Output 'Delta sync started' } catch { Write-Output "Delta sync skipped: $_" }
diff --git a/clients/cascades-tucson/scripts/debug-gpp-2.ps1 b/clients/cascades-tucson/scripts/debug-gpp-2.ps1
new file mode 100644
index 00000000..abd03bcc
--- /dev/null
+++ b/clients/cascades-tucson/scripts/debug-gpp-2.ps1
@@ -0,0 +1,10 @@
+Write-Output "=== Recent GP events mentioning Preferences/Shortcut/CSE ==="
+Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 100 -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'Shortcut|Preference|Extension|loopback|Nurse|Kiosk' } | Select-Object -First 20 | ForEach-Object { Write-Output "$($_.TimeCreated) [id=$($_.Id) lvl=$($_.Level)] $($_.Message.Substring(0,[Math]::Min(300,$_.Message.Length)))"; Write-Output "---" }
+Write-Output ""
+Write-Output "=== Verify Shortcuts.xml in kiosk GPO SYSVOL ==="
+$kioskGuid = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Id
+$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts\Shortcuts.xml"
+if (Test-Path $xmlPath) {
+ Write-Output "EXISTS: $xmlPath"
+ Get-Content $xmlPath -Raw | Write-Output
+} else { Write-Output "MISSING: $xmlPath" }
diff --git a/clients/cascades-tucson/scripts/debug-gpp-shortcuts.ps1 b/clients/cascades-tucson/scripts/debug-gpp-shortcuts.ps1
new file mode 100644
index 00000000..fe768746
--- /dev/null
+++ b/clients/cascades-tucson/scripts/debug-gpp-shortcuts.ps1
@@ -0,0 +1,14 @@
+# Run as the logged-in user to see what GPOs apply to THEM
+Write-Output "=== Who am I ==="
+whoami
+Write-Output ""
+Write-Output "=== User GPO results ==="
+gpresult /scope user /r 2>&1
+Write-Output ""
+Write-Output "=== User desktop contents ==="
+$desk = [Environment]::GetFolderPath("Desktop")
+Write-Output "Desktop path: $desk"
+Get-ChildItem "$desk\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output ""
+Write-Output "=== Event log: GP Preferences ==="
+Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 20 -ErrorAction SilentlyContinue | Where-Object { $_.Message -match 'Shortcut|Preference|CSE|Extension' } | ForEach-Object { Write-Output "$($_.TimeCreated) [$($_.Id)] $($_.Message.Substring(0,[Math]::Min(200,$_.Message.Length)))" }
diff --git a/clients/cascades-tucson/scripts/dedup-shortcuts-final.ps1 b/clients/cascades-tucson/scripts/dedup-shortcuts-final.ps1
new file mode 100644
index 00000000..e5395bf1
--- /dev/null
+++ b/clients/cascades-tucson/scripts/dedup-shortcuts-final.ps1
@@ -0,0 +1,33 @@
+# Clean shortcuts from Default profile (stops future new users getting dupes)
+Remove-Item "C:\Users\Default\Desktop\ALIS.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "C:\Users\Default\Desktop\LinkRx.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "C:\Users\Default\Desktop\Helpany.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "C:\Users\Default\Desktop\PharmCare.url" -Force -ErrorAction SilentlyContinue
+Write-Output "Cleaned Default profile desktop"
+
+# Clean pilot.test per-user desktop
+Remove-Item "C:\Users\pilot.test\Desktop\ALIS.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "C:\Users\pilot.test\Desktop\LinkRx.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "C:\Users\pilot.test\Desktop\Helpany.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "C:\Users\pilot.test\Desktop\PharmCare.url" -Force -ErrorAction SilentlyContinue
+Write-Output "Cleaned pilot.test desktop"
+
+# Clean any other user desktops that might have copies
+Get-ChildItem "C:\Users" -Directory | Where-Object { $_.Name -notin 'Public','Default','Default User','All Users' } | ForEach-Object {
+ $desk = Join-Path $_.FullName "Desktop"
+ $removed = 0
+ foreach ($f in 'ALIS.url','Helpany.url','PharmCare.url','LinkRx.url') {
+ $p = Join-Path $desk $f
+ if (Test-Path $p) { Remove-Item $p -Force; $removed++ }
+ }
+ if ($removed -gt 0) { Write-Output "Cleaned $removed shortcuts from $($_.Name)" }
+}
+
+# Verify
+Write-Output ""
+Write-Output "=== Public Desktop (canonical, all users see these) ==="
+Get-ChildItem "C:\Users\Public\Desktop\*" | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output "=== Default Desktop (empty now) ==="
+Get-ChildItem "C:\Users\Default\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output "=== pilot.test Desktop ==="
+Get-ChildItem "C:\Users\pilot.test\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
diff --git a/clients/cascades-tucson/scripts/find-all-shortcuts.ps1 b/clients/cascades-tucson/scripts/find-all-shortcuts.ps1
new file mode 100644
index 00000000..0049fe1d
--- /dev/null
+++ b/clients/cascades-tucson/scripts/find-all-shortcuts.ps1
@@ -0,0 +1,24 @@
+# Check every possible shortcut location
+Write-Output "=== C:\Users\Public\Desktop ==="
+Get-ChildItem "C:\Users\Public\Desktop\*" | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" }
+Write-Output ""
+Write-Output "=== C:\Users\pilot.test\Desktop ==="
+Get-ChildItem "C:\Users\pilot.test\Desktop\*" | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" }
+Write-Output ""
+Write-Output "=== C:\Users\Default\Desktop ==="
+Get-ChildItem "C:\Users\Default\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" }
+Write-Output ""
+Write-Output "=== All Users profile Desktop ==="
+$allUsers = [Environment]::GetFolderPath("CommonDesktopDirectory")
+Write-Output " Path: $allUsers"
+Get-ChildItem "$allUsers\*" | ForEach-Object { Write-Output " $($_.Name) [$($_.FullName)]" }
+Write-Output ""
+Write-Output "=== pilot.test shell:desktop (resolved) ==="
+$shell = "C:\Users\pilot.test\AppData\Roaming\Microsoft\Windows\Desktop"
+if (Test-Path $shell) { Get-ChildItem "$shell\*" | ForEach-Object { Write-Output " $($_.Name)" } } else { Write-Output " (not present)" }
+Write-Output ""
+Write-Output "=== OneDrive Desktop redirect? ==="
+$od = Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -ErrorAction SilentlyContinue
+if ($od) { Write-Output " Desktop = $($od.Desktop)" }
+$odSys = Get-ItemProperty "Registry::HKEY_USERS\*\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name Desktop -ErrorAction SilentlyContinue
+$odSys | ForEach-Object { Write-Output " HKU Desktop = $($_.Desktop) [$($_.PSPath)]" }
diff --git a/clients/cascades-tucson/scripts/find-shortcut-source-1.ps1 b/clients/cascades-tucson/scripts/find-shortcut-source-1.ps1
new file mode 100644
index 00000000..d3eb000e
--- /dev/null
+++ b/clients/cascades-tucson/scripts/find-shortcut-source-1.ps1
@@ -0,0 +1,16 @@
+# Check SYSVOL for GPP Shortcuts/Files XML and any scripts referencing our URLs
+$sysvol = "\\cascades.local\SYSVOL\cascades.local\Policies"
+Write-Output "=== GPP XML files ==="
+Get-ChildItem $sysvol -Recurse -Include "Shortcuts.xml","Files.xml" -ErrorAction SilentlyContinue | ForEach-Object {
+ Write-Output " $($_.FullName)"
+ Get-Content $_.FullName -Raw
+}
+Write-Output ""
+Write-Output "=== Scripts referencing shortcuts ==="
+Get-ChildItem $sysvol -Recurse -Include *.ps1,*.bat,*.cmd,*.vbs -ErrorAction SilentlyContinue | ForEach-Object {
+ $c = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue
+ if ($c -match 'alis|helpany|pharmcare|linkrx|\.url') {
+ Write-Output "MATCH: $($_.FullName)"
+ Write-Output $c
+ }
+}
diff --git a/clients/cascades-tucson/scripts/find-shortcut-source.ps1 b/clients/cascades-tucson/scripts/find-shortcut-source.ps1
new file mode 100644
index 00000000..9e559137
--- /dev/null
+++ b/clients/cascades-tucson/scripts/find-shortcut-source.ps1
@@ -0,0 +1,52 @@
+# 1. Check GPO shortcut preferences (GP Preferences > Shortcuts)
+Write-Output "=== GPO Results: Shortcut Preferences ==="
+$gpResults = gpresult /scope user /xml 2>$null
+if ($gpResults) {
+ $xml = [xml]$gpResults
+ # Look for shortcut extensions
+ $ns = @{gp='http://www.microsoft.com/GroupPolicy/Settings/Shortcuts'}
+ $shortcuts = $xml.SelectNodes('//gp:Shortcut', $ns)
+ if ($shortcuts.Count -gt 0) {
+ foreach ($s in $shortcuts) { Write-Output " GPP Shortcut: $($s.OuterXml.Substring(0, [Math]::Min(300, $s.OuterXml.Length)))" }
+ } else { Write-Output " No GPP shortcuts found in XML" }
+ # Also check for file preferences
+ $ns2 = @{gp='http://www.microsoft.com/GroupPolicy/Settings/Files'}
+ $files = $xml.SelectNodes('//gp:FileSetting', $ns2)
+ if ($files.Count -gt 0) {
+ foreach ($f in $files) { Write-Output " GPP File: $($f.OuterXml.Substring(0, [Math]::Min(300, $f.OuterXml.Length)))" }
+ }
+}
+
+# 2. Check logon scripts in GPO
+Write-Output ""
+Write-Output "=== Logon Scripts (GPO) ==="
+$scripts = Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\*\*" -ErrorAction SilentlyContinue
+if ($scripts) { $scripts | ForEach-Object { Write-Output " Script: $($_.Script) Params: $($_.Parameters)" } } else { Write-Output " None" }
+
+# 3. Check SYSVOL for any scripts referencing our URLs
+Write-Output ""
+Write-Output "=== SYSVOL scripts mentioning ALIS/Helpany/PharmCare/LinkRx ==="
+$sysvol = "\\cascades.local\SYSVOL\cascades.local"
+Get-ChildItem "$sysvol\Policies" -Recurse -Include *.ps1,*.bat,*.cmd,*.vbs -ErrorAction SilentlyContinue | ForEach-Object {
+ $content = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue
+ if ($content -match 'alis|helpany|pharmcare|linkrx|\.url') {
+ Write-Output " MATCH: $($_.FullName)"
+ }
+}
+
+# 4. Check GP Preferences XML in SYSVOL for shortcut/file items
+Get-ChildItem "$sysvol\Policies" -Recurse -Include "Shortcuts.xml","Files.xml","Drives.xml" -ErrorAction SilentlyContinue | ForEach-Object {
+ Write-Output " GPP XML: $($_.FullName)"
+ $c = Get-Content $_.FullName -Raw
+ if ($c -match 'alis|helpany|pharmcare|linkrx|\.url') { Write-Output " -> contains shortcut references" }
+}
+
+# 5. Check scheduled tasks
+Write-Output ""
+Write-Output "=== Scheduled tasks mentioning shortcuts ==="
+Get-ScheduledTask | Where-Object { $_.Actions.Execute -match 'shortcut|url|alis|helpany|pharmcare' -or $_.TaskName -match 'shortcut|desktop' } | ForEach-Object { Write-Output " Task: $($_.TaskName) -> $($_.Actions.Execute)" }
+
+# 6. Check ActiveSetup
+Write-Output ""
+Write-Output "=== Active Setup (per-user on first login) ==="
+Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\*" -ErrorAction SilentlyContinue | Where-Object { $_.StubPath -match 'url|shortcut|alis|helpany|pharmcare|linkrx|desktop' } | ForEach-Object { Write-Output " $($_.PSChildName): $($_.StubPath)" }
diff --git a/clients/cascades-tucson/scripts/fix-cmd-popup.ps1 b/clients/cascades-tucson/scripts/fix-cmd-popup.ps1
new file mode 100644
index 00000000..d5cbd063
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-cmd-popup.ps1
@@ -0,0 +1,19 @@
+Import-Module GroupPolicy
+$guid = '32d76052-4d92-446c-95fb-614653f84742'
+# Remove the logon script (causing CMD popup) - GPP shortcuts work now
+$scriptsDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Scripts"
+if (Test-Path $scriptsDir) { Remove-Item $scriptsDir -Recurse -Force; Write-Output "Removed Scripts dir" }
+# Remove the script registry entries from kiosk GPO
+$base = 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0'
+Remove-GPRegistryValue -Guid $guid -Key "$base\0" -ValueName 'Script' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base\0" -ValueName 'Parameters' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base\0" -ValueName 'IsPowershell' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'GPO-ID' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'SOM-ID' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'FileSysPath' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'DisplayName' -ErrorAction SilentlyContinue
+Remove-GPRegistryValue -Guid $guid -Key "$base" -ValueName 'GPOName' -ErrorAction SilentlyContinue
+Write-Output "Removed logon script GPO entries"
+# Block Microsoft Store for caregivers
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Policies\Microsoft\WindowsStore' -ValueName 'RemoveWindowsStore' -Type DWord -Value 1 | Out-Null
+Write-Output "Microsoft Store blocked"
diff --git a/clients/cascades-tucson/scripts/fix-cse-correct.ps1 b/clients/cascades-tucson/scripts/fix-cse-correct.ps1
new file mode 100644
index 00000000..f9d643fa
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-cse-correct.ps1
@@ -0,0 +1,17 @@
+Import-Module ActiveDirectory
+$kioskGuid = '32d76052-4d92-446c-95fb-614653f84742'
+$dn = "CN={$kioskGuid},CN=Policies,CN=System,DC=cascades,DC=local"
+# {C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7} = Group Policy Shortcuts CSE (verified in client registry)
+# {0F6B957D-509E-11D1-A7CC-0000F87571E3} = GPMC tool snap-in
+$cse = '[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]'
+Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse}
+Write-Output "CSE set: $((Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames)"
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+$ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse"
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+}
+Set-Content $gptPath $ini -Force
+Get-Content $gptPath
diff --git a/clients/cascades-tucson/scripts/fix-cse-final.ps1 b/clients/cascades-tucson/scripts/fix-cse-final.ps1
new file mode 100644
index 00000000..dfe63287
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-cse-final.ps1
@@ -0,0 +1,32 @@
+Import-Module ActiveDirectory
+# Check what the original working GPO had
+$cwDN = "CN={3B5CD9A6-A278-4676-A9FD-9396D21A8261},CN=Policies,CN=System,DC=cascades,DC=local"
+$cwExt = (Get-ADObject $cwDN -Properties gPCUserExtensionNames).gPCUserExtensionNames
+Write-Output "Original Caregiver Workstation CSE: $cwExt"
+
+# Fix the kiosk GPO with the CORRECT Shortcuts CSE
+$kioskGuid = '32d76052-4d92-446c-95fb-614653f84742'
+$kioskDN = "CN={$kioskGuid},CN=Policies,CN=System,DC=cascades,DC=local"
+# {C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7} = Group Policy Shortcuts CSE
+# Use same tool GUID as original, or the generic preference tool GUID
+$cse = '[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{CF7639F3-ABA2-41DB-97F2-81E2C5DBFC5D}]'
+if ($cwExt) { $cse = $cwExt }
+Set-ADObject $kioskDN -Replace @{gPCUserExtensionNames=$cse}
+$verify = (Get-ADObject $kioskDN -Properties gPCUserExtensionNames).gPCUserExtensionNames
+Write-Output "Kiosk GPO CSE set to: $verify"
+
+# Update GPT.INI
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+if ($ini -match 'gPCUserExtensionNames=') { $ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse" } else { $ini = $ini.TrimEnd() + "`r`ngPCUserExtensionNames=$cse`r`n" }
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+}
+Set-Content $gptPath $ini -Force
+Write-Output "GPT.INI:"
+Get-Content $gptPath
+
+# Verify Shortcuts.xml still exists
+$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts\Shortcuts.xml"
+if (Test-Path $xmlPath) { Write-Output "Shortcuts.xml: EXISTS" } else { Write-Output "Shortcuts.xml: MISSING - need to restore" }
diff --git a/clients/cascades-tucson/scripts/fix-cse-guids.ps1 b/clients/cascades-tucson/scripts/fix-cse-guids.ps1
new file mode 100644
index 00000000..729460df
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-cse-guids.ps1
@@ -0,0 +1,28 @@
+Import-Module ActiveDirectory
+# Kiosk GPO GUID (known)
+$guid = '32d76052-4d92-446c-95fb-614653f84742'
+# Correct CSE GUIDs for GP Preferences Shortcuts
+# CSE: {BC75B1ED-5833-4858-9BB8-CBF0B166DF9D} = GP Preferences engine
+# Tool: {0F6B957E-509E-11D1-A7CC-0000F87571E3} = Shortcuts snap-in
+$cse = '[{BC75B1ED-5833-4858-9BB8-CBF0B166DF9D}{0F6B957E-509E-11D1-A7CC-0000F87571E3}]'
+$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local"
+Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse}
+$verify = (Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames
+Write-Output "AD gPCUserExtensionNames: $verify"
+
+# Fix GPT.INI too
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+$ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse"
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+}
+Set-Content $gptPath $ini -Force
+Write-Output "GPT.INI:"
+Get-Content $gptPath
+
+# Verify the Shortcuts.xml exists
+$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Preferences\Shortcuts\Shortcuts.xml"
+Write-Output ""
+if (Test-Path $xmlPath) { Write-Output "Shortcuts.xml: EXISTS"; Get-Content $xmlPath -Raw } else { Write-Output "Shortcuts.xml: MISSING" }
diff --git a/clients/cascades-tucson/scripts/fix-desktop-shortcuts.ps1 b/clients/cascades-tucson/scripts/fix-desktop-shortcuts.ps1
new file mode 100644
index 00000000..1c3495e0
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-desktop-shortcuts.ps1
@@ -0,0 +1,15 @@
+# Remove per-user duplicates (Public Desktop is the canonical source)
+$userDesktop = "C:\Users\pilot.test\Desktop"
+Remove-Item "$userDesktop\ALIS.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "$userDesktop\Helpany.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "$userDesktop\LinkRx.url" -Force -ErrorAction SilentlyContinue
+Remove-Item "$userDesktop\PharmCare.url" -Force -ErrorAction SilentlyContinue
+Write-Output "Cleared per-user shortcut duplicates"
+
+# Verify Public Desktop has the right 3
+Write-Output ""
+Write-Output "=== Public Desktop (all users) ==="
+Get-ChildItem "C:\Users\Public\Desktop\*" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output ""
+Write-Output "=== pilot.test Desktop (should be empty of our URLs now) ==="
+Get-ChildItem "$userDesktop\*.url","$userDesktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
diff --git a/clients/cascades-tucson/scripts/fix-edge-auto-profile.ps1 b/clients/cascades-tucson/scripts/fix-edge-auto-profile.ps1
new file mode 100644
index 00000000..ca40a4bb
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-edge-auto-profile.ps1
@@ -0,0 +1,12 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Nurse Station Kiosk'
+# Auto-create and sign into Edge profile from the OS account (PRT, no prompt)
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'EdgeDefaultProfileEnabled' -Type DWord -Value 1 | Out-Null
+# Don't show the sign-in prompt on new tab page
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'SignInCtaOnNtpEnabled' -Type DWord -Value 0 | Out-Null
+# Disable profile picker at launch
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'BrowserGuestModeEnabled' -Type DWord -Value 0 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'BrowserAddProfileEnabled' -Type DWord -Value 0 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'UserDataSnapshotRetentionLimit' -Type DWord -Value 0 | Out-Null
+Write-Output 'Updated GPO:'
+Get-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' | ForEach-Object { Write-Output " $($_.ValueName)=$($_.Value)" }
diff --git a/clients/cascades-tucson/scripts/fix-edge-sso.ps1 b/clients/cascades-tucson/scripts/fix-edge-sso.ps1
new file mode 100644
index 00000000..73228a85
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-edge-sso.ps1
@@ -0,0 +1,9 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Nurse Station Kiosk'
+# BrowserSignin=2 forces Edge to sign in with the OS account (PRT -> SSO)
+# Keep SyncDisabled=1 + ClearBrowsingDataOnExit=1 so no data persists
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'BrowserSignin' -Type DWord -Value 2 | Out-Null
+# Also enable SSO for work sites via the OS primary account
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'RoamingProfileSupportEnabled' -Type DWord -Value 0 | Out-Null
+Write-Output 'Updated: BrowserSignin=2 (force OS account), RoamingProfileSupportEnabled=0'
+Get-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' | ForEach-Object { Write-Output "$($_.ValueName)=$($_.Value)" }
diff --git a/clients/cascades-tucson/scripts/fix-gpo-cse-guids.ps1 b/clients/cascades-tucson/scripts/fix-gpo-cse-guids.ps1
new file mode 100644
index 00000000..91f5c74a
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-gpo-cse-guids.ps1
@@ -0,0 +1,22 @@
+Import-Module GroupPolicy
+Import-Module ActiveDirectory
+$guid = '3B5CD9A6-A278-4676-A9FD-9396D21A8261'
+# GP Preferences CSE GUIDs for Shortcuts
+$cse = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]'
+# Update AD object
+$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local"
+Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse}
+Write-Output "AD gPCUserExtensionNames set: $cse"
+# Update GPT.INI
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $newIni = "[General]`r`nVersion=$newVer`r`ndisplayName=New Group Policy Object`r`ngPCUserExtensionNames=$cse`r`n"
+ Set-Content $gptPath $newIni -Force
+ Write-Output "GPT.INI updated, version $ver -> $newVer"
+}
+# Verify
+$obj = Get-ADObject $dn -Properties gPCUserExtensionNames
+Write-Output "Verify AD: $($obj.gPCUserExtensionNames)"
+Write-Output (Get-Content $gptPath -Raw)
diff --git a/clients/cascades-tucson/scripts/fix-pilot-test-accounts.ps1 b/clients/cascades-tucson/scripts/fix-pilot-test-accounts.ps1
new file mode 100644
index 00000000..c65931f9
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-pilot-test-accounts.ps1
@@ -0,0 +1,14 @@
+Import-Module ActiveDirectory
+# 1. Remove the duplicate created today
+Remove-ADUser -Identity 'test.caregiver' -Confirm:$false
+Write-Output 'Removed duplicate test.caregiver'
+# 2. Ensure pilot.test is in SG-Caregivers (kiosk GPO filter) - keep SG-Caregivers-Test
+Add-ADGroupMember -Identity 'SG-Caregivers' -Members 'pilot.test'
+# 3. Reset password to the documented pilot value so it is deterministic
+$pw = ConvertTo-SecureString 'CareTest2026!' -AsPlainText -Force
+Set-ADAccountPassword -Identity 'pilot.test' -NewPassword $pw -Reset
+Set-ADUser 'pilot.test' -ChangePasswordAtLogon $false -Enabled $true
+$v = Get-ADUser 'pilot.test' -Properties MemberOf, Enabled
+Write-Output "pilot.test enabled=$($v.Enabled)"
+Write-Output "Groups: $($v.MemberOf -join '; ')"
+try { Import-Module ADSync -ErrorAction Stop; Start-ADSyncSyncCycle -PolicyType Delta | Out-Null; Write-Output 'Delta sync started' } catch { Write-Output "Delta sync skipped: $_" }
diff --git a/clients/cascades-tucson/scripts/fix-shortcut-target.ps1 b/clients/cascades-tucson/scripts/fix-shortcut-target.ps1
new file mode 100644
index 00000000..b618edef
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-shortcut-target.ps1
@@ -0,0 +1,16 @@
+# Fix GPP shortcuts to use %DesktopDir% (per-user, deployed at logon by GPO)
+$kioskGuid = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Id
+$xmlPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts\Shortcuts.xml"
+$xml = Get-Content $xmlPath -Raw
+$xml = $xml -replace '%CommonDesktopDir%', '%DesktopDir%'
+Set-Content $xmlPath $xml -Encoding UTF8 -Force
+Write-Output "Changed shortcuts to %DesktopDir%"
+# Bump version
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+ Set-Content $gptPath $ini -Force
+ Write-Output "Version: $ver -> $newVer"
+}
diff --git a/clients/cascades-tucson/scripts/fix-shortcuts-check-office.ps1 b/clients/cascades-tucson/scripts/fix-shortcuts-check-office.ps1
new file mode 100644
index 00000000..336c8331
--- /dev/null
+++ b/clients/cascades-tucson/scripts/fix-shortcuts-check-office.ps1
@@ -0,0 +1,22 @@
+# 1. Show all shortcuts on public + pilot.test desktop
+Write-Output "=== Public Desktop ==="
+Get-ChildItem "C:\Users\Public\Desktop\*.url","C:\Users\Public\Desktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+Write-Output "=== pilot.test Desktop ==="
+Get-ChildItem "C:\Users\pilot.test\Desktop\*.url","C:\Users\pilot.test\Desktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+
+# 2. Check if M365 Apps / Office is installed
+Write-Output ""
+Write-Output "=== Installed Office ==="
+$office = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*","HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match 'Microsoft 365|Microsoft Office|Teams' } | Select-Object DisplayName, DisplayVersion
+if ($office) { $office | ForEach-Object { Write-Output " $($_.DisplayName) v$($_.DisplayVersion)" } } else { Write-Output " None found" }
+
+# 3. Check for Teams specifically
+Write-Output ""
+Write-Output "=== Teams ==="
+$teamsNew = Get-AppxPackage -AllUsers -Name '*MSTeams*' -ErrorAction SilentlyContinue
+$teamsClassic = Get-Process Teams -ErrorAction SilentlyContinue
+if ($teamsNew) { Write-Output " New Teams (MSIX): $($teamsNew.Version)" } else { Write-Output " New Teams: not installed" }
+$teamsExe = Test-Path "C:\Program Files\WindowsApps\MSTeams_*"
+$teamsExe2 = Test-Path "C:\Program Files (x86)\Teams Installer\Teams.exe"
+Write-Output " WindowsApps MSTeams: $teamsExe"
+Write-Output " Classic installer: $teamsExe2"
diff --git a/clients/cascades-tucson/scripts/hide-last-user-gpupdate.ps1 b/clients/cascades-tucson/scripts/hide-last-user-gpupdate.ps1
new file mode 100644
index 00000000..521a2182
--- /dev/null
+++ b/clients/cascades-tucson/scripts/hide-last-user-gpupdate.ps1
@@ -0,0 +1,6 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Caregiver Device Lockdown'
+# Hide last logged-on username on the lock/login screen
+Set-GPRegistryValue -Name $gpo -Key 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'DontDisplayLastUserName' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System' -ValueName 'dontdisplaylockeduser' -Type DWord -Value 3 | Out-Null
+Write-Output "Added DontDisplayLastUserName=1, dontdisplaylockeduser=3"
diff --git a/clients/cascades-tucson/scripts/identify-gpo-and-fix.ps1 b/clients/cascades-tucson/scripts/identify-gpo-and-fix.ps1
new file mode 100644
index 00000000..3f565fe6
--- /dev/null
+++ b/clients/cascades-tucson/scripts/identify-gpo-and-fix.ps1
@@ -0,0 +1,50 @@
+Import-Module GroupPolicy
+# Identify which GPO this is
+$gpo = Get-GPO -Guid '3B5CD9A6-A278-4676-A9FD-9396D21A8261'
+Write-Output "GPO: $($gpo.DisplayName) (ID: $($gpo.Id))"
+Write-Output "Status: $($gpo.GpoStatus)"
+
+# Remove the GPP Shortcuts.xml (stops it recreating shortcuts on login)
+$path = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\User\Preferences\Shortcuts\Shortcuts.xml"
+if (Test-Path $path) {
+ Remove-Item $path -Force
+ Write-Output "REMOVED: $path"
+ # Clean up empty dir
+ $dir = Split-Path $path
+ if ((Get-ChildItem $dir -ErrorAction SilentlyContinue).Count -eq 0) {
+ Remove-Item $dir -Force
+ Write-Output "Cleaned empty Shortcuts dir"
+ }
+} else {
+ Write-Output "Already removed"
+}
+
+# Bump GPO version so clients pick up the change
+# Read current version, increment user version
+$gpoPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\GPT.INI"
+$ini = Get-Content $gpoPath -Raw
+Write-Output ""
+Write-Output "GPT.INI before:"
+Write-Output $ini
+# Parse version: low 16 bits = computer, high 16 bits = user
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]
+ $userVer = ($ver -shr 16) + 1
+ $compVer = $ver -band 0xFFFF
+ $newVer = ($userVer -shl 16) -bor $compVer
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+ Set-Content $gpoPath $ini -Force
+ Write-Output "GPT.INI after (version $ver -> $newVer):"
+ Write-Output $ini
+}
+
+# Also clean the per-user desktop shortcuts one more time
+Get-ChildItem "C:\Users" -Directory | Where-Object { $_.Name -notin 'Public','Default','Default User','All Users' } | ForEach-Object {
+ $desk = Join-Path $_.FullName "Desktop"
+ foreach ($f in 'ALIS.url','Helpany.url','PharmCare.url','LinkRx.url') {
+ $p = Join-Path $desk $f
+ if (Test-Path $p) { Remove-Item $p -Force }
+ }
+}
+Write-Output ""
+Write-Output "Cleaned per-user desktop shortcuts"
diff --git a/clients/cascades-tucson/scripts/kiosk-gpo-firstrun.ps1 b/clients/cascades-tucson/scripts/kiosk-gpo-firstrun.ps1
new file mode 100644
index 00000000..f0396be1
--- /dev/null
+++ b/clients/cascades-tucson/scripts/kiosk-gpo-firstrun.ps1
@@ -0,0 +1,6 @@
+Import-Module GroupPolicy
+$gpo = 'CSC - Nurse Station Kiosk'
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'HideFirstRunExperience' -Type DWord -Value 1 | Out-Null
+Set-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' -ValueName 'AutoImportAtFirstRun' -Type DWord -Value 4 | Out-Null
+Write-Output 'Added: HideFirstRunExperience=1, AutoImportAtFirstRun=4 (disabled)'
+Get-GPRegistryValue -Name $gpo -Key 'HKCU\Software\Policies\Microsoft\Edge' | ForEach-Object { Write-Output "$($_.ValueName)=$($_.Value)" }
diff --git a/clients/cascades-tucson/scripts/list-packaged-apps.ps1 b/clients/cascades-tucson/scripts/list-packaged-apps.ps1
new file mode 100644
index 00000000..0f70235d
--- /dev/null
+++ b/clients/cascades-tucson/scripts/list-packaged-apps.ps1
@@ -0,0 +1,4 @@
+# List all packaged apps installed for all users on this machine
+Get-AppxPackage -AllUsers | Select-Object Name, PackageFamilyName | Sort-Object Name | ForEach-Object {
+ Write-Output "$($_.Name) | $($_.PackageFamilyName)"
+}
diff --git a/clients/cascades-tucson/scripts/move-shortcuts-to-kiosk-gpo.ps1 b/clients/cascades-tucson/scripts/move-shortcuts-to-kiosk-gpo.ps1
new file mode 100644
index 00000000..654e348f
--- /dev/null
+++ b/clients/cascades-tucson/scripts/move-shortcuts-to-kiosk-gpo.ps1
@@ -0,0 +1,36 @@
+Import-Module GroupPolicy
+# Move GPP shortcuts from CSC - Caregiver Workstation to CSC - Nurse Station Kiosk
+$kioskGuid = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Id
+$cwGuid = '3B5CD9A6-A278-4676-A9FD-9396D21A8261'
+# Read current shortcuts XML from Caregiver Workstation GPO
+$srcDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$cwGuid}\User\Preferences\Shortcuts"
+$srcXml = "$srcDir\Shortcuts.xml"
+$content = Get-Content $srcXml -Raw -ErrorAction SilentlyContinue
+Write-Output "Source XML exists: $($null -ne $content)"
+# Write to Nurse Station Kiosk GPO
+$dstDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\User\Preferences\Shortcuts"
+New-Item -ItemType Directory -Path $dstDir -Force | Out-Null
+Set-Content "$dstDir\Shortcuts.xml" $content -Encoding UTF8 -Force
+Write-Output "Copied shortcuts to kiosk GPO"
+# Remove from Caregiver Workstation GPO
+Remove-Item $srcXml -Force
+Write-Output "Removed from Caregiver Workstation GPO"
+# Set CSE GUIDs on kiosk GPO AD object
+$cse = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]'
+$dn = "CN={$kioskGuid},CN=Policies,CN=System,DC=cascades,DC=local"
+$existing = (Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames
+if ($existing) { $merged = $existing + $cse } else { $merged = $cse }
+Set-ADObject $dn -Replace @{gPCUserExtensionNames=$merged}
+Write-Output "CSE GUIDs set on kiosk GPO"
+# Bump kiosk GPO version
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$kioskGuid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+ # Add CSE to GPT.INI too
+ if ($ini -notmatch 'gPCUserExtensionNames') { $ini = $ini.TrimEnd() + "`r`ngPCUserExtensionNames=$cse`r`n" }
+ Set-Content $gptPath $ini -Force
+ Write-Output "Kiosk GPO version bumped: $ver -> $newVer"
+}
+Write-Output (Get-Content $gptPath -Raw)
diff --git a/clients/cascades-tucson/scripts/remove-unwanted-apps.ps1 b/clients/cascades-tucson/scripts/remove-unwanted-apps.ps1
new file mode 100644
index 00000000..deebd43a
--- /dev/null
+++ b/clients/cascades-tucson/scripts/remove-unwanted-apps.ps1
@@ -0,0 +1,49 @@
+# Remove user-facing apps caregivers don't need
+# Store is blocked so they can't reinstall
+$remove = @(
+ '4DF9E0F8.Netflix',
+ '7EE7776C.LinkedInforWindows',
+ 'AcerIncorporated.AcerCareCenterS',
+ 'AcerIncorporated.AcerCollectionS',
+ 'AcerIncorporated.AcerRegistration',
+ 'C27EB4BA.DropboxOEM',
+ 'Evernote.Evernote',
+ 'Microsoft.549981C3F5F10',
+ 'Microsoft.Copilot',
+ 'Microsoft.Edge.GameAssist',
+ 'Microsoft.GamingApp',
+ 'Microsoft.Getstarted',
+ 'Microsoft.Microsoft3DViewer',
+ 'Microsoft.Messaging',
+ 'Microsoft.MixedReality.Portal',
+ 'Microsoft.OneConnect',
+ 'Microsoft.People',
+ 'Microsoft.Print3D',
+ 'Microsoft.SkypeApp',
+ 'Microsoft.WindowsCamera',
+ 'Microsoft.WindowsMaps',
+ 'Microsoft.Xbox.TCUI',
+ 'Microsoft.XboxApp',
+ 'Microsoft.XboxGameOverlay',
+ 'Microsoft.XboxGamingOverlay',
+ 'Microsoft.XboxIdentityProvider',
+ 'Microsoft.XboxSpeechToTextOverlay',
+ 'Microsoft.YourPhone',
+ 'Microsoft.ZuneVideo',
+ 'SpotifyAB.SpotifyMusic',
+ 'Microsoft.WindowsTerminal'
+)
+foreach ($app in $remove) {
+ $pkg = Get-AppxPackage -AllUsers -Name $app -ErrorAction SilentlyContinue
+ if ($pkg) {
+ $pkg | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
+ Write-Output "Removed: $app"
+ }
+ # Also remove provisioned (prevents reinstall on new profiles)
+ $prov = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq $app }
+ if ($prov) {
+ $prov | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue
+ Write-Output "Deprovisioned: $app"
+ }
+}
+Write-Output "Done. Kept: Edge, Office, Teams, Outlook, Calculator, Notepad, printing."
diff --git a/clients/cascades-tucson/scripts/restore-gpp-shortcuts-public.ps1 b/clients/cascades-tucson/scripts/restore-gpp-shortcuts-public.ps1
new file mode 100644
index 00000000..914cef01
--- /dev/null
+++ b/clients/cascades-tucson/scripts/restore-gpp-shortcuts-public.ps1
@@ -0,0 +1,15 @@
+$dir = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\User\Preferences\Shortcuts"
+New-Item -ItemType Directory -Path $dir -Force | Out-Null
+$a = ''
+$b = ''
+$c = ''
+$xml = '' + $a + $b + $c + ''
+Set-Content "$dir\Shortcuts.xml" $xml -Encoding UTF8 -Force
+Write-Output "Restored GPP shortcuts -> CommonDesktopDir"
+$gpoPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{3B5CD9A6-A278-4676-A9FD-9396D21A8261}\GPT.INI"
+$ini = Get-Content $gpoPath -Raw
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ Set-Content $gpoPath ($ini -replace "Version=\d+","Version=$newVer") -Force
+ Write-Output "GPO version: $ver -> $newVer"
+}
diff --git a/clients/cascades-tucson/scripts/setup-logon-1.ps1 b/clients/cascades-tucson/scripts/setup-logon-1.ps1
new file mode 100644
index 00000000..00341795
--- /dev/null
+++ b/clients/cascades-tucson/scripts/setup-logon-1.ps1
@@ -0,0 +1,13 @@
+$guid = '32d76052-4d92-446c-95fb-614653f84742'
+# Write logon script
+$bat = "@echo off`r`nif not exist `"%USERPROFILE%\Desktop\ALIS.url`" (`r`n echo [InternetShortcut]> `"%USERPROFILE%\Desktop\ALIS.url`"`r`n echo URL=https://cascadestucson.alisonline.com/>> `"%USERPROFILE%\Desktop\ALIS.url`"`r`n)`r`nif not exist `"%USERPROFILE%\Desktop\PharmCare.url`" (`r`n echo [InternetShortcut]> `"%USERPROFILE%\Desktop\PharmCare.url`"`r`n echo URL=https://pharmcare.linkrxnow.com/>> `"%USERPROFILE%\Desktop\PharmCare.url`"`r`n)`r`nif not exist `"%USERPROFILE%\Desktop\Helpany.url`" (`r`n echo [InternetShortcut]> `"%USERPROFILE%\Desktop\Helpany.url`"`r`n echo URL=https://app.helpany.com/start>> `"%USERPROFILE%\Desktop\Helpany.url`"`r`n)"
+$gpoScripts = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Scripts\Logon"
+New-Item -ItemType Directory -Path $gpoScripts -Force | Out-Null
+Set-Content "$gpoScripts\deploy-caregiver-shortcuts.bat" $bat -Force
+$ini = "[Logon]`r`n0CmdLine=deploy-caregiver-shortcuts.bat`r`n0Parameters=`r`n"
+Set-Content "$gpoScripts\scripts.ini" $ini -Force
+# Remove broken GPP
+$xmlDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Preferences"
+if (Test-Path $xmlDir) { Remove-Item $xmlDir -Recurse -Force }
+Write-Output "Logon script + scripts.ini written, GPP removed"
+Get-Content "$gpoScripts\deploy-caregiver-shortcuts.bat"
diff --git a/clients/cascades-tucson/scripts/setup-logon-2.ps1 b/clients/cascades-tucson/scripts/setup-logon-2.ps1
new file mode 100644
index 00000000..0e990ff7
--- /dev/null
+++ b/clients/cascades-tucson/scripts/setup-logon-2.ps1
@@ -0,0 +1,16 @@
+Import-Module ActiveDirectory
+$guid = '32d76052-4d92-446c-95fb-614653f84742'
+$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local"
+$cse = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'
+Set-ADObject $dn -Replace @{gPCUserExtensionNames=$cse}
+Write-Output "CSE: $((Get-ADObject $dn -Properties gPCUserExtensionNames).gPCUserExtensionNames)"
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI"
+$ini = Get-Content $gptPath -Raw
+if ($ini -match 'gPCUserExtensionNames=') { $ini = $ini -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$cse" } else { $ini = $ini.TrimEnd() + "`r`ngPCUserExtensionNames=$cse`r`n" }
+if ($ini -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $ini = $ini -replace "Version=\d+", "Version=$newVer"
+}
+Set-Content $gptPath $ini -Force
+Write-Output "GPT.INI:"
+Get-Content $gptPath
diff --git a/clients/cascades-tucson/scripts/setup-logon-script.ps1 b/clients/cascades-tucson/scripts/setup-logon-script.ps1
new file mode 100644
index 00000000..8610652e
--- /dev/null
+++ b/clients/cascades-tucson/scripts/setup-logon-script.ps1
@@ -0,0 +1,70 @@
+Import-Module GroupPolicy
+$guid = '32d76052-4d92-446c-95fb-614653f84742'
+
+# 1. Write the logon script to SYSVOL (netlogon share)
+$scriptContent = @'
+@echo off
+REM Deploy caregiver desktop shortcuts
+if not exist "%USERPROFILE%\Desktop\ALIS.url" (
+ echo [InternetShortcut] > "%USERPROFILE%\Desktop\ALIS.url"
+ echo URL=https://cascadestucson.alisonline.com/ >> "%USERPROFILE%\Desktop\ALIS.url"
+)
+if not exist "%USERPROFILE%\Desktop\PharmCare.url" (
+ echo [InternetShortcut] > "%USERPROFILE%\Desktop\PharmCare.url"
+ echo URL=https://pharmcare.linkrxnow.com/ >> "%USERPROFILE%\Desktop\PharmCare.url"
+)
+if not exist "%USERPROFILE%\Desktop\Helpany.url" (
+ echo [InternetShortcut] > "%USERPROFILE%\Desktop\Helpany.url"
+ echo URL=https://app.helpany.com/start >> "%USERPROFILE%\Desktop\Helpany.url"
+)
+'@
+$netlogon = "\\cascades.local\SYSVOL\cascades.local\scripts"
+Set-Content "$netlogon\deploy-caregiver-shortcuts.bat" $scriptContent -Force
+Write-Output "Logon script written to: $netlogon\deploy-caregiver-shortcuts.bat"
+
+# 2. Remove the broken GPP Shortcuts.xml
+$xmlDir = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Preferences\Shortcuts"
+if (Test-Path $xmlDir) {
+ Remove-Item $xmlDir -Recurse -Force
+ Write-Output "Removed GPP Shortcuts dir"
+}
+
+# 3. Set the logon script on the kiosk GPO
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0' -ValueName 'Script' -Type String -Value 'deploy-caregiver-shortcuts.bat' | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0' -ValueName 'Parameters' -Type String -Value '' | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0' -ValueName 'IsPowershell' -Type DWord -Value 0 | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'GPO-ID' -Type String -Value "cn={$guid},cn=policies,cn=system,DC=cascades,DC=local" | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'SOM-ID' -Type String -Value 'OU=Caregiver Devices,OU=Staff PCs,OU=Workstations,DC=cascades,DC=local' | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'FileSysPath' -Type String -Value "\\cascades.local\SysVol\cascades.local\Policies\{$guid}\User\Scripts\Logon" | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'DisplayName' -Type String -Value 'CSC - Nurse Station Kiosk' | Out-Null
+Set-GPRegistryValue -Guid $guid -Key 'HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0' -ValueName 'GPOName' -Type String -Value $guid | Out-Null
+Write-Output "Logon script GPO registry entries set"
+
+# 4. Also copy the bat into the GPO's own scripts folder
+$gpoScripts = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\User\Scripts\Logon"
+New-Item -ItemType Directory -Path $gpoScripts -Force | Out-Null
+Copy-Item "$netlogon\deploy-caregiver-shortcuts.bat" "$gpoScripts\deploy-caregiver-shortcuts.bat" -Force
+Write-Output "Script copied to GPO scripts folder"
+
+# 5. Write scripts.ini
+$ini = "[Logon]`r`n0CmdLine=deploy-caregiver-shortcuts.bat`r`n0Parameters=`r`n"
+Set-Content "$gpoScripts\scripts.ini" $ini -Force
+Write-Output "scripts.ini written"
+
+# 6. Update CSE GUIDs for Scripts
+$scriptsCSE = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'
+$dn = "CN={$guid},CN=Policies,CN=System,DC=cascades,DC=local"
+Set-ADObject $dn -Replace @{gPCUserExtensionNames=$scriptsCSE}
+Write-Output "CSE GUIDs set for Scripts"
+
+# 7. Bump version
+$gptPath = "\\cascades.local\SYSVOL\cascades.local\Policies\{$guid}\GPT.INI"
+$gptIni = Get-Content $gptPath -Raw
+$gptIni = $gptIni -replace 'gPCUserExtensionNames=.*', "gPCUserExtensionNames=$scriptsCSE"
+if ($gptIni -match 'Version=(\d+)') {
+ $ver = [int]$matches[1]; $newVer = ((($ver -shr 16)+1) -shl 16) -bor ($ver -band 0xFFFF)
+ $gptIni = $gptIni -replace "Version=\d+", "Version=$newVer"
+}
+Set-Content $gptPath $gptIni -Force
+Write-Output "GPT.INI updated"
+Get-Content $gptPath
diff --git a/clients/cascades-tucson/scripts/verify-kiosk-2.ps1 b/clients/cascades-tucson/scripts/verify-kiosk-2.ps1
new file mode 100644
index 00000000..43a60834
--- /dev/null
+++ b/clients/cascades-tucson/scripts/verify-kiosk-2.ps1
@@ -0,0 +1,19 @@
+Import-Module GroupPolicy
+Write-Output "=== Kiosk GPO permissions ==="
+Get-GPPermission -Name 'CSC - Nurse Station Kiosk' -All | ForEach-Object { Write-Output " $($_.Trustee.Name) ($($_.Trustee.SidType)): $($_.Permission) denied=$($_.Denied)" }
+Write-Output ""
+Write-Output "=== Kiosk GPO links ==="
+$gpo = Get-GPO -Name 'CSC - Nurse Station Kiosk'
+Write-Output " ID: $($gpo.Id) Status: $($gpo.GpoStatus)"
+# Check links via AD
+$links = Get-ADOrganizationalUnit -Filter * -Properties gpLink | Where-Object { $_.gpLink -match $gpo.Id }
+$links | ForEach-Object { Write-Output " Linked: $($_.DistinguishedName)" }
+Write-Output ""
+Write-Output "=== Caregiver Workstation GPO permissions ==="
+Get-GPPermission -Name 'CSC - Caregiver Workstation' -All | ForEach-Object { Write-Output " $($_.Trustee.Name) ($($_.Trustee.SidType)): $($_.Permission) denied=$($_.Denied)" }
+Write-Output ""
+Write-Output "=== Caregiver Workstation GPO links ==="
+$gpo2 = Get-GPO -Name 'CSC - Caregiver Workstation'
+Write-Output " ID: $($gpo2.Id) Status: $($gpo2.GpoStatus)"
+$links2 = Get-ADOrganizationalUnit -Filter * -Properties gpLink | Where-Object { $_.gpLink -match $gpo2.Id }
+$links2 | ForEach-Object { Write-Output " Linked: $($_.DistinguishedName)" }
diff --git a/clients/cascades-tucson/scripts/verify-kiosk-config.ps1 b/clients/cascades-tucson/scripts/verify-kiosk-config.ps1
new file mode 100644
index 00000000..65068610
--- /dev/null
+++ b/clients/cascades-tucson/scripts/verify-kiosk-config.ps1
@@ -0,0 +1,40 @@
+Write-Output "=== 1. OU placement ==="
+$comp = ([adsisearcher]"(&(objectClass=computer)(cn=NURSESTATION-PC))").FindOne()
+Write-Output "DN: $($comp.Properties.distinguishedname)"
+
+Write-Output ""
+Write-Output "=== 2. GPOs linked to this machine ==="
+gpresult /scope computer /r 2>&1 | Select-String "Applied Group Policy|CSC|Caregiver|Kiosk|Nurse|Lockdown"
+
+Write-Output ""
+Write-Output "=== 3. Loopback processing (UserPolicyMode) ==="
+$lp = Get-ItemProperty "HKLM:\Software\Policies\Microsoft\Windows\System" -Name UserPolicyMode -ErrorAction SilentlyContinue
+if ($lp) { Write-Output "UserPolicyMode=$($lp.UserPolicyMode) (1=Merge)" } else { Write-Output "NOT SET" }
+
+Write-Output ""
+Write-Output "=== 4. DontDisplayLastUserName ==="
+$dl = Get-ItemProperty "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name DontDisplayLastUserName -ErrorAction SilentlyContinue
+Write-Output "DontDisplayLastUserName=$($dl.DontDisplayLastUserName)"
+
+Write-Output ""
+Write-Output "=== 5. Kiosk GPO security filter (who gets locked down) ==="
+Import-Module GroupPolicy
+$acl = (Get-GPO -Name 'CSC - Nurse Station Kiosk').Path
+$perms = Get-GPPermission -Name 'CSC - Nurse Station Kiosk' -All
+$perms | ForEach-Object { Write-Output " $($_.Trustee.Name) : $($_.Permission)" }
+
+Write-Output ""
+Write-Output "=== 6. Scheduled task: profile cleanup ==="
+Get-ScheduledTask -TaskName '*Caregiver*' -ErrorAction SilentlyContinue | ForEach-Object {
+ Write-Output "Task: $($_.TaskName) State: $($_.State)"
+ Write-Output "Trigger: $($_.Triggers | ForEach-Object { $_.CimClass.CimClassName })"
+}
+
+Write-Output ""
+Write-Output "=== 7. Desktop shortcuts ==="
+Write-Output "Public:"
+Get-ChildItem "C:\Users\Public\Desktop\*.url","C:\Users\Public\Desktop\*.lnk" -ErrorAction SilentlyContinue | ForEach-Object { Write-Output " $($_.Name)" }
+
+Write-Output ""
+Write-Output "=== 8. Hybrid join + PRT capable ==="
+dsregcmd /status | Select-String "AzureAdJoined|DomainJoined|TenantId" | ForEach-Object { $_.Line.Trim() }
diff --git a/clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-nurse-station-kiosk-build.md b/clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-nurse-station-kiosk-build.md
new file mode 100644
index 00000000..25256388
--- /dev/null
+++ b/clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-nurse-station-kiosk-build.md
@@ -0,0 +1,100 @@
+# Cascades of Tucson — Nurse Station Kiosk GPO Build (NURSESTATION-PC)
+
+## User
+- **User:** Howard Enos (howard)
+- **Machine:** Howard-Home
+- **Role:** tech
+
+## Session Summary
+
+Continued from the earlier 7/17 session (roadmap refresh + Juan Andrade offboard). This session built and iteratively debugged the nurse-station kiosk configuration for NURSESTATION-PC, delivering on WS3 step 3b: shared caregiver desktops with phone-parity lockdown.
+
+The kiosk GPO (`CSC - Nurse Station Kiosk`, GUID `32d76052-4d92-446c-95fb-614653f84742`) was built with Edge policies for caregivers: `BrowserSignin=2` (force OS account sign-in for SSO), `EdgeDefaultProfileEnabled=1` (auto-profile from PRT, no picker), `ClearBrowsingDataOnExit=1`, `PasswordManagerEnabled=0`, `AutofillAddressEnabled=0`, `AutofillCreditCardEnabled=0`, `SyncDisabled=1`, `HideFirstRunExperience=1`, `AutoImportAtFirstRun=4`, `BrowserGuestModeEnabled=0`, `BrowserAddProfileEnabled=0`, `SignInCtaOnNtpEnabled=0`, `RoamingProfileSupportEnabled=0`, `UserDataSnapshotRetentionLimit=0`. The GPO is linked to `OU=Caregiver Devices,OU=Staff PCs,OU=Workstations` with `GpoApply` filtered to `SG-Caregivers` only; non-caregivers log in with no lockdown via the loopback merge (`UserPolicyMode=1`) on the `CSC - Caregiver Device Lockdown` GPO.
+
+GPP Shortcuts (ALIS, PharmCare, Helpany) were deployed via the kiosk GPO after multiple rounds of debugging. The root cause of non-delivery was wrong CSE GUIDs: the correct CSE for GP Preferences Shortcuts is `{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}` (verified from client registry), not `{BC75B1ED-...}` (Printers) or `{42B5FAAE-...}` (Scripts). Shortcuts target `%DesktopDir%` (per-user desktop), deployed at logon via loopback. The original `CSC - Caregiver Workstation` GPO shortcuts (in the user OU, filtered to `SG-Caregivers-Test`) were moved to the kiosk GPO and removed from the original to prevent duplication.
+
+Additional configurations: `DontDisplayLastUserName=1` + `dontdisplaylockeduser=3` on the lockdown GPO (hides previous usernames on the login screen); both nurse printers (`\\CS-SERVER\Nurses - Brother MFC-L8900CDW` and `\\CS-SERVER\Health Services - Konica Minolta C368`) added as machine-level connections via `rundll32 printui.dll /ga`; UI restrictions (NoRun, NoControlPanel, NoSetFolders, DisableCMD, DisableRegistryTools, DisableTaskMgr, DisableUserInstalls, NoNetHood, NoRecentDocsHistory, ClearRecentDocsOnExit) applied via the kiosk GPO; Microsoft Store blocked via `RemoveWindowsStore=1`.
+
+Session ended with app restriction still incomplete. The UI restrictions (no CMD/PowerShell/Settings/Control Panel/Run/Task Manager/Store) are in place, but user-facing Store apps (Camera, Netflix, Xbox, Spotify, etc.) are still launchable from the Start menu. Howard rejected removing the apps from the machine because non-caregiver users need access. AppLocker with group-specific Deny rules for SG-Caregivers is the correct next step, but was not completed this session.
+
+## Key Decisions
+
+- `BrowserSignin=2` + `EdgeDefaultProfileEnabled=1` chosen to force Edge SSO via PRT, eliminating the need for caregivers to enter credentials in the browser after Windows login. `BrowserSignin=0` (original setting) was blocking PRT passthrough entirely.
+- GPP shortcuts placed in the kiosk GPO (machine OU, SG-Caregivers filter) rather than the Caregiver Workstation GPO (user OU, SG-Caregivers-Test filter) so all SG-Caregivers members get shortcuts on any caregiver device, not just test-group members.
+- Shortcuts use `%DesktopDir%` (per-user desktop) not `%CommonDesktopDir%` (Public Desktop) because GPP user preferences targeting CommonDesktopDir require a user logon to process but the chicken-and-egg problem means the first login has no shortcuts.
+- Printers added as machine-level connections (`/ga` flag) rather than per-user connections so every user gets them automatically without GPO printer deployment complexity.
+- `DontDisplayLastUserName` placed in the `CSC - Caregiver Device Lockdown` GPO (not the kiosk GPO) because it's a computer-level policy (HKLM) and must apply regardless of which user is at the login screen.
+- App removal rejected by Howard (non-caregivers need the apps) — AppLocker with SG-Caregivers Deny rules is the planned approach for the next session.
+- `pilot.test` AD account (from June) used as the test identity instead of creating a new `test.caregiver` account. A duplicate `test.caregiver` was created by mistake and deleted same session. `pilot.test` was added to `SG-Caregivers` (kiosk GPO filter) in addition to existing `SG-Caregivers-Test` membership. Password reset to `CareTest2026!`.
+
+## Problems Encountered
+
+- **PRT not issuing (`AzureAdPrt : NO`):** NURSESTATION-PC was hybrid-joined but PRT acquisition failed. Root cause: stale PRT attempt cached for `sysadmin@cascadestucson.com` with `AADSTS50126` (invalid credentials). Fixed by clearing WAM token broker cache (`Microsoft.AAD.BrokerPlugin_cw5n1h2txyewy\AC\TokenBroker`) for all users + reboot.
+- **Edge showing sync/profile picker:** `BrowserSignin=0` blocked Edge from using the PRT entirely. Changed to `BrowserSignin=2` (force OS account) + `EdgeDefaultProfileEnabled=1` (auto-profile, no picker). Also needed to clear stale Edge profile data (`C:\Users\pilot.test\AppData\Local\Microsoft\Edge\User Data`).
+- **Duplicate desktop shortcuts:** Three sources stacking: (1) Public Desktop (manually placed), (2) per-user desktop from Default profile (copied at first login), (3) GPP shortcuts from `CSC - Caregiver Workstation` GPO (`action="R"` to `%DesktopDir%`). Fixed by cleaning Default profile desktop, removing manual Public Desktop shortcuts, and consolidating all shortcuts into the kiosk GPO GPP only.
+- **GPP shortcuts not deploying (multiple rounds):** Wrong CSE GUIDs on the GPO AD object and GPT.INI. Tried `{42B5FAAE-...}` (Scripts) and `{BC75B1ED-...}` (Printers) before discovering the correct Shortcuts CSE is `{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}` via `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions` on the client machine. Also discovered the original `CSC - Caregiver Workstation` GPO was filtered to `SG-Caregivers-Test` (not `SG-Caregivers`), so `a.vallejo` (in SG-Caregivers only) never received those shortcuts.
+- **CMD window popup at logon:** Caused by a `.bat` logon script configured in the kiosk GPO (created as a shortcut deployment workaround before GPP was fixed). Removed the scripts.ini, Scripts directory, and GPO registry entries for the logon script.
+- **Duplicate AD test account:** `test.caregiver` created, then discovered `pilot.test` already existed from June with ALIS staff email mapping and Business Premium license. Deleted `test.caregiver`, added `pilot.test` to `SG-Caregivers`, reset password.
+
+## Configuration Changes
+
+**On CS-SERVER (via RMM):**
+- GPO `CSC - Nurse Station Kiosk` (`32d76052-4d92-446c-95fb-614653f84742`): 15 Edge HKCU policies, GPP Shortcuts.xml (ALIS/PharmCare/Helpany to `%DesktopDir%`), CSE GUIDs `[{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]`, UI restrictions (NoRun, NoControlPanel, DisableCMD, DisableRegistryTools, DisableTaskMgr, DisableUserInstalls, NoNetHood, NoRecentDocsHistory, ClearRecentDocsOnExit, NoSetFolders, NoSMHelp), RemoveWindowsStore=1
+- GPO `CSC - Caregiver Device Lockdown`: added `DontDisplayLastUserName=1` + `dontdisplaylockeduser=3` (HKLM)
+- GPO `CSC - Caregiver Workstation` (`3B5CD9A6-A278-4676-A9FD-9396D21A8261`): GPP Shortcuts.xml removed (moved to kiosk GPO)
+- AD: `pilot.test` added to `SG-Caregivers`, password reset; duplicate `test.caregiver` account created then deleted
+
+**On NURSESTATION-PC (via RMM):**
+- WAM token broker cache cleared for all user profiles
+- Edge profile data cleared for pilot.test
+- Per-user + Default profile desktop shortcuts cleaned (Public Desktop cleared, GPO handles deployment)
+- Machine-level printer connections: `\\CS-SERVER\Nurses - Brother MFC-L8900CDW` + `\\CS-SERVER\Health Services - Konica Minolta C368` via `rundll32 printui.dll /ga`
+- Multiple gpupdate /force cycles
+
+**Local scripts created:**
+- `clients/cascades-tucson/scripts/`: create-test-caregiver.ps1, align-test-pilot-upn.ps1, audit-test-accounts.ps1, fix-pilot-test-accounts.ps1, kiosk-gpo-firstrun.ps1, fix-edge-sso.ps1, fix-edge-auto-profile.ps1, clear-prt-cache.ps1, check-hybrid-join.ps1, check-printers.ps1, add-nurse-printer.ps1, find-all-shortcuts.ps1, dedup-shortcuts-final.ps1, find-shortcut-source.ps1, identify-gpo-and-fix.ps1, restore-gpp-shortcuts-public.ps1, fix-shortcut-target.ps1, move-shortcuts-to-kiosk-gpo.ps1, cleanup-and-gpupdate.ps1, check-gpp-apply.ps1, debug-gpp-shortcuts.ps1, debug-gpp-2.ps1, check-cse-client.ps1, fix-cse-final.ps1, fix-cse-correct.ps1, fix-gpo-cse-guids.ps1, verify-kiosk-config.ps1, verify-kiosk-2.ps1, caregiver-app-restrictions.ps1, app-restrict-1.ps1, app-restrict-2.ps1, fix-cmd-popup.ps1, list-packaged-apps.ps1, remove-unwanted-apps.ps1, hide-last-user-gpupdate.ps1, clear-edge-profiles-gpupdate.ps1, check-avallejo.ps1
+
+## Credentials & Secrets
+
+- `pilot.test` AD account: `cascades\pilot.test` / `CareTest2026!` (password reset this session; vault: `clients/cascades-tucson/pilot-test-ad.sops.yaml`)
+- `a.vallejo` caregiver account: `cascades\a.vallejo` / `Sunrise4827` (from vault: `clients/cascades-tucson/caregiver-temp-passwords-2026-07-01.sops.yaml`)
+- Duplicate `test.caregiver` account created with password `KioskTest-7492!`, then DELETED same session. Vault entry `test-caregiver-ad.sops.yaml` also deleted.
+
+## Infrastructure & Servers
+
+- NURSESTATION-PC: RMM agent `f5a89784-834f-47b1-82e2-7e3e9dd337ff`, hybrid-joined (AzureAdJoined=YES, DomainJoined=YES), DeviceId `d3bf931f-f128-4261-8398-b46c34a4b342`, TenantId `207fa277-e9d8-4eb7-ada1-1064d2221498`, DN `CN=NURSESTATION-PC,OU=Caregiver Devices,OU=Staff PCs,OU=Workstations,DC=cascades,DC=local`
+- CS-SERVER: RMM agent `c39f1de7-d5b6-45ae-b132-e06977ab1713`
+- Kiosk GPO: `CSC - Nurse Station Kiosk`, GUID `32d76052-4d92-446c-95fb-614653f84742`, linked to `OU=Caregiver Devices`, GpoApply=SG-Caregivers
+- Lockdown GPO: `CSC - Caregiver Device Lockdown`, UserPolicyMode=1 (loopback merge)
+- Caregiver Workstation GPO: `CSC - Caregiver Workstation`, GUID `3B5CD9A6-A278-4676-A9FD-9396D21A8261`, linked to `OU=Caregivers,OU=Departments`, GpoApply=SG-Caregivers-Test
+- Reception GPO `CSC - Reception Workstation Policy` also applies to NURSESTATION-PC (pre-existing, flagged)
+- Printers: `\\CS-SERVER\Nurses - Brother MFC-L8900CDW` (TCP_192.168.2.75), `\\CS-SERVER\Health Services - Konica Minolta C368` (TCP_192.168.1.138)
+- GP Preferences Shortcuts CSE GUID: `{C418DD9D-0D14-4efb-8FBF-CFE535C8FAC7}` (verified from client `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions`)
+
+## Commands & Outputs
+
+- `dsregcmd /status` on NURSESTATION-PC: `AzureAdJoined: YES`, `DomainJoined: YES`, `AzureAdPrt: NO` (initially), `DeviceAuthStatus: SUCCESS`; PRT failure was `AADSTS50126` for stale `sysadmin@` credential
+- `rundll32 printui.dll,PrintUIEntry /ga /n \\CS-SERVER\Nurses - Brother MFC-L8900CDW` — added machine-level printer
+- GPP Shortcuts CSE discovery: `Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions"` revealed `{C418DD9D-...}` = "Group Policy Shortcuts"
+- `gpresult /scope computer /r` confirmed applied GPOs: CSC - Caregiver Device Lockdown, CSC - Always Wait For Network, CSC - Reception Workstation Policy, CSC - Point and Print
+
+## Pending / Incomplete Tasks
+
+1. **App restriction for caregivers (INCOMPLETE):** UI restrictions block CMD/PowerShell/Settings/Control Panel/Run/Task Manager/Store, but Store apps (Camera, Netflix, Xbox, Spotify) are still launchable. Howard rejected removing apps from the machine (non-caregivers need them). Next step: AppLocker with Packaged App Deny rules scoped to SG-Caregivers — `Allow Domain Users: *` (baseline) + `Deny SG-Caregivers: [Netflix, Camera, Xbox, etc.]`. Needs AppIdentity service enabled + AppLocker XML policy in the Lockdown GPO (Computer Configuration).
+2. **ASSISTNURSE-PC:** Second nurse station not yet configured. Needs: move from CN=Computers to OU=Caregiver Devices + deploy machine-level printers + gpupdate. GPO settings will apply automatically.
+3. **PRT verification:** After token cache clear + reboot, need to confirm `AzureAdPrt: YES` on next caregiver login and verify ALIS SSO is fully silent (no password prompt in browser).
+4. **`CSC - Reception Workstation Policy`:** Still applies to NURSESTATION-PC (pre-existing, flagged to Howard, unresolved).
+5. **Cleanup after pilot:** Delete `pilot.test` AD account + delta sync when WS3 caregiver go-live is complete.
+6. **Carried from earlier session:** break-glass accounts + FIDO2, caregiver allow-list flip, relicense 29 suspended-Standard, image backup repair, domain-join tail, network tail, WS8 SharePoint/Teams, WS9 Medtelligent scoping, ticket-verify pass.
+
+## Reference Information
+
+- Session log (earlier today): `clients/cascades-tucson/session-logs/2026-07/2026-07-17-howard-roadmap-finish-line-refresh.md`
+- Kiosk GPO SYSVOL: `\\cascades.local\SYSVOL\cascades.local\Policies\{32d76052-4d92-446c-95fb-614653f84742}`
+- Shortcuts XML: `...\User\Preferences\Shortcuts\Shortcuts.xml` (3 entries: ALIS, PharmCare, Helpany)
+- Vault pilot.test: `clients/cascades-tucson/pilot-test-ad.sops.yaml`
+- Vault (superseded cloud-only): `clients/cascades-tucson/pilot-test-user.sops.yaml`
+- Phone kiosk config (Intune): `CSC - Android Shared Phones Restrictions` id `070a76c2-a8c3-4f7f-9ba7-1f4ac5084184`
+- Caregiver controls doc: `clients/cascades-tucson/docs/security/hipaa-caregiver-controls.md`
+- ALIS SSO app: `d5108493-cba8-4f08-90b6-1bb0bc09eb2a`
+- Syncro customer 20149445; prepaid block 21.5 hrs (live 7/15)
diff --git a/errorlog.md b/errorlog.md
index 19a3505c..6ceceff1 100644
--- a/errorlog.md
+++ b/errorlog.md
@@ -19,6 +19,8 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure ·
+2026-07-17 | Howard-Home | coord | coord API call failed (HTTP 422) [ctx: http=422 cmd=todo done resp={"error": "Request validation failed", "details": {"validation_errors": [{"field]
+
2026-07-17 | GURU-5070 | remediation-tool/exchange | [correction] Repeatedly used investigator-exo tier for Exchange REST -> 401 on every adminapi call (Security Investigator app lacks Exchange.ManageAsApp). Correct tier is exchange-op (only app with both Exchange.ManageAsApp + Exchange Admin role). Mike's 6th time hitting this. Fixed docs (SKILL.md, gotchas.md) + user-breach-check.sh (was using investigator-exo -> mailbox delegate/forwarding checks silently returned empty on every breach check) + memory reference_exchange_online_exchangeop_tier. [ctx: tenant=azcomputerguru.com ref=reference_exchange_online_exchangeop_tier]
2026-07-17 | GURU-5070 | vault/secret-echo | [friction] grep filter to redact vault output missed the JSON field 'private_key' (filter had 'key:' with colon + 'apikey', not bare 'private_key') -> SA private key printed to transcript. Fix: when displaying vault entries, allowlist known plaintext fields (name/status/username/notes/url) instead of denylisting secret patterns; or pipe through 'sops -d' with an explicit field select. [ctx: ref=vault-skill file=msp-tools/acg-msp-access-google-workspace.sops.yaml]