> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chappiesdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Chappie SDK Security Model, Boundaries, and Hardening

> Understand Chappie's on-device credential storage, token exposure boundaries, privacy manifest, transcript file protection, and hardening recommendations.

Chappie is a pure in-process Swift SDK — credentials and conversation data stay on the user's device. There is no intermediate Chappie proxy server. Requests travel directly from the user's device to the ChatGPT/Codex backend, and credentials are stored only in the device Keychain.

## Trust boundary

Chappie connects directly from the user's device to the ChatGPT/Codex backend using credentials that the user established through the OAuth device flow. There is no Chappie cloud service, no relay, and no server-side credential custody. This means:

* Credential refresh happens on-device without any Chappie intermediary.
* Conversation content is never routed through Chappie infrastructure.
* Your users' ChatGPT credentials never leave the device (unless the user opts in to iCloud Keychain sync, which the default accessibility level prevents).

<Note>
  A pure in-process SDK cannot make credentials impossible for a hostile host app to obtain. The SDK runs inside the host app process and uses the host app's Keychain entitlement context. Keychain storage prevents accidental leakage and protects against other apps, but it is not a trust boundary between an app and a framework loaded inside that app.
</Note>

## What Chappie does not expose

Chappie's public API never surfaces raw OAuth tokens, refresh tokens, ID tokens, or authorization headers to host app code. The two primary SDK objects expose only safe, derived data:

| Object               | What it exposes                                                                                               |
| -------------------- | ------------------------------------------------------------------------------------------------------------- |
| `ChappieAuthSession` | Auth state enum (`.signedIn`, `.signedOut`, etc.) and `ChappieAccountInfo` (email, user ID, account ID, plan) |
| `ChappieClient`      | Response text, streaming events, usage limits, model list, account metadata                                   |

This design prevents accidental logging or network transmission of bearer-token material through app code.

## Credential refresh and reauthentication

Chappie refreshes expired tokens automatically before every request and retries once on an unexpected `401` after refreshing. Your app never needs to manage token refresh manually. When Chappie cannot refresh silently — because the refresh token is missing, or the token endpoint returns `400`, `401`, or `403` — it surfaces the `ChappieAuthState.reauthenticationRequired` state on the auth session. Handle this state by showing your sign-in UI:

```swift theme={null}
switch authSession.state {
case .reauthenticationRequired:
    showSignInSheet()
default:
    break
}
```

The corresponding error type is `ChappieAuthError` with `requiresReauthentication == true` for `.missingRefreshToken` and `.tokenExchangeFailed` with those status codes.

## Keychain storage

Credentials are stored as a generic-password Keychain item with the following defaults:

* **Accessibility:** `kSecAttrAccessibleWhenUnlockedThisDeviceOnly` — the item is readable only while the device is unlocked and never migrates to another device, iCloud Keychain, or a backup.
* **Service:** `"com.chappie.sdk"` — change this to your own reverse-DNS identifier via `ChappieConfiguration.keychainService`.

Apps that need background credential access can opt in to `ChappieKeychainAccessibility.afterFirstUnlockThisDeviceOnly`, but foreground-only apps should keep the default.

## Privacy manifest

The SDK bundles `PrivacyInfo.xcprivacy` inside the `ChappieSDK` package target. It declares:

* **Collected data type:** Linked account identifiers and email, used for app functionality.
* **Tracking:** None. No tracking domains are declared.

Review the manifest before App Store distribution and update it if your integration of the SDK introduces additional data collection or uses required-reason APIs.

## Transcript storage (ChappieSDKRuntime)

`ChappieFileThreadStore` persists complete `ChappieThread` JSON to the app support directory. That JSON can contain user input text, assistant output text, tool-call argument payloads, tool outputs, raw API payloads, runtime errors, and compaction summaries. The file store does **not** redact or classify content.

The default storage policy applies these filesystem controls automatically:

<Steps>
  <Step title="Backup exclusion">
    Transcript directories and JSON files are excluded from iCloud and iTunes device backups.
  </Step>

  <Step title="iOS file protection">
    Transcript directories and files use `NSFileProtectionComplete` on iOS, so they are inaccessible while the device is locked.
  </Step>

  <Step title="macOS sandbox">
    On macOS, Chappie relies on the app sandbox and platform filesystem protections. There is no macOS equivalent to iOS Data Protection classes.
  </Step>
</Steps>

If your app should not persist specific fields (for example, sensitive tool arguments or PII in user messages), redact those fields before saving or implement a custom `ChappieThreadStore` that filters content at write time.

Apps that need to read transcripts in the background before the device is unlocked can choose a less restrictive file-protection level:

```swift theme={null}
import ChappieSDKRuntime

let store = ChappieFileThreadStore(
    storagePolicy: ChappieFileThreadStoreStoragePolicy(
        fileProtection: .completeUntilFirstUserAuthentication
    )
)
```

## Harness guardrail

The default `ChappieHarness.default` includes system instructions that prevent the model from presenting itself as the Codex desktop app or other Codex surfaces. This keeps the assistant clearly scoped to your app's context and avoids product boundary confusion for users.

## Product boundary

Chappie's product shape is an in-app harness for interacting with OpenAI/ChatGPT directly. It is not a local Codex Desktop control-plane client, a JSON-RPC app-server, or a third-party proxy API. Apps that need server-side custody of OpenAI credentials should build that as a separate backend product outside the SDK.

## Production hardening checklist

<CardGroup cols={2}>
  <Card title="Keep default Keychain accessibility" icon="lock">
    Use `.whenUnlockedThisDeviceOnly` unless you have a confirmed background-access requirement. It prevents credential migration and restricts readability to foreground contexts.
  </Card>

  <Card title="Link ChappieSDKRuntime only if needed" icon="database">
    `ChappieSDKRuntime` adds file-backed transcript storage. If your app does not need durable conversation history, omit it to reduce your attack surface.
  </Card>

  <Card title="Redact before storing" icon="eye-slash">
    If you use a custom `ChappieThreadStore` or inspect thread JSON, redact PII and sensitive tool arguments before they reach persistent storage.
  </Card>

  <Card title="Use distinct Keychain accounts" icon="people-group">
    For multi-user apps, pass a stable per-user identifier as `keychainAccount` in `ChappieConfiguration`. Shared slots allow one user's credentials to overwrite another's.
  </Card>
</CardGroup>
