#909 App-originated tool calls silently bypass rate limiting and per-workflow circuit-breaker isolation (ProxyDurableContext is not a DurableContext)
Description
EditEARS SPEC:
- While an app action is executing, when it invokes a rate-limited tool, the Highway engine shall apply the same rate limit that applies when a workflow invokes that tool directly.
- While an app action is executing, when it invokes a circuit-broken tool, the Highway engine shall apply per-workflow-run circuit-breaker isolation using the real workflow_run_id.
- If a decorator cannot resolve a usable context, then the Highway engine shall fail closed or log at WARNING, and shall not silently skip the control.
- The Highway engine shall have a test proving the rate limit BLOCKS an app-originated call once the cap is exceeded, not only that it permits one.
EVIDENCE (static, verified):
- enterprise/ipc/proxy.py:23 - ProxyDurableContext sets self.workflow_run_id = 'proxy-placeholder'; it does NOT subclass DurableContext.
- enterprise/ipc/proxy.py:36-42 - __getattr__ returns a method_proxy callable for ANY unknown attribute, so proxy.tenant_id evaluates to a FUNCTION OBJECT rather than a string, and never raises.
- docker/highway-core/engine/tools/decorators/rate_limit.py:139-141 - 'if not isinstance(ctx, DurableContext): return func(*args, **kwargs)' -> rate limiting is skipped entirely for the proxy.
- docker/highway-core/engine/tools/decorators/circuit_breaker.py:163-165 - 'if isinstance(ctx, DurableContext)' is False for the proxy, so workflow_run_id stays None and per-workflow CB isolation is lost.
- enterprise/apps/sdk/context_net.py:155-161 - AppContext.send_email calls send_email_tool(ctx=self._ctx, ...) IN THE CHILD with the proxy as ctx.
- enterprise/tools/email_tool.py:238 - send_email_tool is decorated @with_rate_limit('tools.email.send', priority_kwarg='priority').
IMPACT: tools.email.send is rate-limited when a workflow calls it and UNLIMITED when an app calls ctx.send_email. Same for any @with_rate_limit tool reachable from the app SDK. A tenant-facing quota control is off on one path with no log line.
NOT YET DONE: no live reproduction (api container was down during analysis). Reproduce by installing an app that loops ctx.send_email past the configured cap and confirming no 429/limit error.
Comments
Loading comments...
Context
Loading context...
Audit History
View AllLoading audit history...