Repository navigation
Allow coderouter legacy cleanup after new accounts - #9689
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughThe migration validates source accounts against encrypted credentials by account ID. Credential imports avoid overwriting newer records and update existing credentials or account metadata only when the incoming revision is newer. ChangesCredential migration
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related issues
Possibly related PRs
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 1 warning)
✅ Passed checks (23 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 `@web/services/coderouter/repository.ts`:
- Around line 240-261: Update importEncryptedCredential so both the credential
upsert and coderouterAccounts metadata update are gated by the same monotonic
revision from the imported credential source. Use that revision for the account
vaultRevision comparison as well as coderouterCredentials.credentialRevision,
preventing stale metadata updates when stored revisions diverge. Add coverage
for missing credentials and divergent stored revisions.
🪄 Autofix
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: 4dcd322c-0004-4d10-acce-c4fb07b8a9a8
📒 Files selected for processing (1)
web/services/coderouter/repository.ts
| const [inserted] = await tx | ||
| .insert(coderouterCredentials) | ||
| .values(encryptedValues(input.encrypted)) | ||
| .onConflictDoUpdate({ | ||
| .onConflictDoNothing({ | ||
| target: coderouterCredentials.accountId, | ||
| set: { | ||
| }) | ||
| .returning({ accountId: coderouterCredentials.accountId }); | ||
| if (!inserted) { | ||
| await tx | ||
| .update(coderouterCredentials) | ||
| .set({ | ||
| ...encryptedValues(input.encrypted), | ||
| updatedAt: new Date(), | ||
| }, | ||
| }); | ||
| }) | ||
| .where(and( | ||
| eq(coderouterCredentials.accountId, input.encrypted.accountId), | ||
| lt( | ||
| coderouterCredentials.credentialRevision, | ||
| input.encrypted.credentialRevision, | ||
| ), | ||
| )); | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 8 \
'export const coderouterAccounts|vaultRevision|credentialRevision|importEncryptedCredential' \
web/db/schema.ts \
web/services/coderouter \
web/scripts/coderouter
rg -n -C 8 \
'importEncryptedCredential|vaultRevision|credentialRevision' \
web --glob '*test*' --glob '*spec*' || trueRepository: manaflow-ai/cmux
Length of output: 50372
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repository.ts around importEncryptedCredential =="
sed -n '150,285p' web/services/coderouter/repository.ts
echo
echo "== migration callers and importEncryptedCredential call sites =="
rg -n -C 5 'importEncryptedCredential|encryptCredential\(\{[\s\S]*?credentialRevision: input\.encrypted\.credentialRevision|credentialRevision: account\.revision|credentialRevision: expectedRevision \+ 1' web/services/coderouter web/scripts/coderouter
echo
echo "== importEncryptedCredential call sites =="
rg -n -C 4 'importEncryptedCredential' webRepository: manaflow-ai/cmux
Length of output: 11046
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== vault.ts relevant contents =="
ast-grep outline web/services/coderouter/vault.ts --view expanded || true
sed -n '1,260p' web/services/coderouter/vault.ts
echo
echo "== coderouter schema relevant insert/update migration/statements context =="
rg -n -C 6 'coderouter_accounts|coderouter_credentials|vault_revision|credential_revision' web/db web/migrations web --glob '*.ts' --glob '*.tsx' --glob '*.sql' || true
echo
echo "== deterministic SQL-like behavior for current import predicate cases =="
python3 - <<'PY'
def update_result(input_revision, stored_credential_revision=None, stored_account_revision=None):
if stored_credential_revision is None:
credential_inserted = True
credential_updated = False
elif stored_credential_revision < input_revision:
credential_inserted = False
credential_updated = True
else:
credential_inserted = False
credential_updated = False
if stored_account_revision is not None and stored_account_revision < input_revision:
account_updated = True
else:
account_updated = False
return {
"credential_inserted": credential_inserted,
"credential_updated": credential_updated,
"account_updated": account_updated,
"stored_credential": stored_credential_revision,
"stored_account": stored_account_revision,
"input": input_revision,
}
cases = [
{"label": "missing credential, stored account newer", "stored_credential": None, "stored_account": 10, "input": 5},
{"label": "older credential, stored account newer", "stored_credential": 1, "stored_account": 10, "input": 5},
{"label": "credential newer, stored account newer", "stored_credential": 20, "stored_account": 10, "input": 5},
{"label": "both newer than import", "stored_credential": 20, "stored_account": 15, "input": 5},
]
for c in cases:
print(c["label"], json := update_result(c["input"], c["stored_credential"], c["stored_account"]))
PYRepository: manaflow-ai/cmux
Length of output: 31655
Gate both credential and account updates with one monotonic revision.
importEncryptedCredential reads only coderouterCredentials.credentialRevision for the credential write and coderouterAccounts.vaultRevision for the metadata write. If the imported revision is newer than the stored credential revision but older than the account revision, account metadata such as label and credentialExpiresAt is overwritten with stale data while the credential row remains newer. Make both statements accept one revision from the credential source, and add coverage for missing credentials plus divergent stored revisions.
🤖 Prompt for 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.
In `@web/services/coderouter/repository.ts` around lines 240 - 261, Update
importEncryptedCredential so both the credential upsert and coderouterAccounts
metadata update are gated by the same monotonic revision from the imported
credential source. Use that revision for the account vaultRevision comparison as
well as coderouterCredentials.credentialRevision, preventing stale metadata
updates when stored revisions diverge. Add coverage for missing credentials and
divergent stored revisions.
Source: Path instructions
The rollback source only needs to be a subset of encrypted RDS. Requiring equal counts would permanently block cleanup if a new account were added after cutover. Cleanup still refuses deletion if any legacy source account lacks an encrypted destination.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Allow legacy credential cleanup when new encrypted accounts exist, and ensure migration only advances credential revisions.
credentialRevisionis higher.Written for commit 6e85fba. Summary will update on new commits.
Summary by CodeRabbit