fix: scope workflow run to org rather than user

This commit is contained in:
Abhishek Kumar 2026-07-10 16:52:43 +05:30
parent 4989bab1e9
commit 43737c67dc
29 changed files with 218 additions and 158 deletions

View file

@ -71,11 +71,11 @@ class YourProvider(TelephonyProvider):
# ---------- webhooks ----------
async def verify_webhook_signature(self, url, params, signature) -> bool: ...
async def get_webhook_response(self, workflow_id, user_id, workflow_run_id) -> str: ...
async def get_webhook_response(self, workflow_id, organization_id, workflow_run_id) -> str: ...
def parse_status_callback(self, data: dict) -> dict: ...
# ---------- websocket ----------
async def handle_websocket(self, websocket, workflow_id, user_id, workflow_run_id): ...
async def handle_websocket(self, websocket, workflow_id, organization_id, workflow_run_id): ...
# ---------- inbound ----------
@classmethod
@ -112,6 +112,14 @@ class YourProvider(TelephonyProvider):
See `api/services/telephony/base.py` for the full docstrings on each method.
<Warning>
`get_webhook_response` and `handle_websocket` receive an `organization_id`, not a
user id. It is the tenant that every workflow and workflow-run lookup must be
scoped by — pass it straight through to `run_pipeline_telephony`. The workflow
owner is deliberately not handed to providers; read it off the workflow row if you
need it for attribution.
</Warning>
## Implementation Guide
### 1. Configuration schemas
@ -385,7 +393,7 @@ For end-to-end testing, save your provider through the telephony-configurations
1. **Trust the registry** — never import another provider's class directly; resolve through the factory helpers (`get_default_telephony_provider`, `get_telephony_provider_by_id`, etc.).
2. **Sensitive fields** — mark every credential field `sensitive=True` in `ProviderUIMetadata`. The save endpoint masks these on read and preserves the original when the client re-submits a masked value.
3. **Inbound signature verification** — always validate inbound webhook signatures in `verify_inbound_signature`. Returning `True` when no signature header is present is acceptable; return `False` when a signature *is* present but invalid.
3. **Inbound signature verification** — always validate inbound webhook signatures in `verify_inbound_signature`, and fail closed. If your provider signs every webhook (most do), a *missing* signature header means the request did not come from the provider: return `False`, exactly as `providers/twilio/` and `providers/plivo/` do. Never `return True` as a placeholder — these handlers are reachable by anyone who can guess a `workflow_run_id`.
4. **Transports load credentials lazily** — call `load_credentials_for_transport` with the `telephony_configuration_id` from the workflow run. Don't read the org's default config from `transport.py`.
5. **Logging** — use `loguru.logger`.