Skip to content

Offer IT-published .pkg, .dmg and .zip apps in the macOS Software Catalog - #5603

Merged
Gabriel Dufresne (GabrielDuf) merged 16 commits into
mainfrom
macos-pkg-dmg-catalog-feeds
Oct 27, 2026
Merged

Gabriel Dufresne (GabrielDuf) merged 16 commits into
mainfrom
macos-pkg-dmg-catalog-feeds

Conversation

@GabrielDuf

@GabrielDuf Gabriel Dufresne (GabrielDuf) commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What it adds

A macOS "Installer packages" manager (pkg), fed by the catalog itself. A catalog in the machine-wide SoftwareCatalog.json declares a pkgFeed: a folder or mounted share read directly, or an https folder read through the index.json that unigetui pkg-index <folder> writes. Every package in the feed joins that catalog.

  • Formats: .pkg, .dmg holding an app or a .pkg, and .zip holding an app. Identity, version, architectures and icon are read from the file (xar table of contents and payload, a read-only mounted image, or the zip entries).
  • Detection: by the package receipt, or by the app in place under its bundle id, so apps already deployed by Jamf or by hand are recognized and updates are offered.
  • Install and update: a private staged copy is checked against the index hash, its identity and Gatekeeper (Developer ID signed and notarized, unless the catalog sets allowUnsignedPackages), then installed as root behind the macOS administrator prompt. .dmg/.zip apps are swapped into /Applications so that a failure keeps the previous version. Uninstall is refused (new CanUninstall capability).
  • Without a password: sudo unigetui pkg-helper install-daemon sets up a root LaunchDaemon so standard users can install too. A client sends only catalog id, package id and version over a Unix socket. The helper resolves and checks the package itself, and refuses anything the catalog does not publish or that a standard user could change (catalog, feed, package file, UniGetUI itself). Without it, installs fall back to the prompt.
  • Catalog Editor: a Package feed dialog sets a catalog's feed and previews what it publishes and which files it skips, with the reason.

Shared changes: InstalledPackagesKeepTheirSource and Sources.CanBeEdited capabilities (replacing Chocolatey and manager-id special cases), and an unpinned catalog entry of a NuGet-based manager now asks the feed for its latest version instead of Version='', so its icon is found.

Docs: docs/PKG_FEEDS.md for administrators, docs/CLI.md, and a section in AGENTS.md.

Testing

  • UniGetUI.PackageEngine.Tests on macOS: all 99 pkg-feed tests and the NuGet tests pass, including real pkgbuild, productbuild, hdiutil and ditto fixtures, an install over the helper socket, and the refusal cases. The rest of the suite fails the same 107 tests as main on macOS (Windows-only areas).
  • Tried in the app on macOS with real vendor files: Zoom (.pkg), GitKraken and ChatGPT (.dmg, ChatGPT installed), and the Devolutions Mac downloads (.dmg and .pkg, detected from the existing installs with updates offered), plus the Package feed dialog.
  • dotnet format whitespace and dotnet format style (--verify-no-changes) pass, and the osx-arm64 NativeAOT publish adds no trim or AOT warnings.
  • Not run locally: the Windows-only UniGetUI.Tests (catalog model, Catalog Editor and identity tests) and the Chocolatey change, which this PR's CI covers. The package helper has not yet run as a real LaunchDaemon on a Mac.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved privileged-helper filesystem trust gaps and installation-selection and reliability defects block safe deployment.

9 open issues
What changed in this PR

Adds IT-published macOS apps to UniGetUI’s existing Software Catalog, letting users install software unavailable through conventional package managers.

Changes:

  • Adds a macOS installer manager for .pkg, .dmg, and .zip feeds, including detection, updates, indexing, and an optional privileged helper.
  • Integrates feed configuration and previews into the Catalog Editor, with capability-based uninstall and source-editing controls.
  • Adds catalog and NuGet regression tests, English strings, and administrator documentation.
