Skip to content

🔒️ Restore macOS security-scoped bookmarks - #625

Merged
vinceglb merged 15 commits into
mainfrom
vinceglb/issue-590-security-scoped-bookmarks
Jul 29, 2026
Merged

🔒️ Restore macOS security-scoped bookmarks#625
vinceglb merged 15 commits into
mainfrom
vinceglb/issue-590-security-scoped-bookmarks

Conversation

@vinceglb

@vinceglb vinceglb commented Jul 27, 2026

Copy link
Copy Markdown
Owner

#590

Summary

  • Store versioned native macOS bookmark data on JVM and Kotlin/Native, with legacy fallback and explicit refresh metadata.
  • Keep PlatformFile.fromBookmarkData() as the supported convenience API and add resolveBookmarkData() for callers that need isStale and shouldRefresh.
  • Use macOS-only security-scoped flags while preserving the existing iOS and watchOS behavior.
  • Use supported CoreFoundation and Security APIs on JVM; macOS sandbox detection fails closed.
  • Share security-scoped access only with normalized descendants, including symlink-safe containment, and keep access alive until returned sources and sinks close.
  • Balance native start/stop calls, share the lease across derived files, release it exactly once, and reject new access after release.
  • Preserve the existing JVM and Apple KLIB PlatformFile public ABI while adding the new bookmark-resolution API.
  • Keep Mintlify content under docs/ and place internal design records and the captured ABI under specs/.

Validation

  • ./gradlew :filekit-core:check :filekit-dialogs:check --no-daemon --console=plain
  • ktlint '**/*.kt' '**/*.kts' '!**/build/**' -R ktlint-compose-0.6.0-all.jar
  • git diff --check origin/main...HEAD
  • Compared the current macOS arm64 KLIB ABI dump with origin/main; there are no removed declarations.
  • Added JVM and macOS regression coverage for version envelopes, legacy refresh metadata, lifecycle balancing, descendant propagation, release behavior, path traversal, symlink escapes, and Windows path normalization.
  • Signed Kotlin/Native and JVM macOS relaunch acceptance was completed during the original implementation: persisted external-directory bookmarks restored after process termination and wrote files again without reopening a picker. The JVM check preserved the signed launcher and used normal Compose JAR native-library signing semantics.
  • The final changes received independent GO reviews from GPT-5.6 Sol High and Claude Opus 5 after iterative P0/P1/P2 review and fixes.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0fdbe8de3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@vinceglb
vinceglb merged commit 80b901d into main Jul 29, 2026
9 checks passed
vinceglb added a commit to nik1062/FileKit that referenced this pull request Jul 29, 2026
…tests

Rebased onto main (80b901d), which added two expect declarations in vinceglb#625 that
Linux had no actual for, so the merge no longer compiled:
- withPath() in jvmAndNativeMain
- resolveBookmarkData() in nonWebMain, replacing the old fromBookmarkData shape
Both are now implemented, mirroring mingwX64.

createdAt() no longer reports st_ctim. That is the inode status change time and
is updated by writes and chmod, so it was reporting a fabricated creation time.
Linux only exposes birth time via statx(STATX_BTIME), which Kotlin/Native does
not bind and which several filesystems do not support, so null is returned.
See https://man7.org/linux/man-pages/man7/inode.7.html

MIME lookup now honours the globs2 `cs` flag, so case sensitive entries such as
`*.C:cs` (C++ source) no longer collide with `*.c` (C source). Compound globs
like `*.tar.gz` stay excluded on purpose: `extension` is the segment after the
last dot, so registering them under "gz" would shadow the correct entry.

filesDir/cacheDir no longer fall back to relative `.local/share` and `.cache`
when HOME is unset, which could plant application data in the working
directory. The passwd database is consulted first and a FileKitException is
thrown if no absolute home can be resolved.

Also:
- Make the globs2 and mime.types parsers pure functions over their content so
  the matching rules are unit testable rather than host dependent.
- Collapse the two duplicated FileKitUserDirectory switches into extension
  properties so XDG keys and folder names cannot drift.
- Expand linuxTest to 25 tests covering timestamps, bookmarks, MIME matching,
  FileKit initialization and directory resolution; rename to the documented
  Subject_action_expectation convention.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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