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

> Discover Palmier Pro security best practices for safe Swift code. Secure your app by using KeychainStore, HTTPS, and careful logging to protect sensitive data.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: best-practices
- Published: 2026-06-21

---

**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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/Clients/AnthropicClient.swift).

```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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Agent/Clients/AnthropicClient.swift) (lines 37-70) and [`Sources/PalmierPro/Agent/Clients/PalmierClient.swift`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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.

```swift
// 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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/Package.swift), audit them for insecure transitive libraries or unnecessary network capabilities.

## Summary

- **Use `KeychainStore`** via [`Sources/PalmierPro/Utilities/KeychainStore.swift`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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`](https://github.com/palmier-io/palmier-pro/blob/main/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.