From 0ab4f96fda2dddad0adfd60bc370f75cfcc9dcde Mon Sep 17 00:00:00 2001 From: Jamie Pine Date: Fri, 12 Dec 2025 18:08:33 -0800 Subject: [PATCH] Update macOS entitlements and post-build script --- AGENTS.md | 129 +++++++++++++++--- .../xcschemes/Spacedrive.xcscheme | 2 +- apps/tauri/package.json | 2 +- apps/tauri/scripts/fix-daemon-entitlements.sh | 33 +++++ apps/tauri/src-tauri/DaemonEntitlements.plist | 23 ++++ apps/tauri/src-tauri/Entitlements.plist | 20 +-- 6 files changed, 172 insertions(+), 37 deletions(-) create mode 100755 apps/tauri/scripts/fix-daemon-entitlements.sh create mode 100644 apps/tauri/src-tauri/DaemonEntitlements.plist diff --git a/AGENTS.md b/AGENTS.md index c52ab0806..512f7db23 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -410,31 +410,120 @@ impl Job for FileCopyJob { ### Documentation -- Module docs: `//!` at top of file -- Public items: `///` with examples -- Focus on why, not what -- Track future work in GitHub issues, not code comments +**Core principle:** Explain WHY, not WHAT. Keep comments as short as possible. One sentence explaining rationale beats a paragraph restating code. + +**Module docs (`//!`):** +- Add a title with `#` for the module name +- Explain what the module does in plain language (not bullet points) +- Include design rationale naturally in prose +- Add runnable code examples showing usage ````rust -//! File sharing operations. +//! # File Sharing System //! -//! Handles creating, revoking, and managing file shares. - -/// Creates a new file share with the specified recipient. -/// -/// # Example -/// -/// ``` -/// let output = share_file(ShareFileInput { -/// file_id: 123, -/// recipient: "user@example.com".to_string(), -/// }).await?; -/// ``` -pub async fn share_file(input: ShareFileInput) -> Result { - // Implementation -} +//! `core::ops::files::share` provides temporary file sharing via signed URLs. +//! Share links expire after 7 days by default to prevent indefinite access to +//! private files. UUID v5 deterministic IDs ensure the same file generates +//! consistent share URLs across devices without coordination. +//! +//! ## Example +//! ```rust,no_run +//! use spacedrive_core::ops::files::share::{ShareFileAction, ShareFileInput}; +//! +//! let input = ShareFileInput { file_id: 123, recipient: "user@example.com" }; +//! let output = ShareFileAction::run(input, &ctx).await?; +//! ``` ```` +**Function docs (`///`):** +- First line: brief one-liner +- Second paragraph: explain design rationale and why this exists +- Document error handling philosophy when relevant +- Explain non-obvious behavior and platform differences + +```rust +/// Creates a share link with automatic expiration. +/// +/// Share links use signed JWTs so the daemon can validate them without +/// database lookups on every request. Expiration is enforced server-side +/// to prevent timezone manipulation. Recipients without library access +/// get read-only access to the specific file only. +/// +/// Returns `ShareError::PermissionDenied` if the file is private and +/// the recipient isn't a library member. The share is still created +/// but marked inactive for audit logging. +pub async fn share_file(input: ShareFileInput) -> Result +``` + +**Inline comments:** +- Delete comments that restate obvious code +- Explain WHY for decisions, not WHAT the code does +- Use one sentence when possible +- Only expand for truly non-obvious consequences + +```rust +// Good: explains WHY +// Lowercase for case-insensitive search matching. +let ext = path.extension().map(|e| e.to_lowercase()); + +// Bad: restates code +// Extract file extension and convert to lowercase +let ext = path.extension().map(|e| e.to_lowercase()); + +// Good: explains consequence +// Preserve ephemeral UUIDs so tags attached during browsing survive promotion to managed location. +let uuid = ephemeral_cache.get(path).unwrap_or_else(|| Uuid::new_v4()); + +// Bad: verbose explanation of obvious behavior +// UUID assignment strategy: +// 1. First check if there's an ephemeral UUID +// 2. If not, generate a new one +let uuid = ephemeral_cache.get(path).unwrap_or_else(|| Uuid::new_v4()); +``` + +**Error handling comments:** +Explain strategy and recovery, not just "log and continue". + +```rust +// Good: explains recovery +// Best-effort: continue with remaining moves, stale paths cleaned up on next reindex. +Err(e) => ctx.log(format!("Failed to move: {}", e)), + +// Bad: states the obvious +// Log error but continue +Err(e) => ctx.log(format!("Failed to move: {}", e)), +``` + +**Platform-specific comments:** +Explain consequences, not implementation blockers. + +```rust +// Good: explains why and fallback +#[cfg(windows)] +pub fn get_inode(_metadata: &std::fs::Metadata) -> Option { + // Windows file indices are unstable across reboots; fall back to path-only matching. + None +} + +// Bad: over-explains implementation details +#[cfg(windows)] +pub fn get_inode(_metadata: &std::fs::Metadata) -> Option { + // Windows doesn't have inodes. + // The method `file_index()` is unstable (issue #63010). + // Returning None is safe as the field is Optional. + None +} +``` + +**Never use:** +- Placeholder comments ("for now", "TODO: extract this later") +- Markdown formatting (`**bold**`, `_italic_`) in code comments +- ASCII diagrams (put those in `/docs/` if needed) +- Section divider comments (`// ========== Section ==========`) +- Comments explaining removed code during refactors + +Track future work in GitHub issues, not code comments. + ### Formatting Run `cargo fmt` before committing. Tabs for indentation. No emojis. diff --git a/apps/mobile/ios/Spacedrive.xcodeproj/xcshareddata/xcschemes/Spacedrive.xcscheme b/apps/mobile/ios/Spacedrive.xcodeproj/xcshareddata/xcschemes/Spacedrive.xcscheme index b2fefaad6..254ea947b 100644 --- a/apps/mobile/ios/Spacedrive.xcodeproj/xcshareddata/xcschemes/Spacedrive.xcscheme +++ b/apps/mobile/ios/Spacedrive.xcodeproj/xcshareddata/xcschemes/Spacedrive.xcscheme @@ -41,7 +41,7 @@ " + exit 1 +fi + +DAEMON_PATH="$BUNDLE_PATH/Contents/MacOS/sd-daemon" +ENTITLEMENTS_PATH="$(dirname "$0")/../src-tauri/DaemonEntitlements.plist" + +if [ ! -f "$DAEMON_PATH" ]; then + echo "Error: Daemon not found at $DAEMON_PATH" + exit 1 +fi + +if [ ! -f "$ENTITLEMENTS_PATH" ]; then + echo "Error: DaemonEntitlements.plist not found at $ENTITLEMENTS_PATH" + exit 1 +fi + +echo "Re-signing daemon with correct entitlements..." +codesign --force --sign - \ + --entitlements "$ENTITLEMENTS_PATH" \ + --options runtime \ + "$DAEMON_PATH" + +echo "✓ Daemon re-signed successfully" diff --git a/apps/tauri/src-tauri/DaemonEntitlements.plist b/apps/tauri/src-tauri/DaemonEntitlements.plist new file mode 100644 index 000000000..70b6ed63b --- /dev/null +++ b/apps/tauri/src-tauri/DaemonEntitlements.plist @@ -0,0 +1,23 @@ + + + + + + + + com.apple.security.network.client + + com.apple.security.network.server + + + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + + com.apple.security.cs.allow-dyld-environment-variables + + + diff --git a/apps/tauri/src-tauri/Entitlements.plist b/apps/tauri/src-tauri/Entitlements.plist index eb640efda..6e1b126f7 100644 --- a/apps/tauri/src-tauri/Entitlements.plist +++ b/apps/tauri/src-tauri/Entitlements.plist @@ -2,9 +2,7 @@ - - com.apple.security.app-sandbox - + com.apple.security.network.client @@ -12,22 +10,14 @@ com.apple.security.network.server - - com.apple.security.files.user-selected.read-write - - com.apple.security.files.bookmarks.app-scope - - - + com.apple.security.cs.allow-unsigned-executable-memory com.apple.security.cs.disable-library-validation - - com.apple.security.application-groups - - com.spacedrive.desktop - + + com.apple.security.cs.allow-dyld-environment-variables +