dograh/api/services
Amaan Javed 076edd1bd0
fix(quota): fail closed when quota verification errors (#331) (#523)
* fix(quota): fail closed when quota verification errors (#331)

Quota enforcement fell open on unexpected errors: the outer `except` in
`authorize_workflow_run_start` returned `has_quota=True`, so a degraded
database or a config-resolution bug let a billable run start unverified.
Billing and abuse protection are control-plane functions, so this is the
wrong default under exactly the degraded conditions that matter.

- Fail closed by default: the outer handler now returns
  `has_quota=False` / `quota_check_failed`, reusing the existing message.
- Add `QUOTA_FAIL_MODE=closed|open` (default `closed`) so OSS self-hosters
  can explicitly opt back into availability; the open path logs loudly.
- Narrow the try-scope so `get_user_by_id` / `get_workflow_run` DB read
  failures surface as their specific `user_not_found` /
  `workflow_run_not_found` codes instead of the generic handler.
- Tests cover the config-resolution and DB-read failure paths (denied,
  not `has_quota=True`) and the `QUOTA_FAIL_MODE=open` escape hatch.

Fixes #331

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(quota): route DB read failures through the fail-mode policy gate

Review (greptile) flagged that the narrowed get_user_by_id / get_workflow_run
catches returned user_not_found / workflow_run_not_found before the outer
QUOTA_FAIL_MODE handler ran, so QUOTA_FAIL_MODE=open never applied to a DB
failure -- the exact "degraded database" case the escape hatch documents.

Revert the two narrowed catches so DB read exceptions fall through to the
single outer policy gate: closed -> quota_check_failed, open -> allow. The
None checks still return the specific not_found codes for genuinely missing
rows; an exception is a "cannot verify" condition, not a definitive absence.

Add a regression test asserting QUOTA_FAIL_MODE=open allows a run when a DB
read throws, and update the two DB-error tests to expect quota_check_failed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(quota): scope the fail-mode comment to credit-verification failures (#331)

Review (cubic) flagged the outer-handler comment as overclaiming: it said the
handler is the single gate for "all cannot-verify errors", but the earlier
workflow-load and org-membership catches always deny with workflow_not_found
regardless of QUOTA_FAIL_MODE. That distinction is intentional (those are
authorization/existence gates, not credit verification), so scope the comment
accordingly. Comment-only, no behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(quota): fail open only when MPS is unreachable

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
2026-07-15 13:03:42 +05:30
..
auth fix: fix superadmin impersonation 2026-07-11 15:51:36 +05:30
campaign fix: scope workflow run to org rather than user 2026-07-10 16:52:43 +05:30
configuration feat: add ElevenLabs realtime STT provider support (#512) (#522) 2026-07-13 14:47:07 +05:30
filesystem chore: refactor file upload mechanism to avoid NFS dependency (#496) 2026-07-03 20:01:52 +05:30
gen_ai chore: cleaup mps v1 billing (#507) 2026-07-07 18:38:29 +05:30
gender Initial Commit 🚀 🚀 2025-09-09 14:37:32 +05:30
integrations feat: add template variable rendering for transfer call destination 2026-07-02 13:36:29 +05:30
pipecat Fix realtime feedback event correlation (#534) 2026-07-14 19:49:58 +05:30
reports feat: billing and credit management v2 (#429) 2026-06-12 14:55:30 +05:30
telephony fix: scope workflow run to org rather than user 2026-07-10 16:52:43 +05:30
voice_prompting_guide chore: add current time in global prompt 2026-07-14 19:52:29 +05:30
worker_sync feat: add worker sync events 2026-04-04 14:26:47 +05:30
workflow fix: fix superadmin impersonation 2026-07-11 15:51:36 +05:30
call_concurrency.py fix: increase concurrency limit an handle it across all call paths (#508) 2026-07-09 18:29:01 +05:30
managed_model_services.py feat: centralise workflow run authorization 2026-06-12 18:16:30 +05:30
mps_billing.py feat: billing and credit management v2 (#429) 2026-06-12 14:55:30 +05:30
mps_service_key_client.py feat: show model pricing in configuration UI (#528) 2026-07-13 14:20:24 +05:30
organization_context.py fix: fix org scoped access for resources (#517) 2026-07-09 23:04:33 +05:30
organization_preferences.py feat: add config v2 to simplify billing (#428) 2026-06-09 16:10:26 +05:30
posthog_client.py fix: increase concurrency limit an handle it across all call paths (#508) 2026-07-09 18:29:01 +05:30
quota_service.py fix(quota): fail closed when quota verification errors (#331) (#523) 2026-07-15 13:03:42 +05:30
storage.py fix: pass s3 compose settings into storage 2026-06-24 18:37:20 +05:30
tool_management.py Feat/dybamic transfer (#521) 2026-07-10 21:40:26 +05:30
user_onboarding.py feat: UI refresh and user onboarding (#430) 2026-06-17 19:49:33 +05:30
workflow_run_artifacts.py chore: refactor file upload mechanism to avoid NFS dependency (#496) 2026-07-03 20:01:52 +05:30
workflow_run_billing.py chore: cleaup mps v1 billing (#507) 2026-07-07 18:38:29 +05:30