picatz / picatz/flowstate

plugin: `ExecuteRequest` carries the task, the identity and the namespace and nothing that names the call — no run, step, attempt or idempotency key, so a plugin cannot be idempotent, cache per run, or correlate its own audit

Open
#1,677 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

engine enhancement security
Dominant language
Go
Stars
9
Forks
0
Avg merge
3h 3m
Merged PRs (30d)
509

Description

Observed behavior

At eb8172f, the whole of what a plugin learns about a call (proto/flowstate/plugin/v1/plugin.proto, message ExecuteRequest):

flowstate.v1.Task task = 1;
flowstate.v1.Scope scope = 2;
flowstate.v1.WorkloadIdentity identity = 3;
string namespace = 4;

The host forwards none of the activity's own facts: grep -n 'Attempt\|RunID\|WorkflowID\|ActivityID' pkg/flowstate/v1/plugin/task.go pkg/flowstate/v1/plugin/host.go is empty. Trace context crosses in headers through otelconnect, and the deadline crosses as Connect's timeout header, so those two are fine. What does not cross:

  • Which run and which step. A plugin writing its own audit line (#1399) or a log line (#1494) can name the tenant and the subject and not the run; the operator correlating a Slack post to a run does it by timestamp.
  • Which attempt. Temporal retries an activity, so a plugin task runs more than once with identical inputs and no way to tell the second from the first. slack.post posts twice; git.commit_push conflicts with itself; sql.exec runs an insert again. #1516 asks for a checkpoint field so a retry can resume; this is the smaller fact underneath it, that a retry cannot even recognize itself.
  • An idempotency key. The engine already derives a stable identity for a step invocation (workflow id, run id, step path, attempt), which is exactly what Stripe-shaped and Slack-shaped APIs accept as an idempotency key. The plugin has to invent one from inputs, which is wrong for two identical posts the author meant.

#1527 rule 2 says identity carries who the run is and never a token; this issue is about the call's identity, which is not a credential and is safe to send everywhere.

Desired outcome

An ExecuteRequest.call message: workflow_id, run_id, step (the one address grammar #1439 decides), attempt, and idempotency_key (a digest of the first four plus the namespace, stable across retries and Continue-As-New, never reused across runs). The SDK exposes it as sdk.CallInfo(ctx), and sdk.HTTPClient sets Idempotency-Key from it by default for requests a task marks idempotent.

Acceptance criteria

  • A conformance case runs a plugin task that fails once and succeeds on retry, and asserts the plugin saw attempt 1 then 2 with the same idempotency_key, on both drivers.
  • slack.post and github.issue_comment send the key on their requests where the provider accepts one, and their READMEs say so.
  • The plugin-side audit record (#1399) and relayed stderr lines (#1494) carry run_id and step.
  • Additive: a plugin built before the field ignores it; the handshake version does not change because absence is not a quiet failure.

Constraints and dependencies

  • The key must not be derivable into anything the plugin could use to address the control plane; it is a digest, not an id it can act on.
  • Adjacent: #1516 (checkpoint and resume), #1399, #1494, #1439, #1527.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with proto/flowstate/plugin/v1/plugin.proto and inspect pkg/flowstate/v1/plugin/task.go and host.go, including both plugin drivers and the existing conformance coverage. Resolve the step representation alongside #1439, then verify the retry case, SDK and HTTP behavior, provider integrations, audit and stderr context, README updates, and additive compatibility described in the acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend-api-design, devtools, distributed-systems, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.