On Station v0.68, Team quorum approval policies do not protect module effects executed through the workflow DAG engine.
I reproduced this by mocking team_approval.gate() to always return blocked, then running a workflow containing a Stripe module effect with mocked Stripe history and charge handlers.
Observed result:
outcome = COMPLETED
history_calls = 1
charge_calls = 1
team_gate_calls = 0
charge_receipt_has_team_approval = False
The module effect was executed even though the Team approval gate would have blocked it if called.
The execution path appears to be:
Team DAG execution
→ workflow_engine.run_workflow()
→ synthesized module integration
→ stripe_billing_bill_client
team_approval.gate() is invoked by studio_integration_send, but the workflow DAG module-effect path does not pass through that approval boundary.
As a result, a Team policy requiring Stripe approval/quorum does not currently prevent a DAG workflow from reaching a Stripe write effect.
For example, a policy requiring:
provider: stripe
role: approver
quorum: 2
can still result in bill_client being executed without the Team approval gate being called.
Expected behavior:
When a Team policy requires approval or quorum for a provider used by a workflow DAG, no corresponding provider effect should execute until the required approval has been satisfied.
For batch workflows, gating each individual effect may also be insufficient because earlier effects could land before a later approval is denied. A safer boundary is after the exact execution plan has been constructed but before the first external effect:
build exact plan
→ compute action/run hash
→ collect required Team quorum
→ execute effects
The approval should be bound to the exact execution being authorized, including a unique run/occurrence identifier, so an approval cannot be reused for a later run with the same plan.
Workflow/run receipts should also preserve the Team approval evidence needed for later verification.