File Description
src/​UniGetUI.Windows.slnx Includes the MacPkg project.
src/​UniGetUI.Tui/​Views/​Pages/​ManagersPage.cs Respects source-editing capability.
src/​UniGetUI.Tests/​SoftwareCatalogTests.cs Tests feed persistence and catalog usability.
src/​UniGetUI.Tests/​CatalogPackageIdentitySetTests.cs Tests source-independent installed identities.
src/​UniGetUI.Tests/​CatalogEditorTests.cs Tests feed editing, saving, and validation.
src/​UniGetUI.PackageEngine.Tests/​UniGetUI.PackageEngine.Tests.csproj References MacPkg for testing.
src/​UniGetUI.PackageEngine.Tests/​NuGetManifestLoaderTests.cs Tests latest-version lookup and cache expiry.
src/​UniGetUI.PackageEngine.PackageEngine/​UniGetUI.PackageEngine.PEInterface.csproj Adds the platform-conditioned manager reference.
src/​UniGetUI.PackageEngine.PackageEngine/​PEInterface.cs Registers MacPkg on macOS.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​UniGetUI.PackageEngine.Managers.MacPkg.csproj Defines the new manager project.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​PkgIndexCommand.cs Generates web-feed indexes and publishes icons.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​PkgHelperCommand.cs Adds daemon setup and privileged installation requests.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​PkgFeedInspector.cs Provides feed previews and diagnostics.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs Implements package discovery, inventory, and updates.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​InternalsVisibleTo.cs Exposes internals to engine tests.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​ZipApp.cs Reads app metadata and icons from ZIP files.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​XarArchive.cs Reads flat-package archives.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​TrustedPath.cs Checks filesystem ownership and permissions.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​Tool.cs Runs native tools with redirected input and output.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgReceipts.cs Reads installed package receipts.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgPayload.cs Extracts app resources from package payloads.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgMetadata.cs Interprets package identity and architecture metadata.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgInstaller.cs Stages, validates, and installs feed packages.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgHelperClient.cs Communicates with the privileged helper.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgFeedIndex.cs Defines source-generated feed serialization.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgFeed.cs Loads and caches folder and web feeds.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgCatalogFeeds.cs Reads machine-wide feed declarations.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​FeedFile.cs Classifies supported installer formats.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​DiskImage.cs Mounts and inspects disk images.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​AppBundle.cs Reads bundle identity, versions, architectures, and icons.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Helpers/​MacPkgSourceHelper.cs Exposes catalog-defined, noneditable sources.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Helpers/​MacPkgOperationHelper.cs Routes managed installs and updates.
src/​UniGetUI.PackageEngine.Managers.MacPkg/​Helpers/​MacPkgDetailsHelper.cs Supplies package details, icons, and versions.
src/​UniGetUI.PackageEngine.Managers.Generic.NuGet/​Internal/​NuGetManifestLoader.cs Resolves unpinned manifests with expiring caching.
src/​UniGetUI.PackageEngine.Managers.Chocolatey/​Chocolatey.cs Declares source-independent installed inventory.
src/​UniGetUI.PackageEngine.Enums/​ManagerCapabilities.cs Adds uninstall, source-editing, and provenance capabilities.
src/​UniGetUI.Core.Tools/​Tools.cs Shares shell and AppleScript escaping helpers.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​SoftwareCatalogPage.axaml Hides unsupported uninstall actions.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​InstalledPackagesPage.cs Filters unsupported uninstall requests.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​CatalogEditorPage.cs Opens and applies feed configuration.
src/​UniGetUI.Avalonia/​Views/​Pages/​SettingsPages/​PackageManagerPage.axaml.cs Respects source-editing capability.
src/​UniGetUI.Avalonia/​Views/​DialogPages/​PkgFeedEditor.axaml.cs Initializes the feed editor control.
src/​UniGetUI.Avalonia/​Views/​DialogPages/​PkgFeedEditor.axaml Adds feed settings and preview controls.
src/​UniGetUI.Avalonia/​ViewModels/​SoftwarePages/​SoftwareCatalogViewModel.cs Expands feeds into catalog tiles and labels.
src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs Implements feed validation and previews.
src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​CatalogEditorViewModel.cs Preserves editable feed settings.
src/​UniGetUI.Avalonia/​Program.cs Dispatches indexing and helper commands.
src/​UniGetUI.Avalonia/​Models/​SoftwareCatalog.cs Adds feed declarations and capability-based matching.
src/​UniGetUI.Avalonia/​Models/​CatalogPackageIdentitySet.cs Generalizes source-independent inventory matching.
src/​UniGetUI.Avalonia/​Infrastructure/​MacAdminFileInstaller.cs Reuses shared escaping helpers.
src/​UniGetUI.Avalonia/​Infrastructure/​AvaloniaAutoUpdater.cs Reuses shared shell quoting.
src/​UniGetUI.Avalonia.slnx Includes the MacPkg project.
src/​Languages/​lang_en.json Adds English feed and installation strings.
docs/​PKG_FEEDS.md Documents publishing, installation, and helper setup.
docs/​CLI.md Documents indexing and helper commands.
AGENTS.md Documents the macOS manager architecture.

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgInstaller.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/TrustedPath.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/TrustedPath.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgFeed.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/Tool.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/MacPkg.cs
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/MacPkg.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/MacPkg.cs
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/PkgHelperCommand.cs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved privileged-installation security issues and operation reliability defects block approval.

