Recursively visit payloads inside ScheduleNexusOperationCommandAttributes when using system nexus#290
Conversation
Opengrep — new findings
Suppress findingsAdd a |
When the payload visitor encounters a ScheduleNexusOperationCommandAttributes targeting the system Nexus endpoint (__temporal_system) and the WorkflowService, its Input is a proto-binary-serialized request whose own fields carry the user payloads rather than an opaque single payload. Decode the envelope, visit the inner payloads recursively (so external storage and codecs apply to the inner payloads, not the envelope), and re-serialize -- leaving the envelope itself un-offloaded and un-codec'd. Ordinary Nexus operations continue to visit Input as a single opaque payload. The (service, operation) -> input proto type mapping comes from a new, dependency-free `nexussystem` registry package generated by nex-gen from a checked-in WIT (nexussystem/wit), wired into the build via the `nexus-system-registry` Make target. The envelope decode/visit/encode logic lives in a hand-written proxy/system_nexus.go helper that the generated interceptor calls; only binary/protobuf envelopes are accepted.
Simplify system Nexus envelope handling per review: - Identify a system Nexus envelope solely by the reserved __temporal_system endpoint (all operations on that endpoint are system Nexus operations), instead of also matching the service name. - Decode the envelope's proto message using the payload's "messageType" metadata via protoregistry.GlobalTypes, removing the need for the generated (service, operation) -> input-type registry. The nexussystem package, its checked-in WIT, and the nexus-system-registry Make target are deleted. - Inline the system-vs-ordinary Input dispatch directly into the generated visitPayloads (the ScheduleNexusOperationCommandAttributes case) rather than a separate helper function; visitSystemNexusEnvelope remains as the envelope decode/visit/encode helper. Envelopes still must be binary/protobuf; missing/unknown message types error.
392a187 to
105dddd
Compare
tconley1428
left a comment
There was a problem hiding this comment.
Let's mention that it only handles system nexus inputs currently. We can't fix that quite yet but it would be good to remember.
| localConcState = &payloadConcurrencyState{sem: concState.sem} | ||
| } | ||
|
|
||
| if err := visitPayloads(ctx, options, msg, localConcState, msg); err != nil { |
There was a problem hiding this comment.
I think this nested concurrent path should follow the top-level VisitPayloads wait-before-return shape. At the top level we do:
proxy/interceptor.go:110
err := visitPayloads(&visitCtx, &options, nil, c, msg)
c.wg.Wait()
if err != nil {
return err
}but here the function returns before waiting if recursive traversal returns an error.
Since localConcState can already have spawned visitor goroutines using the shared semaphore, an early traversal error or cancellation can let those goroutines continue after VisitPayloads returns.
There is a similar nested waitgroup pattern in defaultWellKnownAnyVisitor around proxy/interceptor.go:281, but it has the same early-return shape. I would use the top-level pattern here instead: store the traversal error, always wait on localConcState.wg, then return the traversal error or localConcState.firstErr.
There was a problem hiding this comment.
Nice catch! Fixed.
What
System Nexus messages shouldn't go through the codec because they're meant to be consumed by the Temporal service itself. But payloads inside the message should go through the codec.
How
Modify the payload visitor to treat
ScheduleNexusOperationCommandAttributescommands in a special way if the endpoint is__temporal_system. Specifically, we deserialize them using proto type information in the metadata, and recursively visiting the payloads inside. This is similar to what we already do foranypb.Anymessages with thedefaultWellKnownAnyVisitor.Tests
make proxy && (cd cmd/proxygenerator && go run ./ -verifyOnly)(generated code is current)go test -tags protolegacy ./...proxy/system_nexus_test.gothat exercise the happy and sad paths for visiting system nexus payloads