Three rehearsal-identity gaps left after #651: the plugin boundary, flow test, and denial provenance
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 9
- Forks
- 0
- Avg merge
- 3h 3m
- Merged PRs (30d)
- 509
Description
Three gaps the #295 sweep found and deliberately did not close in #651, each for a different reason. Filed together because they share a subject and separately because they want different answers.
1. A plugin cannot tell a rehearsal from production
ProtoWorkloadIdentity drops the local marker on the way out, and flowstate.v1.WorkloadIdentity has no field to carry it. So a plugin receiving a caller identity from flow run local sees something indistinguishable from a production one.
This predates #295 and is the largest of the three, because it is a schema change and a plugin SDK contract change: a plugin that starts trusting a new field is a plugin that behaves differently against an older host, so the absent case has to read as something safe rather than as "not local".
The security direction is the one to get right. A rehearsal marker that a plugin can be tricked into not seeing is worse than none, because the plugin would then treat a rehearsal as production — which is the direction that spends real resources. The unforgeable in-process marker exists precisely because a serialized boolean is forgeable by whoever serializes it, and that reasoning has to survive the crossing rather than be dropped at it.
2. flow test's starter: does not reach run.identity
A test case is not a run somebody started, and flowtest takes no policy flags — so the seam #651 adds has nothing to feed it there. Documented rather than changed, and the question left open is whether flow test should grow policy flags at all, or whether a case that wants to exercise an identity-dependent policy is really asking for a different verb.
Worth deciding before someone answers it accidentally: flow test is the loop an author lives in, and adding deployment configuration to it is exactly the pressure the "a validator must not report what a deployment decides" rule exists to resist.
3. A denial does not say it came from a rehearsal
The issue that started this proposed a local-specific annotation on a denial. After #651 that annotation would explain a correct answer — a local denial and a production denial for the same identity are now the same answer, which was the whole point.
It is still arguably worth having, because an author reading a denial in a rehearsal may not know the policy file they passed is the reason. The cost is threading a local boolean through CheckTaskPolicy, which is the seam both drivers share, to change nothing but a message. That is the kind of parameter that gets read by something eventually, and this repository has been bitten by a value that exists to be informational and then becomes load-bearing.
Follows #295 and #651.
Generated by Claude Code
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing ProtoWorkloadIdentity into flowstate.v1.WorkloadIdentity and the plugin boundary, then inspect flowtest's starter:/run.identity path and the shared CheckTaskPolicy seam. Read the related decisions in #295 and #651 before choosing scope. Done should mean each gap has an explicit decision and consistent contract, test behavior, or denial wording.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend-api-design, cli, security, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100