feat(hybridcloud): Propagate ViewerContext through cross-silo RPC#112248
feat(hybridcloud): Propagate ViewerContext through cross-silo RPC#112248
Conversation
Pack ViewerContext into the RPC meta dict on the sending side and restore it via viewer_context_scope on the receiving side. This closes the gap where cross-silo RPC handlers had no ViewerContext despite the original request having one. Uses the existing reserved meta key in the RPC wire format. Backwards compatible — old callers send empty meta, receivers treat missing viewer_context as None. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 542e8dc. Configure here.
| viewer_context_scope(ViewerContext.deserialize(vc_data)) | ||
| if vc_data | ||
| else contextlib.nullcontext() | ||
| ) |
There was a problem hiding this comment.
Deserialization error outside try block causes unhandled 500
Low Severity
ViewerContext.deserialize(vc_data) is called outside the try block (line 75), so any exception from malformed vc_data (e.g. a non-dict truthy value) produces an unhandled 500 instead of a ParseError. This contrasts with the auth_context parsing just above, which wraps AuthenticationContext.parse_obj() in its own try/except for clean error reporting. Since meta comes from the request body, a malformed viewer_context value will bypass all exception handling in the method.
Reviewed by Cursor Bugbot for commit 542e8dc. Configure here.


Pack ViewerContext into the RPC
metadict on the sending side (_send_to_remote_silo) and restore it viaviewer_context_scopeon the receiving side (InternalRpcServiceEndpoint).Previously, cross-silo RPC handlers had no ViewerContext — the middleware saw RPC signature auth, not the original user. The real user identity was only available through
AuthenticationContext(which most RPC calls don't pass). Now the contextvar is automatically propagated throughmeta, which was already reserved in the wire format for exactly this kind of use.Backwards compatible — old callers send
meta: {}, receivers treat missingviewer_contextasNone.Also adds
ViewerContext.deserialize()as the inverse ofserialize().Part of the ViewerContext RFC.