Skip to content

Add RecordName value type for record identifiers - #472

Open
leogdion wants to merge 1 commit into
v1.0.0-beta.5from
465-record-name
Open

Add RecordName value type for record identifiers#472
leogdion wants to merge 1 commit into
v1.0.0-beta.5from
465-record-name

Conversation

@leogdion

@leogdion leogdion commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Introduce RecordName as a string-backed struct (JSON string, string-literal) instead of a typealias or enum.
  • Adopt it on identity-bearing MistKit APIs (Reference, RecordInfo, CloudKitRecord, lookup/write conveniences). OpenAPI generated types stay String.
  • ownerRecordName / user-identity names left as String / UserRecordName.

Closes #465

May need a rebase onto #470 if both touch Reference conversion.

Test plan

  • swift test (MistKit)
  • Example packages (MistDemo, CelestraCloud, BushelCloud) still compile

Made with Cursor

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 53ee39f0-7397-43f3-9a3e-12385e6353e6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@claude

claude Bot commented Sep 3, 2026

Copy link
Copy Markdown

Review: RecordName value type (closes #465)

Reviewed the diff (93 files) plus the merged tree in this checkout. The mechanical rollout — RecordInfo, Reference, RecordOperation, CloudKitRecord, the batch/lookup/share conveniences, and all three example packages (BushelCloud, CelestraCloud, MistDemo) — is thorough and consistent. RecordName itself is a solid design: RawRepresentable<String> + ExpressibleByStringLiteral + a hand-written single-JSON-string Codable (matches the CLAUDE.md convention for wire-identity types) + Comparable/Hashable, and it preserves the exact wire shape (auto-synthesized Codable on Reference etc. still emits a bare string), so this shouldn't change any JSON on the wire. Good call keeping MistKitOpenAPI's generated types as plain String and converting only at the MistKit boundary.

A few things worth a look before merge:

1. Likely swift-format violation

Sources/MistKit/CloudKitService/CloudKitService+CreateShare.swift:76:

rootRecordName ?? RecordName(rawValue: "mistkit-share-root-\(UUID().uuidString.lowercased())")

This line is 102 chars; .swift-format's lineLength is configured at 100. ./Scripts/lint.sh should catch this — worth running mise exec -- swift-format -i -r Sources/ before merge (I wasn't able to run the build/lint/test suite myself in this environment, so please double check).

2. @_implements used to route around a naming collision

Examples/BushelCloud/Sources/BushelCloudKit/Extensions/{DataSourceMetadata,RestoreImageRecord,SwiftVersionRecord,XcodeVersionRecord}+CloudKit.swift each add:

@_implements(CloudKitRecord, recordName)
public var cloudKitRecordName: RecordName {
  RecordName(rawValue: recordName)
}

@_implements is an underscored/private compiler attribute (not part of the documented Swift language surface) that lets a differently-named member satisfy a protocol requirement — used here because these BushelFoundation models already expose their own recordName: String domain field and can't also declare a same-named RecordName-typed member. It works, but it's a fairly exotic mechanism to lean on in application code, and it's currently untested/unexercised: cloudKitRecordName isn't referenced anywhere else in the repo (grep -rn cloudKitRecordName only turns up the 4 declarations). That's consistent with the SyncEngine.syncRecords refactor in the same PR, which deliberately dropped its T: CloudKitRecord constraint in favor of explicit recordType:/name: KeyPath<T, String>/fields: parameters — i.e. it sidesteps the protocol's new recordName: RecordName requirement rather than using it. So today @_implements exists purely to keep the CloudKitRecord conformance compiling (for from/toCloudKitFields/formatForDisplay), not because anything calls .recordName through the protocol on these types. Given that, it might be simpler/more conventional to have these 4 conformances not rely on @_implements at all — e.g. thread RecordName in from the call site the same way syncRecords now does, or give the protocol member a distinct name — rather than establishing @_implements as a repo pattern for future adopters to copy.

3. Breaking API change could be called out more explicitly

CloudKitRecord.recordName is a public protocol requirement whose type changed from String to RecordName (Sources/MistKit/RecordManagement/CloudKitRecord.swift:77) — source-breaking for any external conformer. ReleaseNotes.md adds one terse bullet under "API Cleanup"; given how deliberate this repo's release process is about flagging breaking changes (per the release runbook), it'd be worth being explicit that this is a breaking change for CloudKitRecord adopters. Also, since this PR is already touching that exact requirement, it's a good opportunity to fix the protocol's doc comment: the "Example Conformance" sample at the top of CloudKitRecord.swift still doesn't show a recordName implementation at all (pre-existing gap, not introduced by this PR, but low-effort to fix here).

4. Minor: test coverage

RecordNameTests.swift covers the Codable round-trip, string-literal init, and Reference conversion, but nothing exercises Hashable/Set or Comparable directly even though Set<RecordName> is now load-bearing (OperationClassification, fetchExistingRecordNames, dedup logic in SyncEngine). Not blocking, just a nice-to-have given how central Set<RecordName> equality/hashing is to the classification logic.

Nothing else stood out — didn't spot correctness bugs in the .rawValue/RecordName(...) conversions I traced through (lookup/create/update/delete, share create/resolve/accept, asset upload, notifications, reference field values).

@codecov

codecov Bot commented Sep 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.73684% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.36%. Comparing base (83877bc) to head (a2a2f45).

Files with missing lines Patch % Lines
Sources/MistKit/Models/RecordTarget.swift 0.00% 1 Missing ⚠️
...mponents/Components.Schemas.ListValuePayload.swift 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                Coverage Diff                @@
##           v1.0.0-beta.5     #472      +/-   ##
=================================================
+ Coverage          86.29%   86.36%   +0.06%     
=================================================
  Files                198      199       +1     
  Lines               4810     4825      +15     
=================================================
+ Hits                4151     4167      +16     
+ Misses               659      658       -1     
Flag Coverage Δ
mistdemo-spm-macos 11.37% <36.84%> (+0.21%) ⬆️
mistdemo-swift-6.4-jammy 11.38% <36.84%> (+0.21%) ⬆️
mistdemo-swift-6.4-noble 11.38% <36.84%> (+0.21%) ⬆️
spm 85.07% <94.73%> (+0.06%) ⬆️
swift-6.1-jammy 85.07% <94.73%> (-0.04%) ⬇️
swift-6.1-noble 85.28% <94.73%> (+0.27%) ⬆️
swift-6.2-jammy 85.07% <94.73%> (+0.19%) ⬆️
swift-6.2-noble 85.05% <94.73%> (+0.15%) ⬆️
swift-6.3-jammy 84.97% <94.73%> (-0.10%) ⬇️
swift-6.3-noble 85.05% <94.73%> (+0.06%) ⬆️
swift-6.4-jammy 84.95% <94.73%> (-0.02%) ⬇️
swift-6.4-noble 85.17% <94.73%> (+0.29%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant