Skip to content

fix: fixes customer FK column issue - #4292

Merged
akshaydeo merged 1 commit into
devfrom
06-11-fix_fixes_customer_fk_column_issue
Jun 11, 2026
Merged

fix: fixes customer FK column issue#4292
akshaydeo merged 1 commit into
devfrom
06-11-fix_fixes_customer_fk_column_issue

Conversation

@roroghost17

@roroghost17 roroghost17 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes a bug where DeleteCustomer fails with a foreign key constraint violation when attempting to DELETE FROM governance_budgets WHERE customer_id = ?. The root cause is that governance_customers.budget_id rows were left populated by a previous migration (migrationAddCustomerBudgetsToBudgetsTable), causing the FK check (fk_governance_customers_budget) to block deletion of the referenced budget rows. Since budget ownership now lives on governance_budgets.customer_id, the legacy budget_id values on governance_customers can be safely nulled — a NULL reference satisfies the FK unconditionally.

Changes

  • Adds a new migration migrationNullLegacyCustomerBudgetID that:
    • Performs a defensive backfill to ensure any governance_budgets rows that still lack a customer_id (e.g. written by an older instance in a mixed-version cluster) are claimed before the legacy references are cleared.
    • Nulls all non-null governance_customers.budget_id values, resolving the FK conflict without dropping the column or constraint (deferred to a major release).
    • Includes a best-effort rollback that repopulates budget_id from governance_budgets.customer_id, picking the oldest budget for customers with multiple budgets.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

go test ./framework/configstore/...
  1. Ensure a customer with an associated budget exists in the database (with governance_customers.budget_id populated).
  2. Run the migration and confirm governance_customers.budget_id is NULL for all rows.
  3. Confirm governance_budgets.customer_id is correctly populated.
  4. Attempt to delete the customer and verify no FK constraint error occurs.

Breaking changes

  • Yes
  • No

The governance_customers.budget_id column and its FK are retained; only the values are cleared.

Related issues

Closes the FK violation bug introduced by the migrationAddCustomerBudgetsToBudgetsTable migration leaving legacy budget_id references intact.

Security considerations

None. This migration only modifies internal budget ownership references and does not affect auth, secrets, or PII.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Summary by CodeRabbit

  • Chores
    • Added a database migration to clean up legacy customer→budget links: claims unowned budgets safely, refreshes affected customer configuration, and clears deprecated legacy references to improve data consistency.
  • Bug Fixes
    • Improved rollback behavior to best-effort restore legacy customer→budget links when possible, preferring the oldest matching budget.

@CLAassistant

CLAassistant commented Jun 11, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

roroghost17 commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds a startup migration that, when the legacy governance_customers.budget_id column exists, backfills unowned governance_budgets.customer_id, refreshes affected customers' config_hash, nulls the legacy budget_id, and provides a best-effort rollback restoring the oldest matching budget per customer.

Changes

Legacy Budget ID Column Migration

Layer / File(s) Summary
Migration trigger integration
framework/configstore/migrations.go
triggerMigrations now calls migrationNullLegacyCustomerBudgetID after the MCP library/source + fast-mode migration steps.
Budget ownership migration logic
framework/configstore/migrations.go
migrationNullLegacyCustomerBudgetID (guarded by legacy-column existence) identifies customers referencing unowned budgets, backfills governance_budgets.customer_id defensively, recomputes affected customers' config_hash, nulls legacy governance_customers.budget_id, and implements a rollback that repopulates budget_id from the oldest matching budget per customer.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • maximhq/bifrost#4284: Modifies the same migration chain around governance_customers unique-name constraint and migration ordering.

Suggested reviewers

  • danpiths
  • akshaydeo

Poem

🐰 I hopped through rows both old and new,
Found budgets lost, and claimed a few,
I nulled the past with careful art,
And left a rollback, just in part,
A tiny rabbit patching glue.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'fix: fixes customer FK column issue' is vague and generic, using non-descriptive terms that don't convey the specific change being made. Replace with a more specific title that describes the actual change, such as 'fix: null legacy customer budget FK to resolve delete constraint violations'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description is mostly complete, addressing all key template sections with relevant information about the bug fix, changes, testing approach, and related concerns.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 06-11-fix_fixes_customer_fk_column_issue

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

