Skip to content

Restrict org status RPCs to authenticated members#1751

Open
riderx wants to merge 5 commits intomainfrom
riderx/fix-rpc-billing-status
Open

Restrict org status RPCs to authenticated members#1751
riderx wants to merge 5 commits intomainfrom
riderx/fix-rpc-billing-status

Conversation

@riderx
Copy link
Member

@riderx riderx commented Mar 8, 2026

Summary (AI generated)

  • Kept is_paying_org and is_trial_org protected to non-public callers in migration 20260308203352_restrict-org-status-rpc-access.sql.
  • Made is_trial_org(uuid) return a non-null integer via COALESCE(..., 0) to satisfy contract and remove nullable edge behavior.
  • Updated existing SQL tests (06_org_functions.sql, 20_test_org_management_functions.sql) to run under authenticated/service-role contexts where needed.
  • Added/retained dedicated role-based RPC coverage in 46_test_org_status_rpcs.sql.

Motivation (AI generated)

CI failures came from existing tests calling now-restricted RPCs in unauthenticated contexts and from legacy nullable expectations after the access-hardening/security fix.

Business Impact (AI generated)

The patch prevents org/payment metadata enumeration from public callers while making org status APIs deterministic for authorized callers, and aligns test coverage with the enforced access model.

Test Plan (AI generated)

  • Ran bun lint.
  • Ran bun lint:backend.
  • Updated SQL tests in supabase/tests for access-context compatibility and function contract expectations.
  • Rebased riderx/fix-rpc-billing-status onto origin/main and force-pushed latest commit.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

📝 Walkthrough

Walkthrough

Adds two SECURITY DEFINER PostgreSQL functions — public.is_paying_org(uuid) and public.is_trial_org(uuid) — that gate access via public.check_min_rights, query public.orgs and public.stripe_info, and have EXECUTE granted only to authenticated and service_role after revoking PUBLIC/anon rights.

Changes

Cohort / File(s) Summary
Org Status RPC Migration
supabase/migrations/20260308203352_restrict-org-status-rpc-access.sql
Adds public.is_paying_org(orgid uuid) RETURNS boolean and public.is_trial_org(orgid uuid) RETURNS integer as SECURITY DEFINER functions. Both call public.check_min_rights, query public.orgs and public.stripe_info, revoke EXECUTE from PUBLIC/anon/authenticated, then grant EXECUTE to authenticated and service_role.
Tests for RPC Access
supabase/tests/46_test_org_status_rpcs.sql
New SQL tests exercising role-based access: admin/org-member, non-member, anonymous (permission denied), and service_role for both is_paying_org and is_trial_org, asserting expected returns and permission errors.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller as Caller (anon/auth/authenticated/service_role)
    participant RPC as is_paying_org / is_trial_org (SECURITY DEFINER)
    participant Rights as public.check_min_rights
    participant Orgs as public.orgs / public.stripe_info

    Caller->>RPC: CALL is_paying_org(orgid) / is_trial_org(orgid)
    RPC->>Rights: check_min_rights(caller, orgid)
    Rights-->>RPC: allowed / denied
    alt allowed
        RPC->>Orgs: SELECT stripe_status, trial_ends FROM stripe_info JOIN orgs
        Orgs-->>RPC: stripe_status / trial_ends
        RPC-->>Caller: boolean / integer (days remaining)
    else denied
        RPC-->>Caller: false / 0
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through rows of orgs and clues,

Where Stripe and trials hide their news.
No anonymous sniffing here, you see —
Only rightful callers bound to be.
A little hop, a guard, a cheer — secure as can be!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is AI-generated with summary, motivation, business impact, and test plan sections, but lacks structured organization matching the template and omits critical checklist items and screenshots section. Restructure the description to match the template exactly: add clear Summary, Test plan with reproduction steps, Screenshots section, and complete the Checklist with proper checkboxes for linting, documentation, E2E tests, and manual testing confirmation.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the primary change: restricting two org status RPC functions to authenticated members only.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch riderx/fix-rpc-billing-status

Comment @coderabbitai help to get the list of available commands and usage tips.

@riderx riderx force-pushed the riderx/fix-rpc-billing-status branch from c6c0200 to bc00e88 Compare March 8, 2026 20:36
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@supabase/migrations/20260308203352_restrict-org-status-rpc-access.sql`:
- Around line 53-55: The SELECT in function public.is_trial_org (using
stripe_info.trial_at, stripe_info.customer_id and orgs.customer_id via orgid)
can return NULL when no stripe_info row or trial_at is NULL; change the return
expression to guarantee a non-null integer—wrap the computed GREATEST(...)
result in COALESCE(..., 0) or fetch into a local integer variable and return 0
when NULL—so the function always returns a non-null integer as declared.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4b0ac10-fb4b-4a1b-bc7a-25a42c1fe259

📥 Commits

Reviewing files that changed from the base of the PR and between 2af3a08 and c6c0200.

📒 Files selected for processing (1)
  • supabase/migrations/20260308203352_restrict-org-status-rpc-access.sql

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 9, 2026

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.

1 participant