diff --git a/windows/apps/bootstrap-winget.ps1 b/windows/apps/bootstrap-winget.ps1 new file mode 100644 index 0000000..2e64179 --- /dev/null +++ b/windows/apps/bootstrap-winget.ps1 @@ -0,0 +1,5 @@ +#Requires -Version 5.1 +$ErrorActionPreference='SilentlyContinue' +# Register the inbox App Installer if present, else nothing to do (offline image w/o it). +Get-AppxPackage -AllUsers Microsoft.DesktopAppInstaller | + ForEach-Object { Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml" } diff --git a/windows/apps/catalog.json b/windows/apps/catalog.json new file mode 100644 index 0000000..1bf4057 --- /dev/null +++ b/windows/apps/catalog.json @@ -0,0 +1,285 @@ +{ + "schemaVersion": 1, + "apps": [ + { + "id": "thunderbird", + "name": "Thunderbird", + "description": "Open-source email, calendar, and chat client.", + "source": { "winget": "Mozilla.Thunderbird" }, + "group": "essentials", + "roles": ["essentials"], + "defaultFor": ["essentials"], + "configure": null + }, + { + "id": "vlc", + "name": "VLC", + "description": "Plays virtually any audio or video file.", + "source": { "winget": "VideoLAN.VLC" }, + "group": "essentials", + "roles": ["essentials"], + "defaultFor": ["essentials"], + "configure": null + }, + { + "id": "7zip", + "name": "7-Zip", + "description": "High-ratio archive extractor and compressor.", + "source": { "winget": "7zip.7zip" }, + "group": "essentials", + "roles": ["essentials"], + "defaultFor": ["essentials"], + "configure": null + }, + { + "id": "libreoffice", + "name": "LibreOffice", + "description": "Full office suite for documents, sheets, and slides.", + "source": { "winget": "TheDocumentFoundation.LibreOffice" }, + "group": "essentials", + "roles": ["essentials"], + "defaultFor": ["essentials"], + "configure": null + }, + { + "id": "ungoogled-chromium", + "name": "ungoogled-chromium", + "description": "Chromium with Google integration stripped.", + "source": { "winget": "eloston.ungoogled-chromium" }, + "group": "essentials", + "roles": ["essentials"], + "defaultFor": [], + "configure": "ungoogled-chromium.ps1" + }, + { + "id": "keepassxc", + "name": "KeePassXC", + "description": "Offline, encrypted password manager.", + "source": { "winget": "KeePassXCTeam.KeePassXC" }, + "group": "essentials", + "roles": ["essentials", "journalist"], + "defaultFor": ["journalist"], + "configure": null + }, + { + "id": "vscodium", + "name": "VSCodium", + "description": "Telemetry-free VS Code build.", + "source": { "winget": "VSCodium.VSCodium" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "git", + "name": "Git", + "description": "Distributed version control system.", + "source": { "winget": "Git.Git" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "dotnet-sdk-9", + "name": ".NET 9 SDK", + "description": "SDK for building .NET 9 applications.", + "source": { "winget": "Microsoft.DotNet.SDK.9" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "nodejs-lts", + "name": "Node.js LTS", + "description": "JavaScript runtime, long-term-support release.", + "source": { "winget": "OpenJS.NodeJS.LTS" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "windows-terminal", + "name": "Windows Terminal", + "description": "Modern tabbed terminal for the shell.", + "source": { "winget": "Microsoft.WindowsTerminal" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "powershell-7", + "name": "PowerShell 7", + "description": "Cross-platform PowerShell shell.", + "source": { "winget": "Microsoft.PowerShell" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "claude-desktop", + "name": "Claude Desktop", + "description": "Anthropic Claude desktop client.", + "source": { "winget": "Anthropic.Claude" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": ["developer"], + "configure": null + }, + { + "id": "visual-studio-2022", + "name": "Visual Studio 2022", + "description": "Full-featured IDE, Community edition.", + "source": { "winget": "Microsoft.VisualStudio.2022.Community" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": [], + "configure": null + }, + { + "id": "jetbrains-rider", + "name": "JetBrains Rider", + "description": "Cross-platform .NET IDE.", + "source": { "winget": "JetBrains.Rider" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": [], + "configure": null + }, + { + "id": "docker-desktop", + "name": "Docker Desktop", + "description": "Container build and run environment.", + "source": { "winget": "Docker.DockerDesktop" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": [], + "configure": null + }, + { + "id": "google-chrome", + "name": "Google Chrome", + "description": "Google's web browser.", + "source": { "winget": "Google.Chrome" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": [], + "configure": null + }, + { + "id": "postgresql", + "name": "PostgreSQL", + "description": "Relational database server.", + "source": { "winget": "PostgreSQL.PostgreSQL" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": [], + "configure": null + }, + { + "id": "bruno", + "name": "Bruno", + "description": "Offline-first API client.", + "source": { "winget": "Bruno.Bruno" }, + "group": "developer", + "roles": ["developer"], + "defaultFor": [], + "configure": null + }, + { + "id": "veracrypt", + "name": "VeraCrypt", + "description": "On-the-fly disk and volume encryption.", + "source": { "winget": "IDRIX.VeraCrypt" }, + "group": "journalist", + "roles": ["journalist", "privacy-max"], + "defaultFor": ["journalist"], + "configure": null + }, + { + "id": "joplin", + "name": "Joplin", + "description": "Encrypted, open-source note-taking app.", + "source": { "winget": "Joplin.Joplin" }, + "group": "journalist", + "roles": ["journalist"], + "defaultFor": ["journalist"], + "configure": null + }, + { + "id": "obs-studio", + "name": "OBS Studio", + "description": "Screen recording and live streaming.", + "source": { "winget": "OBSProject.OBSStudio" }, + "group": "journalist", + "roles": ["journalist"], + "defaultFor": [], + "configure": null + }, + { + "id": "standard-notes", + "name": "Standard Notes", + "description": "End-to-end encrypted notes app.", + "source": { "winget": "StandardNotes.StandardNotes" }, + "group": "journalist", + "roles": ["journalist"], + "defaultFor": [], + "configure": null + }, + { + "id": "signal", + "name": "Signal", + "description": "Encrypted private messaging.", + "source": { "winget": "OpenWhisperSystems.Signal" }, + "group": "journalist", + "roles": ["journalist"], + "defaultFor": [], + "configure": null + }, + { + "id": "tor-browser", + "name": "Tor Browser", + "description": "Anonymous browsing over the Tor network.", + "source": { "winget": "TorProject.TorBrowser" }, + "group": "journalist", + "roles": ["journalist"], + "defaultFor": [], + "configure": null + }, + { + "id": "spotify", + "name": "Spotify", + "description": "Music and podcast streaming.", + "source": { "winget": "Spotify.Spotify" }, + "group": "daily-driver", + "roles": ["daily-driver"], + "defaultFor": [], + "configure": null + }, + { + "id": "zoom", + "name": "Zoom", + "description": "Video conferencing client.", + "source": { "winget": "Zoom.Zoom" }, + "group": "daily-driver", + "roles": ["daily-driver"], + "defaultFor": [], + "configure": null + }, + { + "id": "discord", + "name": "Discord", + "description": "Voice, video, and text chat.", + "source": { "winget": "Discord.Discord" }, + "group": "daily-driver", + "roles": ["daily-driver"], + "defaultFor": [], + "configure": null + } + ] +} diff --git a/windows/apps/configure/ungoogled-chromium.ps1 b/windows/apps/configure/ungoogled-chromium.ps1 new file mode 100644 index 0000000..a3a6d07 --- /dev/null +++ b/windows/apps/configure/ungoogled-chromium.ps1 @@ -0,0 +1,7 @@ +#Requires -Version 5.1 +$ErrorActionPreference='SilentlyContinue' +$pol='HKLM:\SOFTWARE\Policies\Chromium' +New-Item $pol -Force | Out-Null +New-ItemProperty $pol -Name 'ForceGoogleSafeSearch' -Value 1 -PropertyType DWord -Force | Out-Null +$ext="$pol\ExtensionInstallSources"; New-Item $ext -Force | Out-Null +New-ItemProperty $ext -Name '1' -Value 'https://chrome.google.com/webstore/*' -PropertyType String -Force | Out-Null diff --git a/windows/installer/build.ps1 b/windows/installer/build.ps1 index 31e3f4c..4656af2 100644 --- a/windows/installer/build.ps1 +++ b/windows/installer/build.ps1 @@ -172,6 +172,17 @@ function Copy-WelcomePayload { } else { Write-Warning " No *.json flavour files found in $flavoursDir -- image will ship with no flavours." } + # Stage the app catalog + configure/bootstrap scripts next to the Welcome app + # (mirrors the flavours copy above): catalog.json, configure\*.ps1, bootstrap-winget.ps1. + $appsDest = Join-Path $dest 'apps' + $null = New-Item -ItemType Directory -Force $appsDest + $appsDir = Join-Path $WindowsDir 'apps' + if (Test-Path $appsDir) { + Copy-Item (Join-Path $appsDir '*') $appsDest -Recurse -Force + Write-Host " Copied app catalog + scripts to $appsDest" + } else { + Write-Warning " No apps dir found at $appsDir -- image will ship with no app catalog." + } # --- Guard: verify the payload actually landed in the mounted image ------- $stagedExe = Join-Path $dest 'SilverOS.Welcome.App.exe' if (-not (Test-Path $stagedExe)) { @@ -181,6 +192,10 @@ function Copy-WelcomePayload { if (-not $stagedFlavours) { throw "Welcome bake failed: no flavour manifests staged in '$destFlavours'. Add *.json files under windows/flavours/ or the installed wizard will have no flavour choices." } + $stagedCatalog = Join-Path $appsDest 'catalog.json' + if (-not (Test-Path $stagedCatalog)) { + throw "Welcome bake failed: app catalog.json missing from image (expected at '$stagedCatalog'). Add windows/apps/catalog.json or the wizard's Apps step will be empty." + } Write-Host " Welcome payload staged at $dest" }