v1.0.0 beta.1#298
Conversation
|
Important Review skippedToo many files! This PR contains 300 files, which is 150 over the limit of 150. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (300)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #298 +/- ##
===========================================
+ Coverage 25.58% 59.85% +34.27%
===========================================
Files 95 532 +437
Lines 8232 19784 +11552
===========================================
+ Hits 2106 11842 +9736
- Misses 6126 7942 +1816
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Code Review: v1.0.0 beta.1This is a large, well-structured release covering CI modernization, example improvements, and library hardening. The overall quality is high — strong test coverage, strict linting, and solid concurrency safety. Below are the findings by area. Overview
Code Quality
Every internal func createQueryRecordsPath(containerIdentifier: String) -> Operations.queryRecords.Input.Path { ... }
internal func createLookupRecordsPath(containerIdentifier: String) -> Operations.lookupRecords.Input.Path { ... }
// ... 8 more identical methodsThese are compiler-safe but are a maintenance burden. If a field like
Potential Bugs
var misdirectedRequestResponse: Components.Responses.UnprocessableEntity? { get }The property is named for HTTP 421 (Misdirected Request) but the type is
public var hasCredentials: Bool {
get async { !apiToken.isEmpty }
}The protocol name implies "valid credentials available," but this only checks that the API token string is non-empty. An expired, malformed, or revoked token will return
PR #279's article code shows: } catch let error as CloudKitError where error.serverErrorCode == .authenticationRequired {
if let redirectURL = error.redirectURL {Neither Performance Considerations
The 11-element closure array is scanned linearly for every error response. At this scale it's not a practical concern, but because only one case can match per response type, a
This helper allocates a new array every call. Since it's used at manifest evaluation time only, this is harmless. But the formatter left inconsistent style in the trailing closure: result.removeAll{
$0 == platform // missing leading space, not 2-space indented
}
SecurityThe The CI/CD
The
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
Experimental Swift features in 20+ Test Coverage139 test files for 104 source files is an excellent ratio. The concurrent token refresh suite and the mock uploader infrastructure for asset upload tests are particularly well-designed. No gaps identified in the reviewed areas. Summary
The 421→422 status code mismatch is the item I'd most want to verify before tagging the release. Everything else is either documentation/cleanup or low-risk. |
Code Review: v1.0.0 beta.1This PR has 300+ changed files (43,756 additions / 24,212 deletions), which exceeds the GitHub diff API limit. A full line-by-line review isn't possible without cloning locally. For a release PR of this scope, I'd suggest:
If you'd like me to review specific files or subsystems from this PR, share the paths and I can dig in. Review by Claude Sonnet 4.6 |
Code Review — v1.0.0-beta.1 (#298)OverviewThis is a significant beta release bringing together multiple improvements merged via sub-PRs: typed Bugs
// AdaptiveTokenManager.swift
internal let storage: (any TokenStorage)? // stored, never written/read
if error.localizedDescription.contains("PEM")
|| error.localizedDescription.contains("format")
pushd $PACKAGE_DIR # breaks if PACKAGE_DIR contains spacesShould be Code Quality
Repeated Test CoveragePerformance suite is skeletal Pagination tests are success-only
CI / Scripts
if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
Security
Positives
Summary of Action Items
|
Code Review: v1.0.0 beta.1OverviewThis is a large release-candidate PR (~49k additions, ~25k deletions, 300+ files) touching three major areas:
Overall quality is high and patterns align well with project conventions. The issues below are refinements. IssuesBug: Wrong field used for error logging in
|
…rd returns CodeFactor reported 19 violations on PR #298: - `CredentialsTokenManagerTests.swift` (274 lines, 16× `conditional_returns_on_newline`): Convert the single suite struct into a namespace enum with four nested sub-suites (PublicDatabase, PrivateShared, UserContext, PrivateKeyLoad) following the existing `CloudKitServiceTests.FetchCaller` layout. Each `guard #available(...) else { return }` becomes multi-line. - `CloudKitError+OpenAPI.swift` (237 lines): Move the 11 per-response private initializers into a sibling `CloudKitError+OpenAPI+Responses.swift`. Bump them from `private` to `internal` so the extractor array in the main file can still call them. Also pick up filename-comment corrections in `OpenAPI/Components/*.swift` that `Scripts/header.sh` (part of `Scripts/lint.sh`) normalized — stale `+MistKit.swift` suffixes were trimmed to match the actual filenames. Verified: - `./Scripts/lint.sh` → 0 violations - `swift test --filter CredentialsTokenManagerTests` → 18 tests pass Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds tests that don't require live CloudKit access — covers the cheapest slice of the patch-coverage gap on PR #298 (codecov/patch: 13%). New test files (all @testable, no network): - Configuration/AuthTokenConfigTests.swift — memberwise init + parsed init via InMemoryProvider, including the missing/empty api.token error path - Configuration/UploadAssetConfigTests.swift — memberwise init for every field - Configuration/TestIntegrationConfigTests.swift — defaults + custom values - Configuration/TestPrivateConfigTests.swift — defaults + private-DB pinning - Commands/QueryCommand/QueryCommandTests+ParseFilter.swift — full coverage of parseFilter / inferFieldValue / shouldIncludeField / buildComparisonFilter (parameterized over every operator alias and error path) - Commands/CreateCommand/CreateCommandTests+GenerateRecordName.swift — prefix, three-part format, suffix range, distinctness across 200 calls - Commands/DemoErrorsRunnerOutputTests.swift — describe(_:) placeholder + echo Source changes are minimal seams that mirror the existing DeleteCommand.mapConflict pattern (internal-static for testability): - QueryCommand: filter parsing helpers extracted into QueryCommand+FilterParsing.swift; private → internal static - CreateCommand.generateRecordName: private → internal 901 MistDemo tests pass; lint + swift-format clean. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review
OverviewPR #298 ("v1.0.0 beta.1") is a large release PR that includes:
Positive Highlights
Issues and Suggestions1. Breaking availability change — needs changelog entry// Before
@available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
// After
@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)This is a breaking API change for any caller deployed on macOS 11 / iOS 14. The PR description and 2. Logging redaction regression riskFile: The original code had: MistKitLogger.logDebug(
"Unhandled response (HTTP \(statusCode)): \(response)",
logger: MistKitLogger.api,
shouldRedact: false // ← explicit
)The new code drops Redacting debug-level logs of unhandled CloudKit responses makes debugging new/unexpected error shapes harder. Consider keeping 3. Smoke tests don't assert anythingSeveral tests in @Test("printRunnerHeader does not throw")
internal func headerDoesNotThrow() async throws {
let runner = try await DemoErrorsRunner(config: MistDemoConfig())
runner.printRunnerHeader()
// No assertion
}If these methods print to stdout, capturing output (or even checking a return value where possible) would make these tests meaningful rather than just crash guards. For methods that truly have no observable output besides side effects, consider at minimum noting this limitation in the test name, e.g. 4. Force-unwrap in test fileFile: try json.data(using: .utf8)!.write(to: tmp)While try Data(json.utf8).write(to: tmp)5. Multi-line doc comment in test helperFile: The doc comment block (lines explaining // Keys are split on "." to form AbsoluteConfigKey components.
internal static func testing(
_ values: [String: ConfigValue]
) -> MistDemoConfiguration {6. Inconsistent smoke-test commentary
// Smoke test: type-check that the value is constructable.
_ = commandBut equivalent smoke tests in 7. PR title mismatchThe PR title "Update README with fixed serialization and integration test" does not match the actual changes (availability bumps, new test suite, logging changes). A more accurate title would help future SecurityNo security concerns found. The logging redaction change (item #2 above) is the closest thing — it actually increases default redaction, which is conservative. The risk is diagnostic, not security-related. Test Coverage AssessmentThe new config tests are thorough for the happy path and most error paths. One gap: there is no test verifying that SummaryThe PR is in good shape overall. The three items most worth addressing before merge are:
Everything else is low-priority style/polish. |
Code Review — v1.0.0 beta.1This is a large release-candidate PR (57k additions / 26k deletions, 1046 files) introducing the v1.0.0-beta.1 API surface, updated CI matrix, two new example apps (BushelCloud, CelestraCloud), and significant MistDemo expansion. Below is a structured review covering the six failing CI checks plus code-level findings. Failing Checks1. 🔴 BushelCloud Ubuntu — compile error (blocking)
Fix: Drop Bonus cleanup: The same job warns about unused public imports — these should be
2. 🔴 CelestraCloud Ubuntu — deprecation-as-error (blocking)Two call sites in Fix:
Bonus cleanup:
3. 🟡 watchOS Platforms — intermittent test failureThis is a simulator timing/scheduling issue — on the watchOS cooperative executor the inner Fix: Wrap the body of internal func cancelsOtherTasks() async throws {
await withKnownIssue(isIntermittent: true) {
await #expect(throws: AsyncTimeoutError.self) {
try await withTimeout(seconds: 0.1) {
try await Task.sleep(nanoseconds: 500_000_000)
return "done"
}
}
}
}4. 🔴 CodeQL — 2 high-severity "Cleartext logging of sensitive information"Both alerts point to Since these are debug-level paths that do go through
Optional: add a brief inline comment at the call sites pointing future reviewers to 5. 🟡 CodeFactor — transientThe check errored ("Something went wrong.", 0 annotations) — not an actionable finding. Re-running or re-pushing should clear it. 6. 🔴 codecov/patch — 15.61% vs 25.58% targetThe cheapest path to closing the gap (~144 more covered lines) is the Highest-ROI targets:
If closing the gap before beta.1 isn't realistic given the PR scope, an alternative is relaxing the codecov target on release branches ( Code-Level FindingsBug: Wrong field logged for batch errors in
|
Code Review — PR #298 (v1.0.0 beta.1)This is a large release-candidate PR (~57k additions, ~26k deletions across 300+ files) covering pagination, user-identity endpoints, authentication refactoring, new example-app features, and CI improvements. My review focused on the MistKit core, the BushelCloud and CelestraCloud examples, and the test suite. The diff was too large to retrieve in full, so I reviewed the key changed files directly from the branch. What Changed
Fixes Confirmed ✅The following issues flagged in the initial CI review have been addressed in the current HEAD:
Remaining IssuesSecurity
logger.debug(" Headers: \(request.headerFields)")
let safeHeaders = request.headerFields.filter { !$0.name.rawName.contains("CloudKit-Request") }
logger.debug(" Headers: \(safeHeaders)")Also CodeQL — Dismissal Still NeededThe two CodeQL Copyright Year Inconsistency
Test Coverage Gap
Design / Code Quality
|
Code Review — v1.0.0-beta.1 (PR #298)This is a large release-candidate merge (1,046 files, +57K/−26K lines, 25 commits) consolidating a significant wave of features and refactors. Overall the PR is in very good shape — almost every CI failure from the initial run has been resolved. CI Status
The Architecture / DesignPer-call credential resolution (
Cleartext-logging split (debug full body vs. warning type/status only) addresses the CodeQL finding cleanly without removing diagnostic value. Protocol-based Issues Confirmed FixedThe following items raised in prior review passes are confirmed resolved by reading the current source:
Remaining Items1.
|
subrepo: subdir: "Examples/BushelCloud" merged: "55f2092" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "55f2092" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f"
subrepo: subdir: "Examples/CelestraCloud" merged: "c44dc4f" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "c44dc4f" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f"
Code Review — PR #298: v1.0.0 beta.1
OverviewThis PR consolidates the v1.0.0 beta.1 milestone across three areas:
The core MistKit library ( Findings🔴 Missing PR description 🟡 Low patch coverage (18.68% per Codecov)
For a beta-1 milestone these are reasonable to land, but each should have a follow-up issue tracking test coverage before stable 1.0. 🟡 🟡 ✅ Strengths
Recommendation✅ Ready to merge with the following tracked follow-ups:
|
…ud CI; exclude internal Python from CodeFactor
- README.md, Examples/BushelCloud/{CLAUDE.md,.docc,.claude/s2s-auth-details.md},
Examples/CelestraCloud/{CLAUDE.md,README.md,.claude/IMPLEMENTATION_NOTES.md}:
drop `try CloudKitService(... database: .public)` from init examples (init is
non-throwing, `database:` moved per-call); rewrite Quick Start auth around
`Credentials` + `APICredentials` / `ServerToServerCredentials` and show
`database: .public(.prefers(.serverToServer))` at the call site.
- Examples/BushelCloud/.github/workflows/{BushelCloud.yml,bushel-cloud-build.yml}:
pin MISTKIT_BRANCH to v1.0.0-beta.1 (matches CelestraCloud) so the subrepo PR
builds against the branch that actually carries the new API. Revert to `main`
once #298 merges.
- .codefactor.yml: exclude Scripts/mermaid-to-pptx.py (internal-use helper).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
subrepo: subdir: "Examples/BushelCloud" merged: "5bb4490" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "5bb4490" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f"
subrepo: subdir: "Examples/CelestraCloud" merged: "ea897c3" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "ea897c3" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f"
Code Review — v1.0.0-beta.1This PR accumulates ~25 commits across several sub-PRs and represents a substantial, well-designed release. The overall architecture is excellent. Notes below are in priority order. Bugs / Logic Issues1. Silent platform fall-through in In if let s2s = serverToServer {
if #available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *) {
return try makeServerToServerManager(s2s)
}
// If #available fails, falls through silently — no error
}
if auth.required {
throw CloudKitError.missingCredentials(...)If a caller provides 2. ZoneInfo(zoneName: zoneID.zoneName ?? "Unknown", ...)If CloudKit returns a zone without a guard let zoneName = zoneID.zoneName else { return nil }
return ZoneInfo(zoneName: zoneName, ...)Security / Privacy3. logger.debug(" Headers: \(request.headerFields)")CloudKit authentication headers ( let safeHeaders = request.headerFields.filter { !$0.name.rawName.hasPrefix("X-Apple-CloudKit-Request") }
logger.debug(" Headers: \(safeHeaders)")4. let bodyData = try await Data(collecting: responseBody, upTo: 1_024 * 1_024)This runs on every request when API Design5. Pre-call validation uses throw CloudKitError.httpErrorWithRawResponse(statusCode: 400, rawResponse: "zoneIDs cannot be empty")No HTTP request was made, so reporting 6. The Positive Observations
SummaryTwo bugs worth fixing before merge (silent platform fall-through, 🤖 Reviewed by Claude Sonnet 4.6 |
Drops speaker-prep artifacts and blog-source files that shouldn't ship
in the repo, and polishes the remaining articles so they read as
release-ready reference docs.
Removed (preserved on branch docs/talk-prep-archive and tag
archive/talk-prep-2026-05-17, both pushed to origin before deletion):
- docs/talk-feedback.md — dry-run debrief notes
- docs/transcriptions/ — raw Riverside transcripts (5 files)
- docs/cloudkit-guide/articles/rebuilding-mistkit-claude-code-part-{1,2}.md
— blog posts with brightdigit.com CMS frontmatter; the surviving
articles now link to the canonical brightdigit.com URLs instead
Polished:
- deploying-mistkit-server-side.md: dropped DRAFT banner, removed all
[VERIFY] markers (rewritten as hedged statements where load-bearing,
removed where the surrounding prose already covered it), removed
invalid featuredImage frontmatter
- authenticating-cloudkit-backend-services.md: same VERIFY-marker
pass; fixed two broken [Celestra](github.com/brightdigit/Celestra)
links to point at the actual CelestraCloud repo
- field-type-polymorphism.md: reframed "Known Gap" + "Future work"
section as "Known Limitation" with descriptive design rationale,
so it reads as reference documentation rather than a sprint plan
- cloudkit-guide/README.md: removed two empty ###### Web Application /
###### Background Job placeholder headers
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
v1.0.0-beta.1 Code ReviewThis is a large, well-structured release. The credential-resolution refactor and new user-identity endpoints are solid work. Notes are ordered by severity. Strengths
IssuesIssue 1: Silent OS-version fallthrough gives a misleading error message When serverToServer is non-nil but the availability check fails (pre-macOS 11 / iOS 14), execution falls through and the error says credentials "are not configured" -- but they ARE configured, just unsupported on this platform. Consider a dedicated unsupportedPlatform error case or a corrected reason string that distinguishes "credentials absent" from "credentials present but platform too old". Issue 2: Client-side validation uses httpErrorWithRawResponse httpErrorWithRawResponse implies the error originated from an HTTP response. The empty-recordType and invalid-limit guards are local argument-validation failures; callers who inspect httpStatusCode will be misled. A dedicated invalidArgument(String) case would be more honest about the error origin. Issue 3: Cooperative cancellation loses type information Task.checkCancellation() errors are mapped through mapToCloudKitError, wrapping CancellationError inside CloudKitError.underlyingError(...). With typed throws, callers cannot detect cancellation without unwrapping. Consider rethrowing CancellationError before the mapping step, or adding a .cancelled case to CloudKitError. Issue 4: AdaptiveTokenManager appears unused by the library path Credentials+TokenManager.swift always constructs concrete managers (APITokenManager, WebAuthTokenManager, ServerToServerAuthManager) directly. AdaptiveTokenManager is public but never reached via Credentials. If it is intended for callers who hold a live reference and upgrade it after a web-auth flow, that use case should be documented. Otherwise this reads as dead public API before 1.0 stable. Minor Nits
SummaryIssues 1 and 2 could confuse operators debugging auth failures in production. Issue 3 makes Structured Concurrency cancellation patterns awkward. Issue 4 risks shipping dead public API at 1.0. The rest is polish. Overall this is in good shape for beta; addressing issues 1-4 before 1.0 stable would be ideal. |
commit de82483 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:35 2026 +0100 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "ea897c3" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "ea897c3" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit 24c8719 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:31 2026 +0100 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "5bb4490" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "5bb4490" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit eee0670 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:13 2026 +0100 docs: sync README/CLAUDE examples to v1.0.0-beta.1 API; pin BushelCloud CI; exclude internal Python from CodeFactor - README.md, Examples/BushelCloud/{CLAUDE.md,.docc,.claude/s2s-auth-details.md}, Examples/CelestraCloud/{CLAUDE.md,README.md,.claude/IMPLEMENTATION_NOTES.md}: drop `try CloudKitService(... database: .public)` from init examples (init is non-throwing, `database:` moved per-call); rewrite Quick Start auth around `Credentials` + `APICredentials` / `ServerToServerCredentials` and show `database: .public(.prefers(.serverToServer))` at the call site. - Examples/BushelCloud/.github/workflows/{BushelCloud.yml,bushel-cloud-build.yml}: pin MISTKIT_BRANCH to v1.0.0-beta.1 (matches CelestraCloud) so the subrepo PR builds against the branch that actually carries the new API. Revert to `main` once #298 merges. - .codefactor.yml: exclude Scripts/mermaid-to-pptx.py (internal-use helper). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> commit 4d60b19 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 20:10:45 2026 +0100 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "c44dc4f" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "c44dc4f" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit 5bc403d Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 20:10:40 2026 +0100 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "55f2092" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "55f2092" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit bce1f23 Author: leogdion <leogdion@brightdigit.com> Date: Sun May 17 20:09:47 2026 +0100 refactor!: prep for talk — shrink API, refactor auth, split OpenAPI (#279) commit 7023a31 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 15 12:56:58 2026 -0400 Fixed Nonisolated Web Auth Token (#347) commit f799128 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 20:27:28 2026 -0400 Add MistDemo-Integration workflow for live CloudKit runs (#345) commit 418e2e4 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 16:03:04 2026 -0400 Resolve #342: v1.0.0-beta.1 follow-ups (#341 #327 #321 #317) + CI fixes (#343) commit d65d20b Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 11:25:10 2026 -0400 Resolve #330: interactive MistDemo (web toggle + native app refresh) (#332) commit a28ab3c Author: leogdion <leogdion@brightdigit.com> Date: Mon May 11 16:31:10 2026 -0400 Resolve #313: paginationLimitExceeded carries accumulated records (#326) commit 7a5da7a Author: leogdion <leogdion@brightdigit.com> Date: Sat May 9 17:09:53 2026 -0400 Fix CI failures + Claude review nits on PR #298 (v1.0.0-beta.1) (#322) commit b3626c0 Author: leogdion <leogdion@brightdigit.com> Date: Sat May 9 16:06:20 2026 -0400 Resolve #312: public+web-auth user-identity endpoints (#310, #311, #27, #28, #34, #35) (#315) * #312 library: add public+web-auth user-identity endpoints and users/caller migration Implements the library side of #312 — adding/renaming user-identity endpoints that require public-database routing with web-auth (user-context) credentials, and unblocking the convenience initializers from their hardcoded database/ environment defaults. #310: `CloudKitService` convenience initializers now accept `database:` and `environment:` parameters with defaults that preserve current behavior. #311: `users/current` → `users/caller`. Renamed in openapi.yaml and the generated client; added a hand-written `fetchCaller()` plus an `@available(*, deprecated, renamed: "fetchCaller")` `fetchCurrentUser()` shim that forwards to the new method. #28: GET `/users/discover` (`discoverAllUserIdentities`). #34: POST `/users/lookup/email` (`lookupUsersByEmail`). #35: POST `/users/lookup/id` (`lookupUsersByRecordName`). The three new endpoints reuse `DiscoverResponse` for parsing — Apple returns `{ users: [UserIdentity] }` for all of them. Each ships with a 5-file test suite mirroring the existing `DiscoverUserIdentities` pattern. #33 (`users/lookup/contacts`) intentionally not implemented: Apple has marked the endpoint deprecated. To be closed as not-planned with a pointer to #34/#35. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312 MistDemo: separate database from authentication and add user-context phases Refactors MistDemo's CloudKit configuration model and integration runner to support the public+web-auth combination required by the user-identity endpoints landed in the prior commit. **Configuration refactor.** Replaces the `DatabaseCredentials` enum (which coupled database choice to a single auth method per case, baking in a public⇒S2S/private⇒webAuth assumption) with two orthogonal types: - `AuthenticationCredentials` — `serverToServer(keyID:privateKey:)` / `webAuth(apiToken:webAuthToken:)` - `DatabaseConfiguration` — pairs a `MistKit.Database` with an `AuthenticationCredentials`. The `make(database:authentication:)` factory rejects private+S2S and shared+S2S (which CloudKit rejects) so invalid combinations remain unrepresentable, while public+webAuth is now a valid construction. `MistKitClientFactory.create(for:)` consumes `toPrimaryConfiguration()`; the new `createUserContext(for:)` returns the optional public+web-auth service from `toUserContextConfiguration()` when web-auth tokens are configured. **Phase plumbing.** `PhaseContext` and `IntegrationTestRunner` now thread an optional `userContextService: CloudKitService?`. `PublicDatabaseTest` takes `includeUserContextPhases:` and conditionally appends the new user-identity phases: - `FetchCallerPhase` (renamed from `FetchCurrentUserPhase`) - `DiscoverUserIdentitiesPhase` (existed; updated to use userContextService) - `DiscoverAllUserIdentitiesPhase` (#28) - `LookupUsersByEmailPhase` (#34) - `LookupUsersByRecordNamePhase` (#35) `PrivateDatabaseTest` no longer includes `FetchCurrentUserPhase`: CloudKit rejects `users/caller` against the private database, matching the rest of the user-identity family. **Call-site updates.** `CurrentUserCommand` and `DemoErrorsRunner` swap `fetchCurrentUser()` → `fetchCaller()`. `TestIntegrationCommand` and `TestPrivateCommand` now build and pass `userContextService`. Tests for `AuthenticationCredentials`, `DatabaseConfiguration.make` validation, and `MistDemoConfig.toPrimaryConfiguration` / `toUserContextConfiguration` ship alongside. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: mark discoverAllUserIdentities() unavailable pending #28 investigation Live verification on 2026-05-08 against iCloud.com.brightdigit.MistDemo returned HTTP 500 from Apple's GET /users/discover. The first 12 phases of mistdemo test-integration --verbose run green (the 8 base public+S2S phases plus FetchCallerPhase, DiscoverUserIdentitiesPhase, LookupUsersByEmailPhase, LookupUsersByRecordNamePhase) — only discoverAllUserIdentities fails, blocking phases beyond it. The endpoint is referenced in CloudKitJS but does not appear in Apple's CloudKit Web Services REST documentation. The actual REST shape is still under investigation under #28. Changes: - Marked `CloudKitService.discoverAllUserIdentities()` `@available(*, unavailable, message: ...)` with a pointer to #28. - Removed `DiscoverAllUserIdentitiesPhase` from MistDemo and from `PublicDatabaseTest.phases`. - Removed the `CloudKitServiceDiscoverAllUserIdentities` test directory (the unavailable method cannot be called from Swift code). The OpenAPI definition, generated client, path builder, response processor, Output extension, and Swift wrapper are all retained. Unblocking is a one-line `@available` removal once the correct REST shape is determined under #28. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: resolve PR review — Credentials API, per-call database, cascade unavailable Addresses all four review threads on PR #315: - Comment #1 (error wording): removed `unsupportedDatabaseAuthCombination` along with `MistDemo.DatabaseConfiguration`; invalid combos now surface as `CloudKitError.missingCredentials` from the library. - Comment #2 (per-call database): user-identity ops in `CloudKitService+UserOperations` hardcode `.public`; record/zone/asset/sync ops accept `database: Database? = nil` falling back to a service-level default. - Comment #3 (unified credentials): new `Credentials` / `ServerToServerCredentials` / `APICredentials` value types replace the legacy `apiToken:`/`webAuthToken:` initializers. The token manager is selected based on the target database (S2S for `.public`, web-auth for `.private`/`.shared`). Lifted `PrivateKeyMaterial` into the library. - Comment #4 (cascade unavailable): removed `Operations.discoverAllUserIdentities.Output: CloudKitResponseType` conformance entirely; `processDiscoverAllUserIdentitiesResponse` is now `@available(*, unavailable)` with a `fatalError` body. Also migrates ~15 MistKit test helpers and the MistDemo factory to the new Credentials API. Breaking changes (pre-1.0): removed legacy `CloudKitService` initializers taking `apiToken:`/`webAuthToken:`; `CloudKitService.apiToken` is removed, `.database` is now `internal`. Out of scope: per-call `TokenManager` dispatch (would let one service mix S2S-for-public and web-auth-for-user-context). MistDemo still constructs a separate `userContextService` for that scenario. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: drop service-level database, per-call credential resolution [skip ci] Resolves the architectural feedback in the PR-315 review: * CloudKitService no longer carries `database` — operations take `database:` per call (defaulting to `.public`); user-identity routes drop the parameter since CloudKit pins them to `.public`. Subsumes Claude's "fetchCaller bypasses self.database" finding. * Credentials.makeTokenManager(for:requiresUserContext:) resolves the appropriate token manager at dispatch time. A single service can now serve public-database S2S record ops and user-identity web-auth routes from one fully-populated `Credentials`. MistKitClient.swift is obsolete and removed; per-call dispatch lives in CloudKitService+ClientDispatch. * Credentials.swift split per SwiftLint one_file_per_declaration into ServerToServerCredentials.swift + APICredentials.swift + Credentials.swift. New typed CredentialsValidationError; init asserts in debug, throws in release (no more precondition crash for dynamic config). * MistDemo: userContextService workaround collapsed — single service handles all phases via per-call resolution. * CI hotfix: 11 unused `public import` lines demoted to `internal` (the warnings-as-errors regression flagged in the review). * Tests: 12-case routing-matrix unit suite for makeTokenManager and a fetchCaller suite parallel to LookupUsers* (success + validation). Obsolete MistKitClient tests removed. * Polish: shorter @available message on discoverAllUserIdentities, structural comment for GET /users/discover in openapi.yaml, ConfigurationError.missingAPIToken (unused) removed. 475/475 tests pass. Library + MistDemo build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Per review on PR #315: listZones, lookupZones, fetchZoneChanges now default to .private since the public database only contains _defaultZone, making .public a degenerate default. MistDemo callers pass context.database / config.base.database explicitly so the --database flag still drives the test runs. Also repairs MistDemo test breakage from 7debe8d: toUserContextCredentials() was removed but tests still referenced it; rewritten against the replacement surface (toPrimaryCredentials embeds apiAuth on .public, plus the new hasUserContextCredentials boolean). The CredentialsValidationTests suite was deleted — it asserted init-time validation that no longer exists under per-call credential resolution; the equivalent .missingCredentials behavior is covered in MistKitTests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: gate @available(*,unavailable) on processDiscoverAllUserIdentitiesResponse to Swift 6.2+ Swift 6.1 rejects calls to an unavailable function from within another unavailable function; 6.2 relaxed that rule. The internal helper processDiscoverAllUserIdentitiesResponse is unavailable in lockstep with its only caller — the also-unavailable CloudKitService.discoverAllUserIdentities() — which built fine on 6.2+ but failed on Swift 6.1 with: error: 'processDiscoverAllUserIdentitiesResponse' is unavailable: Pending #28: discoverAllUserIdentities is not yet ready. Wrap just the attribute in `#if swift(>=6.2)` so the body is shared and 6.1 compiles. Inline doc records the intent and the one-line cleanup (delete the #if/#endif) once 6.1 is dropped from the matrix. A `swiftlint:disable:next unavailable_function` is required because swiftlint does not evaluate #if and otherwise sees a fatalError-only function without the attribute. Verified: swift build + swift test pass on Swift 6.1.3 (Linux container) and on macOS Swift 6.2+ (475/475 tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: split unhandled-response logging into debug (full body) + warning (type/status only) CodeQL's swift/cleartext-logging flagged the existing warning logs because lookupUsersByEmail(_:) propagates email-PII taint through the response object. Move full \(response) interpolation to .debug so the detail stays available for development without flowing into ops logs; keep .warning at type(of:) + HTTP status code only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: add --lookup-email / CLOUDKIT_LOOKUP_EMAIL to exercise users/lookup/email LookupUsersByEmailPhase previously skipped whenever fetchCaller() didn't return an email (which is the common case). Plumb a configurable lookup email through TestIntegrationConfig / TestPrivateConfig → PhaseContext so the phase can be driven against a known-discoverable iCloud account. Falls back to caller email, then to a clearer skip message naming the flag/env var. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: point CLAUDE.md lint section at mise (and Scripts/lint.sh) swift-format / swiftlint / periphery are pinned in mise.toml; the previous "requires swiftlint installation" wording led to PATH lookups that fail in this repo. Replace with `mise exec --` invocations and flag the full ./Scripts/lint.sh pipeline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: address review punch list — invalidPrivateKey, recoverable unavailable response, supportsUserContextPhases derivation - CloudKitError: add invalidPrivateKey(path:underlying:) so PEM-load failures carry the file path + original error instead of bare Foundation NSError. Wrap loadPEM() at the single call site in Credentials+TokenManager. Add PrivateKeyMaterial.filePath accessor for the diagnostic. - processDiscoverAllUserIdentitiesResponse: replace fatalError with throw CloudKitError.unsupportedOperationType so a stray Swift 6.1 caller (where the @available cascade does not apply) gets a recoverable error instead of a crash. - TestPrivateCommand: derive supportsUserContextPhases from config.base.hasUserContextCredentials, mirroring TestIntegrationCommand, so user-identity phases skip cleanly when web-auth env vars are absent. - toPrimaryCredentials: replace try? with do/catch + stderr INFO line so operators see when web-auth is missing on a .public setup. - CLAUDE.md: annotate discoverAllUserIdentities() as unavailable pending #28. - CredentialsTokenManagerTests: fill the missing routing-matrix branches (user-context × .private/.shared, .shared + token-only) and cover the new .invalidPrivateKey path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> commit 6f92a71 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 8 13:16:56 2026 -0400 Resolve #308: docs refresh + CI fixes + sub-issues #165, #285 (#309) commit a1e2162 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 8 07:16:10 2026 -0400 Add query pagination support with continuation markers (#306) commit c62bf44 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 15:52:45 2026 -0400 Improve error handling: typed TokenManagerError and safe RecordOperation conversion (#305) commit 7c4b678 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:27:10 2026 -0400 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "4244497" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "4244497" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "b9763ee528" commit f14e751 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:27:07 2026 -0400 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "123a732" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "123a732" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "b9763ee528" commit a0f0af9 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:26:32 2026 -0400 updating example packages commit 125dab5 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:01:18 2026 -0400 Refactor AuthenticationMiddleware so each Authenticator applies itself (#294) commit f989fd1 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:23:23 2026 -0400 Strengthen environment and database configuration validation (#293) commit b0f00a7 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:18:52 2026 -0400 Add operation classification and batch sync result tracking (#296) commit 63a4e50 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:09:27 2026 -0400 Move CloudKitResponseType default implementations to protocol extension (#292) commit ae1af15 Author: leogdion <leogdion@brightdigit.com> Date: Wed May 6 20:20:44 2026 -0400 Test suite improvements for v1.0.0-beta.1 (#286) (#287) commit 5475bfa Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 20:21:32 2026 -0400 MistDemo: --database flag + demo-errors command (closes #259, #269) (#282) commit 8b21425 Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 20:21:17 2026 -0400 Refactor IntegrationTestRunner into protocol-based phase pipeline (#254) (#283) commit 9709f3d Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 08:54:16 2026 -0400 Replace custom AsyncChannel with swift-async-algorithms (#280) commit d53467a Author: leogdion <leogdion@brightdigit.com> Date: Mon May 4 12:49:25 2026 -0400 CI Updates for May 2026 (#277) commit d7b1a21 Author: Leo Dion <leogdion@brightdigit.com> Date: Thu Apr 30 09:39:09 2026 -0400 MistDemo improvements: test split, CRUD, auth fix, native app (#271) (#273) commit 0ab2ab6 Author: leogdion <leogdion@brightdigit.com> Date: Wed Apr 29 15:49:34 2026 -0400 First Draft Revision of Docs (#268)
commit de82483 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:35 2026 +0100 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "ea897c3" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "ea897c3" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit 24c8719 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:31 2026 +0100 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "5bb4490" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "5bb4490" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit eee0670 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:13 2026 +0100 docs: sync README/CLAUDE examples to v1.0.0-beta.1 API; pin BushelCloud CI; exclude internal Python from CodeFactor - README.md, Examples/BushelCloud/{CLAUDE.md,.docc,.claude/s2s-auth-details.md}, Examples/CelestraCloud/{CLAUDE.md,README.md,.claude/IMPLEMENTATION_NOTES.md}: drop `try CloudKitService(... database: .public)` from init examples (init is non-throwing, `database:` moved per-call); rewrite Quick Start auth around `Credentials` + `APICredentials` / `ServerToServerCredentials` and show `database: .public(.prefers(.serverToServer))` at the call site. - Examples/BushelCloud/.github/workflows/{BushelCloud.yml,bushel-cloud-build.yml}: pin MISTKIT_BRANCH to v1.0.0-beta.1 (matches CelestraCloud) so the subrepo PR builds against the branch that actually carries the new API. Revert to `main` once #298 merges. - .codefactor.yml: exclude Scripts/mermaid-to-pptx.py (internal-use helper). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> commit 4d60b19 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 20:10:45 2026 +0100 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "c44dc4f" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "c44dc4f" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit 5bc403d Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 20:10:40 2026 +0100 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "55f2092" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "55f2092" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit bce1f23 Author: leogdion <leogdion@brightdigit.com> Date: Sun May 17 20:09:47 2026 +0100 refactor!: prep for talk — shrink API, refactor auth, split OpenAPI (#279) commit 7023a31 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 15 12:56:58 2026 -0400 Fixed Nonisolated Web Auth Token (#347) commit f799128 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 20:27:28 2026 -0400 Add MistDemo-Integration workflow for live CloudKit runs (#345) commit 418e2e4 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 16:03:04 2026 -0400 Resolve #342: v1.0.0-beta.1 follow-ups (#341 #327 #321 #317) + CI fixes (#343) commit d65d20b Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 11:25:10 2026 -0400 Resolve #330: interactive MistDemo (web toggle + native app refresh) (#332) commit a28ab3c Author: leogdion <leogdion@brightdigit.com> Date: Mon May 11 16:31:10 2026 -0400 Resolve #313: paginationLimitExceeded carries accumulated records (#326) commit 7a5da7a Author: leogdion <leogdion@brightdigit.com> Date: Sat May 9 17:09:53 2026 -0400 Fix CI failures + Claude review nits on PR #298 (v1.0.0-beta.1) (#322) commit b3626c0 Author: leogdion <leogdion@brightdigit.com> Date: Sat May 9 16:06:20 2026 -0400 Resolve #312: public+web-auth user-identity endpoints (#310, #311, #27, #28, #34, #35) (#315) * #312 library: add public+web-auth user-identity endpoints and users/caller migration Implements the library side of #312 — adding/renaming user-identity endpoints that require public-database routing with web-auth (user-context) credentials, and unblocking the convenience initializers from their hardcoded database/ environment defaults. #310: `CloudKitService` convenience initializers now accept `database:` and `environment:` parameters with defaults that preserve current behavior. #311: `users/current` → `users/caller`. Renamed in openapi.yaml and the generated client; added a hand-written `fetchCaller()` plus an `@available(*, deprecated, renamed: "fetchCaller")` `fetchCurrentUser()` shim that forwards to the new method. #28: GET `/users/discover` (`discoverAllUserIdentities`). #34: POST `/users/lookup/email` (`lookupUsersByEmail`). #35: POST `/users/lookup/id` (`lookupUsersByRecordName`). The three new endpoints reuse `DiscoverResponse` for parsing — Apple returns `{ users: [UserIdentity] }` for all of them. Each ships with a 5-file test suite mirroring the existing `DiscoverUserIdentities` pattern. #33 (`users/lookup/contacts`) intentionally not implemented: Apple has marked the endpoint deprecated. To be closed as not-planned with a pointer to #34/#35. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312 MistDemo: separate database from authentication and add user-context phases Refactors MistDemo's CloudKit configuration model and integration runner to support the public+web-auth combination required by the user-identity endpoints landed in the prior commit. **Configuration refactor.** Replaces the `DatabaseCredentials` enum (which coupled database choice to a single auth method per case, baking in a public⇒S2S/private⇒webAuth assumption) with two orthogonal types: - `AuthenticationCredentials` — `serverToServer(keyID:privateKey:)` / `webAuth(apiToken:webAuthToken:)` - `DatabaseConfiguration` — pairs a `MistKit.Database` with an `AuthenticationCredentials`. The `make(database:authentication:)` factory rejects private+S2S and shared+S2S (which CloudKit rejects) so invalid combinations remain unrepresentable, while public+webAuth is now a valid construction. `MistKitClientFactory.create(for:)` consumes `toPrimaryConfiguration()`; the new `createUserContext(for:)` returns the optional public+web-auth service from `toUserContextConfiguration()` when web-auth tokens are configured. **Phase plumbing.** `PhaseContext` and `IntegrationTestRunner` now thread an optional `userContextService: CloudKitService?`. `PublicDatabaseTest` takes `includeUserContextPhases:` and conditionally appends the new user-identity phases: - `FetchCallerPhase` (renamed from `FetchCurrentUserPhase`) - `DiscoverUserIdentitiesPhase` (existed; updated to use userContextService) - `DiscoverAllUserIdentitiesPhase` (#28) - `LookupUsersByEmailPhase` (#34) - `LookupUsersByRecordNamePhase` (#35) `PrivateDatabaseTest` no longer includes `FetchCurrentUserPhase`: CloudKit rejects `users/caller` against the private database, matching the rest of the user-identity family. **Call-site updates.** `CurrentUserCommand` and `DemoErrorsRunner` swap `fetchCurrentUser()` → `fetchCaller()`. `TestIntegrationCommand` and `TestPrivateCommand` now build and pass `userContextService`. Tests for `AuthenticationCredentials`, `DatabaseConfiguration.make` validation, and `MistDemoConfig.toPrimaryConfiguration` / `toUserContextConfiguration` ship alongside. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: mark discoverAllUserIdentities() unavailable pending #28 investigation Live verification on 2026-05-08 against iCloud.com.brightdigit.MistDemo returned HTTP 500 from Apple's GET /users/discover. The first 12 phases of mistdemo test-integration --verbose run green (the 8 base public+S2S phases plus FetchCallerPhase, DiscoverUserIdentitiesPhase, LookupUsersByEmailPhase, LookupUsersByRecordNamePhase) — only discoverAllUserIdentities fails, blocking phases beyond it. The endpoint is referenced in CloudKitJS but does not appear in Apple's CloudKit Web Services REST documentation. The actual REST shape is still under investigation under #28. Changes: - Marked `CloudKitService.discoverAllUserIdentities()` `@available(*, unavailable, message: ...)` with a pointer to #28. - Removed `DiscoverAllUserIdentitiesPhase` from MistDemo and from `PublicDatabaseTest.phases`. - Removed the `CloudKitServiceDiscoverAllUserIdentities` test directory (the unavailable method cannot be called from Swift code). The OpenAPI definition, generated client, path builder, response processor, Output extension, and Swift wrapper are all retained. Unblocking is a one-line `@available` removal once the correct REST shape is determined under #28. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: resolve PR review — Credentials API, per-call database, cascade unavailable Addresses all four review threads on PR #315: - Comment #1 (error wording): removed `unsupportedDatabaseAuthCombination` along with `MistDemo.DatabaseConfiguration`; invalid combos now surface as `CloudKitError.missingCredentials` from the library. - Comment #2 (per-call database): user-identity ops in `CloudKitService+UserOperations` hardcode `.public`; record/zone/asset/sync ops accept `database: Database? = nil` falling back to a service-level default. - Comment #3 (unified credentials): new `Credentials` / `ServerToServerCredentials` / `APICredentials` value types replace the legacy `apiToken:`/`webAuthToken:` initializers. The token manager is selected based on the target database (S2S for `.public`, web-auth for `.private`/`.shared`). Lifted `PrivateKeyMaterial` into the library. - Comment #4 (cascade unavailable): removed `Operations.discoverAllUserIdentities.Output: CloudKitResponseType` conformance entirely; `processDiscoverAllUserIdentitiesResponse` is now `@available(*, unavailable)` with a `fatalError` body. Also migrates ~15 MistKit test helpers and the MistDemo factory to the new Credentials API. Breaking changes (pre-1.0): removed legacy `CloudKitService` initializers taking `apiToken:`/`webAuthToken:`; `CloudKitService.apiToken` is removed, `.database` is now `internal`. Out of scope: per-call `TokenManager` dispatch (would let one service mix S2S-for-public and web-auth-for-user-context). MistDemo still constructs a separate `userContextService` for that scenario. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: drop service-level database, per-call credential resolution [skip ci] Resolves the architectural feedback in the PR-315 review: * CloudKitService no longer carries `database` — operations take `database:` per call (defaulting to `.public`); user-identity routes drop the parameter since CloudKit pins them to `.public`. Subsumes Claude's "fetchCaller bypasses self.database" finding. * Credentials.makeTokenManager(for:requiresUserContext:) resolves the appropriate token manager at dispatch time. A single service can now serve public-database S2S record ops and user-identity web-auth routes from one fully-populated `Credentials`. MistKitClient.swift is obsolete and removed; per-call dispatch lives in CloudKitService+ClientDispatch. * Credentials.swift split per SwiftLint one_file_per_declaration into ServerToServerCredentials.swift + APICredentials.swift + Credentials.swift. New typed CredentialsValidationError; init asserts in debug, throws in release (no more precondition crash for dynamic config). * MistDemo: userContextService workaround collapsed — single service handles all phases via per-call resolution. * CI hotfix: 11 unused `public import` lines demoted to `internal` (the warnings-as-errors regression flagged in the review). * Tests: 12-case routing-matrix unit suite for makeTokenManager and a fetchCaller suite parallel to LookupUsers* (success + validation). Obsolete MistKitClient tests removed. * Polish: shorter @available message on discoverAllUserIdentities, structural comment for GET /users/discover in openapi.yaml, ConfigurationError.missingAPIToken (unused) removed. 475/475 tests pass. Library + MistDemo build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Per review on PR #315: listZones, lookupZones, fetchZoneChanges now default to .private since the public database only contains _defaultZone, making .public a degenerate default. MistDemo callers pass context.database / config.base.database explicitly so the --database flag still drives the test runs. Also repairs MistDemo test breakage from 7debe8d: toUserContextCredentials() was removed but tests still referenced it; rewritten against the replacement surface (toPrimaryCredentials embeds apiAuth on .public, plus the new hasUserContextCredentials boolean). The CredentialsValidationTests suite was deleted — it asserted init-time validation that no longer exists under per-call credential resolution; the equivalent .missingCredentials behavior is covered in MistKitTests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: gate @available(*,unavailable) on processDiscoverAllUserIdentitiesResponse to Swift 6.2+ Swift 6.1 rejects calls to an unavailable function from within another unavailable function; 6.2 relaxed that rule. The internal helper processDiscoverAllUserIdentitiesResponse is unavailable in lockstep with its only caller — the also-unavailable CloudKitService.discoverAllUserIdentities() — which built fine on 6.2+ but failed on Swift 6.1 with: error: 'processDiscoverAllUserIdentitiesResponse' is unavailable: Pending #28: discoverAllUserIdentities is not yet ready. Wrap just the attribute in `#if swift(>=6.2)` so the body is shared and 6.1 compiles. Inline doc records the intent and the one-line cleanup (delete the #if/#endif) once 6.1 is dropped from the matrix. A `swiftlint:disable:next unavailable_function` is required because swiftlint does not evaluate #if and otherwise sees a fatalError-only function without the attribute. Verified: swift build + swift test pass on Swift 6.1.3 (Linux container) and on macOS Swift 6.2+ (475/475 tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: split unhandled-response logging into debug (full body) + warning (type/status only) CodeQL's swift/cleartext-logging flagged the existing warning logs because lookupUsersByEmail(_:) propagates email-PII taint through the response object. Move full \(response) interpolation to .debug so the detail stays available for development without flowing into ops logs; keep .warning at type(of:) + HTTP status code only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: add --lookup-email / CLOUDKIT_LOOKUP_EMAIL to exercise users/lookup/email LookupUsersByEmailPhase previously skipped whenever fetchCaller() didn't return an email (which is the common case). Plumb a configurable lookup email through TestIntegrationConfig / TestPrivateConfig → PhaseContext so the phase can be driven against a known-discoverable iCloud account. Falls back to caller email, then to a clearer skip message naming the flag/env var. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: point CLAUDE.md lint section at mise (and Scripts/lint.sh) swift-format / swiftlint / periphery are pinned in mise.toml; the previous "requires swiftlint installation" wording led to PATH lookups that fail in this repo. Replace with `mise exec --` invocations and flag the full ./Scripts/lint.sh pipeline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: address review punch list — invalidPrivateKey, recoverable unavailable response, supportsUserContextPhases derivation - CloudKitError: add invalidPrivateKey(path:underlying:) so PEM-load failures carry the file path + original error instead of bare Foundation NSError. Wrap loadPEM() at the single call site in Credentials+TokenManager. Add PrivateKeyMaterial.filePath accessor for the diagnostic. - processDiscoverAllUserIdentitiesResponse: replace fatalError with throw CloudKitError.unsupportedOperationType so a stray Swift 6.1 caller (where the @available cascade does not apply) gets a recoverable error instead of a crash. - TestPrivateCommand: derive supportsUserContextPhases from config.base.hasUserContextCredentials, mirroring TestIntegrationCommand, so user-identity phases skip cleanly when web-auth env vars are absent. - toPrimaryCredentials: replace try? with do/catch + stderr INFO line so operators see when web-auth is missing on a .public setup. - CLAUDE.md: annotate discoverAllUserIdentities() as unavailable pending #28. - CredentialsTokenManagerTests: fill the missing routing-matrix branches (user-context × .private/.shared, .shared + token-only) and cover the new .invalidPrivateKey path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> commit 6f92a71 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 8 13:16:56 2026 -0400 Resolve #308: docs refresh + CI fixes + sub-issues #165, #285 (#309) commit a1e2162 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 8 07:16:10 2026 -0400 Add query pagination support with continuation markers (#306) commit c62bf44 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 15:52:45 2026 -0400 Improve error handling: typed TokenManagerError and safe RecordOperation conversion (#305) commit 7c4b678 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:27:10 2026 -0400 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "4244497" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "4244497" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "b9763ee528" commit f14e751 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:27:07 2026 -0400 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "123a732" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "123a732" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "b9763ee528" commit a0f0af9 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:26:32 2026 -0400 updating example packages commit 125dab5 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:01:18 2026 -0400 Refactor AuthenticationMiddleware so each Authenticator applies itself (#294) commit f989fd1 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:23:23 2026 -0400 Strengthen environment and database configuration validation (#293) commit b0f00a7 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:18:52 2026 -0400 Add operation classification and batch sync result tracking (#296) commit 63a4e50 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:09:27 2026 -0400 Move CloudKitResponseType default implementations to protocol extension (#292) commit ae1af15 Author: leogdion <leogdion@brightdigit.com> Date: Wed May 6 20:20:44 2026 -0400 Test suite improvements for v1.0.0-beta.1 (#286) (#287) commit 5475bfa Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 20:21:32 2026 -0400 MistDemo: --database flag + demo-errors command (closes #259, #269) (#282) commit 8b21425 Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 20:21:17 2026 -0400 Refactor IntegrationTestRunner into protocol-based phase pipeline (#254) (#283) commit 9709f3d Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 08:54:16 2026 -0400 Replace custom AsyncChannel with swift-async-algorithms (#280) commit d53467a Author: leogdion <leogdion@brightdigit.com> Date: Mon May 4 12:49:25 2026 -0400 CI Updates for May 2026 (#277) commit d7b1a21 Author: Leo Dion <leogdion@brightdigit.com> Date: Thu Apr 30 09:39:09 2026 -0400 MistDemo improvements: test split, CRUD, auth fix, native app (#271) (#273) commit 0ab2ab6 Author: leogdion <leogdion@brightdigit.com> Date: Wed Apr 29 15:49:34 2026 -0400 First Draft Revision of Docs (#268)
commit de82483 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:35 2026 +0100 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "ea897c3" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "ea897c3" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit 24c8719 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:31 2026 +0100 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "5bb4490" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "5bb4490" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit eee0670 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 21:14:13 2026 +0100 docs: sync README/CLAUDE examples to v1.0.0-beta.1 API; pin BushelCloud CI; exclude internal Python from CodeFactor - README.md, Examples/BushelCloud/{CLAUDE.md,.docc,.claude/s2s-auth-details.md}, Examples/CelestraCloud/{CLAUDE.md,README.md,.claude/IMPLEMENTATION_NOTES.md}: drop `try CloudKitService(... database: .public)` from init examples (init is non-throwing, `database:` moved per-call); rewrite Quick Start auth around `Credentials` + `APICredentials` / `ServerToServerCredentials` and show `database: .public(.prefers(.serverToServer))` at the call site. - Examples/BushelCloud/.github/workflows/{BushelCloud.yml,bushel-cloud-build.yml}: pin MISTKIT_BRANCH to v1.0.0-beta.1 (matches CelestraCloud) so the subrepo PR builds against the branch that actually carries the new API. Revert to `main` once #298 merges. - .codefactor.yml: exclude Scripts/mermaid-to-pptx.py (internal-use helper). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> commit 4d60b19 Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 20:10:45 2026 +0100 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "c44dc4f" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "c44dc4f" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit 5bc403d Author: Leo Dion <leogdion@brightdigit.com> Date: Sun May 17 20:10:40 2026 +0100 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "55f2092" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "55f2092" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "6f293daa9f" commit bce1f23 Author: leogdion <leogdion@brightdigit.com> Date: Sun May 17 20:09:47 2026 +0100 refactor!: prep for talk — shrink API, refactor auth, split OpenAPI (#279) commit 7023a31 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 15 12:56:58 2026 -0400 Fixed Nonisolated Web Auth Token (#347) commit f799128 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 20:27:28 2026 -0400 Add MistDemo-Integration workflow for live CloudKit runs (#345) commit 418e2e4 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 16:03:04 2026 -0400 Resolve #342: v1.0.0-beta.1 follow-ups (#341 #327 #321 #317) + CI fixes (#343) commit d65d20b Author: leogdion <leogdion@brightdigit.com> Date: Thu May 14 11:25:10 2026 -0400 Resolve #330: interactive MistDemo (web toggle + native app refresh) (#332) commit a28ab3c Author: leogdion <leogdion@brightdigit.com> Date: Mon May 11 16:31:10 2026 -0400 Resolve #313: paginationLimitExceeded carries accumulated records (#326) commit 7a5da7a Author: leogdion <leogdion@brightdigit.com> Date: Sat May 9 17:09:53 2026 -0400 Fix CI failures + Claude review nits on PR #298 (v1.0.0-beta.1) (#322) commit b3626c0 Author: leogdion <leogdion@brightdigit.com> Date: Sat May 9 16:06:20 2026 -0400 Resolve #312: public+web-auth user-identity endpoints (#310, #311, #27, #28, #34, #35) (#315) * #312 library: add public+web-auth user-identity endpoints and users/caller migration Implements the library side of #312 — adding/renaming user-identity endpoints that require public-database routing with web-auth (user-context) credentials, and unblocking the convenience initializers from their hardcoded database/ environment defaults. #310: `CloudKitService` convenience initializers now accept `database:` and `environment:` parameters with defaults that preserve current behavior. #311: `users/current` → `users/caller`. Renamed in openapi.yaml and the generated client; added a hand-written `fetchCaller()` plus an `@available(*, deprecated, renamed: "fetchCaller")` `fetchCurrentUser()` shim that forwards to the new method. #28: GET `/users/discover` (`discoverAllUserIdentities`). #34: POST `/users/lookup/email` (`lookupUsersByEmail`). #35: POST `/users/lookup/id` (`lookupUsersByRecordName`). The three new endpoints reuse `DiscoverResponse` for parsing — Apple returns `{ users: [UserIdentity] }` for all of them. Each ships with a 5-file test suite mirroring the existing `DiscoverUserIdentities` pattern. #33 (`users/lookup/contacts`) intentionally not implemented: Apple has marked the endpoint deprecated. To be closed as not-planned with a pointer to #34/#35. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312 MistDemo: separate database from authentication and add user-context phases Refactors MistDemo's CloudKit configuration model and integration runner to support the public+web-auth combination required by the user-identity endpoints landed in the prior commit. **Configuration refactor.** Replaces the `DatabaseCredentials` enum (which coupled database choice to a single auth method per case, baking in a public⇒S2S/private⇒webAuth assumption) with two orthogonal types: - `AuthenticationCredentials` — `serverToServer(keyID:privateKey:)` / `webAuth(apiToken:webAuthToken:)` - `DatabaseConfiguration` — pairs a `MistKit.Database` with an `AuthenticationCredentials`. The `make(database:authentication:)` factory rejects private+S2S and shared+S2S (which CloudKit rejects) so invalid combinations remain unrepresentable, while public+webAuth is now a valid construction. `MistKitClientFactory.create(for:)` consumes `toPrimaryConfiguration()`; the new `createUserContext(for:)` returns the optional public+web-auth service from `toUserContextConfiguration()` when web-auth tokens are configured. **Phase plumbing.** `PhaseContext` and `IntegrationTestRunner` now thread an optional `userContextService: CloudKitService?`. `PublicDatabaseTest` takes `includeUserContextPhases:` and conditionally appends the new user-identity phases: - `FetchCallerPhase` (renamed from `FetchCurrentUserPhase`) - `DiscoverUserIdentitiesPhase` (existed; updated to use userContextService) - `DiscoverAllUserIdentitiesPhase` (#28) - `LookupUsersByEmailPhase` (#34) - `LookupUsersByRecordNamePhase` (#35) `PrivateDatabaseTest` no longer includes `FetchCurrentUserPhase`: CloudKit rejects `users/caller` against the private database, matching the rest of the user-identity family. **Call-site updates.** `CurrentUserCommand` and `DemoErrorsRunner` swap `fetchCurrentUser()` → `fetchCaller()`. `TestIntegrationCommand` and `TestPrivateCommand` now build and pass `userContextService`. Tests for `AuthenticationCredentials`, `DatabaseConfiguration.make` validation, and `MistDemoConfig.toPrimaryConfiguration` / `toUserContextConfiguration` ship alongside. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: mark discoverAllUserIdentities() unavailable pending #28 investigation Live verification on 2026-05-08 against iCloud.com.brightdigit.MistDemo returned HTTP 500 from Apple's GET /users/discover. The first 12 phases of mistdemo test-integration --verbose run green (the 8 base public+S2S phases plus FetchCallerPhase, DiscoverUserIdentitiesPhase, LookupUsersByEmailPhase, LookupUsersByRecordNamePhase) — only discoverAllUserIdentities fails, blocking phases beyond it. The endpoint is referenced in CloudKitJS but does not appear in Apple's CloudKit Web Services REST documentation. The actual REST shape is still under investigation under #28. Changes: - Marked `CloudKitService.discoverAllUserIdentities()` `@available(*, unavailable, message: ...)` with a pointer to #28. - Removed `DiscoverAllUserIdentitiesPhase` from MistDemo and from `PublicDatabaseTest.phases`. - Removed the `CloudKitServiceDiscoverAllUserIdentities` test directory (the unavailable method cannot be called from Swift code). The OpenAPI definition, generated client, path builder, response processor, Output extension, and Swift wrapper are all retained. Unblocking is a one-line `@available` removal once the correct REST shape is determined under #28. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: resolve PR review — Credentials API, per-call database, cascade unavailable Addresses all four review threads on PR #315: - Comment #1 (error wording): removed `unsupportedDatabaseAuthCombination` along with `MistDemo.DatabaseConfiguration`; invalid combos now surface as `CloudKitError.missingCredentials` from the library. - Comment #2 (per-call database): user-identity ops in `CloudKitService+UserOperations` hardcode `.public`; record/zone/asset/sync ops accept `database: Database? = nil` falling back to a service-level default. - Comment #3 (unified credentials): new `Credentials` / `ServerToServerCredentials` / `APICredentials` value types replace the legacy `apiToken:`/`webAuthToken:` initializers. The token manager is selected based on the target database (S2S for `.public`, web-auth for `.private`/`.shared`). Lifted `PrivateKeyMaterial` into the library. - Comment #4 (cascade unavailable): removed `Operations.discoverAllUserIdentities.Output: CloudKitResponseType` conformance entirely; `processDiscoverAllUserIdentitiesResponse` is now `@available(*, unavailable)` with a `fatalError` body. Also migrates ~15 MistKit test helpers and the MistDemo factory to the new Credentials API. Breaking changes (pre-1.0): removed legacy `CloudKitService` initializers taking `apiToken:`/`webAuthToken:`; `CloudKitService.apiToken` is removed, `.database` is now `internal`. Out of scope: per-call `TokenManager` dispatch (would let one service mix S2S-for-public and web-auth-for-user-context). MistDemo still constructs a separate `userContextService` for that scenario. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: drop service-level database, per-call credential resolution [skip ci] Resolves the architectural feedback in the PR-315 review: * CloudKitService no longer carries `database` — operations take `database:` per call (defaulting to `.public`); user-identity routes drop the parameter since CloudKit pins them to `.public`. Subsumes Claude's "fetchCaller bypasses self.database" finding. * Credentials.makeTokenManager(for:requiresUserContext:) resolves the appropriate token manager at dispatch time. A single service can now serve public-database S2S record ops and user-identity web-auth routes from one fully-populated `Credentials`. MistKitClient.swift is obsolete and removed; per-call dispatch lives in CloudKitService+ClientDispatch. * Credentials.swift split per SwiftLint one_file_per_declaration into ServerToServerCredentials.swift + APICredentials.swift + Credentials.swift. New typed CredentialsValidationError; init asserts in debug, throws in release (no more precondition crash for dynamic config). * MistDemo: userContextService workaround collapsed — single service handles all phases via per-call resolution. * CI hotfix: 11 unused `public import` lines demoted to `internal` (the warnings-as-errors regression flagged in the review). * Tests: 12-case routing-matrix unit suite for makeTokenManager and a fetchCaller suite parallel to LookupUsers* (success + validation). Obsolete MistKitClient tests removed. * Polish: shorter @available message on discoverAllUserIdentities, structural comment for GET /users/discover in openapi.yaml, ConfigurationError.missingAPIToken (unused) removed. 475/475 tests pass. Library + MistDemo build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Per review on PR #315: listZones, lookupZones, fetchZoneChanges now default to .private since the public database only contains _defaultZone, making .public a degenerate default. MistDemo callers pass context.database / config.base.database explicitly so the --database flag still drives the test runs. Also repairs MistDemo test breakage from 7debe8d: toUserContextCredentials() was removed but tests still referenced it; rewritten against the replacement surface (toPrimaryCredentials embeds apiAuth on .public, plus the new hasUserContextCredentials boolean). The CredentialsValidationTests suite was deleted — it asserted init-time validation that no longer exists under per-call credential resolution; the equivalent .missingCredentials behavior is covered in MistKitTests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: gate @available(*,unavailable) on processDiscoverAllUserIdentitiesResponse to Swift 6.2+ Swift 6.1 rejects calls to an unavailable function from within another unavailable function; 6.2 relaxed that rule. The internal helper processDiscoverAllUserIdentitiesResponse is unavailable in lockstep with its only caller — the also-unavailable CloudKitService.discoverAllUserIdentities() — which built fine on 6.2+ but failed on Swift 6.1 with: error: 'processDiscoverAllUserIdentitiesResponse' is unavailable: Pending #28: discoverAllUserIdentities is not yet ready. Wrap just the attribute in `#if swift(>=6.2)` so the body is shared and 6.1 compiles. Inline doc records the intent and the one-line cleanup (delete the #if/#endif) once 6.1 is dropped from the matrix. A `swiftlint:disable:next unavailable_function` is required because swiftlint does not evaluate #if and otherwise sees a fatalError-only function without the attribute. Verified: swift build + swift test pass on Swift 6.1.3 (Linux container) and on macOS Swift 6.2+ (475/475 tests). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: split unhandled-response logging into debug (full body) + warning (type/status only) CodeQL's swift/cleartext-logging flagged the existing warning logs because lookupUsersByEmail(_:) propagates email-PII taint through the response object. Move full \(response) interpolation to .debug so the detail stays available for development without flowing into ops logs; keep .warning at type(of:) + HTTP status code only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #312: add --lookup-email / CLOUDKIT_LOOKUP_EMAIL to exercise users/lookup/email LookupUsersByEmailPhase previously skipped whenever fetchCaller() didn't return an email (which is the common case). Plumb a configurable lookup email through TestIntegrationConfig / TestPrivateConfig → PhaseContext so the phase can be driven against a known-discoverable iCloud account. Falls back to caller email, then to a clearer skip message naming the flag/env var. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: point CLAUDE.md lint section at mise (and Scripts/lint.sh) swift-format / swiftlint / periphery are pinned in mise.toml; the previous "requires swiftlint installation" wording led to PATH lookups that fail in this repo. Replace with `mise exec --` invocations and flag the full ./Scripts/lint.sh pipeline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * #315: address review punch list — invalidPrivateKey, recoverable unavailable response, supportsUserContextPhases derivation - CloudKitError: add invalidPrivateKey(path:underlying:) so PEM-load failures carry the file path + original error instead of bare Foundation NSError. Wrap loadPEM() at the single call site in Credentials+TokenManager. Add PrivateKeyMaterial.filePath accessor for the diagnostic. - processDiscoverAllUserIdentitiesResponse: replace fatalError with throw CloudKitError.unsupportedOperationType so a stray Swift 6.1 caller (where the @available cascade does not apply) gets a recoverable error instead of a crash. - TestPrivateCommand: derive supportsUserContextPhases from config.base.hasUserContextCredentials, mirroring TestIntegrationCommand, so user-identity phases skip cleanly when web-auth env vars are absent. - toPrimaryCredentials: replace try? with do/catch + stderr INFO line so operators see when web-auth is missing on a .public setup. - CLAUDE.md: annotate discoverAllUserIdentities() as unavailable pending #28. - CredentialsTokenManagerTests: fill the missing routing-matrix branches (user-context × .private/.shared, .shared + token-only) and cover the new .invalidPrivateKey path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> commit 6f92a71 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 8 13:16:56 2026 -0400 Resolve #308: docs refresh + CI fixes + sub-issues #165, #285 (#309) commit a1e2162 Author: leogdion <leogdion@brightdigit.com> Date: Fri May 8 07:16:10 2026 -0400 Add query pagination support with continuation markers (#306) commit c62bf44 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 15:52:45 2026 -0400 Improve error handling: typed TokenManagerError and safe RecordOperation conversion (#305) commit 7c4b678 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:27:10 2026 -0400 git subrepo push Examples/CelestraCloud subrepo: subdir: "Examples/CelestraCloud" merged: "4244497" upstream: origin: "git@github.com:brightdigit/CelestraCloud.git" branch: "mistkit" commit: "4244497" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "b9763ee528" commit f14e751 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:27:07 2026 -0400 git subrepo push Examples/BushelCloud subrepo: subdir: "Examples/BushelCloud" merged: "123a732" upstream: origin: "git@github.com:brightdigit/BushelCloud.git" branch: "mistkit" commit: "123a732" git-subrepo: version: "0.4.9" origin: "https://github.com/Homebrew/brew" commit: "b9763ee528" commit a0f0af9 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:26:32 2026 -0400 updating example packages commit 125dab5 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 11:01:18 2026 -0400 Refactor AuthenticationMiddleware so each Authenticator applies itself (#294) commit f989fd1 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:23:23 2026 -0400 Strengthen environment and database configuration validation (#293) commit b0f00a7 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:18:52 2026 -0400 Add operation classification and batch sync result tracking (#296) commit 63a4e50 Author: leogdion <leogdion@brightdigit.com> Date: Thu May 7 10:09:27 2026 -0400 Move CloudKitResponseType default implementations to protocol extension (#292) commit ae1af15 Author: leogdion <leogdion@brightdigit.com> Date: Wed May 6 20:20:44 2026 -0400 Test suite improvements for v1.0.0-beta.1 (#286) (#287) commit 5475bfa Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 20:21:32 2026 -0400 MistDemo: --database flag + demo-errors command (closes #259, #269) (#282) commit 8b21425 Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 20:21:17 2026 -0400 Refactor IntegrationTestRunner into protocol-based phase pipeline (#254) (#283) commit 9709f3d Author: leogdion <leogdion@brightdigit.com> Date: Tue May 5 08:54:16 2026 -0400 Replace custom AsyncChannel with swift-async-algorithms (#280) commit d53467a Author: leogdion <leogdion@brightdigit.com> Date: Mon May 4 12:49:25 2026 -0400 CI Updates for May 2026 (#277) commit d7b1a21 Author: Leo Dion <leogdion@brightdigit.com> Date: Thu Apr 30 09:39:09 2026 -0400 MistDemo improvements: test split, CRUD, auth fix, native app (#271) (#273) commit 0ab2ab6 Author: leogdion <leogdion@brightdigit.com> Date: Wed Apr 29 15:49:34 2026 -0400 First Draft Revision of Docs (#268)
No description provided.