Station v0.71 accepts boolean max_spend_cents values during staging, but later drops the boolean before workflow execution, causing the declared spend cap to disappear.
Confirmed with a harmless in-memory effect.
Reproduction:
- Stage/run a workflow with:
max_spend_cents = true
- The staging path accepts the value because workflow_mcp.py coerces it using int(...).
- During execution, workflow_engine.py rejects boolean as a valid cap value and normalizes it to None.
- The effect then executes successfully with no spend cap applied.
Observed:
- boolean cap accepted at staging
- effective cap becomes None
- workflow completes
- effect executes
A malformed string such as "oops" is rejected, so the issue is specifically that bool is accepted as an integer-like value.
Root cause:
workflow_mcp.py uses int(...) when parsing max_spend_cents, and in Python bool is a subclass of int.
Later, workflow_engine.py excludes bool from valid integer cap values and turns it into None.
This creates an inconsistent validation path where the caller appears to have declared a cap, but execution silently runs uncapped.
There is also a related inconsistency for negative values: source comments indicate -1 means no cap, while runtime handling can reject priced effects instead.
Expected:
max_spend_cents should be validated strictly and consistently before execution.
Boolean values must be rejected explicitly.
Negative-value semantics should also be normalized consistently:
- either support a documented sentinel such as -1 for no cap,
- or reject negative values entirely.
Suggested fix:
- reject bool explicitly before integer coercion;
- require a real integer type/value for max_spend_cents;
- normalize or reject negative values consistently across staging and runtime;
- add regression coverage ensuring malformed caps cannot silently become uncapped execution.
Impact:
A malformed boolean spend cap can pass the staging path and result in a live effect executing without the spend limit the caller intended to apply.
Confirmed against Station v0.71 source and runtime behavior using a harmless stub effect.