feat(BA-6704): cascade app config subtree deletion from the definition#12518
Merged
Conversation
jopemachine
added a commit
that referenced
this pull request
Jul 3, 2026
Co-Authored-By: Claude Fable 5 <[email protected]>
15c3f60 to
c96d21f
Compare
This was referenced Jul 3, 2026
jopemachine
added a commit
that referenced
this pull request
Jul 3, 2026
Co-Authored-By: Claude Fable 5 <[email protected]>
65f7b52 to
4602841
Compare
4afa2cb to
ec8f884
Compare
jopemachine
added a commit
that referenced
this pull request
Jul 6, 2026
Co-Authored-By: Claude Fable 5 <[email protected]>
398066c to
bdb60d0
Compare
ec8f884 to
4afa2cb
Compare
bdb60d0 to
398066c
Compare
4afa2cb to
2177b3f
Compare
jopemachine
added a commit
that referenced
this pull request
Jul 6, 2026
Co-Authored-By: Claude Fable 5 <[email protected]>
398066c to
b8cdd23
Compare
jopemachine
commented
Jul 6, 2026
Co-Authored-By: Claude Fable 5 <[email protected]>
Co-Authored-By: Claude Fable 5 <[email protected]>
Resolve diverged alembic heads after merging origin/main: rebase a560420476b6 onto e9a1c77b42d0 (add kernel resource_group_id column). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The fragment create path now relies on the FK to app_config_allow_list to reject writes with no allow-list row (surfaced as AppConfigFragmentWriteNotAllowed via the creator spec's integrity checks). With the only consumer gone, drop the ExistsQuerier type and the exists() methods it fed (ReadOps, allow-list repository). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
With the write-gate gone, the repository no longer needs the raw spec. Accept a Creator[AppConfigFragmentRow] in create() (repository + db_source), matching the sibling allow-list/definition repositories; the service wraps the action's spec. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Removing ExistsQuerier from repositories/base invalidated the pants cache for these tests, re-running fixtures that were only green from stale cache. Each lists a partial with_tables/ORM subset, so SQLAlchemy's global configure_mappers() fails on KernelRow.image_row -> "ImageRow" (reachable via VFolderRow/RBAC relationships) because ImageRow was never registered. Register ImageRow per fixture: the vfolder search tests add it (with its ContainerRegistryRow FK parent) to with_tables; the role-scope test adds it to the existing _ORM_CLUSTER registration tuple. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
1c046fa to
368d2bf
Compare
HyeockJinKim
approved these changes
Jul 7, 2026
Comment on lines
+75
to
+79
| # 3. fragments -> definitions: drop the redundant direct FK (it blocks the cascade). | ||
| op.execute( | ||
| "ALTER TABLE app_config_fragments " | ||
| "DROP CONSTRAINT IF EXISTS fk_app_config_fragments_config_name_app_config_definitions" | ||
| ) |
This was referenced Jul 9, 2026
Closed
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.
Summary
Ties fragments to their allow-list entry with a composite FK and lets deletion cascade the whole subtree
definition → allow_list → fragment(BEP-1052 review feedback):ON DELETE CASCADE.app_config_fragments (config_name, scope_type)referencesapp_config_allow_list, so purging an allow-list entry drops every fragment written under it — a revoked value disappears from the merge in the same statement, with no orphaned fragments to clean up separately.app_config_allow_list.config_name → app_config_definitionschanges fromNO ACTIONtoON DELETE CASCADE, and the redundant directapp_config_fragments.config_name → app_config_definitionsFK is dropped (not made cascade). A fragment already requires a matching allow-list entry (composite FK, both columnsNOT NULL) whoseconfig_nameis registered, so registration is guaranteed transitively — the direct FK added no integrity and only blocked the definition delete (aNO ACTIONcheck firing before the allow-list cascade cleared the fragments). Result: retiring a config name (DELETEits definition row) cascades cleanly throughallow_listdown to the fragments.only_ifgates on fragment update/purge are provably dead and are removed (from the actions, service, repository, and db_source). The create gate stays — it surfaces the domain error (AppConfigFragmentWriteNotAllowed) instead of a raw FK violation.a560420476b6: deletes orphaned fragments, adds the composite allow-list FK, swaps the allow-list→definition FK toCASCADE, and drops the redundant direct fragment→definition FK. Constraint names are discovered via the inspector (they differ between a migration-built DB and a metadata-built dev DB). Upgrade/downgrade round-trip and the livedefinition → allow_list → fragmentcascade were verified against a local DB; the end state is exactly two FKs.rank— the "reads never consult the allow-list" wording was stale), and the create-only write gate.📚 Stacked PRs
Part of the AppConfigFragment / AppConfig stack under BEP-1052 (epic BA-5781). Merge in order:
feat(BA-6552): app_config_fragments DB model and Alembic migrationfeat(BA-6553): repository layerrefactor(BA-6619): consolidate AppConfigScopeType into common.datarefactor(BA-6620): ExistsQuerier + AppConfigAllowList.existsfeat(BA-6554): AppConfigFragment service layerfeat(BA-6628): move fragment rank to the allow list with scope defaults(replaces feat(BA-6628): conditional-bulk repository primitives #12429)feat(BA-6628): expose allow-list rank on the v2 API surfacefeat(BA-6704): cascade app config subtree deletion from the definition← you are herefeat(BA-6626): app_config_fragment bulk repository layerfeat(BA-6618): AppConfigFragment bulk CRUD service layerfeat(BA-6555): app_config service layer (merge engine)feat(BA-6556): AppConfig REST v2 API🤖 Generated with Claude Code
📚 Documentation preview 📚: https://sorna--12518.org.readthedocs.build/en/12518/
📚 Documentation preview 📚: https://sorna-ko--12518.org.readthedocs.build/ko/12518/