Skip to content

feat(desktop): add a sandboxed Mac App Store build variant - #1581

Merged
giswqs merged 2 commits into
mainfrom
feat/mac-app-store-build
Jul 31, 2026
Merged

feat(desktop): add a sandboxed Mac App Store build variant#1581
giswqs merged 2 commits into
mainfrom
feat/mac-app-store-build

Conversation

@giswqs

@giswqs giswqs commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

Adds a Mac App Store (MAS) build of GeoLibre Desktop that satisfies App Store review rules, alongside the existing Developer ID notarized builds. The App Store requires the App Sandbox and forbids downloading or executing code (guideline 2.5.2), which the default build's runtime bootstrap of uv, Python, and martin cannot pass. The MAS variant compiles those services out and keeps every client-side engine.

What is included

Rust (mas cargo feature, apps/geolibre-desktop/src-tauri)

  • Compiles out the 7 process-spawning commands (sidecar, Jupyter, martin) and external plugin installation, plus all their support code (uv/martin download chains, process-group and port management, sidecar plumbing).
  • Invoke-compatible stubs keep the generate_handler! list unchanged; load_external_plugin_bundles returns an empty result so startup degrades silently.
  • compile_error! forbids mas + native-duckdb (DuckDB loads its spatial extension as unsigned native code at runtime).

Frontend (GEOLIBRE_MAS_BUILD=1 -> __GEOLIBRE_MAS_BUILD__ define)

  • Follows the existing IS_STORE_BUILD pattern; Rollup dead-code-eliminates the gated branches.
  • Hides sidecar-only surfaces: AI Segmentation, Add Data PostgreSQL and File Geodatabase, the PostGIS browser tree, save-edits-to-source, and the external plugin marketplace.
  • Processing dialogs behave like the web build: Whitebox WASM, browser conversions, client raster tools, Turf/Pyodide vector tools, CereusDB WASM SQL. The Notebook panel falls back to JupyterLite, which stays in the MAS bundle (Pyodide runs inside WebKit, which App Review permits).
  • The three invoke wrappers (sidecar.ts, jupyter.ts, martin.ts) throw a translated message under MAS as a safety net; the in-app updater is stripped via the existing GEOLIBRE_STORE_BUILD flag (Store apps update only through the Store).
  • Shapefiles under the sandbox: sibling files of a picked .shp cannot be read, so the MAS build matches .dbf/.shx/.prj/.cpg companions out of the same multi-selection (shapefileCompanionPathsFromSelection, unit tested).

Packaging and CI

  • tauri.mas.conf.json overlay: App Sandbox entitlements, embedded provisioning profile, Apple Distribution signing, hardened runtime off, no bundled sidecar resources.
  • Entitlements template rendered with the team id by scripts/render-mas-entitlements.sh; Info.plist adds ITSAppUsesNonExemptEncryption.
  • npm run tauri:build:mas wires the cargo feature, config overlay, and frontend flags; it refuses --native-duckdb.
  • .github/workflows/mas-store.yml (manual dispatch, mirrors msix-store.yml): temporary keychain, universal build, verifies the app-sandbox entitlement in the signature, produces a signed .pkg artifact for Transporter submission.
  • docs/mac-app-store.md documents the variant, its limitations, required secrets, and submission steps.

Also fixes cargo check --features native-duckdb on main, broken by the locked duckdb crate marking Value #[non_exhaustive].

Test plan

  • cargo check / cargo test pass with and without --features mas (28 and 10 tests respectively), zero new warnings; the mas,native-duckdb combination fails with the intended compile_error!.
  • Frontend suite: 4464 pass, 4 failures are pre-existing on main (BSD date in appimage-update-info/metainfo-generated on macOS runners only).
  • New tests/mas-build.test.ts (9 tests) covers the hide helpers and shapefile companion matching.
  • tsc -b clean; smoke build with GEOLIBRE_MAS_BUILD=1 succeeds and the bundle drops the gated commands (DCE verified); default build re-verified unchanged.
  • Not yet exercised: an actual signed sandboxed run and App Store Connect upload (needs the APPLE_MAS_* secrets, documented in the new doc).

Follow-ups

  • Create the APPLE_MAS_* secrets and the App Store Connect app record, then run the mas-store.yml workflow.
  • Optional in-app hint when a loose .shp is picked without its companions under MAS.

Summary by CodeRabbit

  • New Features
    • Added a Mac App Store edition with sandboxed packaging, signing, and distribution support.
    • Retained client-side functionality while adapting processing, notebooks, and data access for sandbox limitations.
    • Added shapefile companion-file support when selecting multiple files.
  • Bug Fixes
    • Improved compatibility with future DuckDB value types.
  • Documentation
    • Added Mac App Store build, signing, and submission guidance.
  • Chores
    • Added automated build validation and release packaging support.

Adds a `mas` build of GeoLibre Desktop that satisfies App Store review
rules (App Sandbox, guideline 2.5.2), alongside the existing Developer ID
notarized builds:

- `mas` cargo feature compiles out everything that downloads or spawns
  external code: the Python sidecar, Jupyter server, martin tile server,
  the uv bootstrap, and external plugin installation. Invoke-compatible
  stubs keep the command registry unchanged; `compile_error!` forbids
  combining with `native-duckdb` (runtime extension loading).
- `GEOLIBRE_MAS_BUILD=1` frontend flag (Vite define, DCE-friendly) hides
  the sidecar-only UI (AI Segmentation, PostgreSQL, File Geodatabase,
  plugin marketplace) and routes processing dialogs to their client-side
  engines (Whitebox WASM, browser conversions, client raster tools,
  Turf/Pyodide vector tools, CereusDB SQL). The Notebook panel keeps
  working via JupyterLite, which stays in the MAS bundle.
- App Sandbox entitlements template + render script, tauri.mas.conf.json
  overlay (Apple Distribution signing, embedded provisioning profile, no
  sidecar resources), and `npm run tauri:build:mas`.
- Shapefile companions: the sandbox denies reading unselected siblings of
  a picked .shp, so the MAS build matches .dbf/.prj/.shx/.cpg out of the
  same multi-selection instead.
- mas-store.yml workflow (manual dispatch, mirrors msix-store.yml):
  builds the universal sandboxed app, verifies the sandbox entitlement,
  and uploads a signed .pkg artifact for Transporter submission.
- docs/mac-app-store.md documents the variant, its limitations, the
  required secrets, and the submission steps.

Also fixes cargo check --features native-duckdb, broken by the locked
duckdb crate making Value non-exhaustive.
Copilot AI review requested due to automatic review settings July 31, 2026 02:22

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a sandboxed Mac App Store build for GeoLibre Desktop. It adds signing and packaging automation, compiles out process-dependent features, hides unsupported UI, uses browser-based fallbacks, handles sandboxed shapefile access, and documents the build and submission process.

Changes

Mac App Store build variant

