Skip to content

feat(apple): connect typed RVT1 client to scoped device gateway - #305

Merged
turinglambdaai merged 15 commits into
mainfrom
feature/rvt1-device-gateway
Oct 23, 2026
Merged

turinglambdaai merged 15 commits into
mainfrom
feature/rvt1-device-gateway

Conversation

@turinglambdaai

@turinglambdaai turinglambdaai commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

What this adds

  • Add a bounded RVT1 frame channel over the authenticated Apple application byte stream, including serialized writes, partial-read buffering, frame-size limits, and fail-closed behavior on malformed/oversized frames.
  • Add RivetDeviceAppleRVT1Client with Hello validation, typed request/response correlation, matching cancellation frames, event delivery, and a lifecycle-aware run() method that keeps the companion application's handler alive until disconnect.
  • Add RivetDeviceAppleRVT1GatewayServer to dispatch through a per-pairing RivetDeviceGatewaySession, forward cancellation, bound concurrent requests, and filter event/state-change delivery against grants. Shutdown revokes the session and cancels outstanding work instead of waiting indefinitely for a slow backend.
  • Add RivetDeviceRVT1BackendHost to decode bounded RivetValue argument lists, call the existing local typed RPC client, and encode results.
  • Add RivetRPCClient so generated Swift APIs can target either the in-process client or the authenticated network client; update generated scaffolding and the taskboard example.
  • Close a state-authorization gap: ordinary invokeRPC can no longer invoke $state/get or $state/set without the package-scoped, state-name-specific authorization path.
  • Add in-memory tests for hello/correlation, client and gateway cancellation, shutdown, request bounds, state grant isolation, event filtering, oversized-frame closure, and backend argument/result encoding.

Security and lifecycle

The RVT1 server accepts an already authenticated RVD1 connection; it does not bypass TLS pinning, pairing confirmation, or credential persistence. It closes the gateway session when the connection ends and returns generic denial errors. The product host still chooses each paired device's scopes and wires host events/state changes to the server.

Validation and remaining product work

Full CI must pass before merge. This PR supplies the reusable post-RVD1 RVT1 path; it does not by itself ship a signed iOS/iPadOS/watchOS app, configure app permissions, choose product-specific scopes, or provide physical-device acceptance.

@turinglambdaai
turinglambdaai force-pushed the feature/rvt1-device-gateway branch from c9f025b to 2ef3688 Compare October 22, 2026 05:47
@turinglambdaai
turinglambdaai force-pushed the feature/rvt1-device-gateway branch from bf395f3 to 1827328 Compare October 22, 2026 06:44

Copy link
Copy Markdown
Owner Author

CI triage / follow-up (2026-10-22): commit d82e9fd fixes two deterministic failures from the previous PR head.

  • Swift package smoke builds resolve the last released SwiftPM runtime, which does not yet export RivetRPCClient. Generated RivetAPI now emits its own RivetGeneratedRPCClient compatibility protocol, extends RivetClient, and provides init(call:) for an authenticated device client's call function. The generator, checked-in host/taskboard outputs, and codegen assertions are updated together.
  • stateRoutesRequireTheExactStateCapability previously expected 0x42 even though the mock host echoes the request payload. The test now checks the actual echoed payload and verifies that the allowed state RPC receives the original arguments.

The new head's 23-job cross-platform matrix is still running; these fixes are not a green-CI or merge claim. Earlier Linux failures in installer/embedded tests were package-install timeouts (exit 124), independent of the Swift assertions.

The hello write suspends while its bytes join the channel's serialized
queue. A product that observes the hello bytes and immediately calls
sendEvent could have its call scheduled on the gateway actor before the
post-send resumption set ready, failing with notRunning even though the
wire order was still correct. Ready now precedes the write; the channel
queue keeps hello ahead of any event, and a failed hello still closes
the server through the existing error path. Reproduced one failure in
roughly six local runs of the per-device filtering test; thirty runs
pass after the fix, and the full Swift suite stays green.
@turinglambdaai
turinglambdaai merged commit eaaf341 into main Oct 23, 2026
23 checks passed
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