Skip to content

Rewrite plugin ABI/registry pipeline, fix PluginKit version mismatch (#1322)#1343

Merged
datlechin merged 5 commits into
mainfrom
fix/1322-plugin-abi-and-registry-overhaul
May 20, 2026
Merged

Rewrite plugin ABI/registry pipeline, fix PluginKit version mismatch (#1322)#1343
datlechin merged 5 commits into
mainfrom
fix/1322-plugin-abi-and-registry-overhaul

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

Fixes the recurring "Plugin was built with PluginKit version N, but version M is required" error that hits users on every ABI bump (#1322, #1237, #923, #912, #443). Reworks the plugin install/load pipeline, registry schema, and update UX.

Core

  • New PluginInstaller actor: per-plugin coalescing, atomic install via FileManager.replaceItem, strips com.apple.quarantine, validates ABI before commit
  • Reconciliation loop replaces single-shot auto-update; runs for all rejected plugins with backoff (immediate, 30s, 5min, max 3 attempts)
  • Close the replaceExistingPlugin race: old bundle stays loaded until the new one registers (loadPluginAsync(replacingBundleId:))
  • Per-plugin install guard (installsInFlight) replaces global isInstalling bool
  • Extract PluginCodeSignatureVerifier (drops a cross-actor Bundle transfer); Task.detached replaces DispatchQueue.global + continuation

Registry / schema v2

  • RegistryBinary.pluginKitVersion for exact-match binary selection; app picks the binary built for its ABI
  • validateRegistryCompatibility returns the resolved binary, threaded into the installer (no double resolve)
  • v1 manifests decode to arm64 + x86_64 synthesized binaries (universal-binary assumption)

CI / scripts

  • build-plugin.yml accepts tag:pluginKitVersion matrix, reads currentPluginKitVersion from source
  • Logic extracted to .github/scripts/update-registry.py (atomic write, per-binary version, prune to 2 latest)
  • scripts/release-all-plugins.sh bulk re-release after ABI bump, with bundled-plugin guard
  • scripts/build-plugin.sh no longer hardcodes team ID; resolves signing identity from keychain

UX (native HIG)

  • Drops the blocking NSAlert at launch; uses UserNotifications (per-plugin identifiers) + Settings tab badge + inline banners
  • Staged update: downloads while a connection is open, swaps when the connection closes or on quit
  • Connection form shows an inline banner with "Update Plugin" for rejected drivers; welcome list shows a warning triangle
  • Built-in plugins no longer show a phantom "update available"

Cleanup (from 4-axis review)

  • Drop dead PluginTableInfo.owner/comment; add avgRowLength/collation/createTime/updateTime to PluginTableMetadata
  • Store capability ids on PluginEntry so unregisterCapabilities does not touch an unloaded bundle
  • PluginUpdateCoordinator dedupes the install/update tracker dance across 3 views
  • Cache pluginsWithRegistryUpdate to avoid O(N×M) per render
  • Theme load stops spamming errors when a user theme file is deleted

Test plan

  • xcodebuild build clean
  • swiftlint --strict: 0 violations
  • 25 new unit tests + updated existing pass (RegistryBinarySelection, PluginInstaller helpers/coalescing, reconciliation, staged tracker, staging cleanup)
  • Manual: fresh install from registry, ABI-mismatch auto-update, staged update with active connection, rejected-driver inline banner, notification permission flow
  • Verify quarantine xattr stripped: xattr -l <plugin>.tableplugin
  • Verify no .bak/.tmp leftovers after install

Notes

  • Registry already migrated to schema v2 (separate commit on TableProApp/plugins)
  • Users on 0.42 and older still need an app update; 0.43 works via tolerant decode

@datlechin datlechin merged commit fc8e515 into main May 20, 2026
1 of 2 checks passed
@datlechin datlechin deleted the fix/1322-plugin-abi-and-registry-overhaul branch May 21, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant