Job code and workflow YAML can reach Sentry, and two of the routes also reach the client over SSE. All of this predates #446; the branch for that issue closes the frame-locals route and nothing else, so I am splitting the rest out rather than growing that PR further.
The frame-locals route is closed on the #446 branch by setting include_local_variables=False in services/entry.py. That one covers stack frames, including the __cause__/__context__ chain, so a handler that re-raises no longer ships the original frame. What it does not cover is anything explicitly attached to an event or logged as text.
Three routes remain. The first is sentry_sdk.set_context("request_data", ...) at services/workflow_chat/workflow_chat.py:1104 and services/job_chat/job_chat.py:748. The payload goes in whole, mask_secrets matches key-shaped values and has no notion of job code, and the context sits on the isolation scope, so one chat request attaches its workflow to every later event in that process. The second is code_edit_context.llm_edit_answer at services/job_chat/job_chat.py:612, which is the model's code answer. The third is LoggingIntegration, which is a default integration that auto_enabling_integrations=False does not switch off, so it picks up the full-prompt log at services/job_chat/prompt.py:536. The set_context and logging routes also reach the caller, because the bridge forwards matching log lines as SSE events (platform/src/bridge.ts:18).
Worth saying out loud in the same place: when a user opts into Langfuse, only the three main() functions pass capture_input=False, so every inner @observe span ships job bodies. That is consent rather than a leak, but nobody reading the code today would know it works that way.
I want to fix these together rather than piecemeal, because the pattern is the same each time and we have now declared this closed six times on the #446 branch alone. The shape of the fix is a single scrubber that knows what job code looks like, applied at before_send rather than at each call site, plus dropping the payload from set_context entirely and logging a digest instead of a prompt.
I will pick this up after #446 merges. Flagging it now so it does not get lost in that review thread.
Job code and workflow YAML can reach Sentry, and two of the routes also reach the client over SSE. All of this predates #446; the branch for that issue closes the frame-locals route and nothing else, so I am splitting the rest out rather than growing that PR further.
The frame-locals route is closed on the #446 branch by setting
include_local_variables=Falseinservices/entry.py. That one covers stack frames, including the__cause__/__context__chain, so a handler that re-raises no longer ships the original frame. What it does not cover is anything explicitly attached to an event or logged as text.Three routes remain. The first is
sentry_sdk.set_context("request_data", ...)atservices/workflow_chat/workflow_chat.py:1104andservices/job_chat/job_chat.py:748. The payload goes in whole,mask_secretsmatches key-shaped values and has no notion of job code, and the context sits on the isolation scope, so one chat request attaches its workflow to every later event in that process. The second iscode_edit_context.llm_edit_answeratservices/job_chat/job_chat.py:612, which is the model's code answer. The third isLoggingIntegration, which is a default integration thatauto_enabling_integrations=Falsedoes not switch off, so it picks up the full-prompt log atservices/job_chat/prompt.py:536. Theset_contextand logging routes also reach the caller, because the bridge forwards matching log lines as SSE events (platform/src/bridge.ts:18).Worth saying out loud in the same place: when a user opts into Langfuse, only the three
main()functions passcapture_input=False, so every inner@observespan ships job bodies. That is consent rather than a leak, but nobody reading the code today would know it works that way.I want to fix these together rather than piecemeal, because the pattern is the same each time and we have now declared this closed six times on the #446 branch alone. The shape of the fix is a single scrubber that knows what job code looks like, applied at
before_sendrather than at each call site, plus dropping the payload fromset_contextentirely and logging a digest instead of a prompt.I will pick this up after #446 merges. Flagging it now so it does not get lost in that review thread.