feat(BA-6837): authorize fragment reads via allow_list read_access tier#12764
Closed
jopemachine wants to merge 13 commits into
Closed
feat(BA-6837): authorize fragment reads via allow_list read_access tier#12764jopemachine wants to merge 13 commits into
jopemachine wants to merge 13 commits into
Conversation
This was referenced Jul 10, 2026
…w_list Decouple read-enablement from write-authorization. Add AppConfigAccessLevel (public < authenticated < owner < admin) and read_access / write_access columns on app_config_allow_list, so the row registers a config layer + its merge rank without its existence implying write access. Creator/updater default and accept the tiers per scope-type policy (public: read=public/write=admin, domain: read=authenticated/write=admin, user: read=owner/write=owner); migration backfills existing rows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve the merged AppConfig for a (user, config_name) on top of the repository's visible-fragments query: - AppConfigData: the merged per-user view (ordered fragments + deep-merged config; None when no fragment contributes) - deep-merge in rank order — nested dicts recurse, lists/scalars are replaced wholesale by the higher-rank fragment - resolve / resolve_bulk actions + processors (bulk repeats duplicate names in order) - mocked-repository service tests Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Surface read_access / write_access (AppConfigAccessLevel) on the app_config_allow_list v2 API, mirroring rank / scope_type: response node + create/update inputs (DTO, GraphQL), adapter mapping and creator/updater spec threading, SDK request/response, and CLI create/update options. Create defaults to the scope-type policy when omitted; update leaves omitted tiers unchanged. Regenerated the GraphQL schema dump. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: octodog <mu001@lablup.com>
…tier Enforce AppConfig's standalone write authorization: each fragment write is checked against the write_access tier of the target (config_name, scope_type) allow_list entry (AppConfigAccessLevel.is_satisfied_by) — no RBAC validator. A user may manage their own user-scope fragment; public/domain default to admin-only; superadmin passes any tier. create authorizes from the creator spec; update/purge load the fragment first; bulk writes authorize per item (unauthorized items become partial failures). Fragment write routes switch from superadmin_required to auth_required; the service gains the allow_list repository (by_config_and_scope) for the tier lookup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: octodog <mu001@lablup.com>
Gate merged-config reads by the read_access tier of each visible layer's allow_list entry, reusing AppConfigAccessLevel.is_satisfied_by. resolve / resolve_bulk drop layers the caller may not read before merging (exact); resolve_public (scope=None, requester=None) yields only public-read layers; scoped_search filters the returned page by each item's tier. The read query list_visible_fragments_bulk now returns VisibleFragment(data, read_access); read actions carry the caller (current_user, or None for anonymous public). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b65cd3a to
6f1d562
Compare
23f8791 to
fe828c8
Compare
6f1d562 to
eff9831
Compare
Member
Author
|
Closing: read authorization is no longer a separate concern. In the finalized design, the allow-list carries a single |
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
Enforces AppConfig read authorization (BA-6837, BEP-1052 / epic BA-5781) — the read-side mirror of BA-6836 (#12759). A config layer's fragments contribute to a caller's read only when the caller satisfies that layer's
read_accesstier (reusingAppConfigAccessLevel.is_satisfied_by). No RBAC validator; the allow-list access tiers are AppConfig's authorization system.How
list_visible_fragments_bulknow selects each layer'sread_accessand returnsVisibleFragment(data, read_access)instead of bare fragment data.resolve/resolve_bulkdrop layers the caller may not read before merging (exact — these are the security-critical end-user paths).resolve_public(scope=None,requester=None) yields onlyread_access == publiclayers.scoped_searchfilters the returned page by each item's tier (looked up viaby_config_and_scope, cached).requester=current_user()(authenticated resolve / scoped-search),requester=None(anonymous public).Default policy → behavior preserved
Default
read_access(public=public, domain=authenticated, user=owner) matches the existing scope-visibility filter, so default reads are unchanged; only an admin-set non-defaultread_access(e.g. a public layer set toadmin) further restricts.Notes
scoped_searchgates the returned page post-fetch;total_count/has_next_pagestill reflect the visible-scope match count before theread_accessgate (paginated counts are not re-derived) — documented in-code. The merged reads (resolve / public) filter fully, so they are exact.📚 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-6702): move fragment rank to the allow list with scope defaultsfeat(BA-6701): expose allow-list rank on the v2 API surfacefeat(BA-6704): cascade app config subtree deletion from the definitionfeat(BA-6626): app_config_fragment bulk repository layerfeat(BA-6618): app_config_fragment bulk CRUD service layerfeat(BA-6810): AppConfigFragment visible-fragments query (repository layer)feat(BA-6834): AppConfig allow_list read/write access levels (model + migration)— read/write separation foundationfeat(BA-6555): AppConfig merge engine + resolve service (service layer)feat(BA-6556): AppConfig REST v2 APIfeat(BA-6835): expose read/write access level on the allow_list v2 APIfeat(BA-6836): authorize fragment writes via allow_list write_access tierfeat(BA-6837): authorize fragment reads via allow_list read_access tier← you are hereAppConfig is treated as RBAC-Global with no RBAC validator;
app_config_allow_list's access tiers are AppConfig's standalone authorization system. The access-level columns sit at the base so every layer above builds on the read/write-separated model.