Security Best Practices for Palmier Pro Developers: A Complete Guide to Safe Swift Code

Store all sensitive credentials in the macOS Keychain via KeychainStore, gate debug environment variables behind #if DEBUG checks, enforce HTTPS for every network request, and mark sensitive data as private in logs to prevent accidental exposure in the Palmier Pro codebase.

Palmier Pro handles sensitive user data including API keys, JWT authentication tokens, and user-generated content. The palmier-io/palmier-pro repository implements several security-focused patterns that developers must extend when building new features. This guide extracts the existing safeguards from the Swift source code and shows how to apply them consistently across the project.

Secure Credential Storage with KeychainStore

The KeychainStore class in Sources/PalmierPro/Utilities/KeychainStore.swift provides the central mechanism for secret storage, wrapping native macOS Keychain Services (SecItemAdd, SecItemUpdate, SecItemCopyMatching, and SecItemDelete). This approach keeps secrets out of plain-text files and leverages the system’s encrypted storage, which respects the user’s lock screen and Keychain access controls.

Never Hard-Code Secrets or Use UserDefaults

Hard-coding API keys in source files or storing them in UserDefaults exposes credentials to anyone with access to the device filesystem or a process dump. The Palmier Pro codebase strictly avoids these patterns by requiring all credentials to pass through the Keychain abstraction.

Implementing a Type-Safe Keychain Wrapper

Create a dedicated enum for each service to encapsulate the account name and provide type-safe access methods. This mirrors the AnthropicKeychain pattern found in Sources/PalmierPro/Agent/Clients/AnthropicClient.swift.

// Example: Save a third‑party API key safely
enum MyServiceKeychain {
    private static let account = "my‑service‑api‑key"

    static func save(_ key: String) {
        KeychainStore.save(key, account: account)
    }

    static func load() -> String? {
        #if DEBUG
        // Allow a developer to override with an env var during CI / local testing
        if let env = ProcessInfo.processInfo.environment["MY_SERVICE_API_KEY"]?
            .trimmingCharacters(in: .whitespacesAndNewlines),
           !env.isEmpty {
            return env
        }
        #endif
        return KeychainStore.load(account: account)
    }

    static func delete() {
        KeychainStore.delete(account: account)
    }
}

Isolate Debug Overrides with Conditional Compilation

The AnthropicClient.swift file demonstrates how to handle local development overrides without risking production leaks. In the load() method (lines 15-23), the code checks for an environment variable only inside a #if DEBUG block, ensuring that production builds never accidentally read from ProcessInfo.processInfo.environment.

Always keep debug-only shortcuts behind #if DEBUG directives. Never ship production keys via environment variables or allow release builds to fall back to unsecured configuration sources.

Enforce Transport Security and HTTPS

All network calls in Palmier Pro use URLRequest with explicit HTTPS endpoints, such as https://api.anthropic.com and BackendConfig.convexHttpURL as seen in Sources/PalmierPro/Agent/Clients/AnthropicClient.swift (lines 37-70) and Sources/PalmierPro/Agent/Clients/PalmierClient.swift (lines 30-48). This guarantees confidentiality and integrity of data in transit.

Never fall back to HTTP when implementing new clients. If you must add custom networking layers, validate certificates explicitly and avoid disabling App Transport Security checks.

Handle Authentication Tokens Safely

The PalmierClient class obtains short-lived JWTs from Clerk.shared.session and injects them as Bearer tokens in the Authorization header. According to Sources/PalmierPro/Agent/Clients/PalmierClient.swift (lines 36-48), the code requests a fresh token per session and never persists the JWT to disk in plain text.

Follow this pattern for any new authenticated service: request a fresh token for each session, verify the session status is .active, and store transient credentials in memory only. Never write JWTs to logs or cache them in user-accessible storage.

Logging Hygiene and Privacy Controls

The Log.swift utility (lines 58-80) supports SwiftLog privacy levels that control redaction in the macOS Console. By default, the codebase uses privacy: .public for many messages, which could unintentionally expose user data or internal state.