4 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Compare updates using bundle versions, not installer versions

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:193

[P2] Without a receipt, p.Installed is the app's bundle version, but p.Item.Version is the installer component's version. A component at 1.0 containing app 10.2 therefore produces a 10.1 → 1.0 update for installed app 10.1, which UpgradablePackagesLoader.IsPackageValid rejects as a downgrade. Keep update comparisons in the bundle-version domain while retaining the separate installer version for feed selection.

9 resolved since last review

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgInstaller.cs
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgInstaller.cs
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/PkgHelperCommand.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/Tool.cs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved privileged-feed authorization and concurrent installation issues remain, alongside update-detection and feed-handling defects.

2 open issues
5 previously missed issues

In code that hasn't changed since last review

Medium severity Clear stale previews and discard outdated feed inspection results

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:96

[P2] Changing Location leaves the previous feed's preview visible, and an in-flight inspection can also publish results after the address changes. This shows feed A's packages and trust warning under feed B's address even though Apply saves B. Clear the preview when Location changes and discard results and errors from inspections of an older location.

Medium severity Announce failed feed checks to screen readers

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:109

A failed Check feed operation only changes Summary, which is rendered as an ordinary TextBlock without a live-region announcement. Screen-reader users therefore receive no failure message when the asynchronous check finishes. Announce this error through AccessibilityAnnouncementService with Assertive priority, as the surrounding Catalog Editor does for its errors.

Medium severity Skip macOS icon conversion when indexing packages on Linux

src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​AppBundle.cs:87

[P2] Linux builds expose pkg-index, but indexing a readable .pkg or .zip with an embedded icon launches the macOS-only /usr/bin/sips here. Process.Start throws Win32Exception, which the feed/icon readers do not catch, aborting index generation. Skip icon conversion outside macOS so Linux can still index these packages without generated icons.

Medium severity Deduplicate ZIP icon entries before building the dictionary

src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​ZipApp.cs:89

[P2] ZIP archives can contain duplicate entry names, so duplicate Contents/Resources/AppIcon.icns entries make ToDictionary throw ArgumentException. Cold folder scans extract ZIP icons, and PkgFeed.IsUnreadable does not catch this exception, so one archive aborts the whole feed scan. Deduplicate icon entry names before constructing the dictionary.

Medium severity Keep receipt-free update comparisons in the app-version domain

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:193

[P2] When receipt-free detection uses the installed app's bundle version, this constructor pairs it with the feed's package/component version, which can use a different numbering scheme. An app update from 2026.2 to 2026.3 inside package version 1.1 passes HasUpdate but is rejected as a downgrade by UpgradablePackagesLoader.IsPackageValid. Keep update comparisons in the app-version domain while retaining the feed's package version separately for installation target selection.

4 resolved since last review

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgInstaller.cs
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/PkgHelperCommand.cs
- Every root install command now takes one machine-wide lock (lockf on
  a root-only folder in /var/run), so an install the helper runs and one
  behind the prompt never share an app's working copies.
- The helper refuses web feeds and packages not served over https: any
  user can listen on a loopback port the real server left free.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgInstaller.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/AppBundle.cs
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/ZipApp.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/MacPkg.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/MacPkg.cs Outdated
- Take the install lock with lockf's "file command" form, which every
  macOS UniGetUI supports, instead of the newer descriptor form.
- Skip icon conversion with sips outside macOS, so pkg-index on Linux
  publishes packages without icons instead of failing.
- Tolerate zip archives that repeat an icon entry's name.
- Read the catalog again when the package lists are refreshed.
- Compare an app found in place with the app's version from the feed,
  not the package's, and find the package from either version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The privileged helper has an unresolved authorization issue and requires human security review and real LaunchDaemon validation on macOS.

2 open issues
2 previously missed issues

