Skip to content

feat(store): kyc row is kept when an org is deleted - #1984

Merged
rohilsurana merged 8 commits into
mainfrom
feat/kyc-soft-delete
Oct 13, 2026
Merged

rohilsurana merged 8 commits into
mainfrom
feat/kyc-soft-delete

Conversation

@rohilsurana

@rohilsurana rohilsurana commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

What changes

The org delete now keeps the KYC row and sets deleted_at, like the other tables the org delete touches.

  • A new migration makes organizations_kyc.org_id unique over live rows only. The old plain unique constraint is dropped. This lets an org get a new KYC row after the old one was deleted.
  • GetByOrgID reads live rows only. The update path of Upsert only touches the live row.
  • Upsert refuses an org that is soft deleted or missing. It returns ErrOrgDoesntExist and writes nothing.
  • Delete is now a soft delete. It still returns success for an org with no KYC row, and a second delete keeps the first delete time.
  • The KYC list join skips a deleted KYC row inside the join condition. A live org whose KYC row is deleted stays in the list, with status false and an empty link.

Why

If an org delete stops right after the KYC step, the org is still live but its KYC status and link are gone. With a soft delete the row is kept for audit and Metabase, like the other tables. This came out of the review on #1974.

Merge order

Merge this PR after #1973 (the org row soft delete). organizations_kyc.org_id has a foreign key to organizations(id) with no delete rule. While the org row is still hard deleted, a kept KYC row makes the org delete fail on that key on every retry.

Merge this PR before #1974. #1974 is stacked on this one and changes the same list query.

Down migration

The down migration adds the plain unique constraint back. It fails if an org has both a deleted and a live KYC row. That can only happen after this change is in use.

Tests

  • Migration: a deleted row and a live row can share an org id, two live rows cannot.
  • Reads skip deleted rows.
  • Delete keeps the row and the first delete time, and works for an org without KYC.
  • Upsert after a delete creates a new live row.
  • Upsert on a soft deleted org is refused, for a first insert and for an org with an existing KYC row. Nothing is written and no audit record is added.
  • The list shows an org with a deleted KYC row with status false.

@vercel

vercel Bot commented Oct 12, 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 Oct 13, 2026 6:09am UTC

@coderabbitai

coderabbitai Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

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: 5aebc1cb-d1ee-4a81-b9be-608e1a1e6f74
📥 Commits

Reviewing files that changed from the base of the PR and between 6119be5 and a5f19be.

📒 Files selected for processing (2)
  • internal/store/postgres/kyc_repository.go
  • internal/store/postgres/kyc_repository_test.go

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Deleted KYC records are excluded from lookups and lists, and cannot be updated.
    • Deleting a KYC record retains it as a soft-deleted record; repeated deletions preserve its original deletion time.
    • A new live KYC record can be added after a previous record is deleted, while duplicate live records remain prevented.
    • Attempts to add KYC data for a deleted or nonexistent organization are rejected without changing existing KYC records.

The KYC repository filters out deleted rows, soft-deletes KYC records, and requires a live organization for upserts. A migration enforces uniqueness among live KYC rows.

Changes: KYC repository lifecycle

Layer / File(s) Summary
Live KYC uniqueness, reads, and deletion
internal/store/postgres/migrations/20261012100000_kyc_org_id_live_unique.*.sql, internal/store/postgres/kyc_repository.go, internal/store/postgres/kyc_repository_test.go
The migration enforces uniqueness for live KYC rows and restores all-row uniqueness on rollback. Repository reads and lists omit deleted rows, and deletion sets deleted_at. Tests cover uniqueness, reads, deletion, and upserting after deletion.
Live organization validation for upserts
internal/store/postgres/kyc_repository.go, internal/store/postgres/kyc_repository_test.go
Upsert updates and inserts KYC only for live organizations. Missing organizations and invalid UUIDs map to KYC errors. Tests check live and soft-deleted organizations, including KYC rows and audit records.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Suggested reviewers: amangit07

Merge Risk: 🔵 Low · up to a5f19

Rolling back the migration can fail if organizations have both a deleted and a live KYC row. Document manual reconciliation for rollback. Normal forward behavior is not affected.

Pre-merge checks · Passed 2
Passed 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.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@coveralls

coveralls commented Oct 12, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 38355103471

Coverage increased (+0.02%) to 54.704%

Details

  • Coverage increased (+0.02%) from the base build.
  • Patch coverage: 46 of 46 lines across 1 file are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 41454
Covered Lines: 22677
Line Coverage: 54.7%
Coverage Strength: 18.62 hits per line

💛 - Coveralls

@rohilsurana

rohilsurana commented Oct 12, 2026 •

Copy link
Copy Markdown
Member Author

Note for reviewers about the organizations side of the queries in this file.

This PR makes sure every read and write of the kyc table skips deleted kyc rows. It also makes Upsert refuse an org that is soft deleted.

One part is left on purpose and comes with #1974, which is stacked on this PR:

#1974 also adds the live checks to the billing joins of the admin org search.

Merge order: #1973 first (see the PR description), then this PR, then #1974.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: raystack/frontier/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cc3a0b77-dba8-414b-885c-adaa6dfd64bf
📥 Commits

Reviewing files that changed from the base of the PR and between 5c6dd0d and 5a09640.

📒 Files selected for processing (4)
  • internal/store/postgres/kyc_repository.go
  • internal/store/postgres/kyc_repository_test.go
  • internal/store/postgres/migrations/20261012100000_kyc_org_id_live_unique.down.sql
  • internal/store/postgres/migrations/20261012100000_kyc_org_id_live_unique.up.sql

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: raystack/frontier/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 52c59f01-f65d-4da8-9200-c49001423f41
📥 Commits

Reviewing files that changed from the base of the PR and between 5a09640 and 6119be5.

📒 Files selected for processing (2)
  • internal/store/postgres/kyc_repository.go
  • internal/store/postgres/kyc_repository_test.go

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.

Comment thread internal/store/postgres/kyc_repository.go
@rohilsurana
rohilsurana merged commit b3d3e2b into main Oct 13, 2026
8 checks passed
@rohilsurana
rohilsurana deleted the feat/kyc-soft-delete branch October 13, 2026 07:17

This branch was successfully deployed

1 active deployment
Preview — a5f19be6 Deployed Oct 13, 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.

3 participants