fix(BA-6896): stop RBAC backfill downgrades from deleting live permissions - #12881
Draft
jopemachine wants to merge 2 commits into
Draft
fix(BA-6896): stop RBAC backfill downgrades from deleting live permissions#12881jopemachine wants to merge 2 commits into
jopemachine wants to merge 2 commits into
Conversation
…sions The RBAC backfill migrations seeded permissions, scope associations, and object permissions for a new entity type, and their downgrades removed them with a blanket DELETE by entity_type. Once the runtime starts using an entity type, operators grant and revoke permissions and attach entities to scopes of their own. Those rows are indistinguishable from the seeded ones, so a downgrade also erased real operator-managed grants -- including the object permissions backing live vfolder invitations -- and a later upgrade only restored the seed. Make these downgrades no-ops, matching the forward-only precedent already set by the sibling backfill migrations, and drop the now-dead delete and revert helpers. Schema-reverting migrations are untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📚 Stacked PRs
BA-6896fix: RBAC backfill downgrades no longer delete live permissions ← you are hereBA-6897fix: pre-constraint RBAC backfill upgrades skip existing rowsMerge in order, bottom-up. Each PR is based on the one above it, so its diff shows only its own layer.
Problem
15 RBAC backfill migrations seed
permissions/association_scopes_entities/object_permissionsfor a new entity type, and theirdowngrade()removes those rows with a blanketDELETE ... WHERE entity_type = %s.Once the runtime starts using an entity type, operators grant and revoke permissions and attach entities to scopes of their own. Those rows are indistinguishable from the seeded ones, so a downgrade also erases real operator-managed grants — including the object permissions backing live vfolder invitations. The loss is unrecoverable: a later
upgradeonly re-creates the seed, not the operator's grants.Verified against a real database
Not a static reading — reproduced with real alembic on a Postgres DB built at head via
mgr schema oneshot. For each migration: seed a permission row on an operator-owned role (indistinguishable from a seeded one),stamp <rev>, thendowngrade <parent>so only that migration's downgrade runs, then check whether the operator's row survived.main(before)¹
3b6297b1bd75deletes only from roles matchingrole_project_%_admin, so it needs a role matching that pattern to bite; with one, it destroys the row like the rest.Solution
Make these
downgrade()s no-ops with a short comment, and drop the now-dead delete/revert helpers.This is not a new convention — it matches the forward-only precedent already set by sibling backfill migrations (
6e5a7a62a687,3632aad9d5d9,f2b9a4c7e103,5a4e677aea42,e3fb172166dc), which are no-ops for exactly this reason.Out of scope
Schema-reverting migrations (constraints, columns, tables) keep their existing
downgrade()— dropping a column the upgrade added is a real, safe revert. Only data backfills are changed here.7h4m7ygnaao1also revertedrefedges back toautoon downgrade; that flips rows the operator may own too, so the whole downgrade is now a no-op.End-to-end verification
Added once the downgrade chain was repaired (#12887, #12907, #12910, #12912 fixed six walls that made this impossible before). A single straight
alembic downgradefrom head tod86417a6bf7b— 175 revisions, no skipped steps — run on a seeded database. Operator-managed permission rows counted byentity_type, sincerole_iddoes not exist in the schema at that depth:The four survivors are the pre-redesign entity types, whose downgrades never matched these rows in the first place.
Follow-up
Making these downgrades no-ops exposes a latent idempotency bug in six of them — fixed in the stacked PR #12883, which should land together with this one.
🤖 Generated with Claude Code