Switch to privacy: .private for any interpolated value that might contain sensitive information, such as API keys, JWTs, or personal identifiers.

// Bad – logs the raw token (public)
Log.agent.debug("Using token: \(jwt)")

// Good – keep the token private
Log.agent.debug("Using token: \(jwt, privacy: .private)")

Only log sanitized, non-identifying strings publicly. Review the Log.swift implementation when adding new log statements to ensure sensitive parameters are explicitly marked private.

Crash Reporting and Error Handling

Crash data is written to a user-accessible file at ~/Library/Logs/PalmierPro/crash.log rather than system logs, as implemented in Sources/PalmierPro/Utilities/Log.swift (lines 23-25). This keeps diagnostics available for debugging without exposing them to other processes that might read the unified logging system.

Errors are transformed into user-friendly messages while preserving the original error chain (lines 26-40). Never expose raw NSError details, stack traces, or internal file paths to the UI; map all errors to safe, localized strings before presenting them to end-users. Avoid sending raw crash dumps to external services without explicit user consent.

Distribution and Code Signing Considerations

Palmier Pro distributes as a Developer ID signed, non-sandboxed application for macOS 26. While the non-sandboxed status allows broader filesystem access, developers should minimize requested permissions and document them clearly in the bundle’s Info.plist. Request only the entitlements and file system access truly necessary for the feature being implemented.

Maintain the existing code-signing workflow to ensure users can verify the binary’s authenticity and integrity. When adding new dependencies in Package.swift, audit them for insecure transitive libraries or unnecessary network capabilities.

Summary

  • Use KeychainStore via Sources/PalmierPro/Utilities/KeychainStore.swift for all API keys, tokens, and credentials; never hard-code secrets or use UserDefaults.
  • Gate debug overrides behind #if DEBUG blocks to prevent shipping test configurations to production.
  • Enforce HTTPS for all URLRequest instances and avoid HTTP fallbacks or insecure certificate validation.
  • Request fresh JWTs per session using the Clerk pattern in PalmierClient.swift rather than storing persistent authentication tokens.
  • Mark sensitive data as privacy: .private in all log statements to prevent leakage in macOS Console.
  • Sanitize errors before UI presentation and keep crash logs in user-accessible directories with consent-based sharing.

Frequently Asked Questions

How should I store third-party API keys when extending Palmier Pro?

Always use the KeychainStore class located in Sources/PalmierPro/Utilities/KeychainStore.swift, which wraps the macOS Keychain Services (SecItemAdd, SecItemCopyMatching). Never store credentials in UserDefaults or hard-code them in the source. Create a type-safe wrapper enum that encapsulates the account name and provides static save(), load(), and delete() methods, following the AnthropicKeychain pattern.

Why does the codebase use #if DEBUG for API key configuration?

The AnthropicClient.swift file uses conditional compilation to allow environment variable overrides only in debug builds, preventing accidental shipment of production secrets. This pattern ensures that production releases always load credentials from the secure Keychain while still allowing developers to inject test keys during local development. Always wrap debug shortcuts in #if DEBUG blocks and never commit production keys to the repository.

How do I prevent sensitive tokens from appearing in macOS Console logs?

The Log.swift utility supports SwiftLog privacy levels; pass privacy: .private when interpolating sensitive values like JWTs or API keys. Avoid using privacy: .public for any data that could identify a user or reveal credentials. Sanitize all log messages to ensure that even .public logs contain only non-identifying metadata.

What transport layer security is enforced for network requests?

All network clients in Palmier Pro, including AnthropicClient and PalmierClient, use URLRequest with explicit HTTPS URLs to ensure encryption in transit. The codebase never falls back to HTTP and obtains fresh JWT tokens from Clerk for each session rather than persisting long-lived credentials. When implementing new services, always validate the HTTPS schema and avoid custom networking layers that might bypass certificate validation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →