Wire landed MistKit endpoints into MistDemo web app (#394)#396
Conversation
Replace the nine 501 "pending" stubs in MistKit-server mode with real Hummingbird handlers that forward to the already-shipped CloudKitService wrappers, restoring parity with CloudKit JS mode: records/lookup, records/changes, zones/list, zones/lookup, zones/changes, users/caller, users/discover, users/lookup/email, users/lookup/id - WebBackend gains nine webXxx methods; CloudKitService conforms via thin forwards split across +Reads (records/zones) and +Users extensions. - New request DTOs (WebRequests+Records/+Users, extended +Zones) and response DTOs (RecordChanges, ZoneChanges, Caller, Users). User routes carry no database selector — they run on the public DB with web-auth. - records/lookup surfaces per-record failures via try get(), matching the webModifySubscriptions precedent. - addUnwiredLandedEndpoints removed; WebServer+Pending now lists only records/resolve (#41, no wrapper yet). - The browser already branched to these /api/* routes in MistKit mode, so no front-end change was needed — wiring the server flips them off the stub. Tests: MockBackend extended with the nine methods + call captures; forwarding and 401-unauthorized tests per route. 963 MistDemo tests pass; swift-format, swiftlint, and header checks clean. Co-Authored-By: Claude Opus 4.7 (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 Run ID: 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✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## v1.0.0-beta.2 #396 +/- ##
================================================
Coverage ? 71.85%
================================================
Files ? 168
Lines ? 3844
Branches ? 0
================================================
Hits ? 2762
Misses ? 1082
Partials ? 0
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 — PR #396: Wire landed MistKit endpoints into MistDemo web appOverviewThis PR replaces nine 501 "pending" stubs in MistDemo's Hummingbird (server) mode with real handlers that forward to existing ✅ What's done well
🔍 Issues / observations1. return try results.map { try $0.get() }If CloudKit returns NOT_FOUND for even one record name, the entire request throws and the caller gets a 500 rather than a partial list. CloudKit's own REST API returns per-record errors in the response body. The PR description says this mirrors 2. lookupInfos: emails.map { UserIdentityLookupInfo(emailAddress: $0) }
3.
4. Test file naming inconsistency The zone-reads tests live in 5. desiredKeys: nil,Returns all fields for every record. No mechanism for the browser to request a projection. Fine for the demo, but if the response payload grows large (assets, large strings), it could be noticeable. A follow-up issue for field projection via the request body would be useful. 6. The three user-request structs in SummaryThe implementation is clean, well-scoped, and test-covered. The only blocking concern I'd flag before merge is item 1 (batch-fail on per-record NOT_FOUND in 🤖 Generated with Claude Code |
Code Review: Wire landed MistKit endpoints into MistDemo web app (#394)OverviewThis PR replaces nine 501 "pending" stubs in Hummingbird/MistKit-server mode with real handlers forwarding to existing What's done well
Minor observations1. Potentially unnecessary The file only uses 2. Silent empty-array fallback in request DTOs
try container.decodeIfPresent([String].self, forKey: .recordNames) ?? []A missing field is almost certainly a caller bug, so a hard decode failure would surface problems faster. For a demo this is acceptable — just worth noting in case these DTOs are reused in a stricter context later. 3.
4. All-or-nothing lookup failure UX Because 5. Thin wrapper boilerplate
No blocking issuesThe implementation is correct, the tests are solid, the cleanup of |
|
Review posted below - see next message |
Code Review: PR 396 - Wire landed MistKit endpoints into MistDemo web app ### Overview This PR replaces nine 501 stubs with real Hummingbird route handlers forwarding to already-shipped CloudKitService wrappers. Implementation is clean, consistent with existing patterns, and well-tested. ### Code Quality and Style Strengths - All route handlers follow the established tokenStore/backendFactory capture, auth guard, decode, runOperation pattern without deviation. - CloudKitService+WebBackend+Reads.swift / +Users.swift file split matches the existing +WriteOperations/+ZoneOperations convention. - Removing PendingVerb and registerPending in favour of registerPendingPost is the right cleanup now that the only remaining stub is a POST. - Per-record error surfacing in webLookupRecords is correctly documented, explaining the intentional fail-fast behaviour matching webModifySubscriptions. Minor observations 1. webListZones, webFetchCaller, etc. are pure one-liner pass-throughs - protocol indirection with no logic. Internally consistent with how webModifyZones wraps modifyZones; WebBackend is doing structural separation rather than enforcing behavioural contracts. Not a problem, just worth noting. 2. WebRequests.DiscoverUsers and WebRequests.LookupUsersByEmail are structurally identical (both decode emails array of strings). Separate types are the right call for type safety; worth knowing if this family grows. 3. WebRequests.ListZones uses a custom init(from:) just to call WebRequests.decodeDatabase for its only field. Consistent with existing zone DTO pattern but adds more code than a synthesised conformance would. ### Potential Issues Missing per-record failure test for records/lookup The comment in CloudKitService+WebBackend+Reads.swift calls out that the get() call surfaces per-record CloudKit errors (e.g. NOT_FOUND). There is no test exercising this code path. The consumePendingError() mechanism in MockBackend supports it. Adding a test would confirm the documented behaviour and prevent a future refactor from silently swallowing per-record errors. Auth failure tests omit database field recordsLookupRequiresAuth, zonesLookupRequiresAuth, and zonesChangesRequiresAuth send bodies without a database key. The 401 short-circuits before body decoding, so these are correct today - but if the auth guard were ever reordered the tests would fail for the wrong reason. Sending a fully valid body in 401 tests makes them more robust. ### Security - Email addresses in users/discover and users/lookup/email are forwarded to Apple CloudKit API. No server-side PII logging is introduced; the previous CodeQL-driven debug-level guard on response bodies is unaffected. - Token presence is checked before any backend call or body decode across all nine new routes. No bypass path is visible. ### Summary Clean implementation, correct auth handling, consistent style. The per-record failure test gap is the only functional blind spot worth addressing before merge; everything else is stylistic and non-blocking. |
Code Review — PR #396: Wire landed MistKit endpoints into MistDemo web appOverviewThis PR replaces nine 501 stubs in MistKit-server mode ( ✅ Strengths
🐛 Potential Issues1. return try results.map { try $0.get() }If a lookup for The comment says this mirrors 2. internal func webDiscoverUsers(
emails: [String]
) async throws -> [UserIdentity] {
try await discoverUserIdentities(
lookupInfos: emails.map { UserIdentityLookupInfo(emailAddress: $0) }
)
}
🔍 Minor Observations3. Empty
self.recordNames = try container.decodeIfPresent([String].self, forKey: .recordNames) ?? []A POST with no 4. No test for the per-record error path in The mock always returns stub records. The 5. Comments describe "what" rather than "why" in the conformance extensions Per CLAUDE.md: "Only add [a comment] when the WHY is non-obvious." The file-header comments like: // Read-side `WebBackend` conformance for records and zones: lookup, changes,
// and zone listing. The primary conformance declaration lives in ...…are navigation aids rather than rationale. The file name already communicates the content. Fine to keep if the convention elsewhere is the same, but worth noting for future files. SummaryThe implementation is solid and production-ready for a demo app. The two actionable items worth resolving before merge:
Everything else is style / nice-to-have. 963 tests passing and the lint pipeline clean are a good baseline. |
…antics Demo web app now exposes only the non-deprecated POST /users/discover for user-identity lookup; the Apple-deprecated /users/lookup/email and /users/lookup/id routes are removed from every layer (route, protocol, conformance, DTO, mock, tests, frontend). Discover accepts emails AND user record names, forwarded as UserIdentityLookupInfo entries; phone-number support is tracked in #398. webLookupRecords keeps its all-or-nothing behavior, but the comment now honestly describes it (dropping the misleading "matches webModifySubscriptions" claim) and a new test locks the semantic: a per-record backend failure surfaces as 500, not a partial 200. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review — PR #396: Wire landed MistKit endpoints into MistDemo web appOverviewThis PR replaces nine 501 stubs with real Hummingbird route handlers that forward to already-shipped ✅ What's working well
IssuesMinor — Missing error-propagation test for
|
Closes #394.
Replaces the nine 501 "pending" stubs in MistKit-server mode (
mistdemo web, Hummingbird) with real handlers forwarding to the already-shippedCloudKitServicewrappers (#215/#45/#47/#48/#367), restoring parity with CloudKit JS mode (the follow-up to #370's scaffolding).Endpoints wired
records/lookuplookupRecords()records/changesfetchRecordChanges()zones/listlistZones()zones/lookuplookupZones()zones/changesfetchZoneChanges()users/callerfetchCaller()users/discoverdiscoverUserIdentities()users/lookup/emaillookupUsersByEmail()users/lookup/idlookupUsersByRecordName()Changes
webXxxmethods onWebBackend;CloudKitServiceconformance split intoCloudKitService+WebBackend+Reads.swift(records/zones) and+Users.swiftfor file-length hygiene.WebRequests+Records/WebRequests+Usersand extendedWebRequests+Zones; newWebResponseshapesRecordChanges,ZoneChanges,Caller,Users. User routes carry nodatabaseselector — they run on the public DB with web-auth, matching the wrappers.records/lookupsurfaces per-record failures viatry $0.get(), mirroring thewebModifySubscriptionsprecedent.addUnwiredLandedEndpointsremoved;WebServer+Pendingnow lists onlyrecords/resolve(Fetching Record Information (records/resolve) #41 — no wrapper yet)./api/*routes in MistKit mode, so no JS change was needed — wiring the server flips each panel off the "pending Wire landed MistKit API endpoints into the MistDemo web app (MistKit-server mode) #394" banner.Tests
MockBackendextended with the nine methods + call-capture structs; per route a forwarding test and a 401-unauthorized test (mirroringWebServerTests+Assets). 963 MistDemo tests pass;swift build,swift-format,swiftlint, and header checks clean.🤖 Generated with Claude Code