Skip to content

Remove temporary-exception entitlement rejected by App Store#578

Merged
PureWeen merged 3 commits into
mainfrom
fix/remove-temporary-exception-entitlement
Apr 13, 2026
Merged

Remove temporary-exception entitlement rejected by App Store#578
PureWeen merged 3 commits into
mainfrom
fix/remove-temporary-exception-entitlement

Conversation

@PureWeen
Copy link
Copy Markdown
Owner

@PureWeen PureWeen commented Apr 9, 2026

Problem

Apple rejected the Mac App Store submission under Guideline 2.4.5(i) - Performance:

Entitlement com.apple.security.temporary-exception.files.home-relative-path.read-only value "/" is not permitted.

Temporary exception entitlements are not approved for new Mac App Store submissions.

Fix

Removed the com.apple.security.temporary-exception.files.home-relative-path.read-write entitlement from Entitlements.AppStore.plist.

This entitlement was unnecessary because:

  • The macOS sandbox remaps HOME to ~/Library/Containers/<bundle-id>/Data/
  • All UserProfile-based paths (~/.polypilot/, ~/.copilot/) resolve inside the container automatically
  • The copilot helper process inherits the sandbox (via Entitlements.Helper.plist) and sees the same remapped HOME

Testing

  • All 3331 unit tests pass
  • No code changes needed — only the entitlements plist was modified

Apple rejected Guideline 2.4.5(i): the temporary-exception entitlement
com.apple.security.temporary-exception.files.home-relative-path is not
permitted for Mac App Store apps.

The exception is unnecessary because the macOS sandbox remaps HOME to
~/Library/Containers/<bundle-id>/Data/, so all UserProfile-based paths
(~/.polypilot/, ~/.copilot/) resolve inside the container automatically.
The copilot helper process inherits the sandbox via Entitlements.Helper.plist
and sees the same remapped HOME.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen
Copy link
Copy Markdown
Owner Author

PureWeen commented Apr 9, 2026

🔍 Multi-Model Code Review — PR #578 (Re-review + Fix)

Remove temporary-exception entitlement rejected by App Store


CI Status

⚠️ No CI checks reported on this branch (platform-specific change)


Previous Review Findings — Final Status

# Finding Previous Status Current Status
1 🟡 Migration marker written unconditionally, sealing failed migrations ❌ STILL PRESENT ✅ FIXED — Marker only written when copiedFiles > 0 && !hadErrors
2 🟡 Migration effectively dead code on sandboxed App Store builds ⚠️ PARTIALLY FIXED (documented) ⚠️ ACCEPTED — Documented as best-effort; code degrades gracefully
3 🟢 Symlink following could cause StackOverflow ❌ STILL PRESENT ✅ FIXED — Symlinks skipped via DirectoryInfo.LinkTarget + depth limit (32)
4 🟢 Missing newline at EOF ❌ STILL PRESENT ✅ FIXED — Trailing newline added

Fixes Applied (commit bcf7f01)

  1. Marker file hardened — Replaced bool migratedAny (set on dir existence) with int copiedFiles + bool hadErrors (tracks actual copy results). Marker is only written when copiedFiles > 0 && !hadErrors. Failed/blocked migrations retry safely on subsequent launches thanks to don't-clobber semantics.

  2. Symlink safetyCopyDirectoryRecursive now checks DirectoryInfo.LinkTarget != null and skips symlinked directories. Added depth limit of 32 as additional guard. This prevents StackOverflowException (uncatchable in .NET) from circular symlinks.

  3. EOF newline — Added trailing newline to Program.cs.

  4. Updated xmldoc — Marker behavior documented: "marker file is only written after a fully successful migration, so blocked or partial migrations retry safely on subsequent launches."

Discarded Finding (1/3, failed adversarial round)

One reviewer flagged synchronous migration blocking UIApplication.Main. In the adversarial round, the other reviewer agreed it's technically correct but not a merge blocker: the migration is one-time, only affects the sideloaded→App Store upgrade cohort, and on App Store builds the sandbox blocks access immediately (no actual I/O). Noted as informational.

Test Coverage

  • ✅ All tests pass after fixes
  • Migration code is Mac Catalyst platform-specific (Program.cs) — cannot be tested from the net10.0 test project (same pattern as RecoverSecretsFromSecureStorage)

Recommendation

Approve — All actionable findings fixed. Entitlement removal is correct. Migration is properly hardened.

PureWeen and others added 2 commits April 9, 2026 14:55
When a user upgrades from a sideloaded (non-sandboxed) build to the
App Store (sandboxed) build, their data at the real ~/.polypilot/ and
~/.copilot/ becomes invisible because the sandbox remaps HOME to the
container directory.

This adds a one-time migration in Program.cs that:
- Detects the sandbox by checking for /Library/Containers/ in HOME
- Derives the real home path from the container path
- Copies .polypilot/ and .copilot/ data into the container
- Uses a .sandbox-migrated marker to prevent repeated attempts
- Skips gracefully if the sandbox blocks access (best-effort)
- Never overwrites existing container data (don't-clobber invariant)

Also fixes stale comments in ConnectionSettings.cs that incorrectly
stated Mac Catalyst runs without app sandbox.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Only write .sandbox-migrated marker when files were actually copied
  and no errors occurred; prevents permanently sealing failed migrations
- Track copy errors via ref bool hadErrors; migratedAny replaced with
  copiedFiles counter for accurate success tracking
- Skip symlinked directories in CopyDirectoryRecursive to prevent
  uncatchable StackOverflowException from circular symlinks
- Add depth limit (32) as additional recursion guard
- Update xmldoc to reflect new marker-only-on-success behavior
- Add trailing newline at EOF

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen merged commit 0909dfe into main Apr 13, 2026
@PureWeen PureWeen deleted the fix/remove-temporary-exception-entitlement branch April 13, 2026 22:13
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