README.md

# CloudKit

Elixir client for the [Apple CloudKit Web Services API](https://developer.apple.com/documentation/cloudkit/).

This package targets the server-side CloudKit API for public database operations such as:

- querying records
- creating, updating, and deleting records
- listing and managing zones
- listing and managing subscriptions
- uploading and downloading assets

## Installation

Add to your `mix.exs`:

```elixir
defp deps do
  [
    {:cloud_kit, "~> 0.1.0"}
  ]
end
```

## Configuration

```elixir
config :cloud_kit,
  container_id: System.get_env("CLOUDKIT_CONTAINER_ID"),
  environment: System.get_env("CLOUDKIT_ENVIRONMENT") || "development",
  server_key_id: System.get_env("CLOUDKIT_SERVER_KEY_ID"),
  private_key_path: System.get_env("CLOUDKIT_PRIVATE_KEY_PATH")
```

Supported options:

- `container_id` - iCloud container identifier
- `environment` - `development` or `production`
- `server_key_id` - CloudKit server-to-server key ID
- `private_key` - inline private key contents
- `private_key_path` - path to the private key file
- `base_url` - defaults to `https://api.apple-cloudkit.com`
- `req_options` - forwarded to `Req`

## Quick Start

```elixir
# List public zones
{:ok, zones} = CloudKit.list_zones()

# Query records
{:ok, result} = CloudKit.query_records(%{recordType: "Items", limit: 10})

# Create a record
{:ok, result} =
  CloudKit.create_record(%{
    recordType: "Items",
    fields: %{
      name: %{value: "Widget"}
    }
  })

# Fetch a record by name
{:ok, record} = CloudKit.fetch_record("record-name")
```

## Assets

```elixir
{:ok, upload} = CloudKit.upload_asset("/path/to/image.png", "Items", "image")
{:ok, binary} = CloudKit.download_asset(download_url)
```

## Auth Model

CloudKit is different from the other Apple clients in this workspace:

- it uses a CloudKit server key
- requests are signed with CloudKit-specific headers
- it does not use a normal bearer JWT flow for record operations

## Live Testing

```bash
cd cloud_kit
source .env && elixir test_live.exs
```

That script validates the key and lists public zones.

## Notes

- The high-level API currently targets the public database paths.
- Your CloudKit container must already be provisioned in Apple’s dashboard.
- Asset upload is a two-step flow: request upload URL, then upload file bytes.

## License

MIT