Skip to content

Apple shell: carry every server request through one HTTP adapter - #65

Merged
JacobStephens2 merged 4 commits into
issue-57from
issue-61
Oct 3, 2026
Merged

JacobStephens2 merged 4 commits into
issue-57from
issue-61

Conversation

@JacobStephens2

@JacobStephens2 JacobStephens2 commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

The Apple shell (iOS and macOS, through CascadeShared) now carries every sync-server request on one code path. The core decides what each request means.

 AppStore.apply(effect)
-  case .pushListening / .sendSignInLink / .verifySignInToken /
-       .revokeSession / .deleteServerListening / .deleteServerAccount
-    carry(effect)            # switch per request → SyncApi typed call → one of 7 settles
+  case .serverRequest(let request)
+    carry(request)
+      Task @MainActor
+        dispatch(await ServerCarrier.send(request))   # → .serverResponse(id, status, body)
 CascadeShared/Sync/
-├── SyncApi.swift        # typed client, VerifyResponse, ListeningResponse, SyncError
+├── ServerCarrier.swift  # sends method + base URL + path, Bearer when given, body verbatim
+├── SyncConfig.swift     # base URL / "sync available" (unchanged, moved)
 └── AccountControlsView.swift   # delete buttons now make the fresh UUID
  • ServerCarrier.send returns status 0 in these cases: no sync server configured, a bad URL, a non-HTTP response, or a thrown error (network, the 15 s timeout, cancellation).
  • The sign-out revoke is now settled like every other request.
  • Dto.swift mirrors the core's wire:
    • Effect.serverRequest(ServerRequest) and Command.serverResponse(id:status:body:).
    • newDeviceId on deleteListeningData / deleteAccount.
    • Optional platform on requestSignInLink.
  • The watch app's phone↔watch protocol is untouched.

Evidence

  • cargo test: every suite passes. The core is unchanged on this branch.
  • Apple build (CI): passes. Run 37161662889 builds CascadeMac, CascadeiOS and CascadeWatch against the new core. The authoring host has no Swift toolchain, so this is the only compile.
  • Not yet checked by hand: sign-in by link, a listening sync, sign-out, delete listening data and delete account against the sync server.
  • I checked the JSON wire shapes by reading them against effect.rs, command.rs and server.rs.

Merge Danger

Door: two-way

Revert the commits to bring back the typed client.

Blast Radius: account-sync

If it is wrong, sign-in, listening sync and the delete actions on iOS and macOS break. Playback, timers and the watch app don't touch this path.

Unaddressed findings

Standards

  • Speculative Generality: platform on requestSignInLink is never sent by this shell. Kept. Issue Apple shell: carry every server request through one HTTP adapter #61 asks for the DTO to carry it, and it matches the core's wire. Only the Windows shell needs a link hand-off.
  • Duplicated Code: UUID().uuidString appears inline in both delete buttons. Kept. The issue says the fresh UUID is "made when the user asks", and a helper for one expression adds little.

Spec

  • The Apple shell sends no platform with the sign-in link request. Intended: "behave as before on this platform". Apple handles the link through its universal link.
  • Content-Type: application/json is now set only when there is a body. Kept. The server reads JSON only on routes that take a body (axum Json extractor), and bodiless DELETEs and logout don't check the header.
  • Hand-testing against the sync server has not been done. No Apple toolchain or device on the authoring host. CI builds it, and the manual run is left for review.

Closes #61

🤖 Generated with Claude Code

JacobStephens2 and others added 4 commits October 3, 2026 19:15
The DTOs mirror the core's new wire: one serverRequest effect in place of
the six request effects, one serverResponse command in place of the seven
settles, newDeviceId on deleteListeningData / deleteAccount (a fresh UUID
made when the user asks) and the optional platform on requestSignInLink.

ServerCarrier replaces the typed SyncApi client and its response types:
it sends any request to the sync-server base URL as described and returns
the serverResponse that settles it, status 0 with no sync server or on a
network error, timeout or cancellation. AppStore carries every request,
the sign-out revoke included, and dispatches the settle on the main actor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JacobStephens2
JacobStephens2 merged commit b4d7f51 into issue-57 Oct 3, 2026
1 check passed
@JacobStephens2
JacobStephens2 deleted the issue-61 branch October 3, 2026 23:42
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