Add records/resolve and records/accept share operations (#41, #42) - #428
Add records/resolve and records/accept share operations (#41, #42)#428leogdion wants to merge 4 commits into
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>
Implements CloudKit Web Services' two sharing endpoints, both documented only in Apple's archived CloudKit Web Services Reference: - `records/resolve` (#41) — resolves share short GUIDs into information about the shared records: root record, `cloudKit.share` record, owner identity, and the caller's participation. - `records/accept` (#42) — accepts shares on behalf of the current user, returning the same result shape with the caller's resulting participation. Both take `{ shortGUIDs: [ShortGUID] }` and return `{ results: [ShortGUIDResult] }`. Apple's reference fixes the path's database scope to `public`, and both act on behalf of the *current* user, so — like `fetchCaller()` — they hard-code `.public(.requires(.webAuth))` and expose no `database:` parameter. Both validate the request as a whole (a bad short GUID fails the entire call), so there is no per-item RecordResult-style failure variant. Spec changes (openapi.yaml, regenerated via Scripts/generate-openapi.sh): - New paths `records/resolve` + `records/accept`. - New schemas `ShortGUID`, `ShortGUIDResult`, `ShortGUIDResultResponse`, `ShareParticipant`, `ShareReference`, `ShareTargetReference`. - Share request keys on `RecordRequest` (`createShortGUID`, `forRecord`, `publicPermission`, `participants`) and share response keys on `RecordResponse` (`shortGUID`, `share`, `publicPermission`, `participants`, `owner`, `currentUserParticipant`), per the #42 gap analysis. Domain models land in Sources/MistKit/Models/Sharing/. `ShareInfo` lifts the share-specific keys off a `cloudKit.share` record, since `RecordInfo` models a plain record and carries no sharing metadata. `Environment` gains `Codable` so `ShareRecordInfo` can synthesize it. Verified: swift build, swift test (571 tests, 178 suites, all passing), swift-format, and ./Scripts/lint.sh (0 violations, no unused code). Closes #41 Closes #42 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Important Review skippedDraft detected. 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 |
Review:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v1.0.0-beta.4 #428 +/- ##
================================================
Coverage ? 77.60%
================================================
Files ? 171
Lines ? 4000
Branches ? 0
================================================
Hits ? 3104
Misses ? 896
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:
|
Flip ResolveCommand off PendingStub, add AcceptCommand, wire integration phases and web routes so records/resolve and records/accept can be tested. Co-authored-by: Cursor <cursoragent@cursor.com>
Code Review — PR #428 (Standards + Spec)Reviewed via two independent parallel passes: does the diff follow this repo's documented conventions (Standards), and does it faithfully implement issues #41/#42 (Spec)? StandardsNo hard violations of documented CLAUDE.md rules found — ACLs are explicit throughout, every Judgement-call smells (baseline, not standards breaches — repo conventions already override where relevant):
Spec(a) Missing/partial requirements: none. Both endpoints, both schema groups, request-side share-creation keys, and response-side share fields are all present. Both curated methods ( (b) Scope beyond the issues' literal text (not flagged as a defect): the MistDemo (c) Implementation accuracy: endpoint paths/operationIds match ( SummaryStandards: 0 hard violations, 4 judgement-call smells (worst: the Both self-flagged verification caveats from the issue threads (no live-service call made against a real CloudKit container; 🤖 Generated with Claude Code |
Summary
Implements CloudKit Web Services' two record-sharing endpoints:
records/resolve(Fetching Record Information (records/resolve) #41) — resolves share short GUIDs into information about the shared records: root record,cloudKit.sharerecord, owner identity, and the caller's participation.records/accept(Accepting Share Records (records/accept) #42) — accepts shares on behalf of the current user, returning the same result shape with the caller's resulting participation.Public API:
Auth: no
database:parameterApple's reference fixes both paths' database scope to
public, and both operations act on behalf of the current user. So — following the existingfetchCaller()precedent — they hard-code.public(.requires(.webAuth))and expose nodatabase:parameter. This is not a silent policy default (cf.feedback_no_silent_policy_defaults): there is no valid alternative for the caller to choose, so the choice is removed from the API rather than defaulted.Both endpoints validate the request as a whole — a bad short GUID fails the entire call rather than producing a per-item error — so there is deliberately no
RecordResult-style per-item failure variant (same reasoning asassets/rereference).How the wire format was verified
Both endpoints are absent from
.claude/docs/webservices.md(and from Apple's current online docs), so per project memoryreference_cloudkit_archived_endpoints.mdthe shapes were confirmed against Apple's archived CloudKit Web Services Reference:POST …/public/records/resolve, request{ shortGUIDs: [ShortGUID] }, response{ results: [ShortGUIDResult] }POST …/public/records/accept, same request/response shapes.claude/docs/webservices.md:1610-1672createShortGUID,forRecord,publicPermission,participants) and the share response keys.claude/docs/cloudkitjs.md(CloudKit.RecordInfo,CloudKit.Share,CloudKit.ShareParticipant)Changes
openapi.yaml(regenerated via./Scripts/generate-openapi.sh—Sources/MistKitOpenAPI/was never hand-edited):records/resolve(operationId: resolveShortGUIDs) andrecords/accept(operationId: acceptShares).ShortGUID,ShortGUIDResult,ShortGUIDResultResponse,ShareParticipant,ShareReference,ShareTargetReference.RecordRequest(createShortGUID,forRecord,publicPermission,participants) and share response keys onRecordResponse(shortGUID,share,publicPermission,participants,owner,currentUserParticipant).Domain models (
Sources/MistKit/Models/Sharing/):ShortGUID,ShareRecordInfo,ShareInfo,ShareParticipant,SharePermission,ShareParticipantType,ShareAcceptanceStatus,ShareDatabaseScope,SharePotentialMatch.ShareInfolifts the share-specific keys off acloudKit.sharerecord, becauseRecordInfomodels a plain record and intentionally carries no sharing metadata.ShareDatabaseScopeis deliberately separate fromDatabase— it is a plain descriptor CloudKit returns, carrying noPublicAuthPreference.EnvironmentgainsCodable(it is already aStringraw-value enum) soShareRecordInfocan synthesize its conformance.Operations:
CloudKitService+ShareOperations.swift,CloudKitResponseProcessor+Sharing.swift, plus the twoOperations.*.Outputerror-mapping extensions andOperationInputPathconformances.Docs: CLAUDE.md/AGENTS.md operations table + a "Share Operations" section; README roadmap moves both issues into a new
v1.0.0-beta.4section.Verification
swift buildswift testmise exec -- swift-format./Scripts/lint.sh(swiftlint + swift-format lint + header.sh + periphery)./Scripts/generate-openapi.shre-runopenapi.yamlTests assert the serialized request body (that
shortGUIDsis sent in order, thatshouldFetchRootRecord/rootRecordDesiredKeysare carried, and that omitted optionals are not emitted as nulls), full response-field mapping, thepotentialMatchListambiguous-caller path,ShareInfoextraction, and top-levelBAD_REQUESThandling for both operations.Not verified
potentialMatchListis the least-documented part of the response — Types.html describesparticipantId+contactInformation{emailAddress, phoneNumber}but shows no example. Modeled as described; the fields are all optional so an unexpected shape degrades rather than throws.createShortGUID/forRecord/publicPermission/participantsrequest keys are modeled in the schema (as Accepting Share Records (records/accept) #42's gap analysis asks) and are reachable viaMistKitOpenAPI, but no curated "create a share" API is exposed onCloudKitService— that is a larger surface deserving its own issue.Closes #41
Closes #42
🤖 Generated with Claude Code