Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0ab2ab6
First Draft Revision of Docs (#268)
leogdion Apr 29, 2026
d7b1a21
MistDemo improvements: test split, CRUD, auth fix, native app (#271) …
leogdion Apr 30, 2026
d53467a
CI Updates for May 2026 (#277)
leogdion May 4, 2026
9709f3d
Replace custom AsyncChannel with swift-async-algorithms (#280)
leogdion May 5, 2026
8b21425
Refactor IntegrationTestRunner into protocol-based phase pipeline (#2…
leogdion May 6, 2026
5475bfa
MistDemo: --database flag + demo-errors command (closes #259, #269) (…
leogdion May 6, 2026
ae1af15
Test suite improvements for v1.0.0-beta.1 (#286) (#287)
leogdion May 7, 2026
63a4e50
Move CloudKitResponseType default implementations to protocol extensi…
leogdion May 7, 2026
b0f00a7
Add operation classification and batch sync result tracking (#296)
leogdion May 7, 2026
f989fd1
Strengthen environment and database configuration validation (#293)
leogdion May 7, 2026
125dab5
Refactor AuthenticationMiddleware so each Authenticator applies itsel…
leogdion May 7, 2026
a0f0af9
updating example packages
leogdion May 7, 2026
f14e751
git subrepo push Examples/BushelCloud
leogdion May 7, 2026
7c4b678
git subrepo push Examples/CelestraCloud
leogdion May 7, 2026
c62bf44
Improve error handling: typed TokenManagerError and safe RecordOperat…
leogdion May 7, 2026
a1e2162
Add query pagination support with continuation markers (#306)
leogdion May 8, 2026
6f92a71
Resolve #308: docs refresh + CI fixes + sub-issues #165, #285 (#309)
leogdion May 8, 2026
b3626c0
Resolve #312: public+web-auth user-identity endpoints (#310, #311, #2…
leogdion May 9, 2026
7a5da7a
Fix CI failures + Claude review nits on PR #298 (v1.0.0-beta.1) (#322)
leogdion May 9, 2026
a28ab3c
Resolve #313: paginationLimitExceeded carries accumulated records (#326)
leogdion May 11, 2026
d65d20b
Resolve #330: interactive MistDemo (web toggle + native app refresh) …
leogdion May 14, 2026
418e2e4
Resolve #342: v1.0.0-beta.1 follow-ups (#341 #327 #321 #317) + CI fix…
leogdion May 14, 2026
f799128
Add MistDemo-Integration workflow for live CloudKit runs (#345)
leogdion May 15, 2026
7023a31
Fixed Nonisolated Web Auth Token (#347)
leogdion May 15, 2026
bce1f23
refactor!: prep for talk — shrink API, refactor auth, split OpenAPI (…
leogdion May 17, 2026
5bc403d
git subrepo push Examples/BushelCloud
leogdion May 17, 2026
4d60b19
git subrepo push Examples/CelestraCloud
leogdion May 17, 2026
eee0670
docs: sync README/CLAUDE examples to v1.0.0-beta.1 API; pin BushelClo…
leogdion May 17, 2026
24c8719
git subrepo push Examples/BushelCloud
leogdion May 17, 2026
de82483
git subrepo push Examples/CelestraCloud
leogdion May 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .claude/docs/data-sources-api-research.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,15 +386,15 @@ let createdAt: FieldValue = .date(Date())

// Reference to another record
let categoryRef: FieldValue = .reference(
FieldValue.Reference(
Reference(
recordName: "category-123",
action: nil // or "DELETE_SELF" for cascade delete
)
)

// Location
let location: FieldValue = .location(
FieldValue.Location(
Location(
latitude: 37.7749,
longitude: -122.4194
)
Expand Down
4 changes: 2 additions & 2 deletions .claude/docs/protocol-extraction-continuation.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,8 @@ struct XcodeVersionRecord: CloudKitRecord {
var version: String
var buildNumber: String
var releaseDate: Date
var swiftVersion: FieldValue.Reference // Reference to SwiftVersionRecord
var macOSVersion: FieldValue.Reference // Reference to another record
var swiftVersion: Reference // Reference to SwiftVersionRecord
var macOSVersion: Reference // Reference to another record

// Implement protocol requirements...
}
Expand Down
2 changes: 2 additions & 0 deletions .codefactor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
exclude:
- "Scripts/mermaid-to-pptx.py"
4 changes: 2 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Swift 6.2",
"image": "swift:6.2",
"name": "Swift 6.3",
"image": "swift:6.3",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": "false",
Expand Down
14 changes: 14 additions & 0 deletions .devcontainer/swift-6.1/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"version": "2.5.7",
"resolved": "ghcr.io/devcontainers/features/common-utils@sha256:dbf431d6b42d55cde50fa1df75c7f7c3999a90cde6d73f7a7071174b3c3d0cc4",
"integrity": "sha256:dbf431d6b42d55cde50fa1df75c7f7c3999a90cde6d73f7a7071174b3c3d0cc4"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "1.3.5",
"resolved": "ghcr.io/devcontainers/features/git@sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251",
"integrity": "sha256:27905dc196c01f77d6ba8709cb82eeaf330b3b108772e2f02d1cd0d826de1251"
}
}
}
15 changes: 0 additions & 15 deletions .devcontainer/swift-6.3-nightly/devcontainer.json

This file was deleted.

32 changes: 32 additions & 0 deletions .devcontainer/swift-6.3/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "Swift 6.3",
"image": "swift:6.3",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": "false",
"username": "vscode",
"upgradePackages": "false"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "os-provided",
"ppa": "false"
}
},
"postStartCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"customizations": {
"vscode": {
"settings": {
"lldb.library": "/usr/lib/liblldb.so"
},
"extensions": [
"sswg.swift-lang"
]
}
},
"remoteUser": "root"
}
29 changes: 29 additions & 0 deletions .github/actions/setup-tools/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Setup mise tools
description: >-
Restore (or build + save) the mise tool cache and put the binaries on PATH.
Implemented as a composite action so the cache scope is the caller job's
scope — reusable workflows scope caches separately, which silently breaks
hand-off between a setup job and a consumer lint job.

runs:
using: composite
steps:
- name: Cache mise tools
id: mise-cache
uses: actions/cache@v4
with:
path: ~/.local/share/mise/installs
key: mise-v2-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('mise.toml') }}
restore-keys: |
mise-v2-${{ runner.os }}-${{ runner.arch }}-
- name: Install mise tools (cache miss)
if: steps.mise-cache.outputs.cache-hit != 'true'
uses: jdx/mise-action@v4
with:
cache: false
- name: Configure PATH for cached mise tools
if: steps.mise-cache.outputs.cache-hit == 'true'
uses: jdx/mise-action@v4
with:
install: false
cache: false
203 changes: 203 additions & 0 deletions .github/workflows/MistDemo-Integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# MistDemo Integration Runs
#
# Live end-to-end runs against the real CloudKit container
# (iCloud.com.brightdigit.MistDemo). Triggered on push to main and
# release branches, and via manual workflow_dispatch (used to re-run
# after rotating CLOUDKIT_WEB_AUTH_TOKEN).
#
# Required repo secrets:
# CLOUDKIT_API_TOKEN - Web Services API token
# CLOUDKIT_WEB_AUTH_TOKEN - Web-auth token (rotate when stale; manual)
# CLOUDKIT_KEY_ID - Server-to-server key ID
# CLOUDKIT_PRIVATE_KEY_BASE64 - Server-to-server PEM, base64-encoded
# (base64 -w0 key.pem)
# CLOUDKIT_CONTAINER_ID - iCloud.com.brightdigit.MistDemo
#
# Two-job design:
# 1) `build` runs in `swift:6.3-noble`, installs the Swift Static
# Linux SDK (musl), and produces a self-contained statically
# linked mistdemo binary.
# 2) `integration` runs on plain `ubuntu-24.04` (no Swift toolchain,
# no LD_LIBRARY_PATH needed) and executes the live CloudKit
# phases against the static binary.
#
# Secrets are NOT exposed to fork pull requests — there is no
# pull_request trigger on this workflow by design.

name: MistDemo Integration

on:
push:
branches:
- main
- 'v*.*.*'
workflow_dispatch:

concurrency:
group: mistdemo-integration-${{ github.ref }}
cancel-in-progress: false

jobs:
build:
name: Build static mistdemo
runs-on: ubuntu-24.04
# Pin to an exact Swift patch — the Static Linux SDK URL + checksum
# below are tied to this same version. Bump together.
container: swift:6.3.2-noble
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
timeout-minutes: 45
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v6

- name: Install Swift Static Linux SDK
run: |
set -euo pipefail
swift sdk install \
https://download.swift.org/swift-6.3.2-release/static-sdk/swift-6.3.2-RELEASE/swift-6.3.2-RELEASE_static-linux-0.1.0.artifactbundle.tar.gz \
--checksum 3fd798bef6f4408f1ea5a6f94ce4d4052830c4326ab85ebc04f983f01b3da407
swift sdk list

- name: swift build --swift-sdk x86_64-swift-linux-musl -c release
working-directory: Examples/MistDemo
run: swift build -c release --swift-sdk x86_64-swift-linux-musl

- name: Verify static linkage
working-directory: Examples/MistDemo
run: |
set -euo pipefail
BIN=.build/x86_64-swift-linux-musl/release/mistdemo
ls -lh "$BIN"
# A statically linked binary either reports "not a dynamic
# executable" (musl) or "statically linked" (glibc). Anything
# else means we picked up shared deps and broke the goal.
LDD_OUTPUT=$(ldd "$BIN" 2>&1 || true)
echo "$LDD_OUTPUT"
if ! echo "$LDD_OUTPUT" | grep -qE 'not a dynamic executable|statically linked'; then
echo "::error::Binary has dynamic dependencies; static link failed"
exit 1
fi

- uses: actions/upload-artifact@v4
with:
name: mistdemo
path: Examples/MistDemo/.build/x86_64-swift-linux-musl/release/mistdemo
retention-days: 1
# Single executable; default zip compression is fine.

integration:
name: Live CloudKit Integration
needs: build
runs-on: ubuntu-24.04
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
timeout-minutes: 30
defaults:
run:
shell: bash
steps:
- uses: actions/download-artifact@v4
with:
name: mistdemo

- name: Prep binary
run: |
set -euo pipefail
chmod +x ./mistdemo
mkdir -p integration-logs
# Smoke check the binary before touching the network.
./mistdemo --help >/dev/null

- name: Decode server-to-server private key
env:
CLOUDKIT_PRIVATE_KEY_BASE64: ${{ secrets.CLOUDKIT_PRIVATE_KEY_BASE64 }}
run: |
set -euo pipefail
KEY_PATH="$RUNNER_TEMP/cloudkit_s2s.pem"
printf '%s' "$CLOUDKIT_PRIVATE_KEY_BASE64" | base64 -d > "$KEY_PATH"
chmod 600 "$KEY_PATH"
# Defensive: mask the decoded PEM line-by-line so it can never
# land in step logs.
while IFS= read -r line; do
[ -n "$line" ] && echo "::add-mask::$line"
done < "$KEY_PATH"
echo "CLOUDKIT_PRIVATE_KEY_PATH=$KEY_PATH" >> "$GITHUB_ENV"

- name: test-public
timeout-minutes: 10
env:
CLOUDKIT_API_TOKEN: ${{ secrets.CLOUDKIT_API_TOKEN }}
CLOUDKIT_KEY_ID: ${{ secrets.CLOUDKIT_KEY_ID }}
CLOUDKIT_CONTAINER_ID: ${{ secrets.CLOUDKIT_CONTAINER_ID }}
CLOUDKIT_ENVIRONMENT: development
run: |
set -o pipefail
./mistdemo test-public \
--record-count 5 \
--asset-size 50 \
2>&1 | tee integration-logs/test-public.log

- name: test-private
timeout-minutes: 10
env:
CLOUDKIT_API_TOKEN: ${{ secrets.CLOUDKIT_API_TOKEN }}
CLOUDKIT_WEB_AUTH_TOKEN: ${{ secrets.CLOUDKIT_WEB_AUTH_TOKEN }}
CLOUDKIT_CONTAINER_ID: ${{ secrets.CLOUDKIT_CONTAINER_ID }}
CLOUDKIT_ENVIRONMENT: development
run: |
set -o pipefail
./mistdemo test-private \
--record-count 5 \
--asset-size 50 \
2>&1 | tee integration-logs/test-private.log

- name: demo-errors
timeout-minutes: 10
env:
CLOUDKIT_API_TOKEN: ${{ secrets.CLOUDKIT_API_TOKEN }}
CLOUDKIT_WEB_AUTH_TOKEN: ${{ secrets.CLOUDKIT_WEB_AUTH_TOKEN }}
CLOUDKIT_KEY_ID: ${{ secrets.CLOUDKIT_KEY_ID }}
CLOUDKIT_CONTAINER_ID: ${{ secrets.CLOUDKIT_CONTAINER_ID }}
CLOUDKIT_ENVIRONMENT: development
run: |
set -o pipefail
./mistdemo demo-errors --scenario all \
2>&1 | tee integration-logs/demo-errors.log
# demo-errors exits 0 by design — assert all scenarios actually
# ran by checking for the per-scenario completion markers.
for marker in "401" "404" "409"; do
grep -q "$marker" integration-logs/demo-errors.log || {
echo "::error::demo-errors did not exercise scenario $marker"
exit 1
}
done

- name: demo-in-filter
timeout-minutes: 10
env:
CLOUDKIT_API_TOKEN: ${{ secrets.CLOUDKIT_API_TOKEN }}
CLOUDKIT_WEB_AUTH_TOKEN: ${{ secrets.CLOUDKIT_WEB_AUTH_TOKEN }}
CLOUDKIT_KEY_ID: ${{ secrets.CLOUDKIT_KEY_ID }}
CLOUDKIT_CONTAINER_ID: ${{ secrets.CLOUDKIT_CONTAINER_ID }}
CLOUDKIT_ENVIRONMENT: development
run: |
set -o pipefail
./mistdemo demo-in-filter \
2>&1 | tee integration-logs/demo-in-filter.log

- name: Upload integration logs
if: always()
uses: actions/upload-artifact@v4
with:
name: integration-logs
path: integration-logs/
retention-days: 14
if-no-files-found: warn

- name: Cleanup decoded private key
if: always()
run: |
if [ -n "${CLOUDKIT_PRIVATE_KEY_PATH:-}" ] && [ -f "$CLOUDKIT_PRIVATE_KEY_PATH" ]; then
rm -f "$CLOUDKIT_PRIVATE_KEY_PATH"
fi
Loading
Loading