Skip to content

fix(db): enforce tenant ownership in session_pins and billing spend queries (#796)#806

Open
devin-ai-integration[bot] wants to merge 4 commits into
mainfrom
devin/tenant-sql-ownership
Open

fix(db): enforce tenant ownership in session_pins and billing spend queries (#796)#806
devin-ai-integration[bot] wants to merge 4 commits into
mainfrom
devin/tenant-sql-ownership

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Convention-compliant rewrite of #800 (by @rohith500). The production fix is preserved verbatim; only the test surface moved to satisfy the AGENTS.md hard rule.

Closes the four SQL ownership gaps from #796 where tenant isolation relied on the app layer always passing same-tenant IDs rather than on the SQL itself (same class as the already-fixed SoftDeleteModelRouterAPIKey in #536):

  • session_pins: added AND installation_id = @installation_id::uuid to GetSessionPin, UpdateSessionPinUsage, IncrementSessionPinUpstreamErrors, ResetSessionPinUpstreamErrors; UpsertSessionPin's ON CONFLICT DO UPDATE gained WHERE router.session_pins.installation_id = EXCLUDED.installation_id so a mismatched caller no-ops instead of overwriting another tenant's pin. installationID threaded through the sessionpin.Store interface and every call site. SweepExpiredSessionPins left untouched (global GC by expires_at).
  • DebitOrgCredits key_spend / user_month_spend CTEs: both now join api_key_id / router_user_id through to model_router_installations.external_id and require it to match the organization_id being debited before bumping the counter; a mismatch no-ops just that CTE (org debit + ledger still proceed).
  • GetUserMonthlySpendAndLimit: has_override / override_limit_usd_micros / spent_usd_micros subqueries now join through model_router_users to model_router_installations.external_id and require a match; org_default_limit_usd_micros stays unjoined (org-scoped only).

All four: mismatch = silent miss/no-op, matching how each query already handles a missing row. Hardening fix, not a response to an active exploit (confirmed in #796 that none are reachable via a current authenticated /v1/* request).

Why a rewrite

#800 added internal/postgres/tenant_isolation_796_test.go, a live-Postgres DB-backed test in internal/. Per root AGENTS.md ("Tests"): "No DB-backed integration tests in internal/. If need real Postgres, docker compose stack is runtime fixture; write scripts under scripts/ rather than *_test.go." The four regression scenarios were ported verbatim (real SessionPinRepo / BillingRepo, no mocks) into scripts/tenant_isolation_check/, gated on ROUTER_TEST_DATABASE_URL, following the existing scripts/feedback_integration_check/ pattern. go test ./... no longer touches Postgres.

Testing

  • make precommit (fmt + vet + build + test) clean.
  • make generate produces no diff under internal/sqlc.
  • go build ./scripts/tenant_isolation_check clean.

Co-authored-by: rohith500 rohith500@users.noreply.github.com

Link to Devin session: https://app.devin.ai/sessions/055a0e376d2b4318b42c4991fb14625f
Requested by: @steventohme

rohith500 and others added 4 commits July 20, 2026 11:08
…r_month_spend, and GetUserMonthlySpendAndLimit (#796)

Signed-off-by: N Rohith Reddy <rohithreddy2202@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…writes (#796)

Signed-off-by: N Rohith Reddy <rohithreddy2202@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…tUserMonthlySpendAndLimit (#796)

Signed-off-by: N Rohith Reddy <rohithreddy2202@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: rohith500 <rohith500@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown

PR author is not in the allowed authors list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants