diff --git a/README.md b/README.md index 2737d5d6..e0d3f785 100644 --- a/README.md +++ b/README.md @@ -948,6 +948,60 @@ sudo tccutil reset ScreenCapture sh.vibetunnel.vibetunnel.debug # For debug bui sudo tccutil reset AppleEvents ``` +## Logging and Privacy + +VibeTunnel uses Apple's unified logging system with the subsystem `sh.vibetunnel.vibetunnel`. By default, macOS redacts sensitive runtime data in logs, showing `` instead of actual values. This is a privacy feature to prevent accidental exposure of sensitive information. + +### Bundle Identifiers + +VibeTunnel uses the following bundle identifiers: + +**Production:** +- `sh.vibetunnel.vibetunnel` - Main macOS app and logging subsystem +- `sh.vibetunnel.vibetunnel.debug` - Debug builds of the macOS app + +**Testing:** +- `sh.vibetunnel.vibetunnel.tests` - macOS test suite +- `sh.vibetunnel.ios.tests` - iOS test suite + +**iOS:** +- `sh.vibetunnel.ios` - iOS keychain service and URL scheme + +### Viewing Unredacted Logs + +To see full log details for debugging, you have several options: + +1. **Use the vtlog script with sudo** (reveals private data): + ```bash + sudo ./scripts/vtlog.sh --info + ``` + +2. **Configure passwordless sudo** for the log command: + ```bash + # Add to sudoers (replace 'yourusername' with your actual username) + sudo visudo + # Add this line: + yourusername ALL=(ALL) NOPASSWD: /usr/bin/log + ``` + +3. **Enable private data logging** using a plist file (recommended): + ```bash + # Create the plist to enable private data for VibeTunnel + sudo mkdir -p /Library/Preferences/Logging/Subsystems + sudo tee /Library/Preferences/Logging/Subsystems/sh.vibetunnel.vibetunnel.plist > /dev/null << 'EOF' + + + + + Enable-Private-Data + + + + EOF + ``` + +For more detailed information about logging privacy and additional methods, see [apple/docs/logging-private-fix.md](apple/docs/logging-private-fix.md). + ## Contributing We welcome contributions! VibeTunnel is a community-driven project and we'd love to have you join us. diff --git a/apple/docs/logging-private-fix.md b/apple/docs/logging-private-fix.md index 2487c7b5..26e1c838 100644 --- a/apple/docs/logging-private-fix.md +++ b/apple/docs/logging-private-fix.md @@ -1,5 +1,35 @@ # Fixing macOS Log Redaction for VibeTunnel +## Quick Fix: Configuration Profile (Recommended) + +We provide a ready-to-use configuration profile that enables full debug logging for VibeTunnel: + +**Location**: `apple/logging/VibeTunnel-Logging.mobileconfig` + +### Installing the Profile + +#### macOS +1. Double-click `apple/logging/VibeTunnel-Logging.mobileconfig` +2. System Settings will open to the Profiles section +3. Click "Install..." and enter your password +4. Restart VibeTunnel + +#### iOS +1. AirDrop or email the profile to your device +2. Open Settings → General → VPN & Device Management +3. Install the "VibeTunnel Debug Logging" profile +4. Restart the VibeTunnel app + +### Verifying It Works +```bash +# You should now see full details instead of +./scripts/vtlog.sh +``` + +### Removing the Profile +- **macOS**: System Settings → Privacy & Security → Profiles → Remove +- **iOS**: Settings → General → VPN & Device Management → Remove Profile + ## The Problem When viewing VibeTunnel logs using Apple's unified logging system, you'll see `` instead of actual values: @@ -133,18 +163,83 @@ logger.info("Connected to \(sessionId)") logger.info("Connected to \(sessionId, privacy: .public)") ``` -### 4. Configure logging system +### 4. Configure logging system (Modern Methods) + +#### Method A: Plist File (Recommended) + +Create a plist file to enable private data logging for VibeTunnel: -Temporarily enable private data for all VibeTunnel logs: ```bash -sudo log config --mode "private_data:on" --subsystem sh.vibetunnel.vibetunnel +# Create the directory if it doesn't exist +sudo mkdir -p /Library/Preferences/Logging/Subsystems + +# Create the plist file +sudo tee /Library/Preferences/Logging/Subsystems/sh.vibetunnel.vibetunnel.plist > /dev/null << 'EOF' + + + + + Enable-Private-Data + + + +EOF + +# Verify it was created +ls -la /Library/Preferences/Logging/Subsystems/sh.vibetunnel.vibetunnel.plist ``` -To revert: +To remove: ```bash -sudo log config --mode "private_data:off" --subsystem sh.vibetunnel.vibetunnel +sudo rm /Library/Preferences/Logging/Subsystems/sh.vibetunnel.vibetunnel.plist ``` +#### Method B: Configuration Profile + +For managed environments or multiple subsystems, create a configuration profile: + +```xml + + + + + PayloadContent + + + PayloadType + com.apple.system.logging + PayloadIdentifier + com.example.logging.vibetunnel + PayloadUUID + $(uuidgen) + PayloadVersion + 1 + Subsystems + + sh.vibetunnel.vibetunnel + + Enable-Private-Data + + + + + + PayloadIdentifier + com.example.vibetunnel.logging + PayloadUUID + $(uuidgen) + PayloadType + Configuration + PayloadVersion + 1 + + +``` + +Install via System Settings → Profiles. + +**Note:** The old `private_data:on` flag was removed in macOS Catalina and no longer works. + ## Using vtlog.sh With passwordless sudo configured, you can now use: diff --git a/apple/logging/README.md b/apple/logging/README.md new file mode 100644 index 00000000..b51d4d32 --- /dev/null +++ b/apple/logging/README.md @@ -0,0 +1,79 @@ +# VibeTunnel Logging Configuration Profile + +This directory contains the configuration profile for enabling full debug logging in VibeTunnel apps. + +## What It Does + +The `VibeTunnel-Logging.mobileconfig` profile enables: +- Debug-level logging for both macOS and iOS apps +- Visibility of private data (no more `` tags) +- Persistent logging at debug level + +## Installation + +### macOS +1. Double-click `VibeTunnel-Logging.mobileconfig` +2. System Settings will open +3. Go to Privacy & Security → Profiles +4. Click on "VibeTunnel Debug Logging" +5. Click "Install..." +6. Enter your password when prompted +7. Restart VibeTunnel for changes to take effect + +### iOS +1. AirDrop or email the `VibeTunnel-Logging.mobileconfig` to your iOS device +2. Tap the file to open it +3. iOS will prompt to review the profile +4. Go to Settings → General → VPN & Device Management +5. Tap on "VibeTunnel Debug Logging" +6. Tap "Install" and enter your passcode +7. Restart the VibeTunnel app + +## Verification + +After installation, logs should show full details: +```bash +# macOS - using vtlog script +./scripts/vtlog.sh + +# iOS - in Xcode console or Console.app +# You should see actual values instead of +``` + +## Removal + +### macOS +1. System Settings → Privacy & Security → Profiles +2. Select "VibeTunnel Debug Logging" +3. Click the minus (-) button +4. Confirm removal + +### iOS +1. Settings → General → VPN & Device Management +2. Tap "VibeTunnel Debug Logging" +3. Tap "Remove Profile" +4. Enter passcode to confirm + +## Security Note + +This profile enables detailed logging which may include sensitive information. Only install on development devices and remove when no longer needed for debugging. + +## Technical Details + +The profile configures logging for all VibeTunnel subsystems: + +### macOS +- `sh.vibetunnel.vibetunnel` - Main macOS app and all components +- `sh.vibetunnel.vibetunnel.debug` - Debug builds +- `sh.vibetunnel.vibetunnel.tests` - Test suite +- `sh.vibetunnel.vibetunnel.tests.debug` - Debug test builds + +### iOS +- `sh.vibetunnel.vibetunnel-mobile` - Main iOS app bundle ID +- `sh.vibetunnel.ios` - Alternative iOS bundle ID (used in services) +- `sh.vibetunnel.ios.tests` - iOS test suite + +All subsystems are configured to: +- Enable at Debug level +- Persist at Debug level +- Show private data (no `` redaction) \ No newline at end of file diff --git a/apple/logging/VibeTunnel-Logging.mobileconfig b/apple/logging/VibeTunnel-Logging.mobileconfig new file mode 100644 index 00000000..fa841c76 --- /dev/null +++ b/apple/logging/VibeTunnel-Logging.mobileconfig @@ -0,0 +1,138 @@ + + + + + PayloadContent + + + PayloadType + com.apple.system.logging + PayloadIdentifier + sh.vibetunnel.logging.all + PayloadUUID + A7B8C9D0-1234-5678-9ABC-DEF012345678 + PayloadVersion + 1 + PayloadDisplayName + VibeTunnel Logging Configuration + PayloadDescription + Enables private data in logs for all VibeTunnel apps and components + Subsystems + + + sh.vibetunnel.vibetunnel + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + sh.vibetunnel.vibetunnel.debug + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + sh.vibetunnel.vibetunnel.tests + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + sh.vibetunnel.vibetunnel.tests.debug + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + sh.vibetunnel.vibetunnel-mobile + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + sh.vibetunnel.ios + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + sh.vibetunnel.ios.tests + + DEFAULT-OPTIONS + + Level + + Enable + Debug + Persist + Debug + + + + + + + PayloadIdentifier + sh.vibetunnel.logging + PayloadUUID + C9D0E1F2-3456-7890-1CDE-F23456789012 + PayloadType + Configuration + PayloadVersion + 1 + PayloadDisplayName + VibeTunnel Debug Logging + PayloadDescription + Enables full debug logging with private data visibility for VibeTunnel applications. Install this profile to see complete log details instead of <private> tags. + PayloadOrganization + VibeTunnel + + \ No newline at end of file diff --git a/ios/README.md b/ios/README.md index 98967541..b7be5d12 100644 --- a/ios/README.md +++ b/ios/README.md @@ -164,7 +164,7 @@ vtlog | grep ServerConfig vtlog -v # Monitor specific subsystem -vtlog --subsystem sh.vibetunnel.vibetunnel +vtlog --subsystem sh.vibetunnel.ios ``` ### Code Quality diff --git a/ios/VibeTunnel-iOS.xcodeproj/project.pbxproj b/ios/VibeTunnel-iOS.xcodeproj/project.pbxproj index 58564d07..d6caeb00 100644 --- a/ios/VibeTunnel-iOS.xcodeproj/project.pbxproj +++ b/ios/VibeTunnel-iOS.xcodeproj/project.pbxproj @@ -333,7 +333,7 @@ ENABLE_TESTING_FRAMEWORKS = YES; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 18.0; - PRODUCT_BUNDLE_IDENTIFIER = "sh.vibetunnel.VibeTunnelTests-Mobile"; + PRODUCT_BUNDLE_IDENTIFIER = "sh.vibetunnel.ios.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_VERSION = 6.0; @@ -426,7 +426,7 @@ ENABLE_TESTING_FRAMEWORKS = YES; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 18.0; - PRODUCT_BUNDLE_IDENTIFIER = "sh.vibetunnel.VibeTunnelTests-Mobile"; + PRODUCT_BUNDLE_IDENTIFIER = "sh.vibetunnel.ios.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; SWIFT_VERSION = 6.0; diff --git a/ios/VibeTunnel/Resources/Info.plist b/ios/VibeTunnel/Resources/Info.plist index 59927c4f..e8bfd8e0 100644 --- a/ios/VibeTunnel/Resources/Info.plist +++ b/ios/VibeTunnel/Resources/Info.plist @@ -78,7 +78,7 @@ vibetunnel CFBundleURLName - com.vibetunnel.app + sh.vibetunnel.ios CFBundleDocumentTypes diff --git a/ios/VibeTunnel/Services/KeychainService.swift b/ios/VibeTunnel/Services/KeychainService.swift index 81d0eb1d..66b90df8 100644 --- a/ios/VibeTunnel/Services/KeychainService.swift +++ b/ios/VibeTunnel/Services/KeychainService.swift @@ -4,7 +4,7 @@ import Security /// Service for securely storing credentials in the iOS Keychain. /// Provides secure storage and retrieval of passwords and tokens. class KeychainService: KeychainServiceProtocol { - private let serviceName = "com.vibetunnel.ios" + private let serviceName = "sh.vibetunnel.ios" /// Errors that can occur during keychain operations. /// Provides specific error cases for keychain failures. diff --git a/ios/VibeTunnel/Utils/Logger.swift b/ios/VibeTunnel/Utils/Logger.swift index 5c5f2628..1127accc 100644 --- a/ios/VibeTunnel/Utils/Logger.swift +++ b/ios/VibeTunnel/Utils/Logger.swift @@ -42,8 +42,8 @@ struct Logger { init(category: String) { self.category = category - // Use the same subsystem as the Mac app for consistency - self.osLogger = os.Logger(subsystem: "sh.vibetunnel.vibetunnel", category: category) + // Use iOS-specific subsystem for proper log filtering + self.osLogger = os.Logger(subsystem: "sh.vibetunnel.ios", category: category) } func verbose(_ message: String) { diff --git a/ios/VibeTunnelTests/AuthenticationTests.swift b/ios/VibeTunnelTests/AuthenticationTests.swift index f5a91bc8..50056659 100644 --- a/ios/VibeTunnelTests/AuthenticationTests.swift +++ b/ios/VibeTunnelTests/AuthenticationTests.swift @@ -300,14 +300,14 @@ struct AuthenticationTests { } let item = KeychainItem( - service: "com.vibetunnel.app", + service: "sh.vibetunnel.ios", account: "user-token", data: "secret-token".data(using: .utf8)!, accessGroup: nil ) #expect(item.query[kSecClass as String] as? String == kSecClassGenericPassword as String) - #expect(item.query[kSecAttrService as String] as? String == "com.vibetunnel.app") + #expect(item.query[kSecAttrService as String] as? String == "sh.vibetunnel.ios") #expect(item.query[kSecAttrAccount as String] as? String == "user-token") } diff --git a/ios/VibeTunnelTests/FileSystemTests.swift b/ios/VibeTunnelTests/FileSystemTests.swift index ae1820b0..68257b65 100644 --- a/ios/VibeTunnelTests/FileSystemTests.swift +++ b/ios/VibeTunnelTests/FileSystemTests.swift @@ -257,7 +257,7 @@ struct FileSystemTests { @Test("Sandbox path validation") func sandboxPaths() { struct SandboxValidator { - let appGroupIdentifier = "group.com.vibetunnel" + let appGroupIdentifier = "group.sh.vibetunnel" var documentsDirectory: String { "~/Documents" diff --git a/ios/scripts/vtlog.sh b/ios/scripts/vtlog.sh index 04c6af29..60d0af20 100755 --- a/ios/scripts/vtlog.sh +++ b/ios/scripts/vtlog.sh @@ -6,7 +6,7 @@ set -euo pipefail # Configuration -SUBSYSTEM="sh.vibetunnel.vibetunnel" +SUBSYSTEM="sh.vibetunnel.ios" DEFAULT_LEVEL="info" # Colors for output diff --git a/mac/VibeTunnel-Mac.xcodeproj/project.pbxproj b/mac/VibeTunnel-Mac.xcodeproj/project.pbxproj index 6546d8be..e05c68f5 100644 --- a/mac/VibeTunnel-Mac.xcodeproj/project.pbxproj +++ b/mac/VibeTunnel-Mac.xcodeproj/project.pbxproj @@ -512,7 +512,7 @@ GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = sh.vibetunnel.vibetunnelTests.debug; + PRODUCT_BUNDLE_IDENTIFIER = sh.vibetunnel.vibetunnel.tests.debug; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VibeTunnel.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/VibeTunnel"; @@ -529,7 +529,7 @@ GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = sh.vibetunnel.vibetunnelTests; + PRODUCT_BUNDLE_IDENTIFIER = sh.vibetunnel.vibetunnel.tests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VibeTunnel.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/VibeTunnel"; diff --git a/web/src/client/styles.css b/web/src/client/styles.css index 7bd6dfad..5afef3f5 100644 --- a/web/src/client/styles.css +++ b/web/src/client/styles.css @@ -2107,8 +2107,8 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n + /* Custom styling */ width: 1rem; height: 1rem; - background-color: rgb(var(--color-bg-primary)); - border: 2px solid rgb(var(--color-border) / 0.5); + background-color: var(--color-bg); + border: 2px solid color-mix(in srgb, var(--color-border) 50%, transparent); border-radius: 3px; position: relative; cursor: pointer; @@ -2122,14 +2122,14 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n + /* Hover state */ .session-toggle-checkbox:hover:not(:checked) { - border-color: rgb(var(--color-border)); - background-color: rgb(var(--color-bg-secondary)); + border-color: var(--color-border); + background-color: var(--color-bg-secondary); } /* Checked state */ .session-toggle-checkbox:checked { - background-color: rgb(var(--color-primary) / 0.15); - border-color: rgb(var(--color-primary) / 0.5); + background-color: color-mix(in srgb, var(--color-primary) 15%, transparent); + border-color: color-mix(in srgb, var(--color-primary) 50%, transparent); } /* Checkmark using pseudo-element */ @@ -2139,7 +2139,7 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n + height: 0.5rem; transform: scale(0); transition: transform 0.15s ease-in-out; - background-color: rgb(var(--color-primary)); + background-color: var(--color-primary); /* Create checkmark shape using clip-path */ clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%); @@ -2153,10 +2153,10 @@ body.initial-session-load .session-flex-responsive > session-card:nth-child(n + /* Focus state */ .session-toggle-checkbox:focus { outline: none; - box-shadow: 0 0 0 2px rgb(var(--color-primary) / 0.25); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 25%, transparent); } /* Focus visible for keyboard navigation */ .session-toggle-checkbox:focus-visible { - box-shadow: 0 0 0 2px rgb(var(--color-primary) / 0.4); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 40%, transparent); } \ No newline at end of file