dograh/api
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
..
alembic fix: fix org scoped access for resources (#517) 2026-07-09 23:04:33 +05:30
assets feat: telephony call transfer (#155) 2026-02-16 14:33:33 +05:30
db fix: fix org scoped access for resources (#517) 2026-07-09 23:04:33 +05:30
errors fix: increase concurrency limit an handle it across all call paths (#508) 2026-07-09 18:29:01 +05:30
mcp_server chore: improve upon mcp prompts (#494) 2026-07-03 18:14:03 +05:30
native/rnnoise Initial Commit 🚀 🚀 2025-09-09 14:37:32 +05:30
routes feat: show model pricing in configuration UI (#528) 2026-07-13 14:20:24 +05:30
schemas fix: error on empty destination when creating a default transfer tool 2026-07-13 16:44:14 +05:30
services fix(quota): fail closed when quota verification errors (#331) (#523) 2026-07-15 13:03:42 +05:30
tasks fix: fix org scoped access for resources (#517) 2026-07-09 23:04:33 +05:30
tests fix(quota): fail closed when quota verification errors (#331) (#523) 2026-07-15 13:03:42 +05:30
utils fix: fix org scoped access for resources (#517) 2026-07-09 23:04:33 +05:30
.cursorignore Initial Commit 🚀 🚀 2025-09-09 14:37:32 +05:30
.dockerignore Initial Commit 🚀 🚀 2025-09-09 14:37:32 +05:30
.env.example feat(auth): gate OSS signup behind ENABLE_SIGNUP flag (#514) 2026-07-13 14:08:25 +05:30
.env.test.example chore: drain active calls before rolling updates (#474) 2026-06-29 06:00:31 +05:30
.gitignore Initial Commit 🚀 🚀 2025-09-09 14:37:32 +05:30
__init__.py Initial Commit 🚀 🚀 2025-09-09 14:37:32 +05:30
AGENTS.md feat: add chat based testing for voice agent (#308) 2026-05-21 15:20:02 +05:30
alembic.ini chore: bump pipecat version and fix tests (#263) 2026-05-04 21:35:37 +05:30
app.py fix: add CORS preflight handler and ACAO header for embed config endpoint (#403) 2026-06-03 21:27:44 +05:30
CLAUDE.md Chore/add setup and contributing docs (#90) 2025-12-27 09:25:20 +05:30
conftest.py feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
constants.py feat(auth): gate OSS signup behind ENABLE_SIGNUP flag (#514) 2026-07-13 14:08:25 +05:30
Dockerfile feat: add Helm chart for Kubernetes deployment (#365) 2026-07-03 12:39:39 +05:30
enums.py fix: increase concurrency limit an handle it across all call paths (#508) 2026-07-09 18:29:01 +05:30
logging_config.py feat: add headless mode, redesign floating widget, refactor lifecycle callbacks (#268) 2026-05-07 12:23:41 +05:30
pyproject.toml chore(main): release dograh 1.41.0 (#497) 2026-07-06 21:37:02 +05:30
pytest.ini feat: refactor node spec and add mcp tools (#244) 2026-04-21 07:56:16 +05:30
requirements.dev.txt feat: add devcontainer based setup (#352) 2026-05-25 20:44:22 +05:30
requirements.txt Implement cost calculator for Tuber (#471) 2026-07-02 12:51:14 +05:30
sdk_expose.py feat: refactor node spec and add mcp tools (#244) 2026-04-21 07:56:16 +05:30