@roroghost17
roroghost17 marked this pull request as ready for review June 11, 2026 13:16

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@framework/configstore/migrations.go`:
- Around line 9813-9829: After the defensive backfill that sets
governance_budgets.customer_id from governance_customers.budget_id and clears
governance_customers.budget_id, recompute and persist the customers' config hash
so config_hash stays in sync with GenerateCustomerHash: identify the affected
governance_customers rows (those whose budget_id was non-NULL / whose id was
used to set governance_budgets.customer_id), call GenerateCustomerHash for each
affected customer and update governance_customers.config_hash accordingly
(perform the selection before clearing budget_id or capture affected IDs in the
same transaction), and ensure these updates occur inside the same migration
transaction so migration/runtime hash generation parity is preserved.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 06530fa2-b2ad-4fe3-ba14-ae5931bcbd7a

📥 Commits

Reviewing files that changed from the base of the PR and between 378148c and 330a1ee.

📒 Files selected for processing (1)
  • framework/configstore/migrations.go

Comment thread framework/configstore/migrations.go
@greptile-apps

greptile-apps Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

The migration correctly resolves the FK violation without dropping the column or constraint, and all three steps operate on the right rows.

The backfill uses EXISTS + correlated subquery consistently, the hash refresh targets only customers whose budget ownership actually changes, and clearing the legacy budget_id column does not affect config_hash because BudgetID is gorm:"-" in the Go struct. No locking, deadlock, or data-loss risks were identified.

framework/configstore/migrations.go — the new migration function is untested; adding a test covering the three key scenarios would close the remaining gap.

Important Files Changed

Filename Overview
framework/configstore/migrations.go Adds migrationNullLegacyCustomerBudgetID: defensive backfill, config_hash refresh for affected customers, then NULL-clear of legacy governance_customers.budget_id. Logic is correct but lacks a dedicated test.

Reviews (3): Last reviewed commit: "fix: fixes customer FK column issue" | Re-trigger Greptile

Comment thread framework/configstore/migrations.go
Comment thread framework/configstore/migrations.go

akshaydeo commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jun 11, 7:14 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 11, 7:17 PM UTC: Graphite couldn't merge this PR because it had merge conflicts.
  • Jun 11, 7:26 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 11, 7:27 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 06-11-feat_adds_per_model_usage_to_quota_api to graphite-base/4292 June 11, 2026 19:16
@akshaydeo
akshaydeo changed the base branch from graphite-base/4292 to dev June 11, 2026 19:16
@akshaydeo
akshaydeo requested a review from a team as a code owner June 11, 2026 19:16
@roroghost17
roroghost17 force-pushed the 06-11-fix_fixes_customer_fk_column_issue branch from 066504c to 8865f7c Compare June 11, 2026 19:21
@akshaydeo
akshaydeo merged commit 5b106c8 into dev Jun 11, 2026
11 of 17 checks passed
@akshaydeo
akshaydeo deleted the 06-11-fix_fixes_customer_fk_column_issue branch June 11, 2026 19:27
akshaydeo pushed a commit that referenced this pull request Jun 12, 2026
## Summary

Fixes a bug where `DeleteCustomer` fails with a foreign key constraint violation when attempting to `DELETE FROM governance_budgets WHERE customer_id = ?`. The root cause is that `governance_customers.budget_id` rows were left populated by a previous migration (`migrationAddCustomerBudgetsToBudgetsTable`), causing the FK check (`fk_governance_customers_budget`) to block deletion of the referenced budget rows. Since budget ownership now lives on `governance_budgets.customer_id`, the legacy `budget_id` values on `governance_customers` can be safely nulled — a `NULL` reference satisfies the FK unconditionally.

## Changes

- Adds a new migration `migrationNullLegacyCustomerBudgetID` that:
  - Performs a defensive backfill to ensure any `governance_budgets` rows that still lack a `customer_id` (e.g. written by an older instance in a mixed-version cluster) are claimed before the legacy references are cleared.
  - Nulls all non-null `governance_customers.budget_id` values, resolving the FK conflict without dropping the column or constraint (deferred to a major release).
  - Includes a best-effort rollback that repopulates `budget_id` from `governance_budgets.customer_id`, picking the oldest budget for customers with multiple budgets.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./framework/configstore/...
```

1. Ensure a customer with an associated budget exists in the database (with `governance_customers.budget_id` populated).
2. Run the migration and confirm `governance_customers.budget_id` is `NULL` for all rows.
3. Confirm `governance_budgets.customer_id` is correctly populated.
4. Attempt to delete the customer and verify no FK constraint error occurs.

## Breaking changes

- [ ] Yes
- [x] No

The `governance_customers.budget_id` column and its FK are retained; only the values are cleared.

## Related issues

Closes the FK violation bug introduced by the `migrationAddCustomerBudgetsToBudgetsTable` migration leaving legacy `budget_id` references intact.

## Security considerations

None. This migration only modifies internal budget ownership references and does not affect auth, secrets, or PII.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **Chores**
  * Added a database migration to clean up legacy customer→budget links: claims unowned budgets safely, refreshes affected customer configuration, and clears deprecated legacy references to improve data consistency.
* **Bug Fixes**
  * Improved rollback behavior to best-effort restore legacy customer→budget links when possible, preferring the oldest matching budget.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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