Add custom/shared zone support to the query path (#146) - #426
Conversation
Adds two project memory files plus their MEMORY.md index entries: - project_beta4_worktree_layout: the branch/worktree split for the remaining v1.0.0-beta.4 issues, the grouping rule (shared openapi.yaml path family => shared branch, to avoid Sources/MistKitOpenAPI/ regeneration collisions), and why #407 was excluded. - project_419_fixed_in_beta3: #419 is already fixed by 5a58120 and verified building on macOS Swift 6.3.2; do not re-implement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`queryRecords` hard-coded `zoneID: .init(zoneName: "_defaultZone")` into the `records/query` request body, which made custom and shared zones unqueryable. Thread an optional `zoneID: ZoneID? = nil` through the query path: - `queryRecords(_:limit:desiredKeys:continuationMarker:zoneID:…)` — the `Query` primitive that builds the request body - both deprecated `queryRecords(recordType:…)` overloads - `queryAllRecords(…)` — forwarded on every page it fetches - `fetchExistingRecordNames(…)` — so a pre-fetch can target the same zone as the `modifyRecords(_:zoneID:)` that follows it Use `ZoneID` rather than the bare `zoneName: String` the issue sketched, so shared zones can carry `ownerName`. This also matches the existing `modifyRecords(_:atomic:zoneID:…)` parameter. `nil` omits the `zoneID` key entirely and lets CloudKit resolve the database's default zone. That is not a silent policy default in the sense of `.claude/memory/feedback_no_silent_policy_defaults.md` — no credential or attribution semantics ride on it — and it keeps the change source-compatible. `database:` still has no default. `RecordManaging`'s query methods stay zone-unaware: that protocol is a deprecated, database-agnostic abstraction. No OpenAPI change was needed — `Components.Schemas.ZoneID` already models `zoneName` + `ownerName`, and `records/query` already references it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
ReviewReviewed the diff ( Code quality & design
Potential bugs / edge cases
PerformanceNo concerns — this only changes what gets serialized into an existing request body; no new allocations, requests, or pagination behavior beyond forwarding SecurityNo concerns. Test coverageThe new
I did not find a test for the NitThe PR description states the wire-level behavior change (dropping the always-present Overall: solid, well-tested, well-documented fix that matches established codebase conventions ( |
|
Review: PR #426 — Custom/shared zone support for the query path Nice, focused change with strong justification for the design calls. Went through the diff plus the surrounding codebase for consistency. Code quality / correctness
Potential issues
Test coverage Security / performance Docs Overall: solid, well-scoped implementation matching established codebase conventions. The memory-file scope creep is the only thing worth asking about before merging. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## v1.0.0-beta.4 #426 +/- ##
================================================
Coverage ? 76.25%
================================================
Files ? 158
Lines ? 3765
Branches ? 0
================================================
Hits ? 2871
Misses ? 894
Partials ? 0
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Wire zoneID and optional zone owner through QueryCommand, the query integration phase, and the web query path so #146 can be exercised live. Co-authored-by: Cursor <cursoragent@cursor.com>
Review: Add custom/shared zone support to the query path (#146)Reviewed against Strengths
Issues
Minor
Performance / SecurityNo concerns on either front. The added parameter is optional and zero-cost when omitted, and zone name/owner are opaque identifiers passed straight through to CloudKit with no new attack surface (same handling as the existing 🤖 Generated with Claude Code |
Summary
queryRecordshard-codedzoneID: .init(zoneName: "_defaultZone")into therecords/queryrequest body (CloudKitService+Operations.swift:85), making custom and shared zones unqueryable. This threads an optional zone through the whole query path.Design decisions
ZoneIDrather thanzoneName: StringThe issue sketched
zoneName: String = "_defaultZone". I used the existingZoneIDtype instead:ZoneIDcarriesownerName, which a bare string cannot. Shared zones live in the owner's database and are unaddressable without it — so azoneName-only parameter would have left the issue's own "working with shared zones" use case unsolved.modifyRecords(_:atomic:zoneID:desiredKeys:numbersAsStrings:database:)already takeszoneID: ZoneID? = nil, with the sameComponents.Schemas.ZoneID(from:)conversion. Query and modify now name their zone the same way.ZoneID.defaultZoneremains available for callers who want to say "default zone" explicitly.Defaulted (
= nil) rather than requiredPer
.claude/memory/feedback_no_silent_policy_defaults.mdthis was a deliberate call, not an oversight:PublicAuthPreference), where a silent default caused records to be mis-attributed. Nothing comparable rides on zone selection — a wrong zone yields wrong-or-empty results, visibly, not a silent security/ownership mistake.nildoes not mean "quietly substitute_defaultZone". It means omit thezoneIDkey from the request entirely and let CloudKit resolve the default zone server-side. There is no client-side policy being invented.zoneID/desiredKeys/numbersAsStrings/zoneWideonmodifyRecordsandfetchRecordChangesare all optional-defaulted).database:still has no default, as CLAUDE.md requires — untouched.Surfaces updated
queryRecords(_:limit:desiredKeys:continuationMarker:zoneID:zoneWide:numbersAsStrings:database:)queryRecords(recordType:…)× 2 (deprecated)zoneIDto the primitivequeryAllRecords(…)zoneIDon every page it fetchesfetchExistingRecordNames(…)modifyRecords(_:zoneID:)that follows it in the classify workflowRecordManaging.queryRecords(recordType:)/queryAllRecords(recordType:)are intentionally left zone-unaware — that protocol is a deprecated, database-agnostic abstraction (it hard-codes.public(.prefers(.serverToServer))too). Callers needing a zone should useCloudKitServicedirectly. Happy to revisit if you'd rather it be zone-aware.No OpenAPI regeneration needed
Components.Schemas.ZoneIDalready models bothzoneNameandownerName, and therecords/queryrequest body already$refs it.openapi.yamlandSources/MistKitOpenAPI/are untouched.Source compatibility
Source-compatible. Every new parameter is defaulted, and each was inserted before the non-defaulted
database:, so existing call sites keep compiling unchanged — confirmed by the Examples build below, which needed no edits.One behavioral change worth flagging: requests previously always carried
"zoneID": {"zoneName": "_defaultZone"}; they now omit the key when no zone is given. CloudKit resolves the same default zone either way, so this is wire-level-different but semantically equivalent. ThequeryOmitsZoneIDByDefaulttest pins the new behavior.Tests
Six new
@Tests inTests/MistKitTests/CloudKitService/Query/CloudKitServiceTests.Query+ZoneID.swift, added as aZone Selectionsuite under the existingCloudKitServiceTests.Queryenum parent (per the enum-vs-struct convention — that parent already spans multiple files). They assert against the serialized request body captured byMockTransport:zoneIDomitted when none is supplied (default-zone behavior unchanged)zoneNameforwarded, with no strayownerNameownerNameforwardedZoneID.defaultZoneforwarded explicitly when askedqueryAllRecordsforwards the zone on both pages of a paginated runfetchExistingRecordNamesforwards the zoneVerification
swift buildswift testmise exec -- swift-format -i -r Sources/ Tests/./Scripts/lint.shExamples/MistDemoswift buildDocs
AGENTS.md(CLAUDE.mdsymlink): new "Zone selection on queries (Feature: Add custom CloudKit zone support for queries #146)" section recording theZoneID-vs-zoneNameand default-vs-required calls.WorkingWithRecords.md: new "Querying a custom or shared zone" subsection with custom-zone and shared-zone examples, plus a note onzoneIDvszoneWide.queryRecords/queryAllRecordsupdated for the new signatures across five.doccarticles.Closes #146
🤖 Generated with Claude Code