In code that hasn't changed since last review

Medium severity Discard stale feed inspection results when location changes

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:96

[P2] The location remains editable during inspection, so checking feed A and switching to feed B can display A's packages and warnings under B's address. Editing the address after completion also leaves the old preview visible. Clear the preview when Location changes and discard both successful and failed results from obsolete inspections before updating the UI.

Medium severity Announce feed check completion and failures to screen readers

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:109

[P2] Feed-check completion and failures only update an ordinary TextBlock bound to Summary; neither the dialog nor this method provides a live-region notification. A screen-reader user activating Check feed is therefore not told whether the asynchronous check finished, skipped files, or failed. Announce the completion summary through AccessibilityAnnouncementService and announce failures assertively, as the existing Catalog Editor does.

5 resolved since last review

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/TrustedPath.cs Outdated
Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgFeed.cs Outdated
…sion

- TrustedPath no longer caches who is an administrator, so an account
  removed from the admin group loses its trust at once in the helper.
- When a vendor republishes one package version with a newer app inside,
  the newest app wins, in the listing, across feeds, and when the user's
  UniGetUI or the helper picks the release to install.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The root installation service still needs fixes, human security review, and real LaunchDaemon deployment validation.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity Discard inspection results after the feed location changes

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:110

The location field and Browse command remain enabled during this await. If an administrator starts checking feed A and changes the location to feed B before it completes, A's packages, warnings and summary appear beneath B's address, while Apply saves B. Discard both successful and failed inspection results when the current location no longer matches the captured location.

Medium severity Detect app updates when receipt versions match

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:190

[P2] A matching receipt hides an update when a vendor republishes package 1.0 with app 12.6.1 while receipt 1.0 and app 12.5.0 are installed: this branch compares only the receipt versions. When receipt versions tie, also check the installed bundle and report an available update in the app-version domain, retaining receipt-based detection otherwise.

2 resolved since last review

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/XarArchive.cs Outdated
- Route the package feeds' JSON through PkgJson, which takes the
  source-generated JsonTypeInfo explicitly, so the repository's
  trim-safety check (MetaTests.TestJsonSerializationOptions) sees it.
- Pin the elevation path in the package-feed tests: the Windows CI
  runner is an administrator, which sent the prompt test down the
  root path.
- Reject a package whose folders nest more than 64 deep before reading
  it recursively, so a crafted file cannot exhaust the stack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unbounded payload-resource retention can exhaust memory before signature verification, and functional issues remain in update detection, command generation and feed previews.

1 open issue
3 previously missed issues

In code that hasn't changed since last review

Medium severity Clear feed inspection state when location changes

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:96

[P2] Changing Location during or after a check leaves the previous feed's packages, summary and trust warning visible, so an administrator can apply feed B while viewing a successful preview of feed A. Clear inspection state when Location changes and discard results and errors whose captured location no longer matches.

Medium severity Reject standalone commands for managed package arguments

src/​UniGetUI.PackageEngine.Managers.MacPkg/​Helpers/​MacPkgOperationHelper.cs:24

[P2] Manual-install actions and bundle script export also consume these arguments through GetStandaloneParameters, producing installer -pkg com.example.app -target /. That command cannot install the feed item: -pkg needs a package file path, and DMG/ZIP apps require the managed flow. Override the standalone overload to reject command generation instead of exposing the display-only arguments as an executable command.

Medium severity Detect newer apps when receipt versions are unchanged

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:190

[P2] When a vendor republishes receipt version 1.0 with a newer embedded app, an existing 1.0 receipt makes this branch suppress the update even though CompareReleases selects the newer release. When receipt versions compare equal, check the installed bundle too and report app-version values if the offered app is newer, while preserving receipt-based detection otherwise.

1 resolved since last review

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/Internal/PkgPayload.cs
Icons are kept until the app's Info.plist names one, so a payload full of
icons could fill memory. At most 32 icons and 32 MiB are now kept, plus
the named one, and an identity check (as on the root side) reads only
the plist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Root-side logging can write through user-controlled symlinks, and unresolved cancellation, update-detection, and preview-state issues affect correctness.

1 open issue
3 previously missed issues

In code that hasn't changed since last review

Medium severity Clear stale inspection results when package location changes

src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​PkgFeedEditorViewModel.cs:95

