Skip to content

feat(store): org service user credentials search skips soft-deleted rows - #1949

Merged
AmanGIT07 merged 2 commits into
mainfrom
soft-delete-org-su-credentials-reads
Sep 25, 2026
Merged

AmanGIT07 merged 2 commits into
mainfrom
soft-delete-org-su-credentials-reads

Conversation

@AmanGIT07

Copy link
Copy Markdown
Contributor

Sixth of the org view repositories. Follows #1946 and #1947.

Summary

The organization service user credentials search leaves out revoked credentials, soft-deleted service users, and soft-deleted organizations.

Changes

  • The base query starts from fromLive(serviceuser_credentials) and adds live on the joined service users.
  • A new inner join on organizations with live on it, so a soft-deleted organization reports no credentials.
  • New docker-backed suite org_serviceuser_credentials_repository_pg_test.go: seeds a revoked credential, a credential whose service user is soft-deleted, and one under a soft-deleted organization, then checks the listing and the text search.

Technical Details

The organization id arrives as a request parameter and only scoped the service users. Without the join, a soft-deleted organization still returned its credentials while an org id nobody owns returned nothing. The join makes those two agree.

This RPC authorizes with IsSuperUser, so the disabled-organization gate in IsAuthorized never runs on it, and that gate steps aside for platform superusers in any case. The check therefore has to live in the query.

The join is on the organizations primary key, so it matches at most one row and cannot duplicate credentials.

Frontier does not set deleted_at on these tables yet, so the search returns the same rows as before.

Test Plan

  • go test -run 'TestOrgServiceUserCredentials' ./internal/store/postgres/ passes (unit tests and the new suite)
  • The new suite fails on main
  • golangci-lint run ./internal/store/postgres/... reports no issues
  • End to end against a local server through AdminService/SearchOrganizationServiceUserCredentials. Two orgs, three service users and four credentials were created through the public RPCs, then deleted_at was set by SQL. The same scenarios ran against main on the same database, with only the binary swapped.
# Scenario This branch main
1 Baseline before any soft delete: three credentials in one org, one in the other PASS PASS
2 The revoked credential is not listed PASS FAIL
3 A credential of a soft-deleted service user is not listed PASS FAIL
4 Only the live credential is listed PASS FAIL
5 The soft-deleted organization reports no credentials PASS FAIL
6 An org id nobody owns reports no credentials PASS PASS
7 Search matching the live credential returns it PASS PASS
8 Search matching the revoked credential returns nothing PASS FAIL

SQL Safety

  • Values flow through ? placeholders, goqu.Ex{}, or goqu.Record{} — never fmt.Sprintf or + building a query that gets executed.
  • ToSQL() callers capture and forward params (query, params, err := stmt.ToSQL(); db.…Context(ctx, …, query, params...)). Never query, _, err := ….
  • No ? placeholders inside single-quoted SQL literals in goqu.L.
  • No new //nolint:forbidigo or // #nosec G20x annotations.

The search reads credentials and service users through the live-row
helpers, and joins organizations so a soft-deleted org reports nothing,
the same as an org id nobody owns.
…deleted rows

Seeds a revoked credential, a credential of a soft-deleted service user,
and one under a soft-deleted organization, then checks the listing and
the text search.
@vercel

vercel Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
frontier Ready Ready Preview Sep 25, 2026 8:10am UTC

@coderabbitai

coderabbitai Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: raystack/frontier/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 95faa3b7-ccbf-4d81-8b4e-ae306446b71f

📥 Commits

Reviewing files that changed from the base of the PR and between f789863 and e0c8197.

📒 Files selected for processing (3)
  • internal/store/postgres/org_serviceuser_credentials_repository.go
  • internal/store/postgres/org_serviceuser_credentials_repository_pg_test.go
  • internal/store/postgres/org_serviceuser_credentials_repository_test.go

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Organization-scoped service-user credential searches now exclude credentials associated with deleted organizations or service users, as well as revoked credentials.

Walkthrough

The service-user credential query now uses live credentials, joins organizations through the service user’s organization ID, and excludes soft-deleted service users and organizations. SQL expectations and PostgreSQL tests cover the filters.

Changes

Credential Search

Layer / File(s) Summary
Live credential query and coverage
internal/store/postgres/org_serviceuser_credentials_repository.go, internal/store/postgres/org_serviceuser_credentials_repository_test.go, internal/store/postgres/org_serviceuser_credentials_repository_pg_test.go
The base query uses fromLive, joins organizations through the service user, and filters out soft-deleted credentials, service users, and organizations. SQL expectations and PostgreSQL tests cover the query behavior.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to e0c81

No actionable issue remains identified for this change; it is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to e0c81

The search now hides revoked credentials and credentials associated with deleted service users or organizations. The organization restriction remains in place, and the change does not grant new access. Some end-to-end security behavior remains unverified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The changed visibility rule affects organization-scoped credential search results for callers of the existing superuser-authorized RPC; it does not itself change credential authentication or grant a new caller access.

Trust Boundaries and Controls

  • observed — The handler takes the organization ID from the request, while the repository retains its organization-ID predicate and adds live-row checks before returning credential search results.

Hardening Proposals

  • proposed — Add an RPC-level check for a superuser searching a soft-deleted organization and for an unauthorized caller; the new database tests exercise the repository directly, not the authorization boundary.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@AmanGIT07
AmanGIT07 merged commit 8c18295 into main Sep 25, 2026
8 checks passed
@AmanGIT07
AmanGIT07 deleted the soft-delete-org-su-credentials-reads branch September 25, 2026 11:42

This branch was successfully deployed

1 active deployment
Preview — e0c81972 Deployed Sep 25, 2026 by vercel[bot]
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