Layer / File(s) Summary
Build, signing, and packaging
.github/workflows/mas-store.yml, scripts/*, apps/geolibre-desktop/vite.config.ts, apps/geolibre-desktop/src-tauri/*, docs/mac-app-store.md
Adds MAS build flags, Tauri configuration, entitlements, signing automation, package scripts, and documentation.
Rust sandbox boundaries
apps/geolibre-desktop/src-tauri/src/lib.rs, apps/geolibre-desktop/src-tauri/src/native_duckdb.rs
Excludes process, download, sidecar, Jupyter, Martin, and plugin functionality from MAS builds. Adds compatible command stubs and a DuckDB fallback.
Runtime access and file handling
apps/geolibre-desktop/src/lib/*, apps/geolibre-desktop/src/lib/tauri-io.ts, apps/geolibre-desktop/src/i18n/locales/en.json, tests/mas-build.test.ts
Rejects unavailable services, selects browser runtimes, routes SQL to CereusDB, and preserves selected shapefile companions.
UI capability filtering
apps/geolibre-desktop/src/components/layout/*, apps/geolibre-desktop/src/components/panels/*, apps/geolibre-desktop/src/hooks/useBrowserTree.ts
Hides unsupported menus and data sources, disables database browsing and source write-back, and selects JupyterLite for MAS builds.
Processing fallbacks and validation
apps/geolibre-desktop/src/components/processing/*, tests/mas-build.test.ts
Uses browser processing engines, suppresses sidecar controls, reports localized unavailable states, and validates MAS behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: craun718

Poem

A rabbit checks the sandbox gate,
Then signs the app and seals its fate.
Sidecars sleep; browser engines run.
Shapefile friends arrive as one.
Hop, hop—the MAS build is done!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding a sandboxed Mac App Store build variant for the desktop application.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/mac-app-store-build

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🔍 Cloudflare PR preview

Item Value
Site https://b801ae73.geolibre-preview.pages.dev
Demo app https://b801ae73.geolibre-preview.pages.dev/demo/
Commit 21c4909

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🔍 GitHub Pages PR preview

Item Value
Site https://opengeos.org/pages-preview/GeoLibre/pr-1581/
Demo app https://opengeos.org/pages-preview/GeoLibre/pr-1581/demo/
Commit 21c4909

Comment thread apps/geolibre-desktop/src/lib/mas-build.ts Outdated
Comment thread apps/geolibre-desktop/src/components/processing/RasterToolsDialog.tsx Outdated
@github-actions

Copy link
Copy Markdown
Contributor

Both inline comments posted. Now finalizing the summary.

Code review

Bugs

  • None found. The mas cargo-feature gating in src-tauri/src/lib.rs was traced end-to-end (imports, structs, the 7 stub commands, install_external_plugin_archive/load_external_plugin_bundles) and is internally consistent — stub signatures match the real commands, so generate_handler! and frontend invoke() calls are unaffected regardless of build variant. High confidence.
  • The shapefileCompanionPathsFromSelection matching logic (case-insensitivity, dotted basenames, directory scoping, self-exclusion) was manually traced and matches its test coverage; no off-by-one or filter errors. High confidence.

Security

  • No path lets a MAS build reach a stubbed/compiled-out Tauri command: sidecar.ts/jupyter.ts/martin.ts all throw a static translated error before invoking, and defensive IS_MAS_BUILD re-checks exist inside PostgresSource.tsx and SegmentationDialog.tsx in case a UI gate is somehow bypassed. High confidence.
  • The mas/native-duckdb mutual exclusion (compile_error! in lib.rs, plus the scripts/tauri-build.mjs CLI check) correctly prevents DuckDB's unsigned native spatial-extension load from reaching a sandboxed build. The entitlements template requests only the three minimal capabilities it documents. High confidence.
  • scripts/render-mas-entitlements.sh and .github/workflows/mas-store.yml handle secrets reasonably (temp keychain with a random password, certs decoded to $RUNNER_TEMP/gitignored paths, keychain deleted in an if: always() step, envsubst scoped to a single variable). High confidence.

Performance

  • Nothing notable; no new hot paths.

Quality

  • apps/geolibre-desktop/src/lib/mas-build.ts:33SHAPEFILE_COMPANION_EXTENSIONS claims to mirror the Rust read_shapefile_siblings's 16-extension sidecar list but only covers 4 (dbf/shx/prj/cpg). Likely fine for the common case (those four are what GDAL needs for a basic read), but under MAS a user who multi-selects the fuller companion set (e.g. .qix/.sbn spatial index) will have those silently dropped. Flagged inline. Medium confidence.
  • apps/geolibre-desktop/src/components/processing/RasterToolsDialog.tsx:186 — the non-MAS branch of a ternary this PR edited kept a hardcoded English string instead of t(), inconsistent with the MAS branch right next to it. Pre-existing string, low severity. Flagged inline. Low confidence.
  • apps/geolibre-desktop/src/lib/updates.ts:22-28 (not touched by this PR) — IS_STORE_BUILD's JSDoc describes it as MSIX-only and "set only by the Store build (msix-store.yml)," but scripts/tauri-build.mjs --mas now also sets GEOLIBRE_STORE_BUILD=1, so the comment is now stale. Not part of the diff, so no inline comment was posted, but worth a follow-up doc fix. Low confidence on severity (doc-only).

CLAUDE.md

  • New i18n key (masBuild.unavailable) is used consistently via t()/i18next.t() across all 8 call sites; RTL-safe Tailwind logical utilities are used in the new JSX. No violations found beyond the RasterToolsDialog nit above.

No high-confidence bugs or security issues were found. The two items above were posted as inline comments; everything else checked out against both the diff and the surrounding source.

@coderabbitai coderabbitai 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.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/mas-store.yml:
- Around line 43-44: Update the “Checkout repository” actions/checkout step to
disable credential persistence by setting persist-credentials to false, before
the subsequent npm ci step runs.
- Around line 46-62: Update the “Verify signing secrets are configured” step to
include APPLE_MAS_CERTIFICATE_PASSWORD in its env mapping and in the for-loop
validation list, ensuring all six documented secrets are checked before the
build proceeds.
- Around line 71-72: Update the “Install Rust stable” workflow step to pin
dtolnay/rust-toolchain to a specific full commit SHA instead of the moving
stable reference, preserving the stable-channel intent and optional comment.

In `@apps/geolibre-desktop/src-tauri/mas/Entitlements.mas.plist.template`:
- Around line 21-22: Update the persisted-scope integration associated with the
files.user-selected.read-write entitlement to persist security-scoped bookmarks
for selected files and folders, resolve each bookmark on application launch, and
call startAccessingSecurityScopedResource before access. If native bookmark
handling is not available, replace the persisted access flow with paths that do
not require permissions to survive relaunches.

In `@apps/geolibre-desktop/src/components/layout/TopToolbar.tsx`:
- Line 97: Use IS_MAS_BUILD in the ADD_DATA_KIND_COMMANDS registration to omit
postgres and gdb entries for MAS builds, and update the OPEN_ADD_DATA_EVENT
handler to reject those kinds before calling setAddDataKind(). Preserve all
existing sources and event behavior outside MAS builds.

In `@apps/geolibre-desktop/src/components/processing/SegmentationDialog.tsx`:
- Around line 82-89: Update the SegmentationDialog form controls to use the
unavailable status for IS_MAS_BUILD, preventing image selection and edits while
the MAS unavailable message is shown. Preserve the existing enabled behavior for
available builds and the web-unavailable path.

In `@scripts/render-mas-entitlements.sh`:
- Around line 18-20: Add an explicit gettext/envsubst installation step before
the rendering command that invokes envsubst, using brew install gettext --HEAD
--no-quarantine followed by brew link --force gettext. Update the related local
usage documentation to state the same prerequisite, while preserving the
existing restricted APPLE_TEAM_ID substitution behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 48e5b301-23a8-4e3b-b0d8-02104e7ee0ed

📥 Commits

Reviewing files that changed from the base of the PR and between 7fad14a and f605732.

📒 Files selected for processing (39)
  • .github/workflows/mas-store.yml
  • .gitignore
  • apps/geolibre-desktop/package.json
  • apps/geolibre-desktop/src-tauri/Cargo.toml
  • apps/geolibre-desktop/src-tauri/Info.plist
  • apps/geolibre-desktop/src-tauri/mas/Entitlements.mas.plist.template
  • apps/geolibre-desktop/src-tauri/src/lib.rs
  • apps/geolibre-desktop/src-tauri/src/native_duckdb.rs
  • apps/geolibre-desktop/src-tauri/tauri.mas.conf.json
  • apps/geolibre-desktop/src/components/layout/SettingsDialog.tsx
  • apps/geolibre-desktop/src/components/layout/TopToolbar.tsx
  • apps/geolibre-desktop/src/components/layout/add-data/sources/GdbSource.tsx
  • apps/geolibre-desktop/src/components/layout/add-data/sources/PostgresSource.tsx
  • apps/geolibre-desktop/src/components/layout/toolbar/AddDataMenu.tsx
  • apps/geolibre-desktop/src/components/layout/toolbar/ProcessingMenu.tsx
  • apps/geolibre-desktop/src/components/panels/LayerPanel.tsx
  • apps/geolibre-desktop/src/components/panels/NotebookPanel.tsx
  • apps/geolibre-desktop/src/components/processing/ConversionDialog.tsx
  • apps/geolibre-desktop/src/components/processing/ProcessingDialog.tsx
  • apps/geolibre-desktop/src/components/processing/RasterToolsDialog.tsx
  • apps/geolibre-desktop/src/components/processing/SegmentationDialog.tsx
  • apps/geolibre-desktop/src/components/processing/VectorToolsDialog.tsx
  • apps/geolibre-desktop/src/hooks/useBrowserTree.ts
  • apps/geolibre-desktop/src/i18n/locales/en.json
  • apps/geolibre-desktop/src/lib/build-flags.ts
  • apps/geolibre-desktop/src/lib/jupyter.ts
  • apps/geolibre-desktop/src/lib/martin.ts
  • apps/geolibre-desktop/src/lib/mas-build.ts
  • apps/geolibre-desktop/src/lib/sedona-workspace.ts
  • apps/geolibre-desktop/src/lib/sidecar.ts
  • apps/geolibre-desktop/src/lib/tauri-io.ts
  • apps/geolibre-desktop/src/vite-env.d.ts
  • apps/geolibre-desktop/vite.config.ts
  • docs/mac-app-store.md
  • mkdocs.yml
  • package.json
  • scripts/render-mas-entitlements.sh
  • scripts/tauri-build.mjs
  • tests/mas-build.test.ts

Comment thread .github/workflows/mas-store.yml
Comment thread .github/workflows/mas-store.yml
Comment thread .github/workflows/mas-store.yml Outdated
Comment thread apps/geolibre-desktop/src-tauri/mas/Entitlements.mas.plist.template
Comment thread apps/geolibre-desktop/src/components/layout/TopToolbar.tsx
Comment thread scripts/render-mas-entitlements.sh Outdated
- Widen the MAS shapefile companion set to the Rust command's full
  16-extension list and make companion extensions selectable in the MAS
  file dialog (they were excluded by the vector filter, so the
  multi-select fallback could not receive them).
- Add APPLE_MAS_CERTIFICATE_PASSWORD to the workflow's secrets check so
  a missing password fails with the actionable message.
- Set persist-credentials: false on the mas-store.yml checkout.
- Pin dtolnay/rust-toolchain to the current stable commit SHA; the job
  later holds signing certificates in its keychain.
- Replace envsubst with sed in render-mas-entitlements.sh (gettext is
  not preinstalled on macOS runners) and validate the team ID format.
- Filter MAS-hidden Add Data kinds from the command palette and reject
  them in the OPEN_ADD_DATA_EVENT handler.
- Disable the Segmentation form inputs under MAS via formUnavailable,
  kept separate from webUnavailable so the desktop-download CTA does not
  appear on a desktop build.
- Move the hardcoded raster sidecar message into i18n
  (toolbar.rasterTool.needsDesktopSidecar).
- Document the security-scoped-bookmark project-restore limitation in
  docs/mac-app-store.md.
@github-actions

Copy link
Copy Markdown
Contributor

Code review

I read through the full diff (Rust mas feature gating in lib.rs, the frontend IS_MAS_BUILD/mas-build.ts helpers, the CI workflow, packaging config, and the new tests) and cross-checked several of the claims made in code comments against the actual source.

Bugs: None found. Notably verified as correct rather than assumed:

  • SHAPEFILE_COMPANION_EXTENSIONS in mas-build.ts exactly mirrors the Rust SHAPEFILE_SIDECAR_EXTENSIONS list (16 entries, same set) — the "mirror" comment is accurate.
  • read_shapefile_siblings (Rust) swallows fs::read_dir/permission errors and returns Ok(vec![]) rather than an Err, so under the App Sandbox readShapefileCompanionFiles's unguarded call to readShapefileSiblings in tauri-io.ts degrades gracefully instead of throwing and dropping the whole picked .shp (confidence: high, traced the actual Rust implementation).
  • MAS_HIDDEN_DATA_SOURCES (postgres, gdb) is exhaustive — grepped every Add Data source for startGeoLibreSidecar/startMartinServer usage and only those two call them.
  • The mas cargo feature's invoke_handler list is unchanged, and every listed command has exactly one implementation (real or stub) per feature combination.
  • tauri:build:mas correctly sets GEOLIBRE_MAS_BUILD=1/GEOLIBRE_STORE_BUILD=1 on the spawned build's env.
  • Reused IS_STORE_BUILD gates (update-check UI) only affect update-flow visibility, not any Microsoft-Store-specific user-facing text, so reusing it for MAS is safe.

Security: None found. The mas feature correctly forbids combination with native-duckdb via compile_error!, the entitlements template validates APPLE_TEAM_ID against a strict regex before shell substitution, and the CI workflow imports signing certs into a scoped temporary keychain with restricted -T tool access and cleans it up in an if: always() step.

Performance: None found.

Quality: The #[cfg(feature = "mas")]/#[cfg(not(feature = "mas"))] gating in lib.rs is mechanically repetitive but consistent and low-risk; stubs preserve exact command signatures so the frontend invoke() call sites don't need per-command awareness of the build variant. Good test coverage for the new pure helpers (shapefileCompanionPathsFromSelection, masHidesDataSource, masHidesMenuItem).

CLAUDE.md: No violations — new user-facing strings go through t()/i18next, no new external tile/map hosts were added (so no CSP allowlist change needed), and no MapLibre control CSS overrides were touched.

I did not find anything worth flagging as an inline comment; the implementation is careful and its safety claims (sandbox degradation behavior, mirrored constant lists) check out against the actual source rather than just the comments.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
.github/workflows/mas-store.yml (3)

94-107: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Make signing-material cleanup failure-safe.

When code in Import signing certificates into a temporary keychain fails before MAS_KEYCHAIN is written, the cleanup step cannot find $MAS_KEYCHAIN. Set MAS_KEYCHAIN immediately after keychain creation and use an error trap to remove both mas-signing.keychain-db and mas.p12 on failure.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/mas-store.yml around lines 94 - 107, Update the temporary
keychain setup in the “Import signing certificates into a temporary keychain”
step so MAS_KEYCHAIN is exported to GITHUB_ENV immediately after security
create-keychain succeeds. Add an error trap covering the remaining setup
commands that deletes both the keychain referenced by MAS_KEYCHAIN and the
temporary mas.p12 file, ensuring cleanup also runs when any command fails before
normal completion.

134-135: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Require the sandbox entitlement to be true.

This check only looks for the entitlement key, so <key>com.apple.security.app-sandbox</key><false/> would still pass. Parse and assert that com.apple.security.app-sandbox equals true before packaging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/mas-store.yml around lines 134 - 135, Update the
entitlement validation in the codesign check to parse the XML output and assert
that com.apple.security.app-sandbox is explicitly true, rather than only
checking for the key. Preserve the existing error and exit behavior when the
entitlement is missing or false before packaging.

100-102: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Restrict signing-key access to the signing tools.

security import -A allows any application to access the imported private key without prompting. The -T /usr/bin/codesign and -T /usr/bin/productbuild entries are already present, so remove -A and handle only the remaining signing-key ACL needs, if any.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/mas-store.yml around lines 100 - 102, Update the security
import command in the MAS signing workflow to remove the -A option, preserving
the explicit /usr/bin/codesign and /usr/bin/productbuild tool permissions. Only
add other ACL entries if required for the signing flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/workflows/mas-store.yml:
- Around line 94-107: Update the temporary keychain setup in the “Import signing
certificates into a temporary keychain” step so MAS_KEYCHAIN is exported to
GITHUB_ENV immediately after security create-keychain succeeds. Add an error
trap covering the remaining setup commands that deletes both the keychain
referenced by MAS_KEYCHAIN and the temporary mas.p12 file, ensuring cleanup also
runs when any command fails before normal completion.
- Around line 134-135: Update the entitlement validation in the codesign check
to parse the XML output and assert that com.apple.security.app-sandbox is
explicitly true, rather than only checking for the key. Preserve the existing
error and exit behavior when the entitlement is missing or false before
packaging.
- Around line 100-102: Update the security import command in the MAS signing
workflow to remove the -A option, preserving the explicit /usr/bin/codesign and
/usr/bin/productbuild tool permissions. Only add other ACL entries if required
for the signing flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0004a2b2-ec5e-4a18-9bec-a5d01f5eb968

📥 Commits

Reviewing files that changed from the base of the PR and between f605732 and 21c4909.

📒 Files selected for processing (9)
  • .github/workflows/mas-store.yml
  • apps/geolibre-desktop/src/components/layout/TopToolbar.tsx
  • apps/geolibre-desktop/src/components/processing/RasterToolsDialog.tsx
  • apps/geolibre-desktop/src/components/processing/SegmentationDialog.tsx
  • apps/geolibre-desktop/src/i18n/locales/en.json
  • apps/geolibre-desktop/src/lib/mas-build.ts
  • apps/geolibre-desktop/src/lib/tauri-io.ts
  • docs/mac-app-store.md
  • scripts/render-mas-entitlements.sh

@giswqs
giswqs merged commit 3060b53 into main Jul 31, 2026
84 checks passed
@giswqs
giswqs deleted the feat/mac-app-store-build branch July 31, 2026 04:35
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.

2 participants