[P2] Checking feed A and then editing Location to B can display A's packages, warnings, and success summary under B's address, while Apply saves B. Completed previews also remain visible after subsequent edits. Clear the preview when Location changes and discard both results and errors from an obsolete inspection.

Medium severity Cancellation skips success handling after root install completes

src/​UniGetUI.PackageEngine.Managers.MacPkg/​Internal/​PkgInstaller.cs:65

[P2] Canceling during a root install still marks the enclosing operation canceled: AbstractOperation.cs:547–549 overwrites even a successful result, so the app is installed but HandleSuccess() and its inventory updates are skipped. This affects the helper and elevated-process paths too; passing CancellationToken.None only prevents the installer from observing cancellation. Add an engine/UI-supported non-cancellable phase when the root install is submitted, while retaining cancellation before that point.

Medium severity Detect updates when receipt and package versions match

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:190

[P2] A receipt hides updates when a vendor republishes the same package version with a newer embedded app: receipt 1.0 versus package 1.0 reports no update even when the installed app is 12.5.0 and the offered app is 12.6.1. Release selection already distinguishes these builds, but this branch never checks the installed bundle. When receipt versions compare equal, use the bundle versions when available, keeping Installed and Offered in the same version domain.

1 resolved since last review

Review effort: Balanced

Comment thread src/UniGetUI.PackageEngine.Managers.MacPkg/PkgHelperCommand.cs Outdated
As root, the helper and the root install set TMPDIR to /tmp, so the
session log went to /tmp/UniGetUI, a path any user could prepare with a
symlink. pkg-helper now runs first in Main, checks for root with
Environment.IsPrivilegedProcess instead of CoreTools, and points TMPDIR
at a root-only folder under /var/run before anything can log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved correctness issues remain, and the new root service needs human security review and real LaunchDaemon validation on macOS.

No open issues 🎉

4 previously missed issues

In code that hasn't changed since last review

Medium severity Honor pinned versions when selecting installers

src/​UniGetUI.PackageEngine.Managers.MacPkg/​Helpers/​MacPkgDetailsHelper.cs:19

[P2] This lookup always selects the latest release, even when details.Package names an explicitly pinned version. With versions 1.0 and 2.0 in the feed, opening details for a catalog entry pinned to 1.0 sets InstallerUrl, hash and size to 2.0; Download installer then saves 2.0 although the catalog's install action targets 1.0. Pass the concrete requested version (or the offered version for an update), using the latest-release lookup only for unversioned requests.

Medium severity Bound feed listing timeouts and preserve cached results

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:101

[P2] A stalled web feed uses a 60-second timeout, so the enclosing 60-second RunListingTaskWithTimeout can expire before cached fallback returns. Persistent stalls also affect the retry, discarding the whole listing—including healthy feeds—and can remove feed-generated catalog tiles despite a saved index. Bound the complete listing below the engine deadline and return cached or partial results within that budget; shortening each request alone does not bound serial reads across multiple feeds.

Medium severity Resolve updates across feeds without breaking installation

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:183

[P2] If inventory was loaded from feed A and a later update check selects a newer release from feed B, the catalog shows Update but clicking it does nothing: LaunchUpdate looks up the installed instance using a source-sensitive hash. Selecting the newest feed here changes that identity without reloading inventory. Make update resolution honor InstalledPackagesKeepTheirSource == false while retaining the selected update's feed for installation.

Medium severity Detect app updates when receipt versions are unchanged

src/​UniGetUI.PackageEngine.Managers.MacPkg/​MacPkg.cs:190

[P2] When a vendor reuses receipt version 1.0 but updates its app from 12.5.0 to 12.6.1, this branch reports no update because the installed receipt is also 1.0. The newer app is ignored even though CompareReleases selects that release. Compare installed and offered app versions when the receipt version cannot distinguish releases, while preserving receipt-only detection for packages without an app.

1 resolved since last review

Review effort: Balanced

@randy-but-a-ro randy-but-a-ro Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Pull request was approved automatically: the AI review is complete and all its review threads are resolved. 🎉

Integration Details
{
	"deliveryId": "768a3cf0-d225-11f1-9052-2c7c2723851b",
	"headSha": "54a6864d95d122a9dbe6a87c3673f3da5548e9f8",
	"reviewer": "copilot-pull-request-reviewer[bot]"
}

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit 0d93c86 into main Oct 27, 2026
7 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the macos-pkg-dmg-catalog-feeds branch